From c8017eb14216eb1def35e787035d888630b32542 Mon Sep 17 00:00:00 2001 From: zealsham Date: Wed, 17 Dec 2025 23:18:24 +0100 Subject: [PATCH] Specifi nginx via environment variable or skip test This pr addresses #1227, it specifies an enironment variable for nginx which will be used during test run. it also removes nginxWithStream package from the dev shell. introduce error enum for nginx failures introduce error enum for nginx failures --- flake.nix | 2 +- ohttp-relay/tests/integration.rs | 82 +++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/flake.nix b/flake.nix index 6c7cab5eb..a607aa409 100644 --- a/flake.nix +++ b/flake.nix @@ -167,7 +167,6 @@ cargo-watch rust-analyzer dart - nginxWithStream ] ++ pkgs.lib.optionals (!pkgs.stdenv.isDarwin) [ cargo-llvm-cov @@ -218,6 +217,7 @@ partitionType = "count"; cargoExtraArgs = "--locked --all-features"; BITCOIND_EXE = nixpkgs.lib.getExe' pkgs.bitcoind "bitcoind"; + NGINX_EXE = nixpkgs.lib.getExe' nginxWithStream "nginx"; nativeBuildInputs = [ nginxWithStream ]; } diff --git a/ohttp-relay/tests/integration.rs b/ohttp-relay/tests/integration.rs index b00c779c6..2f0230061 100644 --- a/ohttp-relay/tests/integration.rs +++ b/ohttp-relay/tests/integration.rs @@ -63,9 +63,21 @@ mod integration { let n_http_port = find_free_port(); let n_https_port = find_free_port(); - let _nginx = - start_nginx(n_http_port, n_https_port, format!("0.0.0.0:{}", relay_port), nginx_cert) - .await; + let _nginx = match start_nginx( + n_http_port, + n_https_port, + format!("0.0.0.0:{}", relay_port), + nginx_cert, + ) + .await + { + Ok(nginx) => nginx, + Err(NginxInitError::NginxNotAvailable) => { + eprintln!("Skipping test: NGINX_EXE environment variable not set"); + return; + } + Err(e) => panic!("Failed to start nginx: {}", e), + }; tokio::select! { _ = example_gateway_http(gateway_port) => { panic!("Gateway is long running"); @@ -102,9 +114,21 @@ mod integration { }); let n_http_port = find_free_port(); let n_https_port = find_free_port(); - let _nginx = - start_nginx(n_http_port, n_https_port, format!("unix:{}", socket_path_str), nginx_cert) - .await?; + let _nginx = match start_nginx( + n_http_port, + n_https_port, + format!("unix:{}", socket_path_str), + nginx_cert, + ) + .await + { + Ok(nginx) => nginx, + Err(NginxInitError::NginxNotAvailable) => { + eprintln!("Skipping test: NGINX_EXE environment variable not set"); + return Ok(()); + } + Err(e) => return Err(Box::new(e) as Box), + }; tokio::select! { _ = example_gateway_http(gateway_port) => { panic!("Gateway is long running"); @@ -362,13 +386,21 @@ mod integration { }); let n_http_port = find_free_port(); let n_https_port = find_free_port(); - let _nginx = start_nginx( + let _nginx = match start_nginx( n_http_port, n_https_port, format!("0.0.0.0:{}", relay_port), nginx_cert, ) - .await; + .await + { + Ok(nginx) => nginx, + Err(NginxInitError::NginxNotAvailable) => { + eprintln!("Skipping test: NGINX_EXE environment variable not set"); + return; + } + Err(e) => panic!("Failed to start nginx: {}", e), + }; tokio::select! { _ = example_gateway_https(gateway_port, gateway_cert) => { panic!("Gateway is long running"); @@ -441,12 +473,13 @@ mod integration { struct NginxProcess { _child: tokio::process::Child, config_path: PathBuf, + nginx_exe: PathBuf, } impl Drop for NginxProcess { fn drop(&mut self) { // NGINX spawns child processes. Gracefully shut them all down. - let _ = std::process::Command::new("nginx") + let _ = std::process::Command::new(&self.nginx_exe) .arg("-s") .arg("stop") .arg("-c") @@ -455,14 +488,37 @@ mod integration { } } + #[derive(Debug)] + enum NginxInitError { + NginxNotAvailable, + UnknownError(Box), + } + + impl std::fmt::Display for NginxInitError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + NginxInitError::NginxNotAvailable => + write!(f, "NGINX_EXE environment variable not set - skipping nginx tests"), + NginxInitError::UnknownError(e) => write!(f, "Unknown error: {}", e), + } + } + } + + impl std::error::Error for NginxInitError {} + async fn start_nginx( n_http_port: u16, n_https_port: u16, proxy_pass: String, cert: Certificate, - ) -> Result> { + ) -> Result { use std::io::Write; + // Check for NGINX_EXE environment variable + let nginx_exe = std::env::var("NGINX_EXE") + .map(PathBuf::from) + .map_err(|_| NginxInitError::NginxNotAvailable)?; + let temp_dir = std::env::var("TMPDIR").unwrap_or_else(|_| "/tmp".into()); // Use Nix's TMPDIR let unique_suffix = uuid::Uuid::new_v4().to_string(); // Ensures uniqueness @@ -498,7 +554,7 @@ mod integration { NamedTempFile::new().expect("Failed to create temp file for nginx config"); writeln!(config_file, "{}", nginx_conf).expect("Failed to write nginx config"); let config_path = config_file.path().to_path_buf(); - let _child = Command::new("nginx") + let _child = Command::new(&nginx_exe) .arg("-c") .arg(config_path.as_os_str()) .spawn() @@ -512,14 +568,14 @@ mod integration { Err(_) if start_time.elapsed() < timeout => { tokio::time::sleep(std::time::Duration::from_millis(100)).await; } - Err(e) => return Err(Box::new(e)), + Err(e) => return Err(NginxInitError::UnknownError(Box::new(e))), } } // Keep the config file open as long as NGINX is using it std::mem::forget(config_file); - Ok(NginxProcess { _child, config_path }) + Ok(NginxProcess { _child, config_path, nginx_exe }) } fn full>(chunk: T) -> BoxBody {