Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
- Add `zinit_client` package to the workspace, enabling its use in the SAL monorepo. This allows for better organization and dependency management. - Update `MONOREPO_CONVERSION_PLAN.md` to reflect the addition of `zinit_client` and its status. This ensures the conversion plan stays up-to-date. - Move `src/zinit_client/` directory to `zinit_client/` for better organization. This improves the overall structure of the project. - Update references to `zinit_client` to use the new path. This ensures the codebase correctly links to the `zinit_client` package.
460 lines
16 KiB
Rust
460 lines
16 KiB
Rust
use rhai::{Engine, EvalAltResult};
|
|
use sal_zinit_client::rhai::register_zinit_module;
|
|
use std::path::Path;
|
|
|
|
/// Helper function to create a Rhai engine with zinit functions registered
|
|
fn create_zinit_engine() -> Result<Engine, Box<EvalAltResult>> {
|
|
let mut engine = Engine::new();
|
|
register_zinit_module(&mut engine)?;
|
|
Ok(engine)
|
|
}
|
|
|
|
/// Helper function to check if a zinit socket is available
|
|
fn get_available_socket_path() -> Option<String> {
|
|
let common_paths = vec![
|
|
"/var/run/zinit.sock",
|
|
"/tmp/zinit.sock",
|
|
"/run/zinit.sock",
|
|
"./zinit.sock",
|
|
];
|
|
|
|
for path in common_paths {
|
|
if Path::new(path).exists() {
|
|
println!("✓ Found Zinit socket at: {}", path);
|
|
return Some(path.to_string());
|
|
}
|
|
}
|
|
|
|
println!("⚠ No Zinit socket found. Rhai integration tests will be skipped.");
|
|
None
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_zinit_list() {
|
|
if let Some(socket_path) = get_available_socket_path() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = format!(
|
|
r#"
|
|
let socket_path = "{}";
|
|
let services = zinit_list(socket_path);
|
|
services
|
|
"#,
|
|
socket_path
|
|
);
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(&script);
|
|
|
|
match result {
|
|
Ok(services) => {
|
|
println!("✓ Rhai zinit_list returned {} services", services.len());
|
|
|
|
// Verify it's a proper map with valid service data
|
|
// Verify all service names are non-empty strings
|
|
for (name, _state) in services.iter() {
|
|
assert!(!name.is_empty(), "Service name should not be empty");
|
|
}
|
|
|
|
// Print some services for debugging
|
|
for (name, state) in services.iter().take(3) {
|
|
println!(" Service: {} -> {:?}", name, state);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai zinit_list failed: {}", e);
|
|
// Don't fail the test - might be expected
|
|
}
|
|
}
|
|
} else {
|
|
println!("⚠ Skipping test_rhai_zinit_list: No Zinit socket available");
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_service_management() {
|
|
if let Some(socket_path) = get_available_socket_path() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = format!(
|
|
r#"
|
|
let socket_path = "{}";
|
|
let service_name = "rhai-test-service";
|
|
let exec_command = "echo 'Hello from Rhai test'";
|
|
let oneshot = true;
|
|
|
|
// Clean up any existing service first
|
|
try {{
|
|
zinit_stop(socket_path, service_name);
|
|
zinit_forget(socket_path, service_name);
|
|
zinit_delete_service(socket_path, service_name);
|
|
}} catch(e) {{
|
|
// Ignore cleanup errors
|
|
}}
|
|
|
|
let results = #{{}};
|
|
|
|
// Test service creation
|
|
try {{
|
|
let create_result = zinit_create_service(socket_path, service_name, exec_command, oneshot);
|
|
results.create = create_result;
|
|
|
|
// Test service monitoring
|
|
try {{
|
|
let monitor_result = zinit_monitor(socket_path, service_name);
|
|
results.monitor = monitor_result;
|
|
|
|
// Test service start
|
|
try {{
|
|
let start_result = zinit_start(socket_path, service_name);
|
|
results.start = start_result;
|
|
|
|
// Test service status
|
|
try {{
|
|
let status_result = zinit_status(socket_path, service_name);
|
|
results.status = status_result;
|
|
}} catch(e) {{
|
|
results.status_error = e.to_string();
|
|
}}
|
|
|
|
// Test service stop
|
|
try {{
|
|
let stop_result = zinit_stop(socket_path, service_name);
|
|
results.stop = stop_result;
|
|
}} catch(e) {{
|
|
results.stop_error = e.to_string();
|
|
}}
|
|
|
|
}} catch(e) {{
|
|
results.start_error = e.to_string();
|
|
}}
|
|
|
|
// Test forget
|
|
try {{
|
|
let forget_result = zinit_forget(socket_path, service_name);
|
|
results.forget = forget_result;
|
|
}} catch(e) {{
|
|
results.forget_error = e.to_string();
|
|
}}
|
|
|
|
}} catch(e) {{
|
|
results.monitor_error = e.to_string();
|
|
}}
|
|
|
|
// Test service deletion
|
|
try {{
|
|
let delete_result = zinit_delete_service(socket_path, service_name);
|
|
results.delete = delete_result;
|
|
}} catch(e) {{
|
|
results.delete_error = e.to_string();
|
|
}}
|
|
|
|
}} catch(e) {{
|
|
results.create_error = e.to_string();
|
|
}}
|
|
|
|
results
|
|
"#,
|
|
socket_path
|
|
);
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(&script);
|
|
|
|
match result {
|
|
Ok(results) => {
|
|
println!("✓ Rhai service management test completed");
|
|
|
|
for (operation, result) in results.iter() {
|
|
println!(" {}: {:?}", operation, result);
|
|
}
|
|
|
|
// Verify we got meaningful results from service management operations
|
|
assert!(
|
|
!results.is_empty(),
|
|
"Should have results from service operations"
|
|
);
|
|
|
|
// Check that we attempted service creation (success or error)
|
|
assert!(
|
|
results.contains_key("create") || results.contains_key("create_error"),
|
|
"Should have attempted service creation"
|
|
);
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai service management test failed: {}", e);
|
|
}
|
|
}
|
|
} else {
|
|
println!("⚠ Skipping test_rhai_service_management: No Zinit socket available");
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_logs_functionality() {
|
|
if let Some(socket_path) = get_available_socket_path() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = format!(
|
|
r#"
|
|
let socket_path = "{}";
|
|
let results = #{{}};
|
|
|
|
// Test getting all logs
|
|
try {{
|
|
let all_logs = zinit_logs_all(socket_path);
|
|
results.all_logs_count = all_logs.len();
|
|
if all_logs.len() > 0 {{
|
|
results.first_log = all_logs[0];
|
|
}}
|
|
}} catch(e) {{
|
|
results.all_logs_error = e.to_string();
|
|
}}
|
|
|
|
// Test getting filtered logs
|
|
try {{
|
|
let filtered_logs = zinit_logs(socket_path, "zinit");
|
|
results.filtered_logs_count = filtered_logs.len();
|
|
}} catch(e) {{
|
|
results.filtered_logs_error = e.to_string();
|
|
}}
|
|
|
|
results
|
|
"#,
|
|
socket_path
|
|
);
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(&script);
|
|
|
|
match result {
|
|
Ok(results) => {
|
|
println!("✓ Rhai logs functionality test completed");
|
|
|
|
for (key, value) in results.iter() {
|
|
println!(" {}: {:?}", key, value);
|
|
}
|
|
|
|
// Verify we got meaningful results from logs operations
|
|
assert!(
|
|
!results.is_empty(),
|
|
"Should have results from logs operations"
|
|
);
|
|
|
|
// Check that we attempted to get logs (success or error)
|
|
assert!(
|
|
results.contains_key("all_logs_count")
|
|
|| results.contains_key("all_logs_error"),
|
|
"Should have attempted to retrieve all logs"
|
|
);
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai logs functionality test failed: {}", e);
|
|
}
|
|
}
|
|
} else {
|
|
println!("⚠ Skipping test_rhai_logs_functionality: No Zinit socket available");
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_kill_functionality() {
|
|
if let Some(socket_path) = get_available_socket_path() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = format!(
|
|
r#"
|
|
let socket_path = "{}";
|
|
let service_name = "rhai-kill-test-service";
|
|
let exec_command = "sleep 30";
|
|
let oneshot = false;
|
|
|
|
let results = #{{}};
|
|
|
|
// Clean up any existing service first
|
|
try {{
|
|
zinit_stop(socket_path, service_name);
|
|
zinit_forget(socket_path, service_name);
|
|
zinit_delete_service(socket_path, service_name);
|
|
}} catch(e) {{
|
|
// Ignore cleanup errors
|
|
}}
|
|
|
|
// Create and start a long-running service for kill testing
|
|
try {{
|
|
let create_result = zinit_create_service(socket_path, service_name, exec_command, oneshot);
|
|
results.create = create_result;
|
|
|
|
try {{
|
|
let monitor_result = zinit_monitor(socket_path, service_name);
|
|
let start_result = zinit_start(socket_path, service_name);
|
|
results.start = start_result;
|
|
|
|
// Test kill with TERM signal
|
|
try {{
|
|
let kill_result = zinit_kill(socket_path, service_name, "TERM");
|
|
results.kill = kill_result;
|
|
}} catch(e) {{
|
|
results.kill_error = e.to_string();
|
|
}}
|
|
|
|
}} catch(e) {{
|
|
results.start_error = e.to_string();
|
|
}}
|
|
|
|
// Clean up
|
|
try {{
|
|
zinit_stop(socket_path, service_name);
|
|
zinit_forget(socket_path, service_name);
|
|
zinit_delete_service(socket_path, service_name);
|
|
}} catch(e) {{
|
|
// Ignore cleanup errors
|
|
}}
|
|
|
|
}} catch(e) {{
|
|
results.create_error = e.to_string();
|
|
}}
|
|
|
|
results
|
|
"#,
|
|
socket_path
|
|
);
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(&script);
|
|
|
|
match result {
|
|
Ok(results) => {
|
|
println!("✓ Rhai kill functionality test completed");
|
|
|
|
for (operation, result) in results.iter() {
|
|
println!(" {}: {:?}", operation, result);
|
|
}
|
|
|
|
// Verify we got meaningful results from kill functionality operations
|
|
assert!(
|
|
!results.is_empty(),
|
|
"Should have results from kill operations"
|
|
);
|
|
|
|
// Check that we attempted service creation for kill testing (success or error)
|
|
assert!(
|
|
results.contains_key("create") || results.contains_key("create_error"),
|
|
"Should have attempted service creation for kill testing"
|
|
);
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai kill functionality test failed: {}", e);
|
|
}
|
|
}
|
|
} else {
|
|
println!("⚠ Skipping test_rhai_kill_functionality: No Zinit socket available");
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_error_handling() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = r#"
|
|
let invalid_socket = "/invalid/path/to/zinit.sock";
|
|
let results = #{};
|
|
|
|
// Test with invalid socket path
|
|
try {
|
|
let services = zinit_list(invalid_socket);
|
|
results.unexpected_success = true;
|
|
} catch(e) {
|
|
results.expected_error = e.to_string();
|
|
}
|
|
|
|
results
|
|
"#;
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(script);
|
|
|
|
match result {
|
|
Ok(results) => {
|
|
println!("✓ Rhai error handling test completed");
|
|
|
|
for (key, value) in results.iter() {
|
|
println!(" {}: {:?}", key, value);
|
|
}
|
|
|
|
// Should have caught an error
|
|
assert!(results.contains_key("expected_error"));
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai error handling test failed: {}", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_rhai_get_service_config() {
|
|
if let Some(socket_path) = get_available_socket_path() {
|
|
let engine = create_zinit_engine().expect("Failed to create Rhai engine");
|
|
|
|
let script = format!(
|
|
r#"
|
|
let socket_path = "{}";
|
|
let results = #{{}};
|
|
|
|
// First get list of services
|
|
try {{
|
|
let services = zinit_list(socket_path);
|
|
results.services_count = services.len();
|
|
|
|
if services.len() > 0 {{
|
|
// Get the first service name
|
|
let service_names = services.keys();
|
|
if service_names.len() > 0 {{
|
|
let first_service = service_names[0];
|
|
results.test_service = first_service;
|
|
|
|
// Try to get its configuration
|
|
try {{
|
|
let config = zinit_get_service(socket_path, first_service);
|
|
results.config_retrieved = true;
|
|
results.config_type = type_of(config);
|
|
}} catch(e) {{
|
|
results.config_error = e.to_string();
|
|
}}
|
|
}}
|
|
}}
|
|
}} catch(e) {{
|
|
results.list_error = e.to_string();
|
|
}}
|
|
|
|
results
|
|
"#,
|
|
socket_path
|
|
);
|
|
|
|
let result: Result<rhai::Map, Box<EvalAltResult>> = engine.eval(&script);
|
|
|
|
match result {
|
|
Ok(results) => {
|
|
println!("✓ Rhai get service config test completed");
|
|
|
|
for (key, value) in results.iter() {
|
|
println!(" {}: {:?}", key, value);
|
|
}
|
|
|
|
// Verify we got meaningful results from get service config operations
|
|
assert!(
|
|
!results.is_empty(),
|
|
"Should have results from config operations"
|
|
);
|
|
|
|
// Check that we attempted to list services (success or error)
|
|
assert!(
|
|
results.contains_key("services_count") || results.contains_key("list_error"),
|
|
"Should have attempted to list services for config testing"
|
|
);
|
|
}
|
|
Err(e) => {
|
|
println!("⚠ Rhai get service config test failed: {}", e);
|
|
}
|
|
}
|
|
} else {
|
|
println!("⚠ Skipping test_rhai_get_service_config: No Zinit socket available");
|
|
}
|
|
}
|