#[cfg(test)]
mod tests {
use super::super::container_types::Container;
use std::process::Command;
use std::thread;
use std::time::Duration;
fn is_nerdctl_available() -> bool {
match Command::new("which").arg("nerdctl").output() {
Ok(output) => output.status.success(),
Err(_) => false,
}
}
#[test]
fn test_container_builder_pattern() {
if !is_nerdctl_available() {
println!("Skipping test: nerdctl is not available");
return;
}
let container = Container::new("test-container")
.unwrap()
.with_port("8080:80")
.with_volume("/tmp:/data")
.with_env("TEST_ENV", "test_value")
.with_detach(true);
assert_eq!(container.name, "test-container");
assert_eq!(container.ports.len(), 1);
assert_eq!(container.ports[0], "8080:80");
assert_eq!(container.volumes.len(), 1);
assert_eq!(container.volumes[0], "/tmp:/data");
assert_eq!(container.env_vars.len(), 1);
assert_eq!(container.env_vars.get("TEST_ENV").unwrap(), "test_value");
assert_eq!(container.detach, true);
}
#[test]
fn test_container_from_image() {
if !is_nerdctl_available() {
println!("Skipping test: nerdctl is not available");
return;
}
let container = Container::from_image("test-container", "alpine:latest").unwrap();
assert_eq!(container.name, "test-container");
assert_eq!(container.image.as_ref().unwrap(), "alpine:latest");
}
#[test]
fn test_container_health_check() {
if !is_nerdctl_available() {
println!("Skipping test: nerdctl is not available");
return;
}
let container = Container::new("test-container")
.unwrap()
.with_health_check("curl -f http://localhost/ || exit 1");
assert!(container.health_check.is_some());
let health_check = container.health_check.unwrap();
assert_eq!(health_check.cmd, "curl -f http://localhost/ || exit 1");
assert!(health_check.interval.is_none());
assert!(health_check.timeout.is_none());
assert!(health_check.retries.is_none());
assert!(health_check.start_period.is_none());
}
#[test]
fn test_container_health_check_options() {
if !is_nerdctl_available() {
println!("Skipping test: nerdctl is not available");
return;
}
let container = Container::new("test-container")
.unwrap()
.with_health_check_options(
"curl -f http://localhost/ || exit 1",
Some("30s"),
Some("10s"),
Some(3),
Some("5s"),
);
assert!(container.health_check.is_some());
let health_check = container.health_check.unwrap();
assert_eq!(health_check.cmd, "curl -f http://localhost/ || exit 1");
assert_eq!(health_check.interval.as_ref().unwrap(), "30s");
assert_eq!(health_check.timeout.as_ref().unwrap(), "10s");
assert_eq!(health_check.retries.unwrap(), 3);
assert_eq!(health_check.start_period.as_ref().unwrap(), "5s");
}
#[test]
#[ignore] fn test_container_runtime_and_resources() {
let nerdctl_check = super::super::execute_nerdctl_command(&["info"]);
if nerdctl_check.is_err() {
println!("Skipping test: nerdctl is not available or properly configured");
println!("Error: {:?}", nerdctl_check.err());
return;
}
let container_name = format!(
"test-runtime-{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
);
let container_result = Container::from_image(&container_name, "busybox:latest")
.unwrap()
.with_detach(true)
.build();
if container_result.is_err() {
println!("Failed to build container: {:?}", container_result.err());
return;
}
let container = container_result.unwrap();
println!("Container created successfully: {}", container_name);
let start_result =
container.exec("sh -c 'for i in $(seq 1 10); do echo $i; sleep 1; done'");
if start_result.is_err() {
println!("Failed to start container: {:?}", start_result.err());
let _ = container.remove();
return;
}
println!("Container started successfully");
thread::sleep(Duration::from_secs(3));
let status_result = container.status();
if status_result.is_err() {
println!("Failed to get container status: {:?}", status_result.err());
let _ = container.stop();
let _ = container.remove();
return;
}
let status = status_result.unwrap();
println!("Container status: {:?}", status);
if status.status != "running" {
println!("Container is not running, status: {}", status.status);
let _ = container.remove();
return;
}
let resources_result = container.resources();
if resources_result.is_err() {
println!("Failed to get resource usage: {:?}", resources_result.err());
let _ = container.stop();
let _ = container.remove();
return;
}
let resources = resources_result.unwrap();
println!("Container resources: {:?}", resources);
if resources.memory_usage == "0B" || resources.memory_usage == "unknown" {
println!(
"Warning: Container memory usage is {}",
resources.memory_usage
);
} else {
println!("Container is using memory: {}", resources.memory_usage);
}
println!("Stopping container...");
let stop_result = container.stop();
if stop_result.is_err() {
println!("Warning: Failed to stop container: {:?}", stop_result.err());
}
println!("Removing container...");
let remove_result = container.remove();
if remove_result.is_err() {
println!(
"Warning: Failed to remove container: {:?}",
remove_result.err()
);
}
println!("Test completed successfully");
}
#[test]
fn test_container_with_custom_command() {
if !is_nerdctl_available() {
println!("Skipping test: nerdctl is not available");
return;
}
let container = Container::new("test-command-container")
.unwrap()
.with_port("8080:80")
.with_volume("/tmp:/data")
.with_env("TEST_ENV", "test_value")
.with_detach(true);
assert_eq!(container.name, "test-command-container");
assert_eq!(container.ports.len(), 1);
assert_eq!(container.ports[0], "8080:80");
assert_eq!(container.volumes.len(), 1);
assert_eq!(container.volumes[0], "/tmp:/data");
assert_eq!(container.env_vars.len(), 1);
assert_eq!(container.env_vars.get("TEST_ENV").unwrap(), "test_value");
assert_eq!(container.detach, true);
let command_args = container_to_command_args(&container);
assert!(command_args.contains(&"--name".to_string()));
assert!(command_args.contains(&"test-command-container".to_string()));
assert!(command_args.contains(&"-p".to_string()));
assert!(command_args.contains(&"8080:80".to_string()));
assert!(command_args.contains(&"-v".to_string()));
assert!(command_args.contains(&"/tmp:/data".to_string()));
assert!(command_args.contains(&"-e".to_string()));
assert!(command_args.contains(&"TEST_ENV=test_value".to_string()));
assert!(command_args.contains(&"-d".to_string()));
println!("Command args: {:?}", command_args);
}
fn container_to_command_args(container: &Container) -> Vec<String> {
let mut args = Vec::new();
args.push("run".to_string());
if container.detach {
args.push("-d".to_string());
}
args.push("--name".to_string());
args.push(container.name.clone());
for port in &container.ports {
args.push("-p".to_string());
args.push(port.clone());
}
for volume in &container.volumes {
args.push("-v".to_string());
args.push(volume.clone());
}
for (key, value) in &container.env_vars {
args.push("-e".to_string());
args.push(format!("{}={}", key, value));
}
if let Some(image) = &container.image {
args.push(image.clone());
}
args
}
}