From 32a29c89f265cc820717c1f3ddd83c2fb33082cb Mon Sep 17 00:00:00 2001 From: c4ch3c4d3 <23181631+c4ch3c4d3@users.noreply.github.com> Date: Thu, 4 Jun 2026 08:29:24 -0600 Subject: [PATCH] feat: fix flaky generate test and format tunnel.rs - Fix race condition in generate test temp_dir() by using PID + atomic counter instead of nanosecond timestamps that collide under parallel test execution - Apply cargo fmt to tunnel.rs for consistent formatting Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- src/generate.rs | 11 +++--- src/tunnel.rs | 102 ++++++++++++++++++------------------------------ 2 files changed, 43 insertions(+), 70 deletions(-) diff --git a/src/generate.rs b/src/generate.rs index a2b35ea..c33125c 100644 --- a/src/generate.rs +++ b/src/generate.rs @@ -200,12 +200,13 @@ mod tests { use crate::redact; fn temp_dir() -> std::path::PathBuf { + // Use process ID + monotonic counter to avoid collisions when tests run in parallel + static COUNTER: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); + let unique = COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed); std::env::temp_dir().join(format!( - "rustunnel_generate_test_{}", - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap_or_default() - .as_nanos() + "rustunnel_generate_test_{}_{}", + std::process::id(), + unique )) } diff --git a/src/tunnel.rs b/src/tunnel.rs index b727294..78c7cfe 100644 --- a/src/tunnel.rs +++ b/src/tunnel.rs @@ -2552,8 +2552,7 @@ mod tests { }); // Start listener - let bind_addr: SocketAddr = - format!("127.0.0.1:{}", listener_port).parse().unwrap(); + let bind_addr: SocketAddr = format!("127.0.0.1:{}", listener_port).parse().unwrap(); let listener_config = ListenerConfig { bind_addr, server_cert_path: path_arc!(dir.path().join("server.crt")), @@ -2561,13 +2560,11 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let listener_task = - tokio::spawn(async move { run_listener(listener_config).await }); + let listener_task = tokio::spawn(async move { run_listener(listener_config).await }); tokio::time::sleep(std::time::Duration::from_millis(200)).await; // Start connector with SOCKS5 (has reconnect loop built-in) - let socks_addr: SocketAddr = - format!("127.0.0.1:{}", socks_port).parse().unwrap(); + let socks_addr: SocketAddr = format!("127.0.0.1:{}", socks_port).parse().unwrap(); let connector_config = ConnectorConfig { target_host: "127.0.0.1".to_string(), target_port: listener_port, @@ -2576,9 +2573,10 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let connector_task = tokio::spawn(async move { - run_connector_with_socks(connector_config, socks_addr).await - }); + let connector_task = + tokio::spawn( + async move { run_connector_with_socks(connector_config, socks_addr).await }, + ); tokio::time::sleep(std::time::Duration::from_millis(400)).await; // Step 1: Verify initial connection works @@ -2599,8 +2597,7 @@ mod tests { tokio::time::sleep(std::time::Duration::from_millis(200)).await; // Step 3: Restart listener - let bind_addr2: SocketAddr = - format!("127.0.0.1:{}", listener_port).parse().unwrap(); + let bind_addr2: SocketAddr = format!("127.0.0.1:{}", listener_port).parse().unwrap(); let listener_config2 = ListenerConfig { bind_addr: bind_addr2, server_cert_path: path_arc!(dir.path().join("server.crt")), @@ -2608,8 +2605,7 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let listener_task2 = - tokio::spawn(async move { run_listener(listener_config2).await }); + let listener_task2 = tokio::spawn(async move { run_listener(listener_config2).await }); tokio::time::sleep(std::time::Duration::from_millis(200)).await; // Step 4: Wait for reconnect loop to re-establish the tunnel @@ -2664,11 +2660,7 @@ mod tests { // Abort should cause graceful shutdown within reasonable time handle.abort(); - let result = tokio::time::timeout( - std::time::Duration::from_secs(3), - handle, - ) - .await; + let result = tokio::time::timeout(std::time::Duration::from_secs(3), handle).await; assert!( result.is_ok(), @@ -2692,8 +2684,7 @@ mod tests { let socks_port = get_free_port(); // Start listener - let bind_addr: SocketAddr = - format!("127.0.0.1:{}", listener_port).parse().unwrap(); + let bind_addr: SocketAddr = format!("127.0.0.1:{}", listener_port).parse().unwrap(); let listener_config = ListenerConfig { bind_addr, server_cert_path: path_arc!(dir.path().join("server.crt")), @@ -2701,12 +2692,10 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let listener_task = - tokio::spawn(async move { run_listener(listener_config).await }); + let listener_task = tokio::spawn(async move { run_listener(listener_config).await }); // Start connector - let socks_addr: SocketAddr = - format!("127.0.0.1:{}", socks_port).parse().unwrap(); + let socks_addr: SocketAddr = format!("127.0.0.1:{}", socks_port).parse().unwrap(); let connector_config = ConnectorConfig { target_host: "127.0.0.1".to_string(), target_port: listener_port, @@ -2715,18 +2704,15 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let connector_task = tokio::spawn(async move { - run_connector_with_socks(connector_config, socks_addr).await - }); + let connector_task = + tokio::spawn( + async move { run_connector_with_socks(connector_config, socks_addr).await }, + ); tokio::time::sleep(std::time::Duration::from_millis(300)).await; // Abort connector — should shut down gracefully connector_task.abort(); - let result = tokio::time::timeout( - std::time::Duration::from_secs(3), - connector_task, - ) - .await; + let result = tokio::time::timeout(std::time::Duration::from_secs(3), connector_task).await; assert!( result.is_ok(), @@ -2773,8 +2759,7 @@ mod tests { }); // Start listener - let bind_addr: SocketAddr = - format!("127.0.0.1:{}", listener_port).parse().unwrap(); + let bind_addr: SocketAddr = format!("127.0.0.1:{}", listener_port).parse().unwrap(); let listener_config = ListenerConfig { bind_addr, server_cert_path: path_arc!(dir.path().join("server.crt")), @@ -2782,13 +2767,11 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let listener_task = - tokio::spawn(async move { run_listener(listener_config).await }); + let listener_task = tokio::spawn(async move { run_listener(listener_config).await }); tokio::time::sleep(std::time::Duration::from_millis(200)).await; // Start connector - let socks_addr: SocketAddr = - format!("127.0.0.1:{}", socks_port).parse().unwrap(); + let socks_addr: SocketAddr = format!("127.0.0.1:{}", socks_port).parse().unwrap(); let connector_config = ConnectorConfig { target_host: "127.0.0.1".to_string(), target_port: listener_port, @@ -2797,9 +2780,10 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let connector_task = tokio::spawn(async move { - run_connector_with_socks(connector_config, socks_addr).await - }); + let connector_task = + tokio::spawn( + async move { run_connector_with_socks(connector_config, socks_addr).await }, + ); tokio::time::sleep(std::time::Duration::from_millis(300)).await; // Open two concurrent streams and send unique data @@ -2828,11 +2812,8 @@ mod tests { // Now shutdown the connector connector_task.abort(); - let shutdown_result = tokio::time::timeout( - std::time::Duration::from_secs(3), - connector_task, - ) - .await; + let shutdown_result = + tokio::time::timeout(std::time::Duration::from_secs(3), connector_task).await; assert!( shutdown_result.is_ok(), "Connector should shut down gracefully even after active streams" @@ -2840,10 +2821,7 @@ mod tests { // Verify ports are released let socks_rebind = TcpListener::bind(socks_addr).await; - assert!( - socks_rebind.is_ok(), - "SOCKS5 port should be released" - ); + assert!(socks_rebind.is_ok(), "SOCKS5 port should be released"); // Cleanup listener_task.abort(); @@ -2860,8 +2838,7 @@ mod tests { let listener_port = get_free_port(); let socks_port = get_free_port(); - let bind_addr: SocketAddr = - format!("127.0.0.1:{}", listener_port).parse().unwrap(); + let bind_addr: SocketAddr = format!("127.0.0.1:{}", listener_port).parse().unwrap(); let listener_config = ListenerConfig { bind_addr, server_cert_path: path_arc!(dir.path().join("server.crt")), @@ -2869,12 +2846,10 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let listener_task = - tokio::spawn(async move { run_listener(listener_config).await }); + let listener_task = tokio::spawn(async move { run_listener(listener_config).await }); tokio::time::sleep(std::time::Duration::from_millis(200)).await; - let socks_addr: SocketAddr = - format!("127.0.0.1:{}", socks_port).parse().unwrap(); + let socks_addr: SocketAddr = format!("127.0.0.1:{}", socks_port).parse().unwrap(); let connector_config = ConnectorConfig { target_host: "127.0.0.1".to_string(), target_port: listener_port, @@ -2883,9 +2858,10 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new(token.clone()), }; - let connector_task = tokio::spawn(async move { - run_connector_with_socks(connector_config, socks_addr).await - }); + let connector_task = + tokio::spawn( + async move { run_connector_with_socks(connector_config, socks_addr).await }, + ); tokio::time::sleep(std::time::Duration::from_millis(400)).await; // The logs should have been emitted (tracing::info!) by the connector @@ -2924,8 +2900,7 @@ mod tests { ca_cert_path: path_arc!(dir.path().join("ca.pem")), auth_token: Arc::new("secret-token-abc".to_string()), }; - let listener_task = - tokio::spawn(async move { run_listener(listener_config).await }); + let listener_task = tokio::spawn(async move { run_listener(listener_config).await }); tokio::time::sleep(std::time::Duration::from_millis(200)).await; // Connect with wrong token @@ -2939,10 +2914,7 @@ mod tests { auth_token: Arc::new(bad_token.to_string()), }; let result = connect_tunnel(connector_config).await; - assert!( - result.is_err(), - "Bad auth token should fail to connect" - ); + assert!(result.is_err(), "Bad auth token should fail to connect"); // Verify error message doesn't leak the actual token values let err_msg = result.unwrap_err().to_string();