use super::container::*;
use crate::core::types::{ContainerConfig, Machine};
#[test]
fn test_fj021_cleanup_with_echo_runtime() {
let machine = Machine {
hostname: "cleanup-box".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "/bin/echo".to_string(),
image: Some("test:latest".to_string()),
name: Some("forjar-cleanup-test".to_string()),
ephemeral: true,
privileged: false,
init: true,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let result = cleanup_container(&machine);
assert!(result.is_ok(), "cleanup with echo runtime should succeed");
}
#[test]
fn test_fj021_exec_container_error_msg_no_config() {
let machine = Machine {
hostname: "precise-host".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: None,
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let err = exec_container(&machine, "echo").unwrap_err();
assert_eq!(err, "machine 'precise-host' has no container config");
}
#[test]
fn test_fj021_ensure_container_error_msg_no_config() {
let machine = Machine {
hostname: "precise-host".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: None,
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let err = ensure_container(&machine).unwrap_err();
assert_eq!(err, "machine 'precise-host' has no container config");
}
#[test]
fn test_fj021_cleanup_container_error_msg_no_config() {
let machine = Machine {
hostname: "precise-host".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: None,
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let err = cleanup_container(&machine).unwrap_err();
assert_eq!(err, "machine 'precise-host' has no container config");
}
#[test]
fn test_fj132_ensure_attached_no_image_required() {
let machine = Machine {
hostname: "attached".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "/bin/echo".to_string(),
image: None,
name: Some("existing-container".to_string()),
ephemeral: false, privileged: false,
init: true,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let result = ensure_container(&machine);
assert!(
result.is_ok() || !result.unwrap_err().contains("no image specified"),
"attached (ephemeral=false) should not require image"
);
}
#[test]
fn test_fj132_ephemeral_guard_skips_non_ephemeral() {
let machine = Machine {
hostname: "persistent".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "/bin/false".to_string(),
image: None,
name: Some("keep-me".to_string()),
ephemeral: false,
privileged: false,
init: true,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let config = machine.container.as_ref().unwrap();
assert!(!config.ephemeral, "test machine should be non-ephemeral");
}
#[test]
fn test_fj132_container_name_default_derivation() {
let machine = Machine {
hostname: "my-test-box".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "docker".to_string(),
image: Some("ubuntu:22.04".to_string()),
name: None,
ephemeral: true,
privileged: false,
init: true,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let name = machine.container_name();
assert!(
name.contains("my-test-box"),
"derived name should contain hostname: {name}"
);
}
#[test]
fn test_fj021_ensure_uses_correct_runtime() {
let machine = Machine {
hostname: "podman-ensure".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "podman".to_string(),
image: Some("alpine:latest".to_string()),
name: Some("forjar-podman-ensure".to_string()),
ephemeral: true,
privileged: false,
init: false,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let result = ensure_container(&machine);
if let Err(e) = result {
assert!(
e.contains("forjar-podman-ensure"),
"ensure error should reference the container name: {e}"
);
}
}
#[test]
fn test_fj021_cleanup_nonexistent_returns_err() {
let machine = Machine {
hostname: "ghost".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "/bin/false".to_string(),
image: Some("test:latest".to_string()),
name: Some("forjar-nonexistent-cleanup".to_string()),
ephemeral: true,
privileged: false,
init: false,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let result = cleanup_container(&machine);
assert!(
result.is_err(),
"cleanup of nonexistent container via /bin/false should error"
);
let err = result.unwrap_err();
assert!(
err.contains("forjar-nonexistent-cleanup"),
"error should contain container name: {err}"
);
}
#[test]
fn test_fj021_ephemeral_guard_cleans_up() {
let machine = Machine {
hostname: "ephemeral-guard".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "/bin/echo".to_string(),
image: Some("test:latest".to_string()),
name: Some("forjar-ephemeral-guard".to_string()),
ephemeral: true,
privileged: false,
init: false,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let config = machine.container.as_ref().unwrap();
assert!(config.ephemeral, "test setup: should be ephemeral");
if config.ephemeral {
let result = cleanup_container(&machine);
assert!(
result.is_ok(),
"ephemeral cleanup via /bin/echo should succeed: {:?}",
result.err()
);
}
}
#[test]
fn test_fj021_container_name_from_machine_key() {
let machine = Machine {
hostname: "web-prod-01".to_string(),
addr: "container".to_string(),
user: "root".to_string(),
arch: "x86_64".to_string(),
ssh_key: None,
roles: vec![],
transport: Some("container".to_string()),
container: Some(ContainerConfig {
runtime: "docker".to_string(),
image: Some("ubuntu:22.04".to_string()),
name: None,
ephemeral: true,
privileged: false,
init: true,
gpus: None,
devices: vec![],
group_add: vec![],
env: std::collections::HashMap::new(),
volumes: vec![],
}),
pepita: None,
cost: 0,
allowed_operators: vec![],
};
let name = machine.container_name();
assert_eq!(
name, "forjar-web-prod-01",
"auto-generated name should be forjar-<hostname>"
);
}