From f1e6a2e0d6dbe4f7a14b3272e3789739aa1d7914 Mon Sep 17 00:00:00 2001 From: j-k Date: Tue, 8 Feb 2022 22:04:41 +0000 Subject: [PATCH] fix port collisions in tests (#143) Co-authored-by: Johann150 --- src/main.rs | 8 +- tests/README.md | 2 +- tests/tests.rs | 216 ++++++++++++++++-------------------------------- 3 files changed, 75 insertions(+), 151 deletions(-) diff --git a/src/main.rs b/src/main.rs index 36cca6d..51df626 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,8 @@ use { url::{Host, Url}, }; +static DEFAULT_PORT: u16 = 1965; + fn main() { env_logger::Builder::from_env( // by default only turn on logging for agate @@ -136,7 +138,7 @@ fn args() -> Result { opts.optmulti( "", "addr", - "Address to listen on (default 0.0.0.0:1965 and [::]:1965; muliple occurences means listening on multiple interfaces)", + &format!("Address to listen on (default 0.0.0.0:{} and [::]:{}; muliple occurences means listening on multiple interfaces)", DEFAULT_PORT, DEFAULT_PORT), "IP:PORT", ); opts.optmulti( @@ -288,8 +290,8 @@ fn args() -> Result { } if addrs.is_empty() { addrs = vec![ - SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 1965), - SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 1965), + SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), DEFAULT_PORT), + SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), DEFAULT_PORT), ]; } diff --git a/tests/README.md b/tests/README.md index d8112da..1e3bdac 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,5 +1,5 @@ # Tests for the Agate gemini server -This folder contains some tests and data used for these tests. Although care is taken to remove any interdependencies between these tests, these may happen. If you want to be on the safe side you could use `cargo test -- --test-threads=1` to run the tests sequentially. +This folder contains some tests and data used for these tests. Also note that you should **NEVER USE THE CERTIFICATE AND KEY DATA PROVIDED HERE** since it is public. diff --git a/tests/tests.rs b/tests/tests.rs index 24b70b3..6a163f8 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -5,21 +5,18 @@ use std::io::{BufRead, BufReader, Read}; use std::net::{SocketAddr, ToSocketAddrs}; use std::path::PathBuf; use std::process::{Command, Stdio}; +use std::sync::atomic::{AtomicU16, Ordering}; use url::Url; static BINARY_PATH: &str = env!("CARGO_BIN_EXE_agate"); -fn addr(port: u16) -> SocketAddr { - use std::net::{IpAddr, Ipv4Addr}; - - (IpAddr::V4(Ipv4Addr::LOCALHOST), port) - .to_socket_addrs() - .unwrap() - .next() - .unwrap() -} +static DEFAULT_PORT: u16 = 1965; +/// this is our atomic port that increments for each test that needs one +/// doing it this way avoids port collisions from manually setting ports +static PORT: AtomicU16 = AtomicU16::new(DEFAULT_PORT); struct Server { + addr: SocketAddr, server: std::process::Child, // is set when output is collected by stop() output: Option>, @@ -27,10 +24,24 @@ struct Server { impl Server { pub fn new(args: &[&str]) -> Self { + use std::net::{IpAddr, Ipv4Addr}; + + // generate unique port/address so tests do not clash + let addr = ( + IpAddr::V4(Ipv4Addr::LOCALHOST), + PORT.fetch_add(1, Ordering::SeqCst), + ) + .to_socket_addrs() + .unwrap() + .next() + .unwrap(); + // start the server let mut server = Command::new(BINARY_PATH) .stderr(Stdio::piped()) .current_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data")) + // add address information + .args(["--addr", &addr.to_string()]) .args(args) .env("RUST_LOG", "debug") .spawn() @@ -53,11 +64,16 @@ impl Server { } Self { + addr, server, output: None, } } + pub fn get_addr(&self) -> SocketAddr { + self.addr + } + pub fn stop(&mut self) -> Result<(), String> { // try to stop the server if let Some(output) = self.output.as_ref() { @@ -110,13 +126,13 @@ impl Drop for Server { } } -fn get(args: &[&str], addr: SocketAddr, url: &str) -> Result { +fn get(args: &[&str], url: &str) -> Result { let mut server = Server::new(args); // actually perform the request - let page = tokio::runtime::Runtime::new() - .unwrap() - .block_on(async { Page::fetch_from(&Url::parse(url).unwrap(), addr, None).await }); + let page = tokio::runtime::Runtime::new().unwrap().block_on(async { + Page::fetch_from(&Url::parse(url).unwrap(), server.get_addr(), None).await + }); server.stop().map_err(|e| anyhow!(e)).and(page) } @@ -125,7 +141,7 @@ fn get(args: &[&str], addr: SocketAddr, url: &str) -> Result