Files
ProxyWarden/src-tauri/tests/helper_tests.rs

135 lines
4.7 KiB
Rust

use proxywarden_lib::helper::{
helper_action_requires_elevation, install_request, parse_helper_response,
proxifyre_apply_request, service_request, HelperAction, HelperCommandOutput,
HelperCommandRunner, HelperCommandSpec, HelperError, HelperResponse, StructuredHelper,
};
use proxywarden_lib::models::ComponentId;
use serde_json::json;
use std::cell::RefCell;
use std::path::PathBuf;
#[test]
fn structured_helper_serializes_request_and_parses_json_response() {
let runner = MockRunner {
output: HelperCommandOutput {
status_code: 0,
stdout: serde_json::to_string(&HelperResponse {
success: true,
action: HelperAction::ProxyfierApply,
changed: true,
message: "Applied".to_string(),
details: json!({ "serviceName": "ProxiFyreService" }),
})
.expect("response json"),
stderr: String::new(),
},
seen: RefCell::new(Vec::new()),
};
let helper = StructuredHelper::new("proxywarden-helper.exe", runner);
let response = helper
.execute(&proxifyre_apply_request(
r"C:\ProgramData\ProxyWarden\generated\proxifyre-app-config.json",
"ProxiFyreService",
))
.expect("helper response");
assert!(response.success);
assert_eq!(response.action, HelperAction::ProxyfierApply);
assert_eq!(response.details["serviceName"], "ProxiFyreService");
}
#[test]
fn helper_runner_receives_json_stdin_and_elevation_flag() {
let runner = MockRunner {
output: HelperCommandOutput {
status_code: 0,
stdout: r#"{"success":true,"action":"service.restart","changed":true,"message":"Restarted","details":{}}"#.to_string(),
stderr: String::new(),
},
seen: RefCell::new(Vec::new()),
};
let helper = StructuredHelper::new("proxywarden-helper.exe", runner);
let request = service_request(ComponentId::Proxyfier, HelperAction::ServiceRestart);
let _ = helper.execute(&request).expect("helper response");
let seen = helper.runner().seen.borrow();
let spec = seen.first().expect("runner should be called");
let stdin: serde_json::Value = serde_json::from_str(&spec.stdin).expect("stdin json");
assert_eq!(spec.program, PathBuf::from("proxywarden-helper.exe"));
assert_eq!(spec.args, vec!["--json"]);
assert!(spec.requires_elevation);
assert_eq!(stdin["action"], "service.restart");
assert_eq!(stdin["component"], "proxyfier");
}
#[test]
fn install_requests_are_explicit_component_actions() {
let control = install_request(ComponentId::ControlApp);
let proxyfier = install_request(ComponentId::Proxyfier);
let singbox = install_request(ComponentId::Singbox);
assert_eq!(control.action, HelperAction::InstallControlApp);
assert_eq!(proxyfier.action, HelperAction::InstallProxyfier);
assert_eq!(singbox.action, HelperAction::InstallSingbox);
assert!(helper_action_requires_elevation(&proxyfier.action));
}
#[test]
fn apply_request_does_not_encode_installer_action() {
let request = proxifyre_apply_request(
r"C:\ProgramData\ProxyWarden\generated\proxifyre-app-config.json",
"ProxiFyreService",
);
assert_eq!(request.action, HelperAction::ProxyfierApply);
assert_eq!(request.component, Some(ComponentId::Proxyfier));
assert_eq!(
request.payload["configPath"],
r"C:\ProgramData\ProxyWarden\generated\proxifyre-app-config.json"
);
}
#[test]
fn non_json_helper_stdout_is_rejected() {
let error = parse_helper_response("Proxyfier restarted successfully")
.expect_err("raw stdout should not be accepted");
assert_eq!(error.code, "helper_response_decode");
}
#[test]
fn failed_helper_exit_is_structured_error() {
let runner = MockRunner {
output: HelperCommandOutput {
status_code: 5,
stdout: String::new(),
stderr: "Access denied".to_string(),
},
seen: RefCell::new(Vec::new()),
};
let helper = StructuredHelper::new("proxywarden-helper.exe", runner);
let error = helper
.execute(&service_request(
ComponentId::Proxyfier,
HelperAction::ServiceRestart,
))
.expect_err("failed exit should become helper error");
assert_eq!(error.code, "helper_exit");
assert!(error.message.contains("Access denied"));
}
struct MockRunner {
output: HelperCommandOutput,
seen: RefCell<Vec<HelperCommandSpec>>,
}
impl HelperCommandRunner for MockRunner {
fn run(&self, spec: &HelperCommandSpec) -> Result<HelperCommandOutput, HelperError> {
self.seen.borrow_mut().push(spec.clone());
Ok(self.output.clone())
}
}