205 lines
7.0 KiB
Rust
205 lines
7.0 KiB
Rust
use proxywarden_lib::adapters::proxifyre::{
|
|
ProxiFyreAdapter, ProxiFyreConfig, PROXIFYRE_OUTPUT_FILE,
|
|
};
|
|
use proxywarden_lib::adapters::proxy_router::{
|
|
ProxyRouterAdapter, ProxyRouterErrorKind, ProxyRouterRequest,
|
|
};
|
|
use proxywarden_lib::models::{
|
|
ComponentId, ComponentState, ComponentStatus, Profile, ProfileItem, ProfileItemType, Protocol,
|
|
ProxyProtocol, Target, TargetKind,
|
|
};
|
|
|
|
#[test]
|
|
fn generates_proxifyre_config_for_discord_external_socks5_target() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let profiles = vec![discord_profile("home-gateway")];
|
|
let targets = vec![external_socks5_target()];
|
|
let components = vec![missing_singbox_component()];
|
|
|
|
let generated = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect("external socks5 target should not require sing-box");
|
|
let config: ProxiFyreConfig =
|
|
serde_json::from_str(&generated.contents).expect("generated config json");
|
|
|
|
assert_eq!(generated.adapter_id, "proxifyre");
|
|
assert_eq!(generated.output_file_name, PROXIFYRE_OUTPUT_FILE);
|
|
assert_eq!(generated.enabled_profiles, 1);
|
|
assert_eq!(generated.routed_apps, 1);
|
|
assert_eq!(config.log_level, "Info");
|
|
assert!(config.bypass_lan);
|
|
assert_eq!(config.proxies.len(), 1);
|
|
assert_eq!(config.proxies[0].app_names, vec!["Discord"]);
|
|
assert_eq!(
|
|
config.proxies[0].socks5_proxy_endpoint,
|
|
"192.168.50.111:8080"
|
|
);
|
|
assert_eq!(config.proxies[0].supported_protocols, vec!["TCP", "UDP"]);
|
|
}
|
|
|
|
#[test]
|
|
fn skips_disabled_profiles_when_generating_proxifyre_config() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let mut disabled = discord_profile("home-gateway");
|
|
disabled.enabled = false;
|
|
let profiles = vec![disabled];
|
|
let targets = vec![external_socks5_target()];
|
|
let components = Vec::new();
|
|
|
|
let generated = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect("disabled profiles should produce empty config");
|
|
let config: ProxiFyreConfig =
|
|
serde_json::from_str(&generated.contents).expect("generated config json");
|
|
|
|
assert_eq!(generated.enabled_profiles, 0);
|
|
assert_eq!(generated.routed_apps, 0);
|
|
assert!(config.proxies.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn includes_folder_paths_when_generating_proxifyre_config() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let mut profile = discord_profile("home-gateway");
|
|
profile.items.push(ProfileItem {
|
|
item_type: ProfileItemType::Folder,
|
|
value: r"C:\Games\MyGame".to_string(),
|
|
recursive: true,
|
|
});
|
|
let profiles = vec![profile];
|
|
let targets = vec![external_socks5_target()];
|
|
let components = Vec::new();
|
|
|
|
let generated = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect("folder paths should be accepted by ProxiFyre config generation");
|
|
let config: ProxiFyreConfig =
|
|
serde_json::from_str(&generated.contents).expect("generated config json");
|
|
|
|
assert_eq!(generated.routed_apps, 2);
|
|
assert_eq!(
|
|
config.proxies[0].app_names,
|
|
vec!["Discord", r"C:\Games\MyGame"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn blocks_local_singbox_target_when_required_component_is_missing() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let profiles = vec![discord_profile("local-singbox")];
|
|
let targets = vec![local_singbox_target()];
|
|
let components = Vec::new();
|
|
|
|
let error = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect_err("local sing-box target should require installed running sing-box");
|
|
|
|
assert_eq!(error.kind, ProxyRouterErrorKind::MissingRequiredComponent);
|
|
}
|
|
|
|
#[test]
|
|
fn local_singbox_target_generates_when_required_component_is_running() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let profiles = vec![discord_profile("local-singbox")];
|
|
let targets = vec![local_singbox_target()];
|
|
let components = vec![running_singbox_component()];
|
|
|
|
let generated = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect("running sing-box should satisfy local target dependency");
|
|
let config: ProxiFyreConfig =
|
|
serde_json::from_str(&generated.contents).expect("generated config json");
|
|
|
|
assert_eq!(config.proxies.len(), 1);
|
|
assert_eq!(config.proxies[0].socks5_proxy_endpoint, "127.0.0.1:1080");
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_http_target_because_proxifyre_adapter_is_socks5_only() {
|
|
let adapter = ProxiFyreAdapter::default();
|
|
let profiles = vec![discord_profile("office-http")];
|
|
let targets = vec![Target {
|
|
id: "office-http".to_string(),
|
|
name: "Office HTTP".to_string(),
|
|
kind: TargetKind::External,
|
|
protocol: ProxyProtocol::Http,
|
|
host: "192.168.50.111".to_string(),
|
|
port: 3128,
|
|
requires_component: None,
|
|
}];
|
|
let components = Vec::new();
|
|
|
|
let error = adapter
|
|
.generate_config(ProxyRouterRequest::new(&profiles, &targets, &components))
|
|
.expect_err("ProxiFyre should reject HTTP targets");
|
|
|
|
assert_eq!(error.kind, ProxyRouterErrorKind::UnsupportedTargetProtocol);
|
|
}
|
|
|
|
fn discord_profile(target_id: &str) -> Profile {
|
|
Profile {
|
|
id: "discord".to_string(),
|
|
name: "Discord".to_string(),
|
|
enabled: true,
|
|
target_id: target_id.to_string(),
|
|
protocols: vec![Protocol::Tcp, Protocol::Udp],
|
|
items: vec![ProfileItem {
|
|
item_type: ProfileItemType::Process,
|
|
value: "Discord".to_string(),
|
|
recursive: false,
|
|
}],
|
|
}
|
|
}
|
|
|
|
fn external_socks5_target() -> Target {
|
|
Target {
|
|
id: "home-gateway".to_string(),
|
|
name: "Home Gateway".to_string(),
|
|
kind: TargetKind::External,
|
|
protocol: ProxyProtocol::Socks5,
|
|
host: "192.168.50.111".to_string(),
|
|
port: 8080,
|
|
requires_component: None,
|
|
}
|
|
}
|
|
|
|
fn local_singbox_target() -> Target {
|
|
Target {
|
|
id: "local-singbox".to_string(),
|
|
name: "Local sing-box".to_string(),
|
|
kind: TargetKind::Local,
|
|
protocol: ProxyProtocol::Socks5,
|
|
host: "127.0.0.1".to_string(),
|
|
port: 1080,
|
|
requires_component: Some(ComponentId::Singbox),
|
|
}
|
|
}
|
|
|
|
fn missing_singbox_component() -> ComponentStatus {
|
|
ComponentStatus {
|
|
id: ComponentId::Singbox,
|
|
name: "Local sing-box".to_string(),
|
|
state: ComponentState::Missing,
|
|
installed: false,
|
|
running: false,
|
|
version: None,
|
|
path: None,
|
|
problems: vec!["Local sing-box is not installed".to_string()],
|
|
actions: vec!["Install Local sing-box".to_string()],
|
|
}
|
|
}
|
|
|
|
fn running_singbox_component() -> ComponentStatus {
|
|
ComponentStatus {
|
|
id: ComponentId::Singbox,
|
|
name: "Local sing-box".to_string(),
|
|
state: ComponentState::Running,
|
|
installed: true,
|
|
running: true,
|
|
version: Some("1.11.0".to_string()),
|
|
path: Some(r"C:\Tools\ProxyWarden\sing-box\sing-box.exe".to_string()),
|
|
problems: Vec::new(),
|
|
actions: vec!["Restart".to_string(), "Stop".to_string()],
|
|
}
|
|
}
|