Skip to content

Commit 4875185

Browse files
committed
Have test server use kernel-allocated port
Formerly, the test runner chose a port for each server invocation, but this wasn't robust if the port it chose was already in use. Now the test runner asks for port zero, which means the kernel chooses an ephemeral port that is free. The server then prints the port it is listening on, and the runner parses that out. Remove the now-variable port sent by curl in the `Host:` header.
1 parent ff93d98 commit 4875185

File tree

2 files changed

+27
-23
lines changed

2 files changed

+27
-23
lines changed

tests/runner.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,13 @@ fn ciphers() {
320320
#[test]
321321
#[ignore]
322322
fn server() {
323-
let (port, port_str) = choose_port();
324-
325323
fn curl(port: u16) {
326324
Command::new("curl")
327325
.env("LD_LIBRARY_PATH", "")
328326
.args([
329327
"-v",
328+
"--header",
329+
"Host: localhost:port",
330330
"--cacert",
331331
"test-ca/rsa/ca.cert",
332332
&format!("https://localhost:{port}/"),
@@ -342,7 +342,7 @@ fn server() {
342342
.env("LD_LIBRARY_PATH", "")
343343
.args([
344344
"target/server",
345-
&port_str,
345+
"0",
346346
"test-ca/rsa/server.key",
347347
"test-ca/rsa/server.cert",
348348
"unauth",
@@ -352,7 +352,7 @@ fn server() {
352352
.spawn()
353353
.unwrap(),
354354
));
355-
wait_for_stdout(&mut openssl_server, "openssl server", b"listening\n");
355+
let port = wait_for_port_announcement(&mut openssl_server, "openssl server");
356356
curl(port);
357357

358358
let openssl_output = print_output(openssl_server.wait_with_timeout());
@@ -361,7 +361,7 @@ fn server() {
361361
Command::new("tests/maybe-valgrind.sh")
362362
.args([
363363
"target/server",
364-
&port_str,
364+
"0",
365365
"test-ca/rsa/server.key",
366366
"test-ca/rsa/server.cert",
367367
"unauth",
@@ -371,7 +371,7 @@ fn server() {
371371
.spawn()
372372
.unwrap(),
373373
));
374-
wait_for_stdout(&mut rustls_server, "rustls server", b"listening\n");
374+
let port = wait_for_port_announcement(&mut rustls_server, "rustls server");
375375
curl(port);
376376

377377
let rustls_output = print_output(rustls_server.wait_with_timeout());
@@ -382,7 +382,7 @@ fn server() {
382382
.env("LD_LIBRARY_PATH", "")
383383
.args([
384384
"target/server",
385-
&port_str,
385+
"0",
386386
"test-ca/rsa/server.key",
387387
"test-ca/rsa/server.cert",
388388
"unauth",
@@ -392,7 +392,7 @@ fn server() {
392392
.spawn()
393393
.unwrap(),
394394
));
395-
wait_for_stdout(&mut openssl_server, "openssl server", b"listening\n");
395+
let port = wait_for_port_announcement(&mut openssl_server, "openssl server");
396396
curl(port);
397397

398398
let openssl_output = print_output(openssl_server.wait_with_timeout());
@@ -401,7 +401,7 @@ fn server() {
401401
Command::new("tests/maybe-valgrind.sh")
402402
.args([
403403
"target/server",
404-
&port_str,
404+
"0",
405405
"test-ca/rsa/server.key",
406406
"test-ca/rsa/server.cert",
407407
"unauth",
@@ -411,7 +411,7 @@ fn server() {
411411
.spawn()
412412
.unwrap(),
413413
));
414-
wait_for_stdout(&mut rustls_server, "rustls server", b"listening\n");
414+
let port = wait_for_port_announcement(&mut rustls_server, "rustls server");
415415
curl(port);
416416

417417
let rustls_output = print_output(rustls_server.wait_with_timeout());
@@ -440,14 +440,12 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str)
440440
.unwrap();
441441
}
442442

443-
let (port, port_str) = choose_port();
444-
445443
let mut openssl_server = KillOnDrop(Some(
446444
Command::new("tests/maybe-valgrind.sh")
447445
.env("LD_LIBRARY_PATH", "")
448446
.args([
449447
"target/server",
450-
&port_str,
448+
"0",
451449
&format!("test-ca/{key_type}/server.key"),
452450
&format!("test-ca/{key_type}/server.cert"),
453451
"unauth",
@@ -457,7 +455,7 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str)
457455
.spawn()
458456
.unwrap(),
459457
));
460-
wait_for_stdout(&mut openssl_server, "openssl server", b"listening\n");
458+
let port = wait_for_port_announcement(&mut openssl_server, "openssl server");
461459
connect(port, key_type, sig_algs, version_flag);
462460

463461
let openssl_output = print_output(openssl_server.wait_with_timeout());
@@ -466,7 +464,7 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str)
466464
Command::new("tests/maybe-valgrind.sh")
467465
.args([
468466
"target/server",
469-
&port_str,
467+
"0",
470468
&format!("test-ca/{key_type}/server.key"),
471469
&format!("test-ca/{key_type}/server.cert"),
472470
"unauth",
@@ -476,7 +474,7 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str)
476474
.spawn()
477475
.unwrap(),
478476
));
479-
wait_for_stdout(&mut rustls_server, "rustls server", b"listening\n");
477+
let port = wait_for_port_announcement(&mut rustls_server, "rustls server");
480478
connect(port, key_type, sig_algs, version_flag);
481479

482480
let rustls_output = print_output(rustls_server.wait_with_timeout());
@@ -838,15 +836,17 @@ fn wait_for_port(port: u16) -> Option<()> {
838836
}
839837
}
840838

841-
/// Read from the `Child`'s `stdout` until the string `expected` is seen.
839+
/// Read from the `Child`'s `stdout` until it says which port is is listening on.
842840
///
843841
/// To ensure this function can be used several times in succession
844842
/// on a given `Child`, this must not read bytes from its `stdout`
845843
/// that appear after `expected`.
846-
fn wait_for_stdout(proc: &mut KillOnDrop, which: &str, expected: &[u8]) {
847-
let mut buffer = Vec::with_capacity(128);
844+
fn wait_for_port_announcement(proc: &mut KillOnDrop, which: &str) -> u16 {
845+
let mut buffer = String::new();
848846
let child = proc.0.as_mut().unwrap();
849847

848+
let expected = "listening on ";
849+
850850
loop {
851851
let mut input = [0u8];
852852
let new = child.stdout.as_mut().unwrap().read(&mut input).unwrap();
@@ -855,10 +855,12 @@ fn wait_for_stdout(proc: &mut KillOnDrop, which: &str, expected: &[u8]) {
855855
print_output(proc.take_inner().wait_with_output().unwrap());
856856
panic!();
857857
}
858-
buffer.push(input[0]);
858+
buffer.push(input[0] as char);
859859

860-
if buffer.ends_with(expected) {
861-
return;
860+
if buffer.contains(expected) && buffer.ends_with("\n") {
861+
let last_line = buffer.lines().last().unwrap();
862+
let port = last_line.get(expected.len()..).unwrap();
863+
return port.parse().unwrap();
862864
}
863865

864866
assert!(

tests/server.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ int main(int argc, char **argv) {
116116
us.sin_port = htons(atoi(port));
117117
REQUIRE(0, bind(listener, (struct sockaddr *)&us, sizeof(us)));
118118
REQUIRE(0, listen(listener, 5));
119-
printf("listening\n");
119+
socklen_t us_len = sizeof(us);
120+
REQUIRE(0, getsockname(listener, (struct sockaddr *)&us, &us_len));
121+
printf("listening on %d\n", ntohs(us.sin_port));
120122
fflush(stdout);
121123
socklen_t them_len = sizeof(them);
122124
int sock = TRACE(accept(listener, (struct sockaddr *)&them, &them_len));

0 commit comments

Comments
 (0)