Skip to content

Commit 03a83c2

Browse files
committed
Check for a free TCP port for the test to listen on.
1 parent 436a1ee commit 03a83c2

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

tests/server_test/mod.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,15 @@ mod shortcut;
6161

6262
use super::{HttpServer, HttpServerHandle};
6363
use std::io::Read;
64-
use std::net::SocketAddr;
64+
use std::net::{SocketAddr, TcpListener};
6565
use std::path::{Path, PathBuf};
6666
use std::process::{Child, Command, Stdio};
67-
use std::sync::atomic::AtomicU32;
67+
use std::sync::atomic::{AtomicU16, AtomicU32};
6868
use std::sync::{Arc, Mutex};
6969
use std::thread;
7070
use std::time::Duration;
7171
use triagebot::test_record::Activity;
7272

73-
/// TCP port that the triagebot binary should listen on.
74-
///
75-
/// Increases by 1 for each test.
76-
static NEXT_TCP_PORT: AtomicU32 = AtomicU32::new(50000);
7773
/// Counter used to give each test a unique sandbox directory in the
7874
/// `target/tmp` directory.
7975
static TEST_COUNTER: AtomicU32 = AtomicU32::new(1);
@@ -150,9 +146,7 @@ fn build(activities: Vec<Activity>) -> ServerTestCtx {
150146
setup_postgres(&db_dir);
151147

152148
let server = HttpServer::new(activities);
153-
// TODO: This is a poor way to choose a TCP port, as it could already
154-
// be in use by something else.
155-
let triagebot_port = NEXT_TCP_PORT.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
149+
let triagebot_port = next_triagebot_port();
156150
let mut child = Command::new(env!("CARGO_BIN_EXE_triagebot"))
157151
.env(
158152
"GITHUB_API_TOKEN",
@@ -375,3 +369,24 @@ fn find_postgres() -> PathBuf {
375369
Or, add them to your PATH."
376370
);
377371
}
372+
373+
/// Returns a free port for the next triagebot process to use.
374+
fn next_triagebot_port() -> u16 {
375+
static NEXT_TCP_PORT: AtomicU16 = AtomicU16::new(50000);
376+
loop {
377+
// This depends on SO_REUSEADDR being set.
378+
//
379+
// This is inherently racey, as the port may become unavailable
380+
// in-between the time it is checked here and triagebot actually binds
381+
// to it.
382+
//
383+
// TODO: This may not work on Windows, may need investigation/fixing.
384+
let triagebot_port = NEXT_TCP_PORT.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
385+
if triagebot_port == 0 {
386+
panic!("can't find port to listen on");
387+
}
388+
if TcpListener::bind(format!("127.0.0.1:{triagebot_port}")).is_ok() {
389+
return triagebot_port;
390+
}
391+
}
392+
}

0 commit comments

Comments
 (0)