diff --git a/tests/helpers.h b/tests/helpers.h index bdc9685..65a07c4 100644 --- a/tests/helpers.h +++ b/tests/helpers.h @@ -17,6 +17,8 @@ static int trace(int rc, const char *str) { static int require(int expect_rc, int got_rc, const char *str) { if (expect_rc != got_rc) { printf("REQUIRED(%s) failed: wanted=%d, got=%d\n", str, expect_rc, got_rc); + fflush(stdout); + fflush(stderr); abort(); } return got_rc; diff --git a/tests/runner.rs b/tests/runner.rs index 372f38b..fdc5604 100644 --- a/tests/runner.rs +++ b/tests/runner.rs @@ -320,13 +320,13 @@ fn ciphers() { #[test] #[ignore] fn server() { - let (port, port_str) = choose_port(); - fn curl(port: u16) { Command::new("curl") .env("LD_LIBRARY_PATH", "") .args([ "-v", + "--header", + "Host: localhost", "--cacert", "test-ca/rsa/ca.cert", &format!("https://localhost:{port}/"), @@ -342,7 +342,7 @@ fn server() { .env("LD_LIBRARY_PATH", "") .args([ "target/server", - &port_str, + "0", "test-ca/rsa/server.key", "test-ca/rsa/server.cert", "unauth", @@ -352,7 +352,7 @@ fn server() { .spawn() .unwrap(), )); - wait_for_stdout(openssl_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut openssl_server, "openssl server"); curl(port); let openssl_output = print_output(openssl_server.wait_with_timeout()); @@ -361,7 +361,7 @@ fn server() { Command::new("tests/maybe-valgrind.sh") .args([ "target/server", - &port_str, + "0", "test-ca/rsa/server.key", "test-ca/rsa/server.cert", "unauth", @@ -371,7 +371,7 @@ fn server() { .spawn() .unwrap(), )); - wait_for_stdout(rustls_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut rustls_server, "rustls server"); curl(port); let rustls_output = print_output(rustls_server.wait_with_timeout()); @@ -382,7 +382,7 @@ fn server() { .env("LD_LIBRARY_PATH", "") .args([ "target/server", - &port_str, + "0", "test-ca/rsa/server.key", "test-ca/rsa/server.cert", "unauth", @@ -392,7 +392,7 @@ fn server() { .spawn() .unwrap(), )); - wait_for_stdout(openssl_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut openssl_server, "openssl server"); curl(port); let openssl_output = print_output(openssl_server.wait_with_timeout()); @@ -401,7 +401,7 @@ fn server() { Command::new("tests/maybe-valgrind.sh") .args([ "target/server", - &port_str, + "0", "test-ca/rsa/server.key", "test-ca/rsa/server.cert", "unauth", @@ -411,7 +411,7 @@ fn server() { .spawn() .unwrap(), )); - wait_for_stdout(rustls_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut rustls_server, "rustls server"); curl(port); 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) .unwrap(); } - let (port, port_str) = choose_port(); - let mut openssl_server = KillOnDrop(Some( Command::new("tests/maybe-valgrind.sh") .env("LD_LIBRARY_PATH", "") .args([ "target/server", - &port_str, + "0", &format!("test-ca/{key_type}/server.key"), &format!("test-ca/{key_type}/server.cert"), "unauth", @@ -457,7 +455,7 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str) .spawn() .unwrap(), )); - wait_for_stdout(openssl_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut openssl_server, "openssl server"); connect(port, key_type, sig_algs, version_flag); 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) Command::new("tests/maybe-valgrind.sh") .args([ "target/server", - &port_str, + "0", &format!("test-ca/{key_type}/server.key"), &format!("test-ca/{key_type}/server.cert"), "unauth", @@ -476,7 +474,7 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str) .spawn() .unwrap(), )); - wait_for_stdout(rustls_server.0.as_mut().unwrap(), b"listening\n"); + let port = wait_for_port_announcement(&mut rustls_server, "rustls server"); connect(port, key_type, sig_algs, version_flag); let rustls_output = print_output(rustls_server.wait_with_timeout()); @@ -485,16 +483,61 @@ fn server_with_key_algorithm(key_type: &str, sig_algs: &str, version_flag: &str) #[test] #[ignore] -fn server_key_algorithms() { +fn server_key_algorithm_rsa_pss_rsae_sha256() { server_with_key_algorithm("rsa", "rsa_pss_rsae_sha256", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_rsa_pss_rsae_sha384() { server_with_key_algorithm("rsa", "rsa_pss_rsae_sha384", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_rsa_pss_rsae_sha512() { server_with_key_algorithm("rsa", "rsa_pss_rsae_sha512", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_rsa_pkcs1_sha256() { server_with_key_algorithm("rsa", "rsa_pkcs1_sha256", "-tls1_2"); +} + +#[test] +#[ignore] +fn server_key_algorithm_rsa_pkcs1_sha384() { server_with_key_algorithm("rsa", "rsa_pkcs1_sha384", "-tls1_2"); +} + +#[test] +#[ignore] +fn server_key_algorithm_rsa_pkcs1_sha512() { server_with_key_algorithm("rsa", "rsa_pkcs1_sha512", "-tls1_2"); +} + +#[test] +#[ignore] +fn server_key_algorithm_ed25519() { server_with_key_algorithm("ed25519", "ed25519", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_ecdsa_secp256r1_sha256() { server_with_key_algorithm("ecdsa-p256", "ecdsa_secp256r1_sha256", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_ecdsa_secp384r1_sha384() { server_with_key_algorithm("ecdsa-p384", "ecdsa_secp384r1_sha384", "-tls1_3"); +} + +#[test] +#[ignore] +fn server_key_algorithm_ecdsa_secp521r1_sha512() { server_with_key_algorithm("ecdsa-p521", "ecdsa_secp521r1_sha512", "-tls1_3"); } @@ -793,33 +836,42 @@ fn wait_for_port(port: u16) -> Option<()> { } } -/// Read from the `Child`'s `stdout` until the string `expected` is seen. +/// Read from the `Child`'s `stdout` until it says which port is is listening on. /// /// To ensure this function can be used several times in succession /// on a given `Child`, this must not read bytes from its `stdout` /// that appear after `expected`. -fn wait_for_stdout(stream: &mut Child, expected: &[u8]) { - let mut buffer = Vec::with_capacity(128); +fn wait_for_port_announcement(proc: &mut KillOnDrop, which: &str) -> u16 { + let mut buffer = String::new(); + let child = proc.0.as_mut().unwrap(); + + let expected = "listening on "; loop { let mut input = [0u8]; - let new = stream.stdout.as_mut().unwrap().read(&mut input).unwrap(); - assert_eq!(new, 1, "stdout EOF -- read so far {buffer:?}"); - buffer.push(input[0]); + let new = child.stdout.as_mut().unwrap().read(&mut input).unwrap(); + if new != 1 { + println!("{which} child stdout premature EOF -- read so far {buffer:?}"); + print_output(proc.take_inner().wait_with_output().unwrap()); + panic!(); + } + buffer.push(input[0] as char); - if buffer.ends_with(expected) { - return; + if buffer.contains(expected) && buffer.ends_with("\n") { + let last_line = buffer.lines().last().unwrap(); + let port = last_line.strip_prefix(expected).unwrap(); + return port.parse().unwrap(); } assert!( buffer.len() < 128, - "{expected:?} did not appear in first part of {stream:?} (instead it was {buffer:?}" + "{expected:?} did not appear in first part of {which} {child:?} (instead it was {buffer:?}" ); - match stream.try_wait() { - Ok(Some(status)) => panic!("process exited already with {status}"), + match child.try_wait() { + Ok(Some(status)) => panic!("{which} process exited already with {status}"), Ok(None) => {} - Err(e) => panic!("subprocess broken {e:?}"), + Err(e) => panic!("{which} subprocess broken {e:?}"), }; } } diff --git a/tests/server.c b/tests/server.c index 4d05565..c2ff776 100644 --- a/tests/server.c +++ b/tests/server.c @@ -116,7 +116,9 @@ int main(int argc, char **argv) { us.sin_port = htons(atoi(port)); REQUIRE(0, bind(listener, (struct sockaddr *)&us, sizeof(us))); REQUIRE(0, listen(listener, 5)); - printf("listening\n"); + socklen_t us_len = sizeof(us); + REQUIRE(0, getsockname(listener, (struct sockaddr *)&us, &us_len)); + printf("listening on %d\n", ntohs(us.sin_port)); fflush(stdout); socklen_t them_len = sizeof(them); int sock = TRACE(accept(listener, (struct sockaddr *)&them, &them_len));