Refactor application structure and simplify implementation

This commit is contained in:
2026-07-22 00:08:09 +03:00
parent dbba3806cc
commit 90b2eb507c
74 changed files with 11362 additions and 6814 deletions
+64 -3
View File
@@ -91,6 +91,7 @@ fn blocks_config_when_server_is_not_selected() {
let adapter = SingBoxAdapter::default();
let mut config = local_singbox_config("nl-1");
config.selected_server_tag = None;
config.selected_server_id = None;
let cache = subscription_cache();
let checker = RecordingChecker::ok("should not run");
@@ -108,8 +109,9 @@ fn blocks_config_when_server_is_not_selected() {
#[test]
fn blocks_config_when_selected_outbound_is_missing() {
let adapter = SingBoxAdapter::default();
let config = local_singbox_config("missing-server");
let cache = subscription_cache();
let config = local_singbox_config("nl-1");
let mut cache = subscription_cache();
cache.config = serde_json::json!({ "outbounds": [] });
let checker = RecordingChecker::ok("should not run");
let error = adapter
@@ -120,10 +122,67 @@ fn blocks_config_when_selected_outbound_is_missing() {
.expect_err("missing outbound should block config");
assert_eq!(error.kind, SingBoxConfigErrorKind::MissingSelectedOutbound);
assert!(error.message.contains("missing-server"));
assert!(error.message.contains("nl-1"));
assert!(checker.calls.borrow().is_empty());
}
#[test]
fn duplicate_tags_generate_the_outbound_selected_by_stable_id() {
let adapter = SingBoxAdapter::default();
let mut config = local_singbox_config("shared-name");
config.selected_server_id = Some("vless|shared-name|second.example.test|8443".to_string());
let cache = SubscriptionCache {
config: serde_json::json!({
"outbounds": [
{
"type": "vless",
"tag": "shared-name",
"server": "first.example.test",
"server_port": 443,
"uuid": "11111111-1111-1111-1111-111111111111"
},
{
"type": "vless",
"tag": "shared-name",
"server": "second.example.test",
"server_port": 8443,
"uuid": "22222222-2222-2222-2222-222222222222"
}
]
}),
servers: vec![
SubscriptionServer {
id: "vless|shared-name|first.example.test|443".to_string(),
tag: "shared-name".to_string(),
server_type: "vless".to_string(),
server: "first.example.test".to_string(),
server_port: 443,
},
SubscriptionServer {
id: "vless|shared-name|second.example.test|8443".to_string(),
tag: "shared-name".to_string(),
server_type: "vless".to_string(),
server: "second.example.test".to_string(),
server_port: 8443,
},
],
user_info: serde_json::Map::new(),
fetched_at: "2026-07-11T00:00:00Z".to_string(),
};
let generated = adapter
.generate_config(
SingBoxGenerationRequest::new(&config, &cache, None),
&RecordingChecker::ok("not used"),
)
.expect("stable id should resolve the second duplicate tag");
let value: serde_json::Value =
serde_json::from_str(&generated.contents).expect("generated config should parse");
assert_eq!(value["outbounds"][0]["server"], "second.example.test");
assert_eq!(value["outbounds"][0]["server_port"], 8443);
}
#[test]
fn propagates_failed_singbox_check_as_structured_error() {
let adapter = SingBoxAdapter::default();
@@ -208,6 +267,7 @@ fn local_singbox_config(selected_server_tag: &str) -> LocalSingBoxConfig {
subscription_url: Some("https://sub.example.test/list".to_string()),
device_hwid: None,
selected_server_tag: Some(selected_server_tag.to_string()),
selected_server_id: Some(format!("vless|{selected_server_tag}|nl.example.test|443")),
listen_host: "127.0.0.1".to_string(),
listen_port: 1080,
service_name: "ProxyWardenSingBox".to_string(),
@@ -234,6 +294,7 @@ fn subscription_cache() -> SubscriptionCache {
]
}),
servers: vec![SubscriptionServer {
id: "vless|nl-1|nl.example.test|443".to_string(),
tag: "nl-1".to_string(),
server_type: "vless".to_string(),
server: "nl.example.test".to_string(),