From 51aa201e71ea7a45711d17f0b9de8dccd6a45dc8 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Fri, 16 Oct 2026 14:36:06 -0700 Subject: [PATCH 1/3] test(relay): reserve the unavailable auth endpoint Co-Authored-By: GPT-6 --- rs/moq-relay/tests/refusals.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/rs/moq-relay/tests/refusals.rs b/rs/moq-relay/tests/refusals.rs index bd9e54f18d0..271fe2eb6d9 100644 --- a/rs/moq-relay/tests/refusals.rs +++ b/rs/moq-relay/tests/refusals.rs @@ -186,9 +186,19 @@ async fn lan_refusals_are_counted() { /// An auth server that cannot be reached is `unavailable`, apart from a refusal. #[tokio::test] async fn unavailable_auth_server_is_counted() { - let closed = std::net::TcpListener::bind("127.0.0.1:0").expect("reserve a port"); - let auth_url = format!("http://{}/", closed.local_addr().expect("reserved address")); - drop(closed); + // Binding without listening keeps the port reserved while refusing connections. + let closed = tokio::net::TcpSocket::new_v4().expect("auth socket"); + closed.bind("127.0.0.1:0".parse().unwrap()).expect("reserve auth port"); + let address = closed.local_addr().expect("reserved address"); + assert!(std::net::TcpListener::bind(address).is_err(), "auth port must stay reserved"); + assert_eq!( + tokio::net::TcpStream::connect(address) + .await + .expect_err("auth socket must refuse connections") + .kind(), + std::io::ErrorKind::ConnectionRefused, + ); + let auth_url = format!("http://{address}/"); let dir = tempfile::tempdir().expect("tempdir"); let mut config = config(dir.path(), false); From a88391d53a6485f2794a05a1d1c8956ee421ef21 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Fri, 16 Oct 2026 14:38:38 -0700 Subject: [PATCH 2/3] style(relay): format auth fixture assertion Co-Authored-By: GPT-6 --- rs/moq-relay/tests/refusals.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rs/moq-relay/tests/refusals.rs b/rs/moq-relay/tests/refusals.rs index 271fe2eb6d9..4672bb4e198 100644 --- a/rs/moq-relay/tests/refusals.rs +++ b/rs/moq-relay/tests/refusals.rs @@ -190,7 +190,10 @@ async fn unavailable_auth_server_is_counted() { let closed = tokio::net::TcpSocket::new_v4().expect("auth socket"); closed.bind("127.0.0.1:0".parse().unwrap()).expect("reserve auth port"); let address = closed.local_addr().expect("reserved address"); - assert!(std::net::TcpListener::bind(address).is_err(), "auth port must stay reserved"); + assert!( + std::net::TcpListener::bind(address).is_err(), + "auth port must stay reserved" + ); assert_eq!( tokio::net::TcpStream::connect(address) .await From 6b67a8194dee6f144c772bacf56c2365ad7ad8fc Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Fri, 16 Oct 2026 15:31:22 -0700 Subject: [PATCH 3/3] test(relay): close unavailable auth connections portably Co-Authored-By: GPT-6 --- rs/moq-relay/tests/refusals.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/rs/moq-relay/tests/refusals.rs b/rs/moq-relay/tests/refusals.rs index 4672bb4e198..d95f08816b0 100644 --- a/rs/moq-relay/tests/refusals.rs +++ b/rs/moq-relay/tests/refusals.rs @@ -183,25 +183,27 @@ async fn lan_refusals_are_counted() { relay.stop().await; } -/// An auth server that cannot be reached is `unavailable`, apart from a refusal. +/// An auth server whose connection fails is `unavailable`, apart from a refusal. #[tokio::test] async fn unavailable_auth_server_is_counted() { - // Binding without listening keeps the port reserved while refusing connections. - let closed = tokio::net::TcpSocket::new_v4().expect("auth socket"); - closed.bind("127.0.0.1:0".parse().unwrap()).expect("reserve auth port"); - let address = closed.local_addr().expect("reserved address"); + // Listen to reserve the port on every OS, then hang up before answering HTTP. + let listener = tokio::net::TcpListener::bind("127.0.0.1:0") + .await + .expect("auth listener"); + let address = listener.local_addr().expect("reserved address"); assert!( std::net::TcpListener::bind(address).is_err(), "auth port must stay reserved" ); - assert_eq!( - tokio::net::TcpStream::connect(address) - .await - .expect_err("auth socket must refuse connections") - .kind(), - std::io::ErrorKind::ConnectionRefused, - ); + let mut tasks = tokio::task::JoinSet::new(); + tasks.spawn(async move { + loop { + let (stream, _) = listener.accept().await.expect("accept auth connection"); + drop(stream); + } + }); let auth_url = format!("http://{address}/"); + assert!(reqwest::get(&auth_url).await.is_err(), "auth endpoint must fail HTTP"); let dir = tempfile::tempdir().expect("tempdir"); let mut config = config(dir.path(), false);