Refine ProxyWarden routing and config flows
This commit is contained in:
@@ -258,6 +258,9 @@ fn proxifyre_install_script_uses_resilient_download_helpers() {
|
||||
|
||||
assert!(script.contains("function Get-SafeUriForLog([string]$uri)"));
|
||||
assert!(script.contains("function Invoke-ReleaseApi([string]$uri, [string]$label)"));
|
||||
assert!(script.contains("function Resolve-ReleaseAsset("));
|
||||
assert!(script.contains("function Get-PinnedWindowsPacketFilterAsset([string]$arch)"));
|
||||
assert!(script.contains("function Get-PinnedProxiFyreAsset([string]$arch)"));
|
||||
assert!(
|
||||
script.contains("function Invoke-Download([string]$uri, [string]$path, [string]$label)")
|
||||
);
|
||||
@@ -266,20 +269,150 @@ fn proxifyre_install_script_uses_resilient_download_helpers() {
|
||||
assert!(script.contains("Invoke-CurlDownload $uri $partialPath"));
|
||||
assert!(script.contains("--user-agent 'proxywarden' --output $partialPath --url $uri"));
|
||||
assert!(script.contains("Move-Item -LiteralPath $partialPath -Destination $path -Force"));
|
||||
assert!(script.contains("function Get-BundledAsset([string]$pattern, [string]$label)"));
|
||||
assert!(script.contains("function Verify-BundledAssetHash([string]$path, [string]$label)"));
|
||||
assert!(script
|
||||
.contains("Invoke-Download $vcRedistUrl $vcRedistPath 'Microsoft Visual C++ Runtime'"));
|
||||
assert!(script.contains("Invoke-ReleaseApi $ndisapiReleaseApi 'Windows Packet Filter'"));
|
||||
assert!(script
|
||||
.contains("Resolve-ReleaseAsset $ndisapiReleaseApi $ndisPattern 'Windows Packet Filter'"));
|
||||
assert!(script.contains(
|
||||
"Invoke-Download $ndisAsset.browser_download_url $ndisPath 'Windows Packet Filter'"
|
||||
));
|
||||
assert!(script.contains("Invoke-ReleaseApi $proxifyreReleaseApi 'ProxiFyre'"));
|
||||
assert!(
|
||||
script.contains("Resolve-ReleaseAsset $proxifyreReleaseApi $proxifyrePattern 'ProxiFyre'")
|
||||
);
|
||||
assert!(script.contains(
|
||||
"Invoke-Download $proxifyreAsset.browser_download_url $proxifyreZipPath 'ProxiFyre'"
|
||||
));
|
||||
assert!(script.contains("github.com/wiresock/ndisapi/releases/download"));
|
||||
assert!(script.contains("github.com/wiresock/proxifyre/releases/download"));
|
||||
let packet_filter_step = script
|
||||
.find("Write-ProxyWardenProgress 'install' 'packet-filter'")
|
||||
.expect("packet filter install step should be present");
|
||||
let vc_runtime_step = script
|
||||
.find("Write-ProxyWardenProgress 'install' 'vc-runtime'")
|
||||
.expect("runtime install step should be present");
|
||||
let proxifyre_step = script
|
||||
.find("Write-ProxyWardenProgress 'install' 'proxifyre'")
|
||||
.expect("proxifyre install step should be present");
|
||||
assert!(packet_filter_step < vc_runtime_step);
|
||||
assert!(vc_runtime_step < proxifyre_step);
|
||||
|
||||
cleanup(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxifyre_install_script_prefers_bundled_assets_before_downloads() {
|
||||
let root = test_root("proxifyre-install-script-bundled-assets");
|
||||
let bundle_dir = root.join("bundle");
|
||||
let script = commands::install_proxifyre_script_with_bundle(
|
||||
&root.join("proxifyre-app-config.json"),
|
||||
Some(&bundle_dir),
|
||||
);
|
||||
|
||||
assert!(script.contains(&format!(
|
||||
"$bundledAssetDir = '{}'",
|
||||
bundle_dir.display().to_string().replace('\'', "''")
|
||||
)));
|
||||
assert!(script.contains("$script:bundledAssetDir = [string]$bundledAssetDir"));
|
||||
assert!(script.contains("function Get-BundledAssetDir"));
|
||||
assert!(script.contains("$manifestPath = [IO.Path]::Combine($assetDir, 'manifest.json')"));
|
||||
assert!(script.contains("$script:bundledAssetManifest = Get-BundledAssetManifest"));
|
||||
assert!(script.contains("Copy-BundledAsset $bundledNdisPath $ndisPath"));
|
||||
assert!(script.contains("Copy-BundledAsset $bundledVcPath $vcRedistPath"));
|
||||
assert!(script.contains("Copy-BundledAsset $bundledProxiFyrePath $proxifyreZipPath"));
|
||||
|
||||
let bundled_ndis = script
|
||||
.find("Get-BundledAsset $ndisPattern 'Windows Packet Filter'")
|
||||
.expect("ndis bundle check should be present");
|
||||
let online_ndis = script
|
||||
.find("Resolve-ReleaseAsset $ndisapiReleaseApi $ndisPattern 'Windows Packet Filter'")
|
||||
.expect("ndis online fallback should be present");
|
||||
assert!(bundled_ndis < online_ndis);
|
||||
|
||||
let bundled_proxifyre = script
|
||||
.find("Get-BundledAsset $proxifyrePattern 'ProxiFyre'")
|
||||
.expect("proxifyre bundle check should be present");
|
||||
let online_proxifyre = script
|
||||
.find("Resolve-ReleaseAsset $proxifyreReleaseApi $proxifyrePattern 'ProxiFyre'")
|
||||
.expect("proxifyre online fallback should be present");
|
||||
assert!(bundled_proxifyre < online_proxifyre);
|
||||
|
||||
cleanup(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn proxifyre_uninstall_script_parses_as_powershell() {
|
||||
let root = test_root("proxifyre-uninstall-script");
|
||||
fs::create_dir_all(&root).expect("test root should be created");
|
||||
let detected = DetectedProxyfier {
|
||||
engine: ProxyfierEngine::ProxiFyre,
|
||||
name: "ProxiFyre".to_string(),
|
||||
install_dir: root.join("ProxiFyre"),
|
||||
executable_path: root.join("ProxiFyre").join("ProxiFyre.exe"),
|
||||
config_path: Some(root.join("ProxiFyre").join("app-config.json")),
|
||||
running: false,
|
||||
service_name: Some("ProxiFyreService".to_string()),
|
||||
service_status: Some("stopped".to_string()),
|
||||
};
|
||||
|
||||
let script = commands::wrap_elevated_package_script(
|
||||
&commands::uninstall_proxifyre_script(Some(&detected)),
|
||||
&root.join("uninstall.log"),
|
||||
);
|
||||
let script_path = root.join("uninstall.ps1");
|
||||
let mut script_bytes = vec![0xEF, 0xBB, 0xBF];
|
||||
script_bytes.extend_from_slice(script.as_bytes());
|
||||
fs::write(&script_path, script_bytes).expect("script should be written");
|
||||
|
||||
let escaped_path = script_path.display().to_string().replace('\'', "''");
|
||||
let parser = format!(
|
||||
"$tokens = $null; $errors = $null; [System.Management.Automation.Language.Parser]::ParseFile('{escaped_path}', [ref]$tokens, [ref]$errors) | Out-Null; if ($errors.Count -gt 0) {{ $errors | ForEach-Object {{ $_.Message }}; exit 1 }}"
|
||||
);
|
||||
let output = ProcessCommand::new("powershell")
|
||||
.args(["-NoProfile", "-NonInteractive", "-Command", &parser])
|
||||
.output()
|
||||
.expect("powershell parser should run");
|
||||
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"uninstall script should parse\nstdout:\n{}\nstderr:\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr),
|
||||
);
|
||||
|
||||
cleanup(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxifyre_uninstall_script_removes_packet_filter_after_proxifyre() {
|
||||
let detected = DetectedProxyfier {
|
||||
engine: ProxyfierEngine::ProxiFyre,
|
||||
name: "ProxiFyre".to_string(),
|
||||
install_dir: PathBuf::from(r"C:\Tools\ProxiFyre"),
|
||||
executable_path: PathBuf::from(r"C:\Tools\ProxiFyre\ProxiFyre.exe"),
|
||||
config_path: Some(PathBuf::from(r"C:\Tools\ProxiFyre\app-config.json")),
|
||||
running: true,
|
||||
service_name: Some("ProxiFyreService".to_string()),
|
||||
service_status: Some("running".to_string()),
|
||||
};
|
||||
let script = commands::uninstall_proxifyre_script(Some(&detected));
|
||||
|
||||
assert!(script.contains("function Resolve-MsiProductCode($program, [string]$label)"));
|
||||
assert!(script.contains("Отказываюсь запускать произвольный UninstallString"));
|
||||
assert!(script.contains("Start-Process -FilePath 'msiexec.exe'"));
|
||||
assert!(script.contains("ArgumentList @('/x', $productCode, '/qn', '/norestart'"));
|
||||
assert!(script.contains("Uninstall-MsiProgram $packetFilter 'Windows Packet Filter'"));
|
||||
let proxifyre_step = script
|
||||
.find("Write-ProxyWardenProgress 'uninstall' 'proxifyre'")
|
||||
.expect("proxifyre uninstall step should be present");
|
||||
let packet_filter_step = script
|
||||
.find("Write-ProxyWardenProgress 'uninstall' 'packet-filter'")
|
||||
.expect("packet filter uninstall step should be present");
|
||||
assert!(proxifyre_step < packet_filter_step);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn singbox_runner_preserves_installer_args_with_spaces() {
|
||||
let script = commands::singbox_installer_runner_script(
|
||||
@@ -287,15 +420,16 @@ fn singbox_runner_preserves_installer_args_with_spaces() {
|
||||
Path::new(r"C:\ProgramData\ProxyWarden\state\install.log"),
|
||||
&[
|
||||
"-InstallRoot".to_string(),
|
||||
r"C:\Program Files\ProxyWarden\sing-box".to_string(),
|
||||
r"C:\Program Files\ProxyWarden\components\sing-box".to_string(),
|
||||
"-ServiceName".to_string(),
|
||||
"ProxyWardenSingBox".to_string(),
|
||||
"-Uninstall".to_string(),
|
||||
],
|
||||
);
|
||||
|
||||
assert!(script
|
||||
.contains("$installerArgs = @('-InstallRoot', 'C:\\Program Files\\ProxyWarden\\sing-box'"));
|
||||
assert!(script.contains(
|
||||
"$installerArgs = @('-InstallRoot', 'C:\\Program Files\\ProxyWarden\\components\\sing-box'"
|
||||
));
|
||||
assert!(script.contains(
|
||||
"& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installerPath @installerArgs"
|
||||
));
|
||||
@@ -390,6 +524,7 @@ fn component_status_merges_detected_existing_proxifyre() {
|
||||
config_path: Some(PathBuf::from(r"C:\Tools\ProxiFyre\app-config.json")),
|
||||
running: true,
|
||||
service_name: Some("ProxiFyreService".to_string()),
|
||||
service_status: Some("running".to_string()),
|
||||
}),
|
||||
None,
|
||||
);
|
||||
@@ -540,8 +675,8 @@ impl ProxyfierDetectionHost for DetectionHost {
|
||||
false
|
||||
}
|
||||
|
||||
fn service_running(&self, _service_name: &str) -> bool {
|
||||
false
|
||||
fn service_status(&self, _service_name: &str) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn registry_install_entries(&self) -> Vec<RegistryInstallEntry> {
|
||||
@@ -625,6 +760,8 @@ fn proxyfier_running() -> ComponentStatus {
|
||||
running: true,
|
||||
version: Some("2.2.1".to_string()),
|
||||
path: Some(r"C:\Tools\ProxiFyre".to_string()),
|
||||
service_name: Some("ProxiFyreService".to_string()),
|
||||
service_status: Some("running".to_string()),
|
||||
problems: Vec::new(),
|
||||
actions: vec!["Restart".to_string()],
|
||||
}
|
||||
@@ -639,6 +776,8 @@ fn singbox_missing() -> ComponentStatus {
|
||||
running: false,
|
||||
version: None,
|
||||
path: None,
|
||||
service_name: Some("ProxyWardenSingBox".to_string()),
|
||||
service_status: None,
|
||||
problems: vec!["Локальный sing-box не установлен".to_string()],
|
||||
actions: vec!["Установить локальный sing-box".to_string()],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user