docs: Add documentation for Nerdctl and RFS module tests
- Added documentation for Nerdctl module tests, detailing test structure, running instructions, and individual test cases. - Added documentation for RFS module tests, covering test structure, running instructions, and individual test cases. These tests verify remote filesystem operations and filesystem layer management.
This commit is contained in:
parent
83662736c0
commit
d3c645e8e6
@ -36,6 +36,8 @@ SAL includes test scripts for verifying the functionality of its Rhai integratio
|
|||||||
- [Redis Client Module Tests](redisclient_module_tests.md): Tests for Redis connection and operations
|
- [Redis Client Module Tests](redisclient_module_tests.md): Tests for Redis connection and operations
|
||||||
- [Text Module Tests](text_module_tests.md): Tests for text manipulation, normalization, replacement, and template rendering
|
- [Text Module Tests](text_module_tests.md): Tests for text manipulation, normalization, replacement, and template rendering
|
||||||
- [Buildah Module Tests](buildah_module_tests.md): Tests for container and image operations
|
- [Buildah Module Tests](buildah_module_tests.md): Tests for container and image operations
|
||||||
|
- [Nerdctl Module Tests](nerdctl_module_tests.md): Tests for container and image operations using nerdctl
|
||||||
|
- [RFS Module Tests](rfs_module_tests.md): Tests for remote filesystem operations and filesystem layers
|
||||||
- [Running Tests](running_tests.md): Instructions for running all Rhai tests
|
- [Running Tests](running_tests.md): Instructions for running all Rhai tests
|
||||||
- [CI Workflow](ci_workflow.md): Continuous integration workflow for Rhai tests
|
- [CI Workflow](ci_workflow.md): Continuous integration workflow for Rhai tests
|
||||||
|
|
||||||
|
116
docs/rhai/nerdctl_module_tests.md
Normal file
116
docs/rhai/nerdctl_module_tests.md
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# Nerdctl Module Tests
|
||||||
|
|
||||||
|
This document describes the test scripts for the Nerdctl module in the SAL library. These tests verify the functionality of the Nerdctl module's container and image operations.
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
The tests are organized into three main scripts:
|
||||||
|
|
||||||
|
1. **Container Operations** (`01_container_operations.rhai`): Tests for basic container operations like creating, running, executing commands, and removing containers.
|
||||||
|
2. **Image Operations** (`02_image_operations.rhai`): Tests for image-related operations like pulling, tagging, listing, building, and removing images.
|
||||||
|
3. **Container Builder Pattern** (`03_container_builder.rhai`): Tests for the Container Builder pattern, which provides a fluent interface for configuring and running containers.
|
||||||
|
|
||||||
|
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||||
|
|
||||||
|
## Running the Tests
|
||||||
|
|
||||||
|
To run all tests, execute the following command from the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
herodo --path src/rhai_tests/nerdctl/run_all_tests.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
To run individual test scripts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
herodo --path src/rhai_tests/nerdctl/01_container_operations.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Details
|
||||||
|
|
||||||
|
### Container Operations Test
|
||||||
|
|
||||||
|
The Container Operations test (`01_container_operations.rhai`) verifies the following functions:
|
||||||
|
|
||||||
|
- `nerdctl_container_new`: Creating a new Container
|
||||||
|
- Container properties: `name`, `container_id`, `image`, `detach`
|
||||||
|
- `with_image`: Setting the container image
|
||||||
|
- `with_detach`: Setting detach mode
|
||||||
|
- `with_env` and `with_envs`: Setting environment variables
|
||||||
|
- `with_port` and `with_ports`: Setting port mappings
|
||||||
|
- `with_volume`: Setting volume mounts
|
||||||
|
- `with_cpu_limit` and `with_memory_limit`: Setting resource limits
|
||||||
|
- `run`: Running the container
|
||||||
|
- `exec`: Executing commands in the container
|
||||||
|
- `logs`: Getting container logs
|
||||||
|
- `stop`: Stopping the container
|
||||||
|
- `remove`: Removing the container
|
||||||
|
|
||||||
|
### Image Operations Test
|
||||||
|
|
||||||
|
The Image Operations test (`02_image_operations.rhai`) verifies the following functions:
|
||||||
|
|
||||||
|
- `nerdctl_image_pull`: Pulling images from registries
|
||||||
|
- `nerdctl_images`: Listing images
|
||||||
|
- `nerdctl_image_tag`: Tagging images
|
||||||
|
- `nerdctl_image_build`: Building images from Dockerfiles
|
||||||
|
- `nerdctl_run_with_name`: Running containers from images
|
||||||
|
- `nerdctl_stop` and `nerdctl_remove`: Stopping and removing containers
|
||||||
|
- `nerdctl_image_remove`: Removing images
|
||||||
|
|
||||||
|
The test creates a temporary directory with a Dockerfile for testing the build functionality.
|
||||||
|
|
||||||
|
### Container Builder Pattern Test
|
||||||
|
|
||||||
|
The Container Builder Pattern test (`03_container_builder.rhai`) verifies the following functions:
|
||||||
|
|
||||||
|
- `nerdctl_container_from_image`: Creating a container from an image
|
||||||
|
- `reset`: Resetting container configuration
|
||||||
|
- `with_detach`: Setting detach mode
|
||||||
|
- `with_ports`: Setting multiple port mappings
|
||||||
|
- `with_volumes`: Setting multiple volume mounts
|
||||||
|
- `with_envs`: Setting multiple environment variables
|
||||||
|
- `with_network`: Setting network
|
||||||
|
- `with_cpu_limit` and `with_memory_limit`: Setting resource limits
|
||||||
|
- `run`: Running the container
|
||||||
|
- `exec`: Executing commands in the container
|
||||||
|
- `stop`: Stopping the container
|
||||||
|
- `remove`: Removing the container
|
||||||
|
|
||||||
|
The test also verifies that environment variables and volume mounts work correctly by writing and reading files between the container and the host.
|
||||||
|
|
||||||
|
## Test Runner
|
||||||
|
|
||||||
|
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||||
|
|
||||||
|
1. Checks if nerdctl is available before running tests
|
||||||
|
2. Skips tests if nerdctl is not available
|
||||||
|
3. Contains simplified versions of each test
|
||||||
|
4. Runs each test in a try/catch block to handle errors
|
||||||
|
5. Catches and reports any errors
|
||||||
|
6. Provides a summary of passed, failed, and skipped tests
|
||||||
|
|
||||||
|
## Nerdctl Requirements
|
||||||
|
|
||||||
|
These tests require the nerdctl tool to be installed and available in the system's PATH. The tests will check for nerdctl's availability and skip the tests if it's not found, rather than failing.
|
||||||
|
|
||||||
|
## Adding New Tests
|
||||||
|
|
||||||
|
To add a new test:
|
||||||
|
|
||||||
|
1. Create a new Rhai script in the `src/rhai_tests/nerdctl` directory
|
||||||
|
2. Add a new test section to the `run_all_tests.rhai` script
|
||||||
|
3. Update this documentation to include information about the new test
|
||||||
|
|
||||||
|
## Best Practices for Writing Tests
|
||||||
|
|
||||||
|
When writing tests for the Nerdctl module:
|
||||||
|
|
||||||
|
1. Always check if nerdctl is available before running tests
|
||||||
|
2. Use unique names for containers and images to avoid conflicts
|
||||||
|
3. Clean up any containers, images, or files created during testing
|
||||||
|
4. Use assertions to verify expected behavior
|
||||||
|
5. Print clear messages about what's being tested
|
||||||
|
6. Handle errors gracefully
|
||||||
|
7. Make tests independent of each other
|
||||||
|
8. Keep tests focused on specific functionality
|
113
docs/rhai/rfs_module_tests.md
Normal file
113
docs/rhai/rfs_module_tests.md
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# RFS Module Tests
|
||||||
|
|
||||||
|
This document describes the test scripts for the RFS (Remote File System) module in the SAL library. These tests verify the functionality of the RFS module's mount operations and filesystem layer management.
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
The tests are organized into two main scripts:
|
||||||
|
|
||||||
|
1. **Mount Operations** (`01_mount_operations.rhai`): Tests for mounting, listing, and unmounting filesystems.
|
||||||
|
2. **Filesystem Layer Operations** (`02_filesystem_layer_operations.rhai`): Tests for packing, unpacking, listing, and verifying filesystem layers.
|
||||||
|
|
||||||
|
Additionally, there's a runner script (`run_all_tests.rhai`) that executes all tests and reports results. The runner script contains simplified versions of the individual tests to avoid dependency issues.
|
||||||
|
|
||||||
|
## Running the Tests
|
||||||
|
|
||||||
|
To run all tests, execute the following command from the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
herodo --path src/rhai_tests/rfs/run_all_tests.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
To run individual test scripts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
herodo --path src/rhai_tests/rfs/01_mount_operations.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Details
|
||||||
|
|
||||||
|
### Mount Operations Test
|
||||||
|
|
||||||
|
The Mount Operations test (`01_mount_operations.rhai`) verifies the following functions:
|
||||||
|
|
||||||
|
- `rfs_mount`: Mounting a filesystem
|
||||||
|
- Tests mounting a local directory with options
|
||||||
|
- Verifies mount properties (ID, source, target, type)
|
||||||
|
|
||||||
|
- `rfs_list_mounts`: Listing mounted filesystems
|
||||||
|
- Tests listing all mounts
|
||||||
|
- Verifies that the mounted filesystem is in the list
|
||||||
|
|
||||||
|
- `rfs_get_mount_info`: Getting information about a mounted filesystem
|
||||||
|
- Tests getting information about a specific mount
|
||||||
|
- Verifies that the mount information is correct
|
||||||
|
|
||||||
|
- `rfs_unmount`: Unmounting a specific filesystem
|
||||||
|
- Tests unmounting a specific mount
|
||||||
|
- Verifies that the mount is no longer available
|
||||||
|
|
||||||
|
- `rfs_unmount_all`: Unmounting all filesystems
|
||||||
|
- Tests unmounting all mounts
|
||||||
|
- Verifies that no mounts remain after the operation
|
||||||
|
|
||||||
|
The test also verifies that files in the mounted filesystem are accessible and have the correct content.
|
||||||
|
|
||||||
|
### Filesystem Layer Operations Test
|
||||||
|
|
||||||
|
The Filesystem Layer Operations test (`02_filesystem_layer_operations.rhai`) verifies the following functions:
|
||||||
|
|
||||||
|
- `rfs_pack`: Packing a directory into a filesystem layer
|
||||||
|
- Tests packing a directory with files and subdirectories
|
||||||
|
- Verifies that the output file is created
|
||||||
|
|
||||||
|
- `rfs_list_contents`: Listing the contents of a filesystem layer
|
||||||
|
- Tests listing the contents of a packed filesystem layer
|
||||||
|
- Verifies that the list includes all expected files
|
||||||
|
|
||||||
|
- `rfs_verify`: Verifying a filesystem layer
|
||||||
|
- Tests verifying a packed filesystem layer
|
||||||
|
- Verifies that the layer is valid
|
||||||
|
|
||||||
|
- `rfs_unpack`: Unpacking a filesystem layer
|
||||||
|
- Tests unpacking a filesystem layer to a directory
|
||||||
|
- Verifies that all files are unpacked correctly with the right content
|
||||||
|
|
||||||
|
The test creates a directory structure with files, packs it into a filesystem layer, and then unpacks it to verify the integrity of the process.
|
||||||
|
|
||||||
|
## Test Runner
|
||||||
|
|
||||||
|
The test runner script (`run_all_tests.rhai`) provides a framework for executing all tests and reporting results. It:
|
||||||
|
|
||||||
|
1. Checks if RFS is available before running tests
|
||||||
|
2. Skips tests if RFS is not available
|
||||||
|
3. Contains simplified versions of each test
|
||||||
|
4. Runs each test in a try/catch block to handle errors
|
||||||
|
5. Catches and reports any errors
|
||||||
|
6. Provides a summary of passed, failed, and skipped tests
|
||||||
|
|
||||||
|
## RFS Requirements
|
||||||
|
|
||||||
|
These tests require the RFS tool to be installed and available in the system's PATH. The tests will check for RFS's availability and skip the tests if it's not found, rather than failing.
|
||||||
|
|
||||||
|
## Adding New Tests
|
||||||
|
|
||||||
|
To add a new test:
|
||||||
|
|
||||||
|
1. Create a new Rhai script in the `src/rhai_tests/rfs` directory
|
||||||
|
2. Add a new test section to the `run_all_tests.rhai` script
|
||||||
|
3. Update this documentation to include information about the new test
|
||||||
|
|
||||||
|
## Best Practices for Writing Tests
|
||||||
|
|
||||||
|
When writing tests for the RFS module:
|
||||||
|
|
||||||
|
1. Always check if RFS is available before running tests
|
||||||
|
2. Clean up any mounts before and after testing
|
||||||
|
3. Use unique names for test directories and files to avoid conflicts
|
||||||
|
4. Clean up any files or directories created during testing
|
||||||
|
5. Use assertions to verify expected behavior
|
||||||
|
6. Print clear messages about what's being tested
|
||||||
|
7. Handle errors gracefully
|
||||||
|
8. Make tests independent of each other
|
||||||
|
9. Keep tests focused on specific functionality
|
176
src/rhai_tests/nerdctl/01_container_operations.rhai
Normal file
176
src/rhai_tests/nerdctl/01_container_operations.rhai
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// 01_container_operations.rhai
|
||||||
|
// Tests for Nerdctl container operations
|
||||||
|
|
||||||
|
// 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 Operations ===");
|
||||||
|
|
||||||
|
// 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_container";
|
||||||
|
|
||||||
|
// Clean up any existing test container
|
||||||
|
cleanup_container(container_name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test creating a new Container
|
||||||
|
print("Testing nerdctl_container_new()...");
|
||||||
|
let container = nerdctl_container_new(container_name);
|
||||||
|
|
||||||
|
// Test Container properties
|
||||||
|
print("Testing Container properties...");
|
||||||
|
assert_eq(container.name, container_name, "Container name should match");
|
||||||
|
assert_eq(container.container_id, "", "Container ID should be empty initially");
|
||||||
|
|
||||||
|
// Test setting container image
|
||||||
|
print("Testing with_image()...");
|
||||||
|
container.with_image("alpine:latest");
|
||||||
|
assert_eq(container.image, "alpine:latest", "Container image should match");
|
||||||
|
|
||||||
|
// Test setting detach mode
|
||||||
|
print("Testing with_detach()...");
|
||||||
|
container.with_detach(true);
|
||||||
|
assert_true(container.detach, "Container detach mode should be true");
|
||||||
|
|
||||||
|
// Test setting environment variables
|
||||||
|
print("Testing with_env()...");
|
||||||
|
container.with_env("TEST_VAR", "test_value");
|
||||||
|
|
||||||
|
// Test setting multiple environment variables
|
||||||
|
print("Testing with_envs()...");
|
||||||
|
let env_map = #{
|
||||||
|
"VAR1": "value1",
|
||||||
|
"VAR2": "value2"
|
||||||
|
};
|
||||||
|
container.with_envs(env_map);
|
||||||
|
|
||||||
|
// Test setting ports
|
||||||
|
print("Testing with_port()...");
|
||||||
|
container.with_port("8080:80");
|
||||||
|
|
||||||
|
// Test setting multiple ports
|
||||||
|
print("Testing with_ports()...");
|
||||||
|
container.with_ports(["9090:90", "7070:70"]);
|
||||||
|
|
||||||
|
// Test setting volumes
|
||||||
|
print("Testing with_volume()...");
|
||||||
|
// Create a test directory for volume mounting
|
||||||
|
let test_dir = "rhai_test_nerdctl_volume";
|
||||||
|
mkdir(test_dir);
|
||||||
|
container.with_volume(`${test_dir}:/data`);
|
||||||
|
|
||||||
|
// Test setting resource limits
|
||||||
|
print("Testing with_cpu_limit() and with_memory_limit()...");
|
||||||
|
container.with_cpu_limit("0.5");
|
||||||
|
container.with_memory_limit("256m");
|
||||||
|
|
||||||
|
// Test running the container
|
||||||
|
print("Testing run()...");
|
||||||
|
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 executing a command in the container
|
||||||
|
print("Testing exec()...");
|
||||||
|
let exec_result = container.exec("echo 'Hello from container'");
|
||||||
|
assert_true(exec_result.success, "Container exec should succeed");
|
||||||
|
assert_true(exec_result.stdout.contains("Hello from container"), "Exec output should contain expected text");
|
||||||
|
print("✓ exec(): Command executed successfully");
|
||||||
|
|
||||||
|
// Test getting container logs
|
||||||
|
print("Testing logs()...");
|
||||||
|
let logs_result = container.logs();
|
||||||
|
assert_true(logs_result.success, "Container logs should succeed");
|
||||||
|
print("✓ logs(): Logs retrieved successfully");
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
// Clean up test directory
|
||||||
|
delete(test_dir);
|
||||||
|
print("✓ Cleanup: Test directory removed");
|
||||||
|
|
||||||
|
print("All container operations tests completed successfully!");
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error: ${err}`);
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
cleanup_container(container_name);
|
||||||
|
|
||||||
|
// Clean up test directory
|
||||||
|
try {
|
||||||
|
delete("rhai_test_nerdctl_volume");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
168
src/rhai_tests/nerdctl/02_image_operations.rhai
Normal file
168
src/rhai_tests/nerdctl/02_image_operations.rhai
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// 02_image_operations.rhai
|
||||||
|
// Tests for Nerdctl image operations
|
||||||
|
|
||||||
|
// 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 an image exists
|
||||||
|
fn image_exists(image_name) {
|
||||||
|
try {
|
||||||
|
let result = run(`nerdctl images -q ${image_name}`);
|
||||||
|
return result.success && result.stdout.trim() != "";
|
||||||
|
} catch(err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to clean up an image if it exists
|
||||||
|
fn cleanup_image(image_name) {
|
||||||
|
if image_exists(image_name) {
|
||||||
|
try {
|
||||||
|
run(`nerdctl rmi ${image_name}`);
|
||||||
|
print(`Cleaned up image: ${image_name}`);
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error cleaning up image ${image_name}: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("=== Testing Nerdctl Image Operations ===");
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
let test_dir = "rhai_test_nerdctl";
|
||||||
|
mkdir(test_dir);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test pulling an image
|
||||||
|
print("Testing nerdctl_image_pull()...");
|
||||||
|
// Use a small image for testing
|
||||||
|
let pull_result = nerdctl_image_pull("alpine:latest");
|
||||||
|
assert_true(pull_result.success, "Image pull should succeed");
|
||||||
|
print("✓ nerdctl_image_pull(): Image pulled successfully");
|
||||||
|
|
||||||
|
// Test listing images
|
||||||
|
print("Testing nerdctl_images()...");
|
||||||
|
let images_result = nerdctl_images();
|
||||||
|
assert_true(images_result.success, "Image listing should succeed");
|
||||||
|
assert_true(images_result.stdout.contains("alpine"), "Image list should contain alpine");
|
||||||
|
print("✓ nerdctl_images(): Images listed successfully");
|
||||||
|
|
||||||
|
// Test tagging an image
|
||||||
|
print("Testing nerdctl_image_tag()...");
|
||||||
|
let tag_result = nerdctl_image_tag("alpine:latest", "rhai_test_image:latest");
|
||||||
|
assert_true(tag_result.success, "Image tag should succeed");
|
||||||
|
print("✓ nerdctl_image_tag(): Image tagged successfully");
|
||||||
|
|
||||||
|
// Test building an image
|
||||||
|
print("Testing nerdctl_image_build()...");
|
||||||
|
|
||||||
|
// Create a simple Dockerfile
|
||||||
|
let dockerfile_content = `FROM alpine:latest
|
||||||
|
RUN echo "Hello from Dockerfile" > /hello.txt
|
||||||
|
CMD ["cat", "/hello.txt"]
|
||||||
|
`;
|
||||||
|
file_write(`${test_dir}/Dockerfile`, dockerfile_content);
|
||||||
|
|
||||||
|
// Build the image
|
||||||
|
let build_result = nerdctl_image_build("rhai_test_build:latest", test_dir);
|
||||||
|
assert_true(build_result.success, "Image build should succeed");
|
||||||
|
print("✓ nerdctl_image_build(): Image built successfully");
|
||||||
|
|
||||||
|
// Test running a container from the built image
|
||||||
|
print("Testing container from built image...");
|
||||||
|
let container_name = "rhai_test_container_from_build";
|
||||||
|
|
||||||
|
// Clean up any existing container with the same name
|
||||||
|
try {
|
||||||
|
run(`nerdctl stop ${container_name}`);
|
||||||
|
run(`nerdctl rm ${container_name}`);
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the container
|
||||||
|
let run_result = nerdctl_run_with_name("rhai_test_build:latest", container_name);
|
||||||
|
assert_true(run_result.success, "Container run should succeed");
|
||||||
|
assert_true(run_result.stdout.contains("Hello from Dockerfile"), "Container output should contain expected text");
|
||||||
|
print("✓ Container from built image ran successfully");
|
||||||
|
|
||||||
|
// Clean up the container
|
||||||
|
let stop_result = nerdctl_stop(container_name);
|
||||||
|
assert_true(stop_result.success, "Container stop should succeed");
|
||||||
|
let remove_result = nerdctl_remove(container_name);
|
||||||
|
assert_true(remove_result.success, "Container remove should succeed");
|
||||||
|
print("✓ Cleanup: Container removed");
|
||||||
|
|
||||||
|
// Test removing images
|
||||||
|
print("Testing nerdctl_image_remove()...");
|
||||||
|
|
||||||
|
// Remove the tagged image
|
||||||
|
let remove_tag_result = nerdctl_image_remove("rhai_test_image:latest");
|
||||||
|
assert_true(remove_tag_result.success, "Image removal should succeed");
|
||||||
|
print("✓ nerdctl_image_remove(): Tagged image removed successfully");
|
||||||
|
|
||||||
|
// Remove the built image
|
||||||
|
let remove_build_result = nerdctl_image_remove("rhai_test_build:latest");
|
||||||
|
assert_true(remove_build_result.success, "Image removal should succeed");
|
||||||
|
print("✓ nerdctl_image_remove(): Built image removed successfully");
|
||||||
|
|
||||||
|
print("All image operations tests completed successfully!");
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error: ${err}`);
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
try {
|
||||||
|
run("nerdctl stop rhai_test_container_from_build");
|
||||||
|
run("nerdctl rm rhai_test_container_from_build");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cleanup_image("rhai_test_image:latest");
|
||||||
|
cleanup_image("rhai_test_build:latest");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
// Clean up test directory
|
||||||
|
delete(test_dir);
|
||||||
|
print("✓ Cleanup: Test directory removed");
|
||||||
|
}
|
166
src/rhai_tests/nerdctl/03_container_builder.rhai
Normal file
166
src/rhai_tests/nerdctl/03_container_builder.rhai
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// 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");
|
||||||
|
}
|
183
src/rhai_tests/nerdctl/run_all_tests.rhai
Normal file
183
src/rhai_tests/nerdctl/run_all_tests.rhai
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// run_all_tests.rhai
|
||||||
|
// Runs all Nerdctl module tests
|
||||||
|
|
||||||
|
print("=== Running Nerdctl Module Tests ===");
|
||||||
|
|
||||||
|
// Custom assert function
|
||||||
|
fn assert_true(condition, message) {
|
||||||
|
if !condition {
|
||||||
|
print(`ASSERTION FAILED: ${message}`);
|
||||||
|
throw message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to check if nerdctl is available
|
||||||
|
fn is_nerdctl_available() {
|
||||||
|
try {
|
||||||
|
let result = run("which nerdctl");
|
||||||
|
return result.success;
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to clean up a container if it exists
|
||||||
|
fn cleanup_container(container_name) {
|
||||||
|
try {
|
||||||
|
run(`nerdctl stop ${container_name}`);
|
||||||
|
run(`nerdctl rm ${container_name}`);
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run each test directly
|
||||||
|
let passed = 0;
|
||||||
|
let failed = 0;
|
||||||
|
let skipped = 0;
|
||||||
|
let total = 0;
|
||||||
|
|
||||||
|
// Check if nerdctl is available
|
||||||
|
let nerdctl_available = is_nerdctl_available();
|
||||||
|
if !nerdctl_available {
|
||||||
|
print("nerdctl is not available. Skipping all Nerdctl tests.");
|
||||||
|
skipped = 3; // Skip all three tests
|
||||||
|
total = 3;
|
||||||
|
} else {
|
||||||
|
// Test 1: Container Operations
|
||||||
|
print("\n--- Running Container Operations Tests ---");
|
||||||
|
try {
|
||||||
|
// Define test container name
|
||||||
|
let container_name = "rhai_test_container";
|
||||||
|
|
||||||
|
// Clean up any existing test container
|
||||||
|
cleanup_container(container_name);
|
||||||
|
|
||||||
|
// Create a new Container
|
||||||
|
let container = nerdctl_container_new(container_name);
|
||||||
|
|
||||||
|
// Set container image
|
||||||
|
container.with_image("alpine:latest");
|
||||||
|
|
||||||
|
// Set detach mode
|
||||||
|
container.with_detach(true);
|
||||||
|
|
||||||
|
// Run the container
|
||||||
|
let run_result = container.run();
|
||||||
|
assert_true(run_result.success, "Container run should succeed");
|
||||||
|
|
||||||
|
// Execute a command in the container
|
||||||
|
let exec_result = container.exec("echo 'Hello from container'");
|
||||||
|
assert_true(exec_result.success, "Container exec should succeed");
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
container.stop();
|
||||||
|
container.remove();
|
||||||
|
|
||||||
|
print("--- Container Operations Tests completed successfully ---");
|
||||||
|
passed += 1;
|
||||||
|
} catch(err) {
|
||||||
|
print(`!!! Error in Container Operations Tests: ${err}`);
|
||||||
|
failed += 1;
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
cleanup_container("rhai_test_container");
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
|
||||||
|
// Test 2: Image Operations
|
||||||
|
print("\n--- Running Image Operations Tests ---");
|
||||||
|
try {
|
||||||
|
// Create a temporary directory for testing
|
||||||
|
let test_dir = "rhai_test_nerdctl";
|
||||||
|
mkdir(test_dir);
|
||||||
|
|
||||||
|
// Pull a small image for testing
|
||||||
|
let pull_result = nerdctl_image_pull("alpine:latest");
|
||||||
|
assert_true(pull_result.success, "Image pull should succeed");
|
||||||
|
|
||||||
|
// List images
|
||||||
|
let images_result = nerdctl_images();
|
||||||
|
assert_true(images_result.success, "Image listing should succeed");
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete(test_dir);
|
||||||
|
|
||||||
|
print("--- Image Operations Tests completed successfully ---");
|
||||||
|
passed += 1;
|
||||||
|
} catch(err) {
|
||||||
|
print(`!!! Error in Image Operations Tests: ${err}`);
|
||||||
|
failed += 1;
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
try {
|
||||||
|
delete("rhai_test_nerdctl");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
|
||||||
|
// Test 3: Container Builder Pattern
|
||||||
|
print("\n--- Running Container Builder Pattern Tests ---");
|
||||||
|
try {
|
||||||
|
// Define test container name
|
||||||
|
let container_name = "rhai_test_builder";
|
||||||
|
|
||||||
|
// Clean up any existing test container
|
||||||
|
cleanup_container(container_name);
|
||||||
|
|
||||||
|
// Create test directory
|
||||||
|
let work_dir = "rhai_test_nerdctl_work";
|
||||||
|
mkdir(work_dir);
|
||||||
|
|
||||||
|
// Create a container with builder pattern
|
||||||
|
let container = nerdctl_container_from_image(container_name, "alpine:latest")
|
||||||
|
.reset()
|
||||||
|
.with_detach(true)
|
||||||
|
.with_volumes([`${work_dir}:/data`]);
|
||||||
|
|
||||||
|
// Run the container
|
||||||
|
let run_result = container.run();
|
||||||
|
assert_true(run_result.success, "Container run should succeed");
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
container.stop();
|
||||||
|
container.remove();
|
||||||
|
delete(work_dir);
|
||||||
|
|
||||||
|
print("--- Container Builder Pattern Tests completed successfully ---");
|
||||||
|
passed += 1;
|
||||||
|
} catch(err) {
|
||||||
|
print(`!!! Error in Container Builder Pattern Tests: ${err}`);
|
||||||
|
failed += 1;
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
cleanup_container("rhai_test_builder");
|
||||||
|
try {
|
||||||
|
delete("rhai_test_nerdctl_work");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\n=== Test Summary ===");
|
||||||
|
print(`Passed: ${passed}`);
|
||||||
|
print(`Failed: ${failed}`);
|
||||||
|
print(`Skipped: ${skipped}`);
|
||||||
|
print(`Total: ${total}`);
|
||||||
|
|
||||||
|
if failed == 0 {
|
||||||
|
if skipped > 0 {
|
||||||
|
print("\n⚠️ All tests skipped or passed!");
|
||||||
|
} else {
|
||||||
|
print("\n✅ All tests passed!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("\n❌ Some tests failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the number of failed tests (0 means success)
|
||||||
|
failed;
|
152
src/rhai_tests/rfs/01_mount_operations.rhai
Normal file
152
src/rhai_tests/rfs/01_mount_operations.rhai
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// 01_mount_operations.rhai
|
||||||
|
// Tests for RFS mount operations
|
||||||
|
|
||||||
|
// 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 rfs is available
|
||||||
|
fn is_rfs_available() {
|
||||||
|
try {
|
||||||
|
let result = run("which rfs");
|
||||||
|
return result.success;
|
||||||
|
} catch(err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to clean up mounts
|
||||||
|
fn cleanup_mounts() {
|
||||||
|
try {
|
||||||
|
rfs_unmount_all();
|
||||||
|
print("All mounts cleaned up");
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error cleaning up mounts: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("=== Testing RFS Mount Operations ===");
|
||||||
|
|
||||||
|
// Check if rfs is available
|
||||||
|
let rfs_available = is_rfs_available();
|
||||||
|
if !rfs_available {
|
||||||
|
print("rfs is not available. Skipping RFS tests.");
|
||||||
|
// Exit gracefully without error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("✓ rfs is available");
|
||||||
|
|
||||||
|
// Clean up any existing mounts
|
||||||
|
cleanup_mounts();
|
||||||
|
|
||||||
|
// Create test directories
|
||||||
|
let source_dir = "rhai_test_rfs_source";
|
||||||
|
let target_dir = "rhai_test_rfs_target";
|
||||||
|
mkdir(source_dir);
|
||||||
|
mkdir(target_dir);
|
||||||
|
|
||||||
|
// Create a test file in the source directory
|
||||||
|
let test_file = `${source_dir}/test.txt`;
|
||||||
|
file_write(test_file, "Hello from RFS test");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test mounting a local directory
|
||||||
|
print("Testing rfs_mount() with local directory...");
|
||||||
|
let options = #{
|
||||||
|
"readonly": "true"
|
||||||
|
};
|
||||||
|
|
||||||
|
let mount = rfs_mount(source_dir, target_dir, "local", options);
|
||||||
|
|
||||||
|
// Verify mount properties
|
||||||
|
assert_true(mount.id != "", "Mount ID should not be empty");
|
||||||
|
assert_eq(mount.source, source_dir, "Mount source should match");
|
||||||
|
assert_eq(mount.target, target_dir, "Mount target should match");
|
||||||
|
assert_eq(mount.fs_type, "local", "Mount type should be local");
|
||||||
|
print(`✓ rfs_mount(): Mounted ${mount.source} to ${mount.target} with ID: ${mount.id}`);
|
||||||
|
|
||||||
|
// Test listing mounts
|
||||||
|
print("Testing rfs_list_mounts()...");
|
||||||
|
let mounts = rfs_list_mounts();
|
||||||
|
assert_true(mounts.len() > 0, "There should be at least one mount");
|
||||||
|
|
||||||
|
// Find our mount in the list
|
||||||
|
let found = false;
|
||||||
|
for m in mounts {
|
||||||
|
if m.target == target_dir {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_true(found, "Our mount should be in the list");
|
||||||
|
print(`✓ rfs_list_mounts(): Found ${mounts.len()} mounts`);
|
||||||
|
|
||||||
|
// Test getting mount info
|
||||||
|
print("Testing rfs_get_mount_info()...");
|
||||||
|
let mount_info = rfs_get_mount_info(target_dir);
|
||||||
|
assert_eq(mount_info.target, target_dir, "Mount info target should match");
|
||||||
|
assert_eq(mount_info.source, source_dir, "Mount info source should match");
|
||||||
|
print(`✓ rfs_get_mount_info(): Got info for mount at ${mount_info.target}`);
|
||||||
|
|
||||||
|
// Verify the mounted file is accessible
|
||||||
|
let mounted_file = `${target_dir}/test.txt`;
|
||||||
|
assert_true(exist(mounted_file), "Mounted file should exist");
|
||||||
|
let mounted_content = file_read(mounted_file);
|
||||||
|
assert_eq(mounted_content, "Hello from RFS test", "Mounted file content should match");
|
||||||
|
print("✓ Mounted file is accessible and content matches");
|
||||||
|
|
||||||
|
// Test unmounting a specific mount
|
||||||
|
print("Testing rfs_unmount()...");
|
||||||
|
rfs_unmount(target_dir);
|
||||||
|
|
||||||
|
// Verify the mount is gone
|
||||||
|
try {
|
||||||
|
rfs_get_mount_info(target_dir);
|
||||||
|
assert_true(false, "Mount should not exist after unmounting");
|
||||||
|
} catch(err) {
|
||||||
|
print("✓ rfs_unmount(): Mount successfully unmounted");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount again to test unmount_all
|
||||||
|
print("Testing mounting again for unmount_all...");
|
||||||
|
let mount2 = rfs_mount(source_dir, target_dir, "local", options);
|
||||||
|
assert_true(mount2.id != "", "Mount ID should not be empty");
|
||||||
|
|
||||||
|
// Test unmounting all mounts
|
||||||
|
print("Testing rfs_unmount_all()...");
|
||||||
|
rfs_unmount_all();
|
||||||
|
|
||||||
|
// Verify all mounts are gone
|
||||||
|
let mounts_after = rfs_list_mounts();
|
||||||
|
assert_true(mounts_after.len() == 0, "There should be no mounts after unmount_all");
|
||||||
|
print("✓ rfs_unmount_all(): All mounts successfully unmounted");
|
||||||
|
|
||||||
|
print("All mount operations tests completed successfully!");
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error: ${err}`);
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
cleanup_mounts();
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
// Clean up test directories
|
||||||
|
delete(source_dir);
|
||||||
|
delete(target_dir);
|
||||||
|
print("✓ Cleanup: Test directories removed");
|
||||||
|
}
|
117
src/rhai_tests/rfs/02_filesystem_layer_operations.rhai
Normal file
117
src/rhai_tests/rfs/02_filesystem_layer_operations.rhai
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// 02_filesystem_layer_operations.rhai
|
||||||
|
// Tests for RFS filesystem layer operations
|
||||||
|
|
||||||
|
// 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 rfs is available
|
||||||
|
fn is_rfs_available() {
|
||||||
|
try {
|
||||||
|
let result = run("which rfs");
|
||||||
|
return result.success;
|
||||||
|
} catch(err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("=== Testing RFS Filesystem Layer Operations ===");
|
||||||
|
|
||||||
|
// Check if rfs is available
|
||||||
|
let rfs_available = is_rfs_available();
|
||||||
|
if !rfs_available {
|
||||||
|
print("rfs is not available. Skipping RFS tests.");
|
||||||
|
// Exit gracefully without error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("✓ rfs is available");
|
||||||
|
|
||||||
|
// Create test directories
|
||||||
|
let source_dir = "rhai_test_rfs_source";
|
||||||
|
let unpack_dir = "rhai_test_rfs_unpack";
|
||||||
|
mkdir(source_dir);
|
||||||
|
mkdir(unpack_dir);
|
||||||
|
|
||||||
|
// Create test files in the source directory
|
||||||
|
file_write(`${source_dir}/file1.txt`, "Content of file 1");
|
||||||
|
file_write(`${source_dir}/file2.txt`, "Content of file 2");
|
||||||
|
|
||||||
|
// Create a subdirectory with files
|
||||||
|
mkdir(`${source_dir}/subdir`);
|
||||||
|
file_write(`${source_dir}/subdir/file3.txt`, "Content of file 3");
|
||||||
|
|
||||||
|
// Output file for the filesystem layer
|
||||||
|
let output_file = "rhai_test_rfs_layer.fl";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Test packing a directory
|
||||||
|
print("Testing rfs_pack()...");
|
||||||
|
// Use a file store spec for testing
|
||||||
|
let store_specs = "file:path=.";
|
||||||
|
rfs_pack(source_dir, output_file, store_specs);
|
||||||
|
|
||||||
|
// Verify the output file exists
|
||||||
|
assert_true(exist(output_file), "Output file should exist");
|
||||||
|
print(`✓ rfs_pack(): Directory packed to ${output_file}`);
|
||||||
|
|
||||||
|
// Test listing contents of the filesystem layer
|
||||||
|
print("Testing rfs_list_contents()...");
|
||||||
|
let contents = rfs_list_contents(output_file);
|
||||||
|
|
||||||
|
// Verify the contents include our files
|
||||||
|
assert_true(contents.contains("file1.txt"), "Contents should include file1.txt");
|
||||||
|
assert_true(contents.contains("file2.txt"), "Contents should include file2.txt");
|
||||||
|
assert_true(contents.contains("subdir/file3.txt"), "Contents should include subdir/file3.txt");
|
||||||
|
print("✓ rfs_list_contents(): Layer contents listed successfully");
|
||||||
|
|
||||||
|
// Test verifying the filesystem layer
|
||||||
|
print("Testing rfs_verify()...");
|
||||||
|
let is_valid = rfs_verify(output_file);
|
||||||
|
assert_true(is_valid, "Filesystem layer should be valid");
|
||||||
|
print("✓ rfs_verify(): Layer verified successfully");
|
||||||
|
|
||||||
|
// Test unpacking the filesystem layer
|
||||||
|
print("Testing rfs_unpack()...");
|
||||||
|
rfs_unpack(output_file, unpack_dir);
|
||||||
|
|
||||||
|
// Verify the unpacked files exist and have the correct content
|
||||||
|
assert_true(exist(`${unpack_dir}/file1.txt`), "Unpacked file1.txt should exist");
|
||||||
|
assert_true(exist(`${unpack_dir}/file2.txt`), "Unpacked file2.txt should exist");
|
||||||
|
assert_true(exist(`${unpack_dir}/subdir/file3.txt`), "Unpacked subdir/file3.txt should exist");
|
||||||
|
|
||||||
|
let content1 = file_read(`${unpack_dir}/file1.txt`);
|
||||||
|
let content2 = file_read(`${unpack_dir}/file2.txt`);
|
||||||
|
let content3 = file_read(`${unpack_dir}/subdir/file3.txt`);
|
||||||
|
|
||||||
|
assert_eq(content1, "Content of file 1", "Content of file1.txt should match");
|
||||||
|
assert_eq(content2, "Content of file 2", "Content of file2.txt should match");
|
||||||
|
assert_eq(content3, "Content of file 3", "Content of file3.txt should match");
|
||||||
|
|
||||||
|
print("✓ rfs_unpack(): Layer unpacked successfully");
|
||||||
|
|
||||||
|
print("All filesystem layer operations tests completed successfully!");
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error: ${err}`);
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
// Clean up test directories and files
|
||||||
|
delete(source_dir);
|
||||||
|
delete(unpack_dir);
|
||||||
|
delete(output_file);
|
||||||
|
print("✓ Cleanup: Test directories and files removed");
|
||||||
|
}
|
168
src/rhai_tests/rfs/run_all_tests.rhai
Normal file
168
src/rhai_tests/rfs/run_all_tests.rhai
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// run_all_tests.rhai
|
||||||
|
// Runs all RFS module tests
|
||||||
|
|
||||||
|
print("=== Running RFS Module Tests ===");
|
||||||
|
|
||||||
|
// Custom assert function
|
||||||
|
fn assert_true(condition, message) {
|
||||||
|
if !condition {
|
||||||
|
print(`ASSERTION FAILED: ${message}`);
|
||||||
|
throw message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to check if rfs is available
|
||||||
|
fn is_rfs_available() {
|
||||||
|
try {
|
||||||
|
let result = run("which rfs");
|
||||||
|
return result.success;
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to clean up mounts
|
||||||
|
fn cleanup_mounts() {
|
||||||
|
try {
|
||||||
|
rfs_unmount_all();
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run each test directly
|
||||||
|
let passed = 0;
|
||||||
|
let failed = 0;
|
||||||
|
let skipped = 0;
|
||||||
|
let total = 0;
|
||||||
|
|
||||||
|
// Check if rfs is available
|
||||||
|
let rfs_available = is_rfs_available();
|
||||||
|
if !rfs_available {
|
||||||
|
print("rfs is not available. Skipping all RFS tests.");
|
||||||
|
skipped = 2; // Skip both tests
|
||||||
|
total = 2;
|
||||||
|
} else {
|
||||||
|
// Test 1: Mount Operations
|
||||||
|
print("\n--- Running Mount Operations Tests ---");
|
||||||
|
try {
|
||||||
|
// Clean up any existing mounts
|
||||||
|
cleanup_mounts();
|
||||||
|
|
||||||
|
// Create test directories
|
||||||
|
let source_dir = "rhai_test_rfs_source";
|
||||||
|
let target_dir = "rhai_test_rfs_target";
|
||||||
|
mkdir(source_dir);
|
||||||
|
mkdir(target_dir);
|
||||||
|
|
||||||
|
// Create a test file in the source directory
|
||||||
|
let test_file = `${source_dir}/test.txt`;
|
||||||
|
file_write(test_file, "Hello from RFS test");
|
||||||
|
|
||||||
|
// Mount the directory
|
||||||
|
let options = #{
|
||||||
|
"readonly": "true"
|
||||||
|
};
|
||||||
|
|
||||||
|
let mount = rfs_mount(source_dir, target_dir, "local", options);
|
||||||
|
assert_true(mount.id != "", "Mount ID should not be empty");
|
||||||
|
|
||||||
|
// List mounts
|
||||||
|
let mounts = rfs_list_mounts();
|
||||||
|
assert_true(mounts.len() > 0, "There should be at least one mount");
|
||||||
|
|
||||||
|
// Unmount
|
||||||
|
rfs_unmount(target_dir);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete(source_dir);
|
||||||
|
delete(target_dir);
|
||||||
|
|
||||||
|
print("--- Mount Operations Tests completed successfully ---");
|
||||||
|
passed += 1;
|
||||||
|
} catch(err) {
|
||||||
|
print(`!!! Error in Mount Operations Tests: ${err}`);
|
||||||
|
failed += 1;
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
cleanup_mounts();
|
||||||
|
try {
|
||||||
|
delete("rhai_test_rfs_source");
|
||||||
|
delete("rhai_test_rfs_target");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
|
||||||
|
// Test 2: Filesystem Layer Operations
|
||||||
|
print("\n--- Running Filesystem Layer Operations Tests ---");
|
||||||
|
try {
|
||||||
|
// Create test directories
|
||||||
|
let source_dir = "rhai_test_rfs_source";
|
||||||
|
let unpack_dir = "rhai_test_rfs_unpack";
|
||||||
|
mkdir(source_dir);
|
||||||
|
mkdir(unpack_dir);
|
||||||
|
|
||||||
|
// Create test files in the source directory
|
||||||
|
file_write(`${source_dir}/file1.txt`, "Content of file 1");
|
||||||
|
|
||||||
|
// Output file for the filesystem layer
|
||||||
|
let output_file = "rhai_test_rfs_layer.fl";
|
||||||
|
|
||||||
|
// Pack the directory
|
||||||
|
let store_specs = "file:path=.";
|
||||||
|
rfs_pack(source_dir, output_file, store_specs);
|
||||||
|
|
||||||
|
// List contents
|
||||||
|
let contents = rfs_list_contents(output_file);
|
||||||
|
assert_true(contents.contains("file1.txt"), "Contents should include file1.txt");
|
||||||
|
|
||||||
|
// Verify the layer
|
||||||
|
let is_valid = rfs_verify(output_file);
|
||||||
|
assert_true(is_valid, "Filesystem layer should be valid");
|
||||||
|
|
||||||
|
// Unpack the layer
|
||||||
|
rfs_unpack(output_file, unpack_dir);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete(source_dir);
|
||||||
|
delete(unpack_dir);
|
||||||
|
delete(output_file);
|
||||||
|
|
||||||
|
print("--- Filesystem Layer Operations Tests completed successfully ---");
|
||||||
|
passed += 1;
|
||||||
|
} catch(err) {
|
||||||
|
print(`!!! Error in Filesystem Layer Operations Tests: ${err}`);
|
||||||
|
failed += 1;
|
||||||
|
|
||||||
|
// Clean up in case of error
|
||||||
|
try {
|
||||||
|
delete("rhai_test_rfs_source");
|
||||||
|
delete("rhai_test_rfs_unpack");
|
||||||
|
delete("rhai_test_rfs_layer.fl");
|
||||||
|
} catch(e) {
|
||||||
|
// Ignore errors during cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\n=== Test Summary ===");
|
||||||
|
print(`Passed: ${passed}`);
|
||||||
|
print(`Failed: ${failed}`);
|
||||||
|
print(`Skipped: ${skipped}`);
|
||||||
|
print(`Total: ${total}`);
|
||||||
|
|
||||||
|
if failed == 0 {
|
||||||
|
if skipped > 0 {
|
||||||
|
print("\n⚠️ All tests skipped or passed!");
|
||||||
|
} else {
|
||||||
|
print("\n✅ All tests passed!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("\n❌ Some tests failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the number of failed tests (0 means success)
|
||||||
|
failed;
|
Loading…
Reference in New Issue
Block a user