...
This commit is contained in:
243
_archive/service_manager/tests/factory_tests.rs
Normal file
243
_archive/service_manager/tests/factory_tests.rs
Normal file
@@ -0,0 +1,243 @@
|
||||
use sal_service_manager::{create_service_manager, ServiceConfig, ServiceManager};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_create_service_manager() {
|
||||
// Test that the factory function creates the appropriate service manager for the platform
|
||||
let manager = create_service_manager().expect("Failed to create service manager");
|
||||
|
||||
// Test basic functionality - should be able to call methods without panicking
|
||||
let list_result = manager.list();
|
||||
|
||||
// The result might be an error (if no service system is available), but it shouldn't panic
|
||||
match list_result {
|
||||
Ok(services) => {
|
||||
println!(
|
||||
"✓ Service manager created successfully, found {} services",
|
||||
services.len()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✓ Service manager created, but got expected error: {}", e);
|
||||
// This is expected on systems without the appropriate service manager
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_config_creation() {
|
||||
// Test creating various service configurations
|
||||
let basic_config = ServiceConfig {
|
||||
name: "test-service".to_string(),
|
||||
binary_path: "/usr/bin/echo".to_string(),
|
||||
args: vec!["hello".to_string(), "world".to_string()],
|
||||
working_directory: None,
|
||||
environment: HashMap::new(),
|
||||
auto_restart: false,
|
||||
};
|
||||
|
||||
assert_eq!(basic_config.name, "test-service");
|
||||
assert_eq!(basic_config.binary_path, "/usr/bin/echo");
|
||||
assert_eq!(basic_config.args.len(), 2);
|
||||
assert_eq!(basic_config.args[0], "hello");
|
||||
assert_eq!(basic_config.args[1], "world");
|
||||
assert!(basic_config.working_directory.is_none());
|
||||
assert!(basic_config.environment.is_empty());
|
||||
assert!(!basic_config.auto_restart);
|
||||
|
||||
println!("✓ Basic service config created successfully");
|
||||
|
||||
// Test config with environment variables
|
||||
let mut env = HashMap::new();
|
||||
env.insert("PATH".to_string(), "/usr/bin:/bin".to_string());
|
||||
env.insert("HOME".to_string(), "/tmp".to_string());
|
||||
|
||||
let env_config = ServiceConfig {
|
||||
name: "env-service".to_string(),
|
||||
binary_path: "/usr/bin/env".to_string(),
|
||||
args: vec![],
|
||||
working_directory: Some("/tmp".to_string()),
|
||||
environment: env.clone(),
|
||||
auto_restart: true,
|
||||
};
|
||||
|
||||
assert_eq!(env_config.name, "env-service");
|
||||
assert_eq!(env_config.binary_path, "/usr/bin/env");
|
||||
assert!(env_config.args.is_empty());
|
||||
assert_eq!(env_config.working_directory, Some("/tmp".to_string()));
|
||||
assert_eq!(env_config.environment.len(), 2);
|
||||
assert_eq!(
|
||||
env_config.environment.get("PATH"),
|
||||
Some(&"/usr/bin:/bin".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
env_config.environment.get("HOME"),
|
||||
Some(&"/tmp".to_string())
|
||||
);
|
||||
assert!(env_config.auto_restart);
|
||||
|
||||
println!("✓ Environment service config created successfully");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_config_clone() {
|
||||
// Test that ServiceConfig can be cloned
|
||||
let original_config = ServiceConfig {
|
||||
name: "original".to_string(),
|
||||
binary_path: "/bin/sh".to_string(),
|
||||
args: vec!["-c".to_string(), "echo test".to_string()],
|
||||
working_directory: Some("/home".to_string()),
|
||||
environment: {
|
||||
let mut env = HashMap::new();
|
||||
env.insert("TEST".to_string(), "value".to_string());
|
||||
env
|
||||
},
|
||||
auto_restart: true,
|
||||
};
|
||||
|
||||
let cloned_config = original_config.clone();
|
||||
|
||||
assert_eq!(original_config.name, cloned_config.name);
|
||||
assert_eq!(original_config.binary_path, cloned_config.binary_path);
|
||||
assert_eq!(original_config.args, cloned_config.args);
|
||||
assert_eq!(
|
||||
original_config.working_directory,
|
||||
cloned_config.working_directory
|
||||
);
|
||||
assert_eq!(original_config.environment, cloned_config.environment);
|
||||
assert_eq!(original_config.auto_restart, cloned_config.auto_restart);
|
||||
|
||||
println!("✓ Service config cloning works correctly");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[test]
|
||||
fn test_macos_service_manager() {
|
||||
use sal_service_manager::LaunchctlServiceManager;
|
||||
|
||||
// Test creating macOS-specific service manager
|
||||
let manager = LaunchctlServiceManager::new();
|
||||
|
||||
// Test basic functionality
|
||||
let list_result = manager.list();
|
||||
match list_result {
|
||||
Ok(services) => {
|
||||
println!(
|
||||
"✓ macOS LaunchctlServiceManager created successfully, found {} services",
|
||||
services.len()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!(
|
||||
"✓ macOS LaunchctlServiceManager created, but got expected error: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_linux_service_manager() {
|
||||
use sal_service_manager::SystemdServiceManager;
|
||||
|
||||
// Test creating Linux-specific service manager
|
||||
let manager = SystemdServiceManager::new();
|
||||
|
||||
// Test basic functionality
|
||||
let list_result = manager.list();
|
||||
match list_result {
|
||||
Ok(services) => {
|
||||
println!(
|
||||
"✓ Linux SystemdServiceManager created successfully, found {} services",
|
||||
services.len()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!(
|
||||
"✓ Linux SystemdServiceManager created, but got expected error: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_status_debug() {
|
||||
use sal_service_manager::ServiceStatus;
|
||||
|
||||
// Test that ServiceStatus can be debugged and cloned
|
||||
let statuses = vec![
|
||||
ServiceStatus::Running,
|
||||
ServiceStatus::Stopped,
|
||||
ServiceStatus::Failed,
|
||||
ServiceStatus::Unknown,
|
||||
];
|
||||
|
||||
for status in &statuses {
|
||||
let cloned = status.clone();
|
||||
let debug_str = format!("{:?}", status);
|
||||
|
||||
assert!(!debug_str.is_empty());
|
||||
assert_eq!(status, &cloned);
|
||||
|
||||
println!(
|
||||
"✓ ServiceStatus::{:?} debug and clone work correctly",
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_manager_error_debug() {
|
||||
use sal_service_manager::ServiceManagerError;
|
||||
|
||||
// Test that ServiceManagerError can be debugged and displayed
|
||||
let errors = vec![
|
||||
ServiceManagerError::ServiceNotFound("test".to_string()),
|
||||
ServiceManagerError::ServiceAlreadyExists("test".to_string()),
|
||||
ServiceManagerError::StartFailed("test".to_string(), "reason".to_string()),
|
||||
ServiceManagerError::StopFailed("test".to_string(), "reason".to_string()),
|
||||
ServiceManagerError::RestartFailed("test".to_string(), "reason".to_string()),
|
||||
ServiceManagerError::LogsFailed("test".to_string(), "reason".to_string()),
|
||||
ServiceManagerError::Other("generic error".to_string()),
|
||||
];
|
||||
|
||||
for error in &errors {
|
||||
let debug_str = format!("{:?}", error);
|
||||
let display_str = format!("{}", error);
|
||||
|
||||
assert!(!debug_str.is_empty());
|
||||
assert!(!display_str.is_empty());
|
||||
|
||||
println!("✓ Error debug: {:?}", error);
|
||||
println!("✓ Error display: {}", error);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_manager_trait_object() {
|
||||
// Test that we can use ServiceManager as a trait object
|
||||
let manager: Box<dyn ServiceManager> =
|
||||
create_service_manager().expect("Failed to create service manager");
|
||||
|
||||
// Test that we can call methods through the trait object
|
||||
let list_result = manager.list();
|
||||
|
||||
match list_result {
|
||||
Ok(services) => {
|
||||
println!("✓ Trait object works, found {} services", services.len());
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✓ Trait object works, got expected error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Test exists method
|
||||
let exists_result = manager.exists("non-existent-service");
|
||||
match exists_result {
|
||||
Ok(false) => println!("✓ Trait object exists method works correctly"),
|
||||
Ok(true) => println!("⚠ Unexpectedly found non-existent service"),
|
||||
Err(_) => println!("✓ Trait object exists method works (with error)"),
|
||||
}
|
||||
}
|
177
_archive/service_manager/tests/rhai/service_lifecycle.rhai
Normal file
177
_archive/service_manager/tests/rhai/service_lifecycle.rhai
Normal file
@@ -0,0 +1,177 @@
|
||||
// Service lifecycle management test script
|
||||
// This script tests REAL complete service lifecycle scenarios
|
||||
|
||||
print("=== Service Lifecycle Management Test ===");
|
||||
|
||||
// Create service manager
|
||||
let manager = create_service_manager();
|
||||
print("✓ Service manager created");
|
||||
|
||||
// Test configuration - real services for testing
|
||||
let test_services = [
|
||||
#{
|
||||
name: "lifecycle-test-1",
|
||||
binary_path: "/bin/echo",
|
||||
args: ["Lifecycle test 1"],
|
||||
working_directory: "/tmp",
|
||||
environment: #{},
|
||||
auto_restart: false
|
||||
},
|
||||
#{
|
||||
name: "lifecycle-test-2",
|
||||
binary_path: "/bin/echo",
|
||||
args: ["Lifecycle test 2"],
|
||||
working_directory: "/tmp",
|
||||
environment: #{ "TEST_VAR": "test_value" },
|
||||
auto_restart: false
|
||||
}
|
||||
];
|
||||
|
||||
let total_tests = 0;
|
||||
let passed_tests = 0;
|
||||
|
||||
// Test 1: Service Creation and Start
|
||||
print("\n1. Testing service creation and start...");
|
||||
for service_config in test_services {
|
||||
print(`\nStarting service: ${service_config.name}`);
|
||||
try {
|
||||
start(manager, service_config);
|
||||
print(` ✓ Service ${service_config.name} started successfully`);
|
||||
passed_tests += 1;
|
||||
} catch(e) {
|
||||
print(` ✗ Service ${service_config.name} start failed: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 2: Service Existence Check
|
||||
print("\n2. Testing service existence checks...");
|
||||
for service_config in test_services {
|
||||
print(`\nChecking existence of: ${service_config.name}`);
|
||||
try {
|
||||
let service_exists = exists(manager, service_config.name);
|
||||
if service_exists {
|
||||
print(` ✓ Service ${service_config.name} exists: ${service_exists}`);
|
||||
passed_tests += 1;
|
||||
} else {
|
||||
print(` ✗ Service ${service_config.name} doesn't exist after start`);
|
||||
}
|
||||
} catch(e) {
|
||||
print(` ✗ Existence check failed for ${service_config.name}: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 3: Status Check
|
||||
print("\n3. Testing status checks...");
|
||||
for service_config in test_services {
|
||||
print(`\nChecking status of: ${service_config.name}`);
|
||||
try {
|
||||
let service_status = status(manager, service_config.name);
|
||||
print(` ✓ Service ${service_config.name} status: ${service_status}`);
|
||||
passed_tests += 1;
|
||||
} catch(e) {
|
||||
print(` ✗ Status check failed for ${service_config.name}: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 4: Service List Check
|
||||
print("\n4. Testing service list...");
|
||||
try {
|
||||
let services = list(manager);
|
||||
print(` ✓ Service list retrieved (${services.len()} services)`);
|
||||
|
||||
// Check if our test services are in the list
|
||||
for service_config in test_services {
|
||||
let found = false;
|
||||
for service in services {
|
||||
if service.contains(service_config.name) {
|
||||
found = true;
|
||||
print(` ✓ Found ${service_config.name} in list`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
print(` ⚠ ${service_config.name} not found in service list`);
|
||||
}
|
||||
}
|
||||
passed_tests += 1;
|
||||
} catch(e) {
|
||||
print(` ✗ Service list failed: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
|
||||
// Test 5: Service Stop
|
||||
print("\n5. Testing service stop...");
|
||||
for service_config in test_services {
|
||||
print(`\nStopping service: ${service_config.name}`);
|
||||
try {
|
||||
stop(manager, service_config.name);
|
||||
print(` ✓ Service ${service_config.name} stopped successfully`);
|
||||
passed_tests += 1;
|
||||
} catch(e) {
|
||||
print(` ✗ Service ${service_config.name} stop failed: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 6: Service Removal
|
||||
print("\n6. Testing service removal...");
|
||||
for service_config in test_services {
|
||||
print(`\nRemoving service: ${service_config.name}`);
|
||||
try {
|
||||
remove(manager, service_config.name);
|
||||
print(` ✓ Service ${service_config.name} removed successfully`);
|
||||
passed_tests += 1;
|
||||
} catch(e) {
|
||||
print(` ✗ Service ${service_config.name} removal failed: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 7: Cleanup Verification
|
||||
print("\n7. Testing cleanup verification...");
|
||||
for service_config in test_services {
|
||||
print(`\nVerifying removal of: ${service_config.name}`);
|
||||
try {
|
||||
let exists_after_remove = exists(manager, service_config.name);
|
||||
if !exists_after_remove {
|
||||
print(` ✓ Service ${service_config.name} correctly doesn't exist after removal`);
|
||||
passed_tests += 1;
|
||||
} else {
|
||||
print(` ✗ Service ${service_config.name} still exists after removal`);
|
||||
}
|
||||
} catch(e) {
|
||||
print(` ✗ Cleanup verification failed for ${service_config.name}: ${e}`);
|
||||
}
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test Summary
|
||||
print("\n=== Lifecycle Test Summary ===");
|
||||
print(`Services tested: ${test_services.len()}`);
|
||||
print(`Total operations: ${total_tests}`);
|
||||
print(`Successful operations: ${passed_tests}`);
|
||||
print(`Failed operations: ${total_tests - passed_tests}`);
|
||||
print(`Success rate: ${(passed_tests * 100) / total_tests}%`);
|
||||
|
||||
if passed_tests == total_tests {
|
||||
print("\n🎉 All lifecycle tests passed!");
|
||||
print("Service manager is working correctly across all scenarios.");
|
||||
} else {
|
||||
print(`\n⚠ ${total_tests - passed_tests} test(s) failed`);
|
||||
print("Some service manager operations need attention.");
|
||||
}
|
||||
|
||||
print("\n=== Service Lifecycle Test Complete ===");
|
||||
|
||||
// Return test results
|
||||
#{
|
||||
summary: #{
|
||||
total_tests: total_tests,
|
||||
passed_tests: passed_tests,
|
||||
success_rate: (passed_tests * 100) / total_tests,
|
||||
services_tested: test_services.len()
|
||||
}
|
||||
}
|
218
_archive/service_manager/tests/rhai/service_manager_basic.rhai
Normal file
218
_archive/service_manager/tests/rhai/service_manager_basic.rhai
Normal file
@@ -0,0 +1,218 @@
|
||||
// Basic service manager functionality test script
|
||||
// This script tests the REAL service manager through Rhai integration
|
||||
|
||||
print("=== Service Manager Basic Functionality Test ===");
|
||||
|
||||
// Test configuration
|
||||
let test_service_name = "rhai-test-service";
|
||||
let test_binary = "/bin/echo";
|
||||
let test_args = ["Hello from Rhai service manager test"];
|
||||
|
||||
print(`Testing service: ${test_service_name}`);
|
||||
print(`Binary: ${test_binary}`);
|
||||
print(`Args: ${test_args}`);
|
||||
|
||||
// Test results tracking
|
||||
let test_results = #{
|
||||
creation: "NOT_RUN",
|
||||
exists_before: "NOT_RUN",
|
||||
start: "NOT_RUN",
|
||||
exists_after: "NOT_RUN",
|
||||
status: "NOT_RUN",
|
||||
list: "NOT_RUN",
|
||||
stop: "NOT_RUN",
|
||||
remove: "NOT_RUN",
|
||||
cleanup: "NOT_RUN"
|
||||
};
|
||||
|
||||
let passed_tests = 0;
|
||||
let total_tests = 0;
|
||||
|
||||
// Test 1: Service Manager Creation
|
||||
print("\n1. Testing service manager creation...");
|
||||
try {
|
||||
let manager = create_service_manager();
|
||||
print("✓ Service manager created successfully");
|
||||
test_results["creation"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service manager creation failed: ${e}`);
|
||||
test_results["creation"] = "FAIL";
|
||||
total_tests += 1;
|
||||
// Return early if we can't create the manager
|
||||
return test_results;
|
||||
}
|
||||
|
||||
// Create the service manager for all subsequent tests
|
||||
let manager = create_service_manager();
|
||||
|
||||
// Test 2: Check if service exists before creation
|
||||
print("\n2. Testing service existence check (before creation)...");
|
||||
try {
|
||||
let exists_before = exists(manager, test_service_name);
|
||||
print(`✓ Service existence check: ${exists_before}`);
|
||||
|
||||
if !exists_before {
|
||||
print("✓ Service correctly doesn't exist before creation");
|
||||
test_results["exists_before"] = "PASS";
|
||||
passed_tests += 1;
|
||||
} else {
|
||||
print("⚠ Service unexpectedly exists before creation");
|
||||
test_results["exists_before"] = "WARN";
|
||||
}
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service existence check failed: ${e}`);
|
||||
test_results["exists_before"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 3: Start the service
|
||||
print("\n3. Testing service start...");
|
||||
try {
|
||||
// Create a service configuration object
|
||||
let service_config = #{
|
||||
name: test_service_name,
|
||||
binary_path: test_binary,
|
||||
args: test_args,
|
||||
working_directory: "/tmp",
|
||||
environment: #{},
|
||||
auto_restart: false
|
||||
};
|
||||
|
||||
start(manager, service_config);
|
||||
print("✓ Service started successfully");
|
||||
test_results["start"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service start failed: ${e}`);
|
||||
test_results["start"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 4: Check if service exists after creation
|
||||
print("\n4. Testing service existence check (after creation)...");
|
||||
try {
|
||||
let exists_after = exists(manager, test_service_name);
|
||||
print(`✓ Service existence check: ${exists_after}`);
|
||||
|
||||
if exists_after {
|
||||
print("✓ Service correctly exists after creation");
|
||||
test_results["exists_after"] = "PASS";
|
||||
passed_tests += 1;
|
||||
} else {
|
||||
print("✗ Service doesn't exist after creation");
|
||||
test_results["exists_after"] = "FAIL";
|
||||
}
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service existence check failed: ${e}`);
|
||||
test_results["exists_after"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 5: Check service status
|
||||
print("\n5. Testing service status...");
|
||||
try {
|
||||
let service_status = status(manager, test_service_name);
|
||||
print(`✓ Service status: ${service_status}`);
|
||||
test_results["status"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service status check failed: ${e}`);
|
||||
test_results["status"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 6: List services
|
||||
print("\n6. Testing service list...");
|
||||
try {
|
||||
let services = list(manager);
|
||||
print("✓ Service list retrieved");
|
||||
|
||||
// Skip service search due to Rhai type constraints with Vec iteration
|
||||
print(" ⚠️ Skipping service search due to Rhai type constraints");
|
||||
|
||||
test_results["list"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service list failed: ${e}`);
|
||||
test_results["list"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 7: Stop the service
|
||||
print("\n7. Testing service stop...");
|
||||
try {
|
||||
stop(manager, test_service_name);
|
||||
print(`✓ Service stopped: ${test_service_name}`);
|
||||
test_results["stop"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service stop failed: ${e}`);
|
||||
test_results["stop"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 8: Remove the service
|
||||
print("\n8. Testing service remove...");
|
||||
try {
|
||||
remove(manager, test_service_name);
|
||||
print(`✓ Service removed: ${test_service_name}`);
|
||||
test_results["remove"] = "PASS";
|
||||
passed_tests += 1;
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Service remove failed: ${e}`);
|
||||
test_results["remove"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test 9: Verify cleanup
|
||||
print("\n9. Testing cleanup verification...");
|
||||
try {
|
||||
let exists_after_remove = exists(manager, test_service_name);
|
||||
if !exists_after_remove {
|
||||
print("✓ Service correctly doesn't exist after removal");
|
||||
test_results["cleanup"] = "PASS";
|
||||
passed_tests += 1;
|
||||
} else {
|
||||
print("✗ Service still exists after removal");
|
||||
test_results["cleanup"] = "FAIL";
|
||||
}
|
||||
total_tests += 1;
|
||||
} catch(e) {
|
||||
print(`✗ Cleanup verification failed: ${e}`);
|
||||
test_results["cleanup"] = "FAIL";
|
||||
total_tests += 1;
|
||||
}
|
||||
|
||||
// Test Summary
|
||||
print("\n=== Test Summary ===");
|
||||
print(`Total tests: ${total_tests}`);
|
||||
print(`Passed: ${passed_tests}`);
|
||||
print(`Failed: ${total_tests - passed_tests}`);
|
||||
print(`Success rate: ${(passed_tests * 100) / total_tests}%`);
|
||||
|
||||
print("\nDetailed Results:");
|
||||
for test_name in test_results.keys() {
|
||||
let result = test_results[test_name];
|
||||
let status_icon = if result == "PASS" { "✓" } else if result == "FAIL" { "✗" } else { "⚠" };
|
||||
print(` ${status_icon} ${test_name}: ${result}`);
|
||||
}
|
||||
|
||||
if passed_tests == total_tests {
|
||||
print("\n🎉 All tests passed!");
|
||||
} else {
|
||||
print(`\n⚠ ${total_tests - passed_tests} test(s) failed`);
|
||||
}
|
||||
|
||||
print("\n=== Service Manager Basic Test Complete ===");
|
||||
|
||||
// Return test results for potential use by calling code
|
||||
test_results
|
252
_archive/service_manager/tests/rhai_integration_tests.rs
Normal file
252
_archive/service_manager/tests/rhai_integration_tests.rs
Normal file
@@ -0,0 +1,252 @@
|
||||
use rhai::{Engine, EvalAltResult};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
/// Helper function to create a Rhai engine for service manager testing
|
||||
fn create_service_manager_engine() -> Result<Engine, Box<EvalAltResult>> {
|
||||
#[cfg(feature = "rhai")]
|
||||
{
|
||||
let mut engine = Engine::new();
|
||||
// Register the service manager module for real testing
|
||||
sal_service_manager::rhai::register_service_manager_module(&mut engine)?;
|
||||
Ok(engine)
|
||||
}
|
||||
#[cfg(not(feature = "rhai"))]
|
||||
{
|
||||
Ok(Engine::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to run a Rhai script file
|
||||
fn run_rhai_script(script_path: &str) -> Result<rhai::Dynamic, Box<EvalAltResult>> {
|
||||
let engine = create_service_manager_engine()?;
|
||||
|
||||
// Read the script file
|
||||
let script_content = fs::read_to_string(script_path)
|
||||
.map_err(|e| format!("Failed to read script file {}: {}", script_path, e))?;
|
||||
|
||||
// Execute the script
|
||||
engine.eval::<rhai::Dynamic>(&script_content)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rhai_service_manager_basic() {
|
||||
let script_path = "tests/rhai/service_manager_basic.rhai";
|
||||
|
||||
if !Path::new(script_path).exists() {
|
||||
println!("⚠ Skipping test: Rhai script not found at {}", script_path);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Running Rhai service manager basic test...");
|
||||
|
||||
match run_rhai_script(script_path) {
|
||||
Ok(result) => {
|
||||
println!("✓ Rhai basic test completed successfully");
|
||||
|
||||
// Try to extract test results if the script returns them
|
||||
if let Some(map) = result.try_cast::<rhai::Map>() {
|
||||
println!("Test results received from Rhai script:");
|
||||
for (key, value) in map.iter() {
|
||||
println!(" {}: {:?}", key, value);
|
||||
}
|
||||
|
||||
// Check if all tests passed
|
||||
let all_passed = map.values().all(|v| {
|
||||
if let Some(s) = v.clone().try_cast::<String>() {
|
||||
s == "PASS"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
if all_passed {
|
||||
println!("✓ All Rhai tests reported as PASS");
|
||||
} else {
|
||||
println!("⚠ Some Rhai tests did not pass");
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Rhai basic test failed: {}", e);
|
||||
assert!(false, "Rhai script execution failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rhai_service_lifecycle() {
|
||||
let script_path = "tests/rhai/service_lifecycle.rhai";
|
||||
|
||||
if !Path::new(script_path).exists() {
|
||||
println!("⚠ Skipping test: Rhai script not found at {}", script_path);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Running Rhai service lifecycle test...");
|
||||
|
||||
match run_rhai_script(script_path) {
|
||||
Ok(result) => {
|
||||
println!("✓ Rhai lifecycle test completed successfully");
|
||||
|
||||
// Try to extract test results if the script returns them
|
||||
if let Some(map) = result.try_cast::<rhai::Map>() {
|
||||
println!("Lifecycle test results received from Rhai script:");
|
||||
|
||||
// Extract summary if available
|
||||
if let Some(summary) = map.get("summary") {
|
||||
if let Some(summary_map) = summary.clone().try_cast::<rhai::Map>() {
|
||||
println!("Summary:");
|
||||
for (key, value) in summary_map.iter() {
|
||||
println!(" {}: {:?}", key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract performance metrics if available
|
||||
if let Some(performance) = map.get("performance") {
|
||||
if let Some(perf_map) = performance.clone().try_cast::<rhai::Map>() {
|
||||
println!("Performance:");
|
||||
for (key, value) in perf_map.iter() {
|
||||
println!(" {}: {:?}", key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Rhai lifecycle test failed: {}", e);
|
||||
assert!(false, "Rhai script execution failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rhai_engine_functionality() {
|
||||
println!("Testing basic Rhai engine functionality...");
|
||||
|
||||
let engine = create_service_manager_engine().expect("Failed to create Rhai engine");
|
||||
|
||||
// Test basic Rhai functionality
|
||||
let test_script = r#"
|
||||
let test_results = #{
|
||||
basic_math: 2 + 2 == 4,
|
||||
string_ops: "hello".len() == 5,
|
||||
array_ops: [1, 2, 3].len() == 3,
|
||||
map_ops: #{ a: 1, b: 2 }.len() == 2
|
||||
};
|
||||
|
||||
let all_passed = true;
|
||||
for result in test_results.values() {
|
||||
if !result {
|
||||
all_passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#{
|
||||
results: test_results,
|
||||
all_passed: all_passed
|
||||
}
|
||||
"#;
|
||||
|
||||
match engine.eval::<rhai::Dynamic>(test_script) {
|
||||
Ok(result) => {
|
||||
if let Some(map) = result.try_cast::<rhai::Map>() {
|
||||
if let Some(all_passed) = map.get("all_passed") {
|
||||
if let Some(passed) = all_passed.clone().try_cast::<bool>() {
|
||||
if passed {
|
||||
println!("✓ All basic Rhai functionality tests passed");
|
||||
} else {
|
||||
println!("✗ Some basic Rhai functionality tests failed");
|
||||
assert!(false, "Basic Rhai tests failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(results) = map.get("results") {
|
||||
if let Some(results_map) = results.clone().try_cast::<rhai::Map>() {
|
||||
println!("Detailed results:");
|
||||
for (test_name, result) in results_map.iter() {
|
||||
let status = if let Some(passed) = result.clone().try_cast::<bool>() {
|
||||
if passed {
|
||||
"✓"
|
||||
} else {
|
||||
"✗"
|
||||
}
|
||||
} else {
|
||||
"?"
|
||||
};
|
||||
println!(" {} {}: {:?}", status, test_name, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Basic Rhai functionality test failed: {}", e);
|
||||
assert!(false, "Basic Rhai test failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rhai_script_error_handling() {
|
||||
println!("Testing Rhai error handling...");
|
||||
|
||||
let engine = create_service_manager_engine().expect("Failed to create Rhai engine");
|
||||
|
||||
// Test script with intentional error
|
||||
let error_script = r#"
|
||||
let result = "test";
|
||||
result.non_existent_method(); // This should cause an error
|
||||
"#;
|
||||
|
||||
match engine.eval::<rhai::Dynamic>(error_script) {
|
||||
Ok(_) => {
|
||||
println!("⚠ Expected error but script succeeded");
|
||||
assert!(
|
||||
false,
|
||||
"Error handling test failed - expected error but got success"
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✓ Error correctly caught: {}", e);
|
||||
// Verify it's the expected type of error
|
||||
assert!(e.to_string().contains("method") || e.to_string().contains("function"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rhai_script_files_exist() {
|
||||
println!("Checking that Rhai test scripts exist...");
|
||||
|
||||
let script_files = [
|
||||
"tests/rhai/service_manager_basic.rhai",
|
||||
"tests/rhai/service_lifecycle.rhai",
|
||||
];
|
||||
|
||||
for script_file in &script_files {
|
||||
if Path::new(script_file).exists() {
|
||||
println!("✓ Found script: {}", script_file);
|
||||
|
||||
// Verify the file is readable and not empty
|
||||
match fs::read_to_string(script_file) {
|
||||
Ok(content) => {
|
||||
if content.trim().is_empty() {
|
||||
assert!(false, "Script file {} is empty", script_file);
|
||||
}
|
||||
println!(" Content length: {} characters", content.len());
|
||||
}
|
||||
Err(e) => {
|
||||
assert!(false, "Failed to read script file {}: {}", script_file, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert!(false, "Required script file not found: {}", script_file);
|
||||
}
|
||||
}
|
||||
|
||||
println!("✓ All required Rhai script files exist and are readable");
|
||||
}
|
317
_archive/service_manager/tests/zinit_integration_tests.rs
Normal file
317
_archive/service_manager/tests/zinit_integration_tests.rs
Normal file
@@ -0,0 +1,317 @@
|
||||
use sal_service_manager::{
|
||||
ServiceConfig, ServiceManager, ServiceManagerError, ServiceStatus, ZinitServiceManager,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
/// Helper function to find an available Zinit socket path
|
||||
async fn get_available_socket_path() -> Option<String> {
|
||||
let socket_paths = [
|
||||
"/var/run/zinit.sock",
|
||||
"/tmp/zinit.sock",
|
||||
"/run/zinit.sock",
|
||||
"./zinit.sock",
|
||||
];
|
||||
|
||||
for path in &socket_paths {
|
||||
// Try to create a ZinitServiceManager to test connectivity
|
||||
if let Ok(manager) = ZinitServiceManager::new(path) {
|
||||
// Test if we can list services (basic connectivity test)
|
||||
if manager.list().is_ok() {
|
||||
println!("✓ Found working Zinit socket at: {}", path);
|
||||
return Some(path.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Helper function to clean up test services
|
||||
async fn cleanup_test_service(manager: &dyn ServiceManager, service_name: &str) {
|
||||
let _ = manager.stop(service_name);
|
||||
let _ = manager.remove(service_name);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_zinit_service_manager_creation() {
|
||||
if let Some(socket_path) = get_available_socket_path().await {
|
||||
let manager = ZinitServiceManager::new(&socket_path);
|
||||
assert!(
|
||||
manager.is_ok(),
|
||||
"Should be able to create ZinitServiceManager"
|
||||
);
|
||||
|
||||
let manager = manager.unwrap();
|
||||
|
||||
// Test basic connectivity by listing services
|
||||
let list_result = manager.list();
|
||||
assert!(list_result.is_ok(), "Should be able to list services");
|
||||
|
||||
println!("✓ ZinitServiceManager created successfully");
|
||||
} else {
|
||||
println!("⚠ Skipping test_zinit_service_manager_creation: No Zinit socket available");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_service_lifecycle() {
|
||||
if let Some(socket_path) = get_available_socket_path().await {
|
||||
let manager = ZinitServiceManager::new(&socket_path).expect("Failed to create manager");
|
||||
let service_name = "test-lifecycle-service";
|
||||
|
||||
// Clean up any existing service first
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
|
||||
let config = ServiceConfig {
|
||||
name: service_name.to_string(),
|
||||
binary_path: "echo".to_string(),
|
||||
args: vec!["Hello from lifecycle test".to_string()],
|
||||
working_directory: Some("/tmp".to_string()),
|
||||
environment: HashMap::new(),
|
||||
auto_restart: false,
|
||||
};
|
||||
|
||||
// Test service creation and start
|
||||
println!("Testing service creation and start...");
|
||||
let start_result = manager.start(&config);
|
||||
match start_result {
|
||||
Ok(_) => {
|
||||
println!("✓ Service started successfully");
|
||||
|
||||
// Wait a bit for the service to run
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
|
||||
// Test service exists
|
||||
let exists = manager.exists(service_name);
|
||||
assert!(exists.is_ok(), "Should be able to check if service exists");
|
||||
|
||||
if let Ok(true) = exists {
|
||||
println!("✓ Service exists check passed");
|
||||
|
||||
// Test service status
|
||||
let status_result = manager.status(service_name);
|
||||
match status_result {
|
||||
Ok(status) => {
|
||||
println!("✓ Service status: {:?}", status);
|
||||
assert!(
|
||||
matches!(status, ServiceStatus::Running | ServiceStatus::Stopped),
|
||||
"Service should be running or stopped (for oneshot)"
|
||||
);
|
||||
}
|
||||
Err(e) => println!("⚠ Status check failed: {}", e),
|
||||
}
|
||||
|
||||
// Test service logs
|
||||
let logs_result = manager.logs(service_name, None);
|
||||
match logs_result {
|
||||
Ok(logs) => {
|
||||
println!("✓ Retrieved logs: {}", logs.len());
|
||||
// For echo command, we should have some output
|
||||
assert!(
|
||||
!logs.is_empty() || logs.contains("Hello"),
|
||||
"Should have log output"
|
||||
);
|
||||
}
|
||||
Err(e) => println!("⚠ Logs retrieval failed: {}", e),
|
||||
}
|
||||
|
||||
// Test service list
|
||||
let list_result = manager.list();
|
||||
match list_result {
|
||||
Ok(services) => {
|
||||
println!("✓ Listed {} services", services.len());
|
||||
assert!(
|
||||
services.contains(&service_name.to_string()),
|
||||
"Service should appear in list"
|
||||
);
|
||||
}
|
||||
Err(e) => println!("⚠ List services failed: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// Test service stop
|
||||
println!("Testing service stop...");
|
||||
let stop_result = manager.stop(service_name);
|
||||
match stop_result {
|
||||
Ok(_) => println!("✓ Service stopped successfully"),
|
||||
Err(e) => println!("⚠ Stop failed: {}", e),
|
||||
}
|
||||
|
||||
// Test service removal
|
||||
println!("Testing service removal...");
|
||||
let remove_result = manager.remove(service_name);
|
||||
match remove_result {
|
||||
Ok(_) => println!("✓ Service removed successfully"),
|
||||
Err(e) => println!("⚠ Remove failed: {}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("⚠ Service creation/start failed: {}", e);
|
||||
// This might be expected if zinit doesn't allow service creation
|
||||
}
|
||||
}
|
||||
|
||||
// Final cleanup
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
} else {
|
||||
println!("⚠ Skipping test_service_lifecycle: No Zinit socket available");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_service_start_and_confirm() {
|
||||
if let Some(socket_path) = get_available_socket_path().await {
|
||||
let manager = ZinitServiceManager::new(&socket_path).expect("Failed to create manager");
|
||||
let service_name = "test-start-confirm-service";
|
||||
|
||||
// Clean up any existing service first
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
|
||||
let config = ServiceConfig {
|
||||
name: service_name.to_string(),
|
||||
binary_path: "sleep".to_string(),
|
||||
args: vec!["5".to_string()], // Sleep for 5 seconds
|
||||
working_directory: Some("/tmp".to_string()),
|
||||
environment: HashMap::new(),
|
||||
auto_restart: false,
|
||||
};
|
||||
|
||||
// Test start_and_confirm with timeout
|
||||
println!("Testing start_and_confirm with timeout...");
|
||||
let start_result = manager.start_and_confirm(&config, 10);
|
||||
match start_result {
|
||||
Ok(_) => {
|
||||
println!("✓ Service started and confirmed successfully");
|
||||
|
||||
// Verify it's actually running
|
||||
let status = manager.status(service_name);
|
||||
match status {
|
||||
Ok(ServiceStatus::Running) => println!("✓ Service confirmed running"),
|
||||
Ok(other_status) => {
|
||||
println!("⚠ Service in unexpected state: {:?}", other_status)
|
||||
}
|
||||
Err(e) => println!("⚠ Status check failed: {}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("⚠ start_and_confirm failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Test start_existing_and_confirm
|
||||
println!("Testing start_existing_and_confirm...");
|
||||
let start_existing_result = manager.start_existing_and_confirm(service_name, 5);
|
||||
match start_existing_result {
|
||||
Ok(_) => println!("✓ start_existing_and_confirm succeeded"),
|
||||
Err(e) => println!("⚠ start_existing_and_confirm failed: {}", e),
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
} else {
|
||||
println!("⚠ Skipping test_service_start_and_confirm: No Zinit socket available");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_service_restart() {
|
||||
if let Some(socket_path) = get_available_socket_path().await {
|
||||
let manager = ZinitServiceManager::new(&socket_path).expect("Failed to create manager");
|
||||
let service_name = "test-restart-service";
|
||||
|
||||
// Clean up any existing service first
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
|
||||
let config = ServiceConfig {
|
||||
name: service_name.to_string(),
|
||||
binary_path: "echo".to_string(),
|
||||
args: vec!["Restart test".to_string()],
|
||||
working_directory: Some("/tmp".to_string()),
|
||||
environment: HashMap::new(),
|
||||
auto_restart: true, // Enable auto-restart for this test
|
||||
};
|
||||
|
||||
// Start the service first
|
||||
let start_result = manager.start(&config);
|
||||
if start_result.is_ok() {
|
||||
// Wait for service to be established
|
||||
sleep(Duration::from_millis(1000)).await;
|
||||
|
||||
// Test restart
|
||||
println!("Testing service restart...");
|
||||
let restart_result = manager.restart(service_name);
|
||||
match restart_result {
|
||||
Ok(_) => {
|
||||
println!("✓ Service restarted successfully");
|
||||
|
||||
// Wait and check status
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
|
||||
let status_result = manager.status(service_name);
|
||||
match status_result {
|
||||
Ok(status) => {
|
||||
println!("✓ Service state after restart: {:?}", status);
|
||||
}
|
||||
Err(e) => println!("⚠ Status check after restart failed: {}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("⚠ Restart failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
cleanup_test_service(&manager, service_name).await;
|
||||
} else {
|
||||
println!("⚠ Skipping test_service_restart: No Zinit socket available");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_error_handling() {
|
||||
if let Some(socket_path) = get_available_socket_path().await {
|
||||
let manager = ZinitServiceManager::new(&socket_path).expect("Failed to create manager");
|
||||
|
||||
// Test operations on non-existent service
|
||||
let non_existent_service = "non-existent-service-12345";
|
||||
|
||||
// Test status of non-existent service
|
||||
let status_result = manager.status(non_existent_service);
|
||||
match status_result {
|
||||
Err(ServiceManagerError::ServiceNotFound(_)) => {
|
||||
println!("✓ Correctly returned ServiceNotFound for non-existent service");
|
||||
}
|
||||
Err(other_error) => {
|
||||
println!(
|
||||
"⚠ Got different error for non-existent service: {}",
|
||||
other_error
|
||||
);
|
||||
}
|
||||
Ok(_) => {
|
||||
println!("⚠ Unexpectedly found non-existent service");
|
||||
}
|
||||
}
|
||||
|
||||
// Test exists for non-existent service
|
||||
let exists_result = manager.exists(non_existent_service);
|
||||
match exists_result {
|
||||
Ok(false) => println!("✓ Correctly reported non-existent service as not existing"),
|
||||
Ok(true) => println!("⚠ Incorrectly reported non-existent service as existing"),
|
||||
Err(e) => println!("⚠ Error checking existence: {}", e),
|
||||
}
|
||||
|
||||
// Test stop of non-existent service
|
||||
let stop_result = manager.stop(non_existent_service);
|
||||
match stop_result {
|
||||
Err(_) => println!("✓ Correctly failed to stop non-existent service"),
|
||||
Ok(_) => println!("⚠ Unexpectedly succeeded in stopping non-existent service"),
|
||||
}
|
||||
|
||||
println!("✓ Error handling tests completed");
|
||||
} else {
|
||||
println!("⚠ Skipping test_error_handling: No Zinit socket available");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user