From 92ec4a9479e3f638807e7f15da484b3c2ea459e8 Mon Sep 17 00:00:00 2001 From: Noam Meltzer Date: Fri, 3 Jan 2025 10:37:12 +0200 Subject: [PATCH] test_proxy_connection: make test more robust (#390) - Support running on macos with podman (this probably also fixes it to work with docker as well). This is done by using a dedicated network name and by dynamically finding the host ip. In macos, both podman & docker are running inside a Linux VM, so it is essential to find a real IP associated with the macos itself. - Run the mock TCP server on a dynamic port. This avoid flakiness in case the port is already in use. --- Cargo.lock | 53 ++++++++++++++++++++++++++++++++----- Cargo.toml | 4 +++ src/protocols/tcp/server.rs | 29 +++++++++++++++----- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 570e76f..61e26d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,7 +333,7 @@ dependencies = [ "tokio-util", "tower-service", "url", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -365,6 +365,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +[[package]] +name = "c_linked_list" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" + [[package]] name = "cc" version = "1.2.5" @@ -545,7 +551,7 @@ dependencies = [ "rustix", "signal-hook", "signal-hook-mio", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -554,7 +560,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -936,6 +942,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + [[package]] name = "generic-array" version = "0.14.7" @@ -946,6 +958,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "get_if_addrs" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" +dependencies = [ + "c_linked_list", + "get_if_addrs-sys", + "libc", + "winapi 0.2.8", +] + +[[package]] +name = "get_if_addrs-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" +dependencies = [ + "gcc", + "libc", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1105,7 +1139,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1198,7 +1232,7 @@ dependencies = [ "pin-project-lite", "tokio", "tower-service", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1762,7 +1796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3240,6 +3274,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -3478,6 +3518,7 @@ dependencies = [ "fastwebsockets", "fdlimit", "futures-util", + "get_if_addrs", "hickory-resolver", "http-body-util", "hyper", diff --git a/Cargo.toml b/Cargo.toml index 47e6414..69858d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,10 @@ rstest = "0.23.0" serial_test = "3.2.0" derive_more = { version = "1.0.0", features = ["from"] } +[target.'cfg(target_os = "macos")'.dev-dependencies] +get_if_addrs = "0.5.3" + + [profile.release] lto = "fat" panic = "abort" diff --git a/src/protocols/tcp/server.rs b/src/protocols/tcp/server.rs index 1d09dde..4ff0c47 100644 --- a/src/protocols/tcp/server.rs +++ b/src/protocols/tcp/server.rs @@ -233,7 +233,7 @@ mod tests { use super::*; use futures_util::pin_mut; use std::borrow::Cow; - use std::net::SocketAddr; + use std::net::IpAddr; use testcontainers::core::WaitFor; use testcontainers::runners::AsyncRunner; use testcontainers::{ContainerAsync, Image, ImageExt}; @@ -263,15 +263,30 @@ mod tests { #[tokio::test] async fn test_proxy_connection() { - let server_addr: SocketAddr = "[::1]:1236".parse().unwrap(); - let server = TcpListener::bind(server_addr).await.unwrap(); + let (network_name, host) = if cfg!(not(target_os = "macos")) { + ("host", "127.0.0.1".parse::().unwrap()) + } else { + let host = get_if_addrs::get_if_addrs() + .unwrap() + .into_iter() + .map(|iface| iface.addr.ip()) + .find(|ip| ip.is_ipv4() && !ip.is_loopback()) + .unwrap(); + ("wstunnel_test_proxy_connection", host) + }; + + let mitm_proxy: ContainerAsync = MitmProxy.with_network(network_name).start().await.unwrap(); + + let proxy_port = mitm_proxy.get_host_port_ipv4(8080).await.unwrap(); - let _mitm_proxy: ContainerAsync = MitmProxy.with_network("host".to_string()).start().await.unwrap(); + // bind to a dynamic port - avoid conflicts + let server = TcpListener::bind((host, 0)).await.unwrap(); + let server_port = server.local_addr().unwrap().port(); let mut client = connect_with_http_proxy( - &"http://localhost:8080".parse().unwrap(), - &Host::Domain("[::1]".to_string()), - 1236, + &Url::parse(&format!("http://127.0.0.1:{proxy_port}")).unwrap(), + &Host::Domain(host.to_string()), + server_port, None, Duration::from_secs(1), &DnsResolver::System,