Files
ProxyWarden/src-tauri/tests/component_detection_tests.rs
T
dokril efda8eb98f
CI / Windows baseline (push) Canceled after 0s
Release v2.0.0
2026-09-10 20:59:52 +03:00

728 lines
26 KiB
Rust

#[cfg(windows)]
use proxywarden_lib::component_detection::SystemProxyfierDetectionHost;
use proxywarden_lib::component_detection::{
detect_proxyfier_install_with_host, detect_singbox_install_with_host,
has_additional_matching_legacy_proxifyre_service_with_host, inventory_proxyfier_with_host,
inventory_singbox_with_host, matches_legacy_proxifyre_2_2_1_manifest,
proxyfier_component_from_detection, proxyfier_component_from_inventory,
service_executable_from_path_name, singbox_component_from_detection, LegacyPackageFileIdentity,
ProxyfierDetectionHost, ProxyfierEngine, RegistryInstallEntry, LEGACY_PROXIFYRE_2_2_1_MANIFEST,
};
use proxywarden_lib::component_inventory::{
BinaryIdentityEvidence, ComponentClassification, OWNERSHIP_MISMATCH,
};
use proxywarden_lib::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_path(r"C:\Tools\ProxiFyre\ProxiFyre.exe")
.with_service_path(
"ProxiFyreService",
r#""C:\Tools\ProxiFyre\ProxiFyre.exe" --service"#,
)
.with_known_binary(r"C:\Tools\ProxiFyre\ProxiFyre.exe")
.with_version(r"C:\Tools\ProxiFyre\ProxiFyre.exe", "2.2.1.0");
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);
assert_eq!(detected.service_name, Some("ProxiFyreService".to_string()));
assert_eq!(detected.service_status, Some("running".to_string()));
assert_eq!(detected.version, Some("2.2.1.0".to_string()));
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_eq!(component.service_name, Some("ProxiFyreService".to_string()));
assert_eq!(component.service_status, Some("running".to_string()));
assert_eq!(component.version, Some("2.2.1.0".to_string()));
assert!(component.problems.is_empty());
}
#[test]
fn detects_current_proxifyre_only_with_strong_marker_and_exact_service_path() {
let root = r"C:\Program Files\ProxyWarden\components\ProxiFyre";
let executable = r"C:\Program Files\ProxyWarden\components\ProxiFyre\ProxiFyre.exe";
let marker = serde_json::json!({
"manager": "ProxyWarden",
"component": "proxifyre",
"serviceName": "ProxiFyreService",
"installRoot": root,
"packetFilterInstalledByProxyWarden": false
})
.to_string();
let host = MockHost::new()
.with_path(root)
.with_path(executable)
.with_text(
r"C:\Program Files\ProxyWarden\components\ProxiFyre\proxywarden-component.json",
&marker,
)
.with_stopped_service_path(
"ProxiFyreService",
r#""C:\Program Files\ProxyWarden\components\ProxiFyre\ProxiFyre.exe" --service"#,
)
.with_version(executable, "2.4.0.0");
let detected = detect_proxyfier_install_with_host(&host).expect("managed current ProxiFyre");
assert_eq!(detected.install_dir, PathBuf::from(root));
assert_eq!(detected.version, Some("2.4.0.0".to_string()));
}
#[test]
fn current_proxifyre_with_foreign_same_name_service_is_ownership_mismatch() {
let root = r"C:\Program Files\ProxyWarden\components\ProxiFyre";
let executable = r"C:\Program Files\ProxyWarden\components\ProxiFyre\ProxiFyre.exe";
let marker = serde_json::json!({
"manager": "ProxyWarden",
"component": "proxifyre",
"serviceName": "ProxiFyreService",
"installRoot": root,
"packetFilterInstalledByProxyWarden": false
})
.to_string();
let host = MockHost::new()
.with_path(root)
.with_path(executable)
.with_text(
r"C:\Program Files\ProxyWarden\components\ProxiFyre\proxywarden-component.json",
&marker,
)
.with_service_path(
"ProxiFyreService",
r#""C:\Foreign\ProxiFyre.exe" --service"#,
);
let inventory = inventory_proxyfier_with_host(&host);
assert_eq!(inventory.classification(), ComponentClassification::Foreign);
assert_eq!(
inventory.selected_candidate().unwrap().issues[0].code,
OWNERSHIP_MISMATCH
);
}
#[test]
fn ignores_empty_common_proxifyre_folder_without_executable() {
let host = MockHost::new().with_path(r"C:\Tools\ProxiFyre");
assert!(detect_proxyfier_install_with_host(&host).is_none());
let component = proxyfier_component_from_detection(None);
assert_eq!(component.state, ComponentState::Missing);
assert!(!component.installed);
}
#[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_does_not_make_portable_proxifyre_managed() {
let host = MockHost::new()
.with_env("PROXYWARDEN_PROXIFYRE_ROOT", r"D:\Portable\ProxiFyre")
.with_path(r"D:\Portable\ProxiFyre\ProxiFyre.exe");
assert!(detect_proxyfier_install_with_host(&host).is_none());
let inventory = inventory_proxyfier_with_host(&host);
assert_eq!(inventory.classification(), ComponentClassification::Foreign);
}
#[test]
fn reports_stopped_proxifyre_service_when_executable_exists() {
let host = MockHost::new()
.with_env("PROXYWARDEN_PROXIFYRE_ROOT", r"C:\Tools\ProxiFyre")
.with_path(r"C:\Tools\ProxiFyre\ProxiFyre.exe")
.with_stopped_service_path(
"ProxiFyreService",
r#""C:\Tools\ProxiFyre\ProxiFyre.exe" --service"#,
)
.with_known_binary(r"C:\Tools\ProxiFyre\ProxiFyre.exe");
let detected =
detect_proxyfier_install_with_host(&host).expect("proxifyre executable should be detected");
let component = proxyfier_component_from_detection(Some(&detected));
assert_eq!(component.state, ComponentState::Installed);
assert!(component.installed);
assert!(!component.running);
assert_eq!(component.service_name, Some("ProxiFyreService".to_string()));
assert_eq!(component.service_status, Some("stopped".to_string()));
assert!(component.problems.is_empty());
}
#[test]
fn primary_and_alias_same_root_remain_discoverable_but_cutover_is_ambiguous() {
let root = Path::new(r"C:\Tools\ProxiFyre");
let executable = root.join("ProxiFyre.exe");
let host = MockHost::new()
.with_path(executable.to_str().expect("fixture path"))
.with_service_path(
"ProxiFyreService",
r#""C:\Tools\ProxiFyre\ProxiFyre.exe" -displayname "ProxiFyre Service" -servicename ProxiFyreService"#,
)
.with_service_path(
"ProxiFyre",
r#""C:\Tools\ProxiFyre\ProxiFyre.exe" --service"#,
)
.with_known_binary(executable.to_str().expect("fixture path"));
assert_eq!(
inventory_proxyfier_with_host(&host).classification(),
ComponentClassification::ManagedLegacy,
"Task 5 discovery/Start/Stop classification stays unchanged"
);
assert!(has_additional_matching_legacy_proxifyre_service_with_host(
&host, root
));
}
#[test]
fn any_present_alias_service_makes_the_strict_service_set_ambiguous() {
let root = Path::new(r"C:\Tools\ProxiFyre");
for host in [
MockHost::new().with_service("ProxiFyre"),
MockHost::new().with_service_path("ProxiFyre", r#""C:\Foreign\ProxiFyre.exe" --service"#),
] {
assert!(has_additional_matching_legacy_proxifyre_service_with_host(
&host, root
));
}
}
#[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"]);
}
#[test]
fn ignores_known_service_name_when_path_points_to_foreign_binary() {
let host = MockHost::new()
.with_env("PROXYWARDEN_PROXIFYRE_ROOT", r"C:\Tools\ProxiFyre")
.with_path(r"C:\Tools\ProxiFyre\ProxiFyre.exe")
.with_service_path(
"ProxiFyreService",
r#""C:\Foreign\ProxiFyre.exe" --service"#,
);
assert!(detect_proxyfier_install_with_host(&host).is_none());
let inventory = inventory_proxyfier_with_host(&host);
let candidate = inventory.selected_candidate().expect("foreign collision");
assert_eq!(candidate.classification, ComponentClassification::Foreign);
assert_eq!(candidate.issues[0].code, OWNERSHIP_MISMATCH);
let component = proxyfier_component_from_inventory(&inventory);
assert_eq!(component.state, ComponentState::Error);
assert!(!component.running);
assert!(component.actions.is_empty());
}
#[test]
fn ignores_known_service_name_without_path_metadata() {
let host = MockHost::new()
.with_env("PROXYWARDEN_PROXIFYRE_ROOT", r"C:\Tools\ProxiFyre")
.with_path(r"C:\Tools\ProxiFyre\ProxiFyre.exe")
.with_service("ProxiFyreService");
assert!(detect_proxyfier_install_with_host(&host).is_none());
let inventory = inventory_proxyfier_with_host(&host);
assert_eq!(inventory.classification(), ComponentClassification::Foreign);
assert_eq!(
inventory.selected_candidate().unwrap().issues[0].code,
OWNERSHIP_MISMATCH
);
}
#[test]
fn detects_running_local_singbox_from_default_install_root_and_service() {
let host = MockHost::new()
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe")
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe")
.with_text(
r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.xml",
winsw_xml(),
)
.with_service_path(
"ProxyWardenSingBox",
r#""C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe""#,
)
.with_version(
r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe",
"1.11.0.0",
);
let detected =
detect_singbox_install_with_host(&host).expect("existing sing-box should be detected");
assert_eq!(
detected.executable_path,
PathBuf::from(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe")
);
assert_eq!(detected.service_name, "ProxyWardenSingBox");
assert!(detected.running);
assert_eq!(detected.version, Some("1.11.0.0".to_string()));
let component = singbox_component_from_detection(Some(&detected));
assert_eq!(component.state, ComponentState::Running);
assert!(component.installed);
assert!(component.running);
assert_eq!(
component.path,
Some(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe".to_string())
);
assert!(component.problems.is_empty());
}
#[test]
fn current_singbox_with_foreign_same_name_service_is_ownership_mismatch() {
let host = MockHost::new()
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe")
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe")
.with_text(
r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.xml",
winsw_xml(),
)
.with_service_path(
"ProxyWardenSingBox",
r#""C:\Foreign\ProxyWardenSingBox.exe""#,
);
let inventory = inventory_singbox_with_host(&host);
assert_eq!(inventory.classification(), ComponentClassification::Foreign);
assert_eq!(
inventory.selected_candidate().unwrap().issues[0].code,
OWNERSHIP_MISMATCH
);
}
#[test]
fn winsw_identity_cannot_be_spoofed_by_comments_or_unrelated_nodes() {
let spoofed_xml = r#"<service>
<!-- <id>ProxyWardenSingBox</id> -->
<!-- <executable>%BASE%\sing-box.exe</executable> -->
<metadata><arguments>run -c "%BASE%\config.json"</arguments></metadata>
<id>ForeignService</id>
<executable>C:\Foreign\sing-box.exe</executable>
<arguments>run -c "C:\Foreign\config.json"</arguments>
</service>"#;
let host = MockHost::new()
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe")
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe")
.with_text(
r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.xml",
spoofed_xml,
)
.with_service_path(
"ProxyWardenSingBox",
r#""C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe""#,
);
let inventory = inventory_singbox_with_host(&host);
assert_eq!(
inventory.classification(),
ComponentClassification::Incomplete
);
assert!(detect_singbox_install_with_host(&host).is_none());
}
#[test]
fn winsw_identity_rejects_duplicate_dtd_cdata_second_root_and_oversized_xml() {
let oversized = format!(
"<service><id>ProxyWardenSingBox</id><executable>%BASE%\\sing-box.exe</executable><arguments>run -c \"%BASE%\\config.json\"</arguments><description>{}</description></service>",
"x".repeat(65 * 1024)
);
let invalid_xml = vec![
r#"<service><id>ProxyWardenSingBox</id><id>ProxyWardenSingBox</id><executable>%BASE%\sing-box.exe</executable><arguments>run -c "%BASE%\config.json"</arguments></service>"#.to_string(),
r#"<!DOCTYPE service [<!ENTITY owned "ProxyWardenSingBox">]><service><id>&owned;</id><executable>%BASE%\sing-box.exe</executable><arguments>run -c "%BASE%\config.json"</arguments></service>"#.to_string(),
r#"<service><id><![CDATA[ProxyWardenSingBox]]></id><executable>%BASE%\sing-box.exe</executable><arguments>run -c "%BASE%\config.json"</arguments></service>"#.to_string(),
format!("{}<service></service>", winsw_xml()),
oversized,
];
for xml in invalid_xml {
let host = current_singbox_host_with_xml(&xml);
assert!(
detect_singbox_install_with_host(&host).is_none(),
"unsafe WinSW XML was accepted"
);
}
}
#[test]
fn winsw_identity_accepts_xml_declaration_bom_and_current_extra_nodes() {
let xml = "\u{feff}<?xml version=\"1.0\" encoding=\"utf-8\"?><service><id>ProxyWardenSingBox</id><name>ProxyWarden Local sing-box</name><executable>%BASE%\\sing-box.exe</executable><arguments>run -c \"%BASE%\\config.json\"</arguments><log mode=\"roll-by-size\"><keepFiles>4</keepFiles></log><onfailure action=\"restart\" /></service>".to_string();
let host = current_singbox_host_with_xml(&xml);
assert!(detect_singbox_install_with_host(&host).is_some());
}
#[test]
fn portable_singbox_env_override_remains_foreign() {
let host = MockHost::new()
.with_env("PROXYWARDEN_SINGBOX_ROOT", r"D:\Portable\sing-box")
.with_path(r"D:\Portable\sing-box\sing-box.exe");
assert!(detect_singbox_install_with_host(&host).is_none());
assert_eq!(
inventory_singbox_with_host(&host).classification(),
ComponentClassification::Foreign
);
}
#[test]
fn missing_local_singbox_returns_optional_install_action_status() {
let component = singbox_component_from_detection(None);
assert_eq!(component.state, ComponentState::Missing);
assert!(!component.installed);
assert!(!component.running);
assert_eq!(component.actions, vec!["Установить Local sing-box"]);
assert!(component.problems.is_empty());
}
#[test]
fn parses_service_pathname_without_accepting_malformed_quotes() {
assert_eq!(
service_executable_from_path_name(
r#""C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe" install"#,
),
Some(PathBuf::from(
r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe"
))
);
assert_eq!(
service_executable_from_path_name(r"C:\Tools\ProxiFyre\ProxiFyre.exe --service"),
Some(PathBuf::from(r"C:\Tools\ProxiFyre\ProxiFyre.exe"))
);
assert!(service_executable_from_path_name(r#""C:\Broken\ProxiFyre.exe --service"#).is_none());
assert!(service_executable_from_path_name(" ").is_none());
}
#[test]
fn frozen_proxifyre_manifest_matches_all_ten_files_and_nothing_less() {
let observed = LEGACY_PROXIFYRE_2_2_1_MANIFEST
.iter()
.rev()
.map(|file| LegacyPackageFileIdentity {
relative_path: PathBuf::from(file.relative_path.to_ascii_uppercase()),
size: file.size,
sha256: file.sha256.to_ascii_uppercase(),
})
.collect::<Vec<_>>();
assert!(matches_legacy_proxifyre_2_2_1_manifest(&observed));
let mut missing = observed.clone();
missing.pop();
assert!(!matches_legacy_proxifyre_2_2_1_manifest(&missing));
let mut wrong_size = observed.clone();
wrong_size[0].size += 1;
assert!(!matches_legacy_proxifyre_2_2_1_manifest(&wrong_size));
let mut wrong_hash = observed.clone();
wrong_hash[0].sha256 = "0".repeat(64);
assert!(!matches_legacy_proxifyre_2_2_1_manifest(&wrong_hash));
let mut extra = observed.clone();
extra.push(LegacyPackageFileIdentity {
relative_path: PathBuf::from("unexpected.dll"),
size: 1,
sha256: "0".repeat(64),
});
assert!(!matches_legacy_proxifyre_2_2_1_manifest(&extra));
let mut duplicate = observed;
duplicate[0] = duplicate[1].clone();
assert!(!matches_legacy_proxifyre_2_2_1_manifest(&duplicate));
}
#[test]
#[cfg(windows)]
fn reads_windows_pe_file_version_without_executing_binary() {
let windows_dir = std::env::var("WINDIR").expect("WINDIR on Windows");
let notepad = PathBuf::from(windows_dir)
.join("System32")
.join("notepad.exe");
let version = SystemProxyfierDetectionHost
.file_version(&notepad)
.expect("notepad PE version");
assert_eq!(version.split('.').count(), 4);
assert!(version
.split('.')
.all(|segment| segment.parse::<u32>().is_ok()));
}
#[test]
fn production_component_detection_has_only_native_windows_owners() {
let source = include_str!("../src/component_detection.rs");
let source_lower = source.to_ascii_lowercase();
for forbidden in [
"command_no_window(",
"get-process",
"get-service",
"get-ciminstance",
"\"powershell\"",
"std::process::command",
"extern \"system\"",
"#[link(",
] {
assert!(
!source_lower.contains(forbidden),
"production detection still contains shell boundary: {forbidden}"
);
}
for native_owner in [
"CreateToolhelp32Snapshot",
"OpenSCManagerW",
"QueryServiceStatusEx",
"QueryServiceConfigW",
"winreg::",
] {
assert!(
source.contains(native_owner),
"native detection owner is missing: {native_owner}"
);
}
}
#[test]
#[cfg(windows)]
fn native_process_inventory_finds_the_running_test_binary() {
let executable_name = std::env::current_exe()
.expect("current test executable")
.file_name()
.expect("current test executable file name")
.to_string_lossy()
.into_owned();
assert!(SystemProxyfierDetectionHost.process_running(&executable_name));
assert!(SystemProxyfierDetectionHost.process_running(&executable_name.to_ascii_uppercase()));
assert!(SystemProxyfierDetectionHost.process_running(executable_name.trim_end_matches(".exe")));
}
#[test]
#[cfg(windows)]
fn native_service_inventory_reads_status_and_path_from_scm() {
let service = SystemProxyfierDetectionHost
.service_info("EventLog")
.expect("Windows EventLog service should be queryable without elevation");
assert_eq!(service.name, "EventLog");
assert!(matches!(
service.status.as_str(),
"stopped"
| "start pending"
| "stop pending"
| "running"
| "continue pending"
| "pause pending"
| "paused"
| "unknown"
));
assert!(service
.path_name
.as_deref()
.is_some_and(|path| !path.trim().is_empty()));
}
#[derive(Default)]
struct MockHost {
env: HashMap<String, String>,
paths: HashSet<String>,
processes: HashSet<String>,
services: HashMap<String, String>,
service_paths: HashMap<String, String>,
texts: HashMap<String, String>,
known_binaries: HashSet<String>,
versions: HashMap<String, String>,
registry: Vec<RegistryInstallEntry>,
}
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(), "running".to_string());
self
}
fn with_service_path(mut self, service: &str, path_name: &str) -> Self {
self.services
.insert(service.to_ascii_lowercase(), "running".to_string());
self.service_paths
.insert(service.to_ascii_lowercase(), path_name.to_string());
self
}
fn with_stopped_service_path(mut self, service: &str, path_name: &str) -> Self {
self.services
.insert(service.to_ascii_lowercase(), "stopped".to_string());
self.service_paths
.insert(service.to_ascii_lowercase(), path_name.to_string());
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
}
fn with_text(mut self, path: &str, contents: &str) -> Self {
self.paths.insert(normalize_path(path));
self.texts
.insert(normalize_path(path), contents.to_string());
self
}
fn with_known_binary(mut self, path: &str) -> Self {
self.known_binaries.insert(normalize_path(path));
self
}
fn with_version(mut self, path: &str, version: &str) -> Self {
self.versions
.insert(normalize_path(path), version.to_string());
self
}
}
impl ProxyfierDetectionHost for MockHost {
fn env_var(&self, name: &str) -> Option<String> {
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_status(&self, service_name: &str) -> Option<String> {
self.services
.get(&service_name.to_ascii_lowercase())
.cloned()
}
fn service_info(
&self,
service_name: &str,
) -> Option<proxywarden_lib::component_detection::DetectedService> {
let key = service_name.to_ascii_lowercase();
self.services.get(&key).map(|status| {
proxywarden_lib::component_detection::DetectedService {
name: service_name.to_string(),
status: status.clone(),
path_name: self.service_paths.get(&key).cloned(),
}
})
}
fn registry_install_entries(&self) -> Vec<RegistryInstallEntry> {
self.registry.clone()
}
fn read_text(&self, path: &Path) -> Option<String> {
self.texts
.get(&normalize_path(&path.display().to_string()))
.cloned()
}
fn file_version(&self, path: &Path) -> Option<String> {
self.versions
.get(&normalize_path(&path.display().to_string()))
.cloned()
}
fn binary_identity(
&self,
_component_id: &proxywarden_lib::models::ComponentId,
path: &Path,
) -> BinaryIdentityEvidence {
if self
.known_binaries
.contains(&normalize_path(&path.display().to_string()))
{
BinaryIdentityEvidence::KnownPackage
} else {
BinaryIdentityEvidence::Unknown
}
}
}
fn normalize_path(path: &str) -> String {
path.replace('/', "\\").to_ascii_lowercase()
}
fn winsw_xml() -> &'static str {
r#"<service>
<id>ProxyWardenSingBox</id>
<executable>%BASE%\sing-box.exe</executable>
<arguments>run -c "%BASE%\config.json"</arguments>
</service>"#
}
fn current_singbox_host_with_xml(xml: &str) -> MockHost {
MockHost::new()
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\sing-box.exe")
.with_path(r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe")
.with_text(
r"C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.xml",
xml,
)
.with_service_path(
"ProxyWardenSingBox",
r#""C:\Program Files\ProxyWarden\components\sing-box\ProxyWardenSingBox.exe""#,
)
}