// 03_container_builder.rhai // Tests for Nerdctl Container Builder pattern // Custom assert function fn assert_true(condition, message) { if !condition { print(`ASSERTION FAILED: ${message}`); throw message; } } // Custom assert_eq function fn assert_eq(actual, expected, message) { if actual != expected { print(`ASSERTION FAILED: ${message}`); print(`Expected: "${expected}"`); print(`Actual: "${actual}"`); throw message; } } // Helper function to check if nerdctl is available fn is_nerdctl_available() { try { let result = run("which nerdctl"); return result.success; } catch(err) { return false; } } // Helper function to check if a container exists fn container_exists(container_name) { try { let result = run(`nerdctl ps -a --format "{{.Names}}" | grep -w ${container_name}`); return result.success; } catch(err) { return false; } } // Helper function to clean up a container if it exists fn cleanup_container(container_name) { if container_exists(container_name) { try { run(`nerdctl stop ${container_name}`); run(`nerdctl rm ${container_name}`); print(`Cleaned up container: ${container_name}`); } catch(err) { print(`Error cleaning up container ${container_name}: ${err}`); } } } print("=== Testing Nerdctl Container Builder Pattern ==="); // Check if nerdctl is available let nerdctl_available = is_nerdctl_available(); if !nerdctl_available { print("nerdctl is not available. Skipping Nerdctl tests."); // Exit gracefully without error return; } print("✓ nerdctl is available"); // Define test container name let container_name = "rhai_test_builder"; // Clean up any existing test container cleanup_container(container_name); // Create test directories let work_dir = "rhai_test_nerdctl_work"; let config_dir = "rhai_test_nerdctl_config"; mkdir(work_dir); mkdir(config_dir); try { // Test creating a container from an image with builder pattern print("Testing nerdctl_container_from_image() with builder pattern..."); // Create a container with a rich set of options using the builder pattern let container = nerdctl_container_from_image(container_name, "alpine:latest") .reset() // Reset to default configuration .with_detach(true) .with_ports(["8080:80", "9090:90"]) .with_volumes([`${work_dir}:/data`, `${config_dir}:/config`]) .with_envs(#{ "ENV1": "value1", "ENV2": "value2", "TEST_MODE": "true" }) .with_network("bridge") .with_cpu_limit("0.5") .with_memory_limit("256m"); // Verify container properties assert_eq(container.name, container_name, "Container name should match"); assert_eq(container.image, "alpine:latest", "Container image should match"); assert_true(container.detach, "Container detach mode should be true"); // Run the container print("Testing run() with builder pattern..."); let run_result = container.run(); assert_true(run_result.success, "Container run should succeed"); assert_true(container.container_id != "", "Container ID should not be empty after run"); print(`✓ run(): Container started with ID: ${container.container_id}`); // Test environment variables print("Testing environment variables..."); let env_result = container.exec("env"); assert_true(env_result.success, "Container exec should succeed"); assert_true(env_result.stdout.contains("ENV1=value1"), "Environment variable ENV1 should be set"); assert_true(env_result.stdout.contains("ENV2=value2"), "Environment variable ENV2 should be set"); assert_true(env_result.stdout.contains("TEST_MODE=true"), "Environment variable TEST_MODE should be set"); print("✓ Environment variables set correctly"); // Test volume mounts print("Testing volume mounts..."); // Create a test file in the work directory file_write(`${work_dir}/test.txt`, "Hello from host"); // Check if the file is accessible in the container let volume_result = container.exec("cat /data/test.txt"); assert_true(volume_result.success, "Container exec should succeed"); assert_true(volume_result.stdout.contains("Hello from host"), "Volume mount should work correctly"); print("✓ Volume mounts working correctly"); // Test writing from container to volume print("Testing writing from container to volume..."); let write_result = container.exec("echo 'Hello from container' > /config/container.txt"); assert_true(write_result.success, "Container exec should succeed"); // Check if the file was created on the host let host_file_content = file_read(`${config_dir}/container.txt`); assert_true(host_file_content.contains("Hello from container"), "Container should be able to write to volume"); print("✓ Container can write to volume"); // Test stopping the container print("Testing stop()..."); let stop_result = container.stop(); assert_true(stop_result.success, "Container stop should succeed"); print("✓ stop(): Container stopped successfully"); // Test removing the container print("Testing remove()..."); let remove_result = container.remove(); assert_true(remove_result.success, "Container remove should succeed"); print("✓ remove(): Container removed successfully"); print("All container builder pattern tests completed successfully!"); } catch(err) { print(`Error: ${err}`); // Clean up in case of error cleanup_container(container_name); throw err; } finally { // Clean up test directories delete(work_dir); delete(config_dir); print("✓ Cleanup: Test directories removed"); }