use super::*; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; fn nonempty_line_count(text: &str) -> usize { text.lines().filter(|line| !line.trim().is_empty()).count() } #[test] fn subtle_stress_single_unknown_dc_under_concurrency_logs_once() { let _guard = unknown_dc_test_lock() .lock() .expect("unknown dc test lock must be available"); clear_unknown_dc_log_cache_for_testing(); let winners = Arc::new(AtomicUsize::new(0)); let mut workers = Vec::new(); for _ in 0..128 { let winners = Arc::clone(&winners); workers.push(std::thread::spawn(move || { if should_log_unknown_dc(31_333) { winners.fetch_add(1, Ordering::Relaxed); } })); } for worker in workers { worker.join().expect("worker must not panic"); } assert_eq!(winners.load(Ordering::Relaxed), 1); } #[test] fn subtle_light_fuzz_scope_hint_matches_oracle() { fn oracle(input: &str) -> bool { let Some(rest) = input.strip_prefix("scope_") else { return false; }; !rest.is_empty() && rest.len() <= MAX_SCOPE_HINT_LEN && rest .bytes() .all(|b| b.is_ascii_alphanumeric() || b == b'-') } let mut state: u64 = 0xC0FF_EE11_D15C_AFE5; for _ in 0..4_096 { state ^= state << 7; state ^= state >> 9; state ^= state << 8; let len = (state as usize % 72) + 1; let mut s = String::with_capacity(len + 6); if (state & 1) == 0 { s.push_str("scope_"); } else { s.push_str("user_"); } for idx in 0..len { let v = ((state >> ((idx % 8) * 8)) & 0xff) as u8; let ch = match v % 6 { 0 => (b'a' + (v % 26)) as char, 1 => (b'A' + (v % 26)) as char, 2 => (b'0' + (v % 10)) as char, 3 => '-', 4 => '_', _ => '.', }; s.push(ch); } let got = validated_scope_hint(&s).is_some(); assert_eq!(got, oracle(&s), "mismatch for input: {s}"); } } #[test] fn subtle_light_fuzz_dc_resolution_never_panics_and_preserves_port() { let mut state: u64 = 0x1234_5678_9ABC_DEF0; for _ in 0..2_048 { state ^= state << 13; state ^= state >> 7; state ^= state << 17; let mut cfg = ProxyConfig::default(); cfg.network.prefer = if (state & 1) == 0 { 4 } else { 6 }; cfg.network.ipv6 = Some((state & 2) != 0); cfg.default_dc = Some(((state >> 8) as u8).max(1)); let dc_idx = (state as i16).wrapping_sub(16_384); let resolved = get_dc_addr_static(dc_idx, &cfg).expect("dc resolution must never fail"); assert_eq!(resolved.port(), crate::protocol::constants::TG_DATACENTER_PORT); let expect_v6 = cfg.network.prefer == 6 && cfg.network.ipv6.unwrap_or(true); assert_eq!(resolved.is_ipv6(), expect_v6); } } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn subtle_integration_parallel_same_dc_logs_one_line() { let _guard = unknown_dc_test_lock() .lock() .expect("unknown dc test lock must be available"); clear_unknown_dc_log_cache_for_testing(); let rel_dir = format!("target/telemt-direct-relay-same-{}", std::process::id()); let rel_file = format!("{rel_dir}/unknown-dc.log"); let abs_dir = std::env::current_dir() .expect("cwd must be available") .join(&rel_dir); std::fs::create_dir_all(&abs_dir).expect("log directory must be creatable"); let abs_file = abs_dir.join("unknown-dc.log"); let _ = std::fs::remove_file(&abs_file); let mut cfg = ProxyConfig::default(); cfg.general.unknown_dc_file_log_enabled = true; cfg.general.unknown_dc_log_path = Some(rel_file); let cfg = Arc::new(cfg); let mut tasks = Vec::new(); for _ in 0..32 { let cfg = Arc::clone(&cfg); tasks.push(tokio::spawn(async move { let _ = get_dc_addr_static(31_777, cfg.as_ref()); })); } for task in tasks { task.await.expect("task must not panic"); } for _ in 0..60 { if let Ok(content) = std::fs::read_to_string(&abs_file) && nonempty_line_count(&content) == 1 { return; } tokio::time::sleep(std::time::Duration::from_millis(20)).await; } let content = std::fs::read_to_string(&abs_file).unwrap_or_default(); assert_eq!(nonempty_line_count(&content), 1); } #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn subtle_integration_parallel_unique_dcs_log_unique_lines() { let _guard = unknown_dc_test_lock() .lock() .expect("unknown dc test lock must be available"); clear_unknown_dc_log_cache_for_testing(); let rel_dir = format!("target/telemt-direct-relay-unique-{}", std::process::id()); let rel_file = format!("{rel_dir}/unknown-dc.log"); let abs_dir = std::env::current_dir() .expect("cwd must be available") .join(&rel_dir); std::fs::create_dir_all(&abs_dir).expect("log directory must be creatable"); let abs_file = abs_dir.join("unknown-dc.log"); let _ = std::fs::remove_file(&abs_file); let mut cfg = ProxyConfig::default(); cfg.general.unknown_dc_file_log_enabled = true; cfg.general.unknown_dc_log_path = Some(rel_file); let cfg = Arc::new(cfg); let dcs = [31_901_i16, 31_902, 31_903, 31_904, 31_905, 31_906, 31_907, 31_908]; let mut tasks = Vec::new(); for dc in dcs { let cfg = Arc::clone(&cfg); tasks.push(tokio::spawn(async move { let _ = get_dc_addr_static(dc, cfg.as_ref()); })); } for task in tasks { task.await.expect("task must not panic"); } for _ in 0..80 { if let Ok(content) = std::fs::read_to_string(&abs_file) && nonempty_line_count(&content) >= 8 { return; } tokio::time::sleep(std::time::Duration::from_millis(20)).await; } let content = std::fs::read_to_string(&abs_file).unwrap_or_default(); assert!( nonempty_line_count(&content) >= 8, "expected at least one line per unique dc, content: {content}" ); }