diff options
Diffstat (limited to 'tests/integration/harness.rs')
| -rw-r--r-- | tests/integration/harness.rs | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/tests/integration/harness.rs b/tests/integration/harness.rs index c015fa8..b985971 100644 --- a/tests/integration/harness.rs +++ b/tests/integration/harness.rs @@ -1,11 +1,8 @@ -use governor::{Quota, RateLimiter}; use std::collections::HashMap; -use std::num::NonZeroU32; use std::path::PathBuf; -use std::sync::Arc; +use std::sync::{Arc, RwLock}; use tempfile::TempDir; -use tokio::net::TcpListener; -use tokio::sync::{RwLock, oneshot}; +use tiny_http::Server; use witryna::build_guard::BuildScheduler; use witryna::config::{BuildOverrides, Config, SiteConfig}; use witryna::polling::PollingManager; @@ -18,18 +15,14 @@ pub struct TestServer { /// Kept alive for RAII cleanup of the config file written during startup. #[allow(dead_code)] pub tempdir: TempDir, - shutdown_tx: Option<oneshot::Sender<()>>, + server: Arc<Server>, + server_thread: Option<std::thread::JoinHandle<()>>, } impl TestServer { /// Start a new test server with the given config. /// Binds to `127.0.0.1:0` (OS-assigned port). - pub async fn start(config: Config) -> Self { - Self::start_with_rate_limit(config, 1000).await - } - - /// Start a new test server with a specific rate limit. - pub async fn start_with_rate_limit(mut config: Config, rate_limit: u32) -> Self { + pub async fn start(mut config: Config) -> Self { let tempdir = TempDir::new().expect("failed to create temp dir"); let config_path = tempdir.path().join("witryna.toml"); @@ -44,38 +37,50 @@ impl TestServer { .await .expect("failed to resolve secrets"); - let quota = Quota::per_minute(NonZeroU32::new(rate_limit).expect("rate limit must be > 0")); - let state = AppState { config: Arc::new(RwLock::new(config)), config_path: Arc::new(config_path), build_scheduler: Arc::new(BuildScheduler::new()), - rate_limiter: Arc::new(RateLimiter::dashmap(quota)), polling_manager: Arc::new(PollingManager::new()), }; - let listener = TcpListener::bind("127.0.0.1:0") - .await - .expect("failed to bind to random port"); - let port = listener.local_addr().unwrap().port(); + let server = Arc::new(Server::http("127.0.0.1:0").expect("failed to bind")); + let port = match server.server_addr() { + tiny_http::ListenAddr::IP(addr) => addr.port(), + _ => unreachable!("expected IP address"), + }; let base_url = format!("http://127.0.0.1:{port}"); - let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>(); - - let server_state = state.clone(); - tokio::spawn(async move { - witryna::test_support::run_server(server_state, listener, async { - let _ = shutdown_rx.await; - }) - .await - .expect("server failed"); - }); + // Shutdown uses server.unblock() directly — no oneshot needed. + // We pass a future that never resolves; shutdown is triggered + // by calling server.unblock() from TestServer::shutdown(). + let server_thread = witryna::test_support::run_server( + state.clone(), + server.clone(), + std::future::pending(), + ); + + // Readiness probe: wait for server to accept connections + let client = reqwest::Client::new(); + for _ in 0..50 { + if client + .get(format!("{base_url}/health")) + .send() + .await + .map(|r| r.status().as_u16() == 200) + .unwrap_or(false) + { + break; + } + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + } Self { base_url, state, tempdir, - shutdown_tx: Some(shutdown_tx), + server, + server_thread: Some(server_thread), } } @@ -91,8 +96,11 @@ impl TestServer { /// Shut down the server gracefully. pub fn shutdown(&mut self) { - if let Some(tx) = self.shutdown_tx.take() { - let _ = tx.send(()); + // Unblock the HTTP request loop directly — no async channel needed + self.server.unblock(); + // Join the HTTP thread to ensure clean teardown + if let Some(handle) = self.server_thread.take() { + let _ = handle.join(); } } } @@ -112,7 +120,6 @@ pub fn test_config(base_dir: PathBuf) -> Config { base_dir, log_dir, log_level: "debug".to_owned(), - rate_limit_per_minute: 10, max_builds_to_keep: 5, git_timeout: None, sites: vec![], @@ -128,7 +135,6 @@ pub fn test_config_with_site(base_dir: PathBuf, site: SiteConfig) -> Config { base_dir, log_dir, log_level: "debug".to_owned(), - rate_limit_per_minute: 10, max_builds_to_keep: 5, git_timeout: None, sites: vec![site], @@ -144,7 +150,6 @@ pub fn test_config_with_sites(base_dir: PathBuf, sites: Vec<SiteConfig>) -> Conf base_dir, log_dir, log_level: "debug".to_owned(), - rate_limit_per_minute: 10, max_builds_to_keep: 5, git_timeout: None, sites, @@ -286,7 +291,6 @@ fn build_config_toml(config: &Config) -> String { {}base_dir = "{}" log_dir = "{}" log_level = "{}" -rate_limit_per_minute = {} max_builds_to_keep = {} "#, config.listen_address, @@ -294,7 +298,6 @@ max_builds_to_keep = {} config.base_dir.display(), config.log_dir.display(), config.log_level, - config.rate_limit_per_minute, config.max_builds_to_keep, ); |
