140 lines
4.7 KiB
Rust
140 lines
4.7 KiB
Rust
#[path = "../src/helper.rs"]
|
|
mod helper;
|
|
#[path = "../src/models.rs"]
|
|
mod models;
|
|
|
|
use helper::{
|
|
helper_action_requires_elevation, install_request, parse_helper_response,
|
|
proxifyre_apply_request, service_request, HelperAction, HelperCommandOutput,
|
|
HelperCommandRunner, HelperCommandSpec, HelperError, HelperResponse, StructuredHelper,
|
|
};
|
|
use 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())
|
|
}
|
|
}
|