#[cfg(feature = "template-redis")]
mod redis_template_tests {
use docker_wrapper::{DockerCommand, RedisTemplate, Template};
use std::time::Duration;
use tokio::time::sleep;
fn test_container_name(suffix: &str) -> String {
format!("test-redis-template-{}-{}", suffix, uuid::Uuid::new_v4())
}
fn random_port() -> u16 {
30000 + (uuid::Uuid::new_v4().as_u128() % 10000) as u16
}
#[tokio::test]
async fn test_redis_basic_start_stop() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("basic");
let redis = RedisTemplate::new(&name).port(random_port());
let container_id = redis.start_and_wait().await?;
assert!(!container_id.is_empty());
assert!(redis.is_running().await?);
let result = redis.exec(vec!["redis-cli", "ping"]).await?;
assert_eq!(result.stdout.trim(), "PONG");
redis.stop().await?;
sleep(Duration::from_millis(500)).await;
assert!(!redis.is_running().await?);
redis.remove().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_with_password() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("password");
let redis = RedisTemplate::new(&name)
.port(random_port())
.password("test_password");
let _container_id = redis.start_and_wait().await?;
let result = redis
.exec(vec!["redis-cli", "-a", "test_password", "ping"])
.await?;
assert_eq!(result.stdout.trim(), "PONG");
let result = redis.exec(vec!["redis-cli", "ping"]).await?;
assert!(result.stdout.contains("NOAUTH") || result.stderr.contains("NOAUTH"));
redis.stop().await?;
redis.remove().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_with_persistence() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("persistence");
let volume_name = format!("{}-data", name);
let redis = RedisTemplate::new(&name)
.port(random_port())
.with_persistence(&volume_name);
let _container_id = redis.start_and_wait().await?;
redis
.exec(vec!["redis-cli", "SET", "test_key", "test_value"])
.await?;
let result = redis.exec(vec!["redis-cli", "GET", "test_key"]).await?;
assert_eq!(result.stdout.trim(), "test_value");
redis.stop().await?;
redis.remove().await?;
let redis2 = RedisTemplate::new(format!("{}-2", name))
.port(random_port())
.with_persistence(&volume_name);
let _container_id2 = redis2.start_and_wait().await?;
let result = redis2.exec(vec!["redis-cli", "GET", "test_key"]).await?;
assert_eq!(result.stdout.trim(), "test_value");
redis2.stop().await?;
redis2.remove().await?;
use docker_wrapper::VolumeRmCommand;
VolumeRmCommand::new(&volume_name).force().execute().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_memory_limit() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("memory");
let redis = RedisTemplate::new(&name)
.port(random_port())
.memory_limit("128m");
let _container_id = redis.start_and_wait().await?;
use docker_wrapper::InspectCommand;
let inspect = InspectCommand::new(&name).execute().await?;
let containers: serde_json::Value = serde_json::from_str(&inspect.stdout)?;
if let Some(first) = containers.as_array().and_then(|arr| arr.first()) {
if let Some(host_config) = first.get("HostConfig") {
if let Some(memory) = host_config.get("Memory").and_then(|m| m.as_i64()) {
assert_eq!(memory, 134217728);
}
}
}
redis.stop().await?;
redis.remove().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_custom_image() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("custom");
let redis = RedisTemplate::new(&name)
.port(random_port())
.custom_image("redis", "6-alpine");
let _container_id = redis.start_and_wait().await?;
let result = redis.exec(vec!["redis-cli", "INFO", "server"]).await?;
assert!(result.stdout.contains("redis_version:6."));
redis.stop().await?;
redis.remove().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_stack() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("stack");
let redis = RedisTemplate::new(&name)
.port(random_port())
.with_redis_stack();
let _container_id = redis.start_and_wait().await?;
let result = redis.exec(vec!["redis-cli", "MODULE", "LIST"]).await?;
assert!(
result.stdout.contains("search")
|| result.stdout.contains("json")
|| result.stdout.contains("timeseries"),
"Redis Stack modules not found in output: {}",
result.stdout
);
redis.stop().await?;
redis.remove().await?;
Ok(())
}
#[tokio::test]
async fn test_redis_logs() -> Result<(), Box<dyn std::error::Error>> {
let name = test_container_name("logs");
let redis = RedisTemplate::new(&name).port(random_port());
let _container_id = redis.start_and_wait().await?;
let logs = redis.logs(false, Some("10")).await?;
assert!(!logs.stdout.is_empty());
assert!(logs.stdout.contains("Ready to accept connections"));
redis.stop().await?;
redis.remove().await?;
Ok(())
}
}