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 = 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)"), } }