#[path = "../src/component_detection.rs"] mod component_detection; #[path = "../src/models.rs"] mod models; use component_detection::{ detect_proxyfier_install_with_host, proxyfier_component_from_detection, ProxyfierDetectionHost, ProxyfierEngine, RegistryInstallEntry, }; use models::ComponentState; use std::{ collections::{HashMap, HashSet}, path::{Path, PathBuf}, }; #[test] fn detects_existing_proxifyre_from_registry_install_location() { let host = MockHost::new() .with_registry("ProxiFyre", r"C:\Tools\ProxiFyre") .with_path(r"C:\Tools\ProxiFyre") .with_service("ProxiFyreService"); let detected = detect_proxyfier_install_with_host(&host) .expect("existing ProxiFyre install should be detected"); assert_eq!(detected.engine, ProxyfierEngine::ProxiFyre); assert_eq!(detected.install_dir, PathBuf::from(r"C:\Tools\ProxiFyre")); assert_eq!( detected.config_path, Some(PathBuf::from(r"C:\Tools\ProxiFyre\app-config.json")) ); assert!(detected.running); let component = proxyfier_component_from_detection(Some(&detected)); assert_eq!(component.state, ComponentState::Running); assert!(component.installed); assert!(component.running); assert_eq!(component.path, Some(r"C:\Tools\ProxiFyre".to_string())); assert!(component.problems.is_empty()); } #[test] fn ignores_plain_proxifier_install() { let host = MockHost::new() .with_registry("Proxifier", r"C:\Program Files\Proxifier") .with_path(r"C:\Program Files\Proxifier") .with_process("Proxifier.exe"); assert!(detect_proxyfier_install_with_host(&host).is_none()); } #[test] fn env_override_can_point_to_portable_proxifyre_install() { let host = MockHost::new() .with_env("VPN_PROXY_PROXIFYRE_ROOT", r"D:\Portable\ProxiFyre") .with_path(r"D:\Portable\ProxiFyre\ProxiFyre.exe"); let detected = detect_proxyfier_install_with_host(&host) .expect("env override should be checked before common paths"); assert_eq!(detected.engine, ProxyfierEngine::ProxiFyre); assert_eq!( detected.executable_path, PathBuf::from(r"D:\Portable\ProxiFyre\ProxiFyre.exe") ); } #[test] fn missing_proxyfier_returns_install_action_status() { let component = proxyfier_component_from_detection(None); assert_eq!(component.state, ComponentState::Missing); assert!(!component.installed); assert_eq!(component.actions, vec!["Установить ProxiFyre"]); } #[derive(Default)] struct MockHost { env: HashMap, paths: HashSet, processes: HashSet, services: HashSet, registry: Vec, } impl MockHost { fn new() -> Self { Self::default() } fn with_env(mut self, name: &str, value: &str) -> Self { self.env.insert(name.to_string(), value.to_string()); self } fn with_path(mut self, path: &str) -> Self { self.paths.insert(normalize_path(path)); self } fn with_process(mut self, process: &str) -> Self { self.processes.insert(process.to_ascii_lowercase()); self } fn with_service(mut self, service: &str) -> Self { self.services.insert(service.to_ascii_lowercase()); self } fn with_registry(mut self, display_name: &str, install_location: &str) -> Self { self.registry.push(RegistryInstallEntry { display_name: display_name.to_string(), install_location: Some(PathBuf::from(install_location)), display_icon: None, }); self } } impl ProxyfierDetectionHost for MockHost { fn env_var(&self, name: &str) -> Option { self.env.get(name).cloned() } fn path_exists(&self, path: &Path) -> bool { self.paths .contains(&normalize_path(&path.display().to_string())) } fn process_running(&self, process_name: &str) -> bool { self.processes.contains(&process_name.to_ascii_lowercase()) } fn service_running(&self, service_name: &str) -> bool { self.services.contains(&service_name.to_ascii_lowercase()) } fn registry_install_entries(&self) -> Vec { self.registry.clone() } } fn normalize_path(path: &str) -> String { path.replace('/', "\\").to_ascii_lowercase() }