From 2f74574332558c4af7c38ecb4da43a66c6596dd9 Mon Sep 17 00:00:00 2001 From: zackees Date: Sun, 23 Aug 2026 20:15:17 -0700 Subject: [PATCH] fix(test): stop asserting a freed ephemeral port stays free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `tcp_readiness_distinguishes_live_and_free_endpoints` failed on a macOS runner, on a PR touching only fbuild-library: assertion failed: !tcp_endpoint_ready(address, Duration::from_millis(100)).await The probe was right and the test was wrong. `tcp_endpoint_ready` is a plain connect-with-timeout, so reporting "ready" means something genuinely accepted. Once the listener is dropped the port returns to the ephemeral pool and the OS may hand it to anyone — including a sibling test in the same binary calling `bind_tcp_listener("127.0.0.1:0")`, since these run in parallel. The test asserted a property the OS does not guarantee, then blamed the probe when the OS exercised its freedom. The live half is sound as a single sample: we hold the listener, so nothing else can answer. Only the dead half needed changing — it now retries with a freshly-bound-then-dropped port each attempt. A real defect in the probe fails all eight; a port-reuse collision would have to win the race eight times running. Deliberately not a `>= `-style loosening of what is asserted: the assertion still fails if a closed endpoint ever reads as ready, which is the property worth having. What changed is the number of samples it takes before concluding that, because one sample cannot distinguish "probe is broken" from "someone took the port". Co-Authored-By: Claude Opus 5 (1M context) --- crates/fbuild-core/src/platform/ipc.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/fbuild-core/src/platform/ipc.rs b/crates/fbuild-core/src/platform/ipc.rs index 4653897cc..fcd6c63f4 100644 --- a/crates/fbuild-core/src/platform/ipc.rs +++ b/crates/fbuild-core/src/platform/ipc.rs @@ -166,11 +166,34 @@ mod tests { #[tokio::test] async fn tcp_readiness_distinguishes_live_and_free_endpoints() { + // Live endpoint: sound as a single sample. We hold the listener, so + // nothing else can be answering on it. let listener = bind_tcp_listener("127.0.0.1:0".parse().unwrap()).expect("bind ephemeral listener"); let address = listener.local_addr().expect("listener address"); assert!(tcp_endpoint_ready(address, Duration::from_millis(500)).await); drop(listener); - assert!(!tcp_endpoint_ready(address, Duration::from_millis(100)).await); + + // Dead endpoint: NOT sound as a single sample, which is what made + // this flaky on macOS runners. Once the listener is dropped the port + // returns to the ephemeral pool, and the OS is free to hand it to + // anyone — including a sibling test in this same binary calling + // `bind_tcp_listener("127.0.0.1:0")`. When that happened the probe + // correctly reported "ready" and the assertion blamed the probe. + // + // Retry with a freshly-bound-then-dropped port each time. A genuine + // defect in `tcp_endpoint_ready` fails every attempt; a port-reuse + // collision has to lose the race repeatedly, which it will not. + let mut address = address; + for attempt in 0..8 { + if !tcp_endpoint_ready(address, Duration::from_millis(100)).await { + return; + } + let listener = bind_tcp_listener("127.0.0.1:0".parse().unwrap()) + .unwrap_or_else(|error| panic!("rebind on attempt {attempt}: {error}")); + address = listener.local_addr().expect("listener address"); + drop(listener); + } + panic!("a closed endpoint reported ready on every attempt — probe is not detecting death"); } }