sal/zinit_client/tests/rhai_integration_tests.rs
Mahmoud-Emad e125bb6511
Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
Rhai Tests / Run Rhai Tests (pull_request) Waiting to run
feat: Migrate SAL to Cargo workspace
- Migrate individual modules to independent crates
- Refactor dependencies for improved modularity
- Update build system and testing infrastructure
- Update documentation to reflect new structure
2025-06-24 12:39:18 +03:00

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
}
#[test]
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");
}
}
#[test]
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");
}
}
#[test]
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");
}
}
#[test]
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");
}
}
#[test]
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);
}
}
}
#[test]
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");
}
}