Files
herolib_rust/packages/system/virt/src/buildah/containers_test.rs
2025-08-05 15:33:03 +02:00

339 lines
9.6 KiB
Rust

#[cfg(test)]
mod tests {
use crate::buildah::BuildahError;
use lazy_static::lazy_static;
use sal_process::CommandResult;
use std::sync::Mutex;
// Create a test-specific implementation of the containers module functions
// that we can use to verify the correct arguments are passed
lazy_static! {
static ref LAST_COMMAND: Mutex<Vec<String>> = Mutex::new(Vec::new());
static ref SHOULD_FAIL: Mutex<bool> = Mutex::new(false);
static ref TEST_MUTEX: Mutex<()> = Mutex::new(()); // Add a mutex for test synchronization
}
fn reset_test_state() {
let mut cmd = LAST_COMMAND.lock().unwrap();
cmd.clear();
let mut fail = SHOULD_FAIL.lock().unwrap();
*fail = false;
}
fn set_should_fail(fail: bool) {
let mut should_fail = SHOULD_FAIL.lock().unwrap();
*should_fail = fail;
}
fn get_last_command() -> Vec<String> {
let cmd = LAST_COMMAND.lock().unwrap();
cmd.clone()
}
// Test-specific implementation of execute_buildah_command
fn test_execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
// Record the command
{
let mut cmd = LAST_COMMAND.lock().unwrap();
cmd.clear();
for arg in args {
cmd.push(arg.to_string());
}
}
// Check if we should fail
let should_fail = {
let fail = SHOULD_FAIL.lock().unwrap();
*fail
};
if should_fail {
Err(BuildahError::CommandFailed("Command failed".to_string()))
} else {
Ok(CommandResult {
stdout: "mock stdout".to_string(),
stderr: "".to_string(),
success: true,
code: 0,
})
}
}
// Test implementations of the container functions
fn test_from(image: &str) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["from", image])
}
fn test_run(container: &str, command: &str) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["run", container, "sh", "-c", command])
}
fn test_bah_run_with_isolation(
container: &str,
command: &str,
isolation: &str,
) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&[
"run",
"--isolation",
isolation,
container,
"sh",
"-c",
command,
])
}
fn test_bah_copy(
container: &str,
source: &str,
dest: &str,
) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["copy", container, source, dest])
}
fn test_bah_add(
container: &str,
source: &str,
dest: &str,
) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["add", container, source, dest])
}
fn test_bah_commit(container: &str, image_name: &str) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["commit", container, image_name])
}
fn test_bah_remove(container: &str) -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["rm", container])
}
fn test_bah_list() -> Result<CommandResult, BuildahError> {
test_execute_buildah_command(&["containers"])
}
fn test_bah_build(
tag: Option<&str>,
context_dir: &str,
file: &str,
isolation: Option<&str>,
) -> Result<CommandResult, BuildahError> {
let mut args = Vec::new();
args.push("build");
if let Some(tag_value) = tag {
args.push("-t");
args.push(tag_value);
}
if let Some(isolation_value) = isolation {
args.push("--isolation");
args.push(isolation_value);
}
args.push("-f");
args.push(file);
args.push(context_dir);
test_execute_buildah_command(&args)
}
// Tests for each function
#[test]
fn test_from_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let image = "alpine:latest";
let result = test_from(image);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["from", "alpine:latest"]);
}
#[test]
fn test_run_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let command = "echo hello";
// Test without isolation
let result = test_run(container, command);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["run", "my-container", "sh", "-c", "echo hello"]);
}
#[test]
fn test_bah_run_with_isolation_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let command = "echo hello";
let isolation = "chroot";
let result = test_bah_run_with_isolation(container, command, isolation);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(
cmd,
vec![
"run",
"--isolation",
"chroot",
"my-container",
"sh",
"-c",
"echo hello"
]
);
}
#[test]
fn test_bah_copy_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let source = "/local/path";
let dest = "/container/path";
let result = test_bah_copy(container, source, dest);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(
cmd,
vec!["copy", "my-container", "/local/path", "/container/path"]
);
}
#[test]
fn test_bah_add_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let source = "/local/path";
let dest = "/container/path";
let result = test_bah_add(container, source, dest);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(
cmd,
vec!["add", "my-container", "/local/path", "/container/path"]
);
}
#[test]
fn test_bah_commit_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let image_name = "my-image:latest";
let result = test_bah_commit(container, image_name);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["commit", "my-container", "my-image:latest"]);
}
#[test]
fn test_bah_remove_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let container = "my-container";
let result = test_bah_remove(container);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["rm", "my-container"]);
}
#[test]
fn test_bah_list_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
let result = test_bah_list();
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["containers"]);
}
#[test]
fn test_bah_build_function() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
// Test with tag, context directory, file, and no isolation
let result = test_bah_build(Some("my-app:latest"), ".", "Dockerfile", None);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(
cmd,
vec!["build", "-t", "my-app:latest", "-f", "Dockerfile", "."]
);
reset_test_state(); // Reset state between sub-tests
// Test with tag, context directory, file, and isolation
let result = test_bah_build(
Some("my-app:latest"),
".",
"Dockerfile.custom",
Some("chroot"),
);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(
cmd,
vec![
"build",
"-t",
"my-app:latest",
"--isolation",
"chroot",
"-f",
"Dockerfile.custom",
"."
]
);
reset_test_state(); // Reset state between sub-tests
// Test with just context directory and file
let result = test_bah_build(None, ".", "Dockerfile", None);
assert!(result.is_ok());
let cmd = get_last_command();
assert_eq!(cmd, vec!["build", "-f", "Dockerfile", "."]);
}
#[test]
fn test_error_handling() {
let _lock = TEST_MUTEX.lock().unwrap(); // Acquire lock for test
reset_test_state();
set_should_fail(true);
let image = "alpine:latest";
let result = test_from(image);
assert!(result.is_err());
match result {
Err(BuildahError::CommandFailed(msg)) => {
assert_eq!(msg, "Command failed");
}
_ => panic!("Expected CommandFailed error"),
}
}
}