mirror of
https://github.com/nimbold/Firelink.git
synced 2026-09-01 13:38:01 +00:00
b5ee53140d
- admit valid magnets immediately while keeping metadata refresh optional - fence Torrent recovery, diagnostics, and allocation presentation by lifecycle - avoid false peer-wait claims when telemetry is missing or malformed - stabilize Properties metric label/value layout for narrow and RTL windows Tests: - npm test -- --run - npm run build - npm run check:i18n - node --test scripts/*.node-test.js - cargo test --all-targets - npm run smoke:torrent - npm run smoke:torrent:failure-paths - git diff --check
126 lines
4.5 KiB
Rust
126 lines
4.5 KiB
Rust
use firelink_lib::ipc::{TorrentFile, TorrentWebSeed};
|
|
use firelink_lib::queue::{
|
|
clamp_download_connections, normalize_aria2_disk_cache, normalize_torrent_bind_address,
|
|
normalize_torrent_dht_message_timeout, normalize_torrent_file_allocation,
|
|
normalize_torrent_web_seeds, EnqueueItem, QueueManager, SpawnPayload,
|
|
};
|
|
use firelink_lib::retry::{backoff_for, is_permanent_network_error, network_error_class};
|
|
use std::time::Duration;
|
|
|
|
#[test]
|
|
fn headless_queue_contracts_reject_unsafe_inputs_and_preserve_bounds() {
|
|
assert_eq!(clamp_download_connections(0), 1);
|
|
assert_eq!(clamp_download_connections(99), 16);
|
|
assert_eq!(normalize_aria2_disk_cache(Some(" 32m ")).unwrap(), "32M");
|
|
assert!(normalize_aria2_disk_cache(Some("0K")).is_err());
|
|
assert_eq!(
|
|
normalize_torrent_bind_address(Some(" 2001:db8::1 ")).unwrap(),
|
|
Some("2001:db8::1".to_string())
|
|
);
|
|
assert!(normalize_torrent_bind_address(Some("not-an-ip")).is_err());
|
|
assert_eq!(normalize_torrent_dht_message_timeout(60).unwrap(), 60);
|
|
assert!(normalize_torrent_dht_message_timeout(61).is_err());
|
|
assert_eq!(normalize_torrent_file_allocation(None).unwrap(), "prealloc");
|
|
assert!(normalize_torrent_file_allocation(Some("sparse")).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn headless_torrent_web_seed_contract_deduplicates_and_expands_per_file() {
|
|
let files = vec![
|
|
TorrentFile {
|
|
index: 1,
|
|
path: "folder/one.bin".to_string(),
|
|
length: 10,
|
|
},
|
|
TorrentFile {
|
|
index: 2,
|
|
path: "two.bin".to_string(),
|
|
length: 20,
|
|
},
|
|
];
|
|
let seeds = vec![
|
|
TorrentWebSeed {
|
|
file_index: 1,
|
|
uri: "https://mirror.example/base".to_string(),
|
|
},
|
|
TorrentWebSeed {
|
|
file_index: 1,
|
|
uri: "https://mirror.example/base".to_string(),
|
|
},
|
|
];
|
|
let normalized = normalize_torrent_web_seeds(Some(&seeds), &files).unwrap();
|
|
assert_eq!(normalized.len(), 1);
|
|
let expanded = firelink_lib::queue::expand_torrent_web_seeds(&normalized, &files).unwrap();
|
|
assert_eq!(
|
|
expanded,
|
|
vec![(1, "https://mirror.example/base/folder/one.bin".to_string())]
|
|
);
|
|
|
|
let credentialed = [TorrentWebSeed {
|
|
file_index: 1,
|
|
uri: "https://user:pass@mirror.example/file".to_string(),
|
|
}];
|
|
assert!(normalize_torrent_web_seeds(Some(&credentialed), &files).is_err());
|
|
let unknown_file = [TorrentWebSeed {
|
|
file_index: 3,
|
|
uri: "https://mirror.example/file".to_string(),
|
|
}];
|
|
assert!(normalize_torrent_web_seeds(Some(&unknown_file), &files).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn headless_enqueue_contract_strips_torrent_credentials_before_task_creation() {
|
|
let item = EnqueueItem {
|
|
id: "torrent".to_string(),
|
|
queue_id: "main".to_string(),
|
|
url: "https://example.test/file.torrent".to_string(),
|
|
destination: "/tmp".to_string(),
|
|
filename: "file.torrent".to_string(),
|
|
username: Some("user".to_string()),
|
|
password: Some("secret".to_string()),
|
|
headers: Some("Cookie: session=secret".to_string()),
|
|
cookies: Some("session=secret".to_string()),
|
|
is_torrent: Some(true),
|
|
..EnqueueItem::default()
|
|
};
|
|
let task = item.into_task();
|
|
assert!(task.payload.username.is_none());
|
|
assert!(task.payload.password.is_none());
|
|
assert!(task.payload.headers.is_none());
|
|
assert!(task.payload.cookies.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn headless_queue_lifecycle_eligibility_and_retry_contracts_hold() {
|
|
assert!(QueueManager::<tauri::Wry>::aria2_allocation_phase_eligible(
|
|
&SpawnPayload::default()
|
|
));
|
|
assert!(
|
|
!QueueManager::<tauri::Wry>::aria2_allocation_phase_eligible(&SpawnPayload {
|
|
is_media: true,
|
|
..SpawnPayload::default()
|
|
})
|
|
);
|
|
assert!(
|
|
!QueueManager::<tauri::Wry>::aria2_allocation_phase_eligible(&SpawnPayload {
|
|
is_torrent: true,
|
|
torrent_file_allocation: Some("none".to_string()),
|
|
..SpawnPayload::default()
|
|
})
|
|
);
|
|
assert!(
|
|
!QueueManager::<tauri::Wry>::aria2_allocation_phase_eligible(&SpawnPayload {
|
|
is_torrent: true,
|
|
torrent_file_allocation: Some("prealloc".to_string()),
|
|
..SpawnPayload::default()
|
|
})
|
|
);
|
|
assert_eq!(backoff_for(0), Duration::from_secs(2));
|
|
assert_eq!(backoff_for(usize::MAX), Duration::from_secs(10));
|
|
assert_eq!(
|
|
network_error_class("HTTP/1.1 503 Service Unavailable"),
|
|
"http"
|
|
);
|
|
assert!(is_permanent_network_error("HTTP 403 Forbidden"));
|
|
}
|