diff --git a/crates/hodeishield-api/tests/api.rs b/crates/hodeishield-api/tests/api.rs index 5e5d391..4be6f57 100644 --- a/crates/hodeishield-api/tests/api.rs +++ b/crates/hodeishield-api/tests/api.rs @@ -585,17 +585,18 @@ fn a_503_with_retry_after_longer_than_max_wait_does_not_retry() { #[test] fn a_connection_error_is_retried() { - // Bind to port 0 to get an ephemeral port, then drop the listener to free it. - // The next connection attempt to that port will be refused. + // Keep the listener bound for the whole test so no other test can take the port. It never + // accepts, so every attempt connects (the kernel completes the handshake) and then gets no + // answer: a timeout, which is retried like a refused connection. let listener = std::net::TcpListener::bind(("127.0.0.1", 0)).expect("bind"); let port = listener.local_addr().expect("addr").port(); - drop(listener); let url = format!("http://127.0.0.1:{port}"); let retry_count = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0)); let counted = std::sync::Arc::clone(&retry_count); let result = Client::builder(url.parse().expect("url"), SecretString::from("hsk_example")) + .timeout(Duration::from_millis(200)) .transient_retries(2, Duration::from_millis(1)) .retry_observer(move |_event| { counted.fetch_add(1, std::sync::atomic::Ordering::SeqCst); @@ -608,6 +609,7 @@ fn a_connection_error_is_retried() { assert!(matches!(result.expect_err("error"), Error::Transport(_))); let retries = retry_count.load(std::sync::atomic::Ordering::SeqCst); assert_eq!(retries, 2, "should have retried exactly 2 times"); + drop(listener); } #[test]