sal/service_manager/tests/factory_tests.rs
Mahmoud-Emad 131d978450 feat: Add service manager support
- Add a new service manager crate for dynamic service management
- Integrate service manager with Rhai for scripting
- Provide examples for circle worker management and basic usage
- Add comprehensive tests for service lifecycle and error handling
- Implement cross-platform support for macOS and Linux (zinit/systemd)
2025-07-01 18:00:21 +03:00

216 lines
7.5 KiB
Rust

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();
// 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();
// 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)"),
}
}