Skip to content

Commit 72f1764

Browse files
committed
test: Use atomic counter with random base for port allocation
Avoid intra-process port collisions between parallel tests by using an atomic counter that increments by 2 for each allocation. The base port is randomized once per process to reduce inter-process collisions. This eliminates the birthday-paradox collisions that occurred when every call independently picked a random port from the range. AI tools were used in preparing this commit.
1 parent cdc77a2 commit 72f1764

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

tests/common/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::collections::{HashMap, HashSet};
1414
use std::env;
1515
use std::future::Future;
1616
use std::path::PathBuf;
17+
use std::sync::atomic::{AtomicU16, Ordering};
1718
use std::sync::{Arc, RwLock};
1819
use std::time::Duration;
1920

@@ -273,9 +274,21 @@ pub(crate) fn random_storage_path() -> PathBuf {
273274
temp_path
274275
}
275276

277+
static NEXT_PORT: AtomicU16 = AtomicU16::new(0);
278+
276279
pub(crate) fn random_listening_addresses() -> Vec<SocketAddress> {
277-
let mut rng = rng();
278-
let port = rng.random_range(10000..65000u16);
280+
// Use an atomic counter to avoid intra-process collisions between parallel tests.
281+
// The base port is randomized once per process to avoid inter-process collisions.
282+
let port = NEXT_PORT
283+
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |p| {
284+
if p == 0 {
285+
let base = rng().random_range(10000..50000u16);
286+
Some(base + 2)
287+
} else {
288+
Some(p + 2)
289+
}
290+
})
291+
.unwrap_or_else(|p| p);
279292
vec![
280293
SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port },
281294
SocketAddress::TcpIpV4 { addr: [127, 0, 0, 1], port: port + 1 },

0 commit comments

Comments
 (0)