diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2026-01-22 22:07:32 +0100 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2026-02-10 18:44:26 +0100 |
| commit | 064a1d01c5c14f5ecc032fa9b8346a4a88b893f6 (patch) | |
| tree | a2023f9ccd297ed8a41a3a0cc5699c2add09244d /src/test_support.rs | |
witryna 0.1.0 — initial releasev0.1.0
Minimalist Git-based static site deployment orchestrator.
Webhook-triggered builds in Podman/Docker containers with atomic
symlink publishing, SIGHUP hot-reload, and zero-downtime deploys.
See README.md for usage, CHANGELOG.md for details.
Diffstat (limited to 'src/test_support.rs')
| -rw-r--r-- | src/test_support.rs | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/test_support.rs b/src/test_support.rs new file mode 100644 index 0000000..8f2d2bf --- /dev/null +++ b/src/test_support.rs @@ -0,0 +1,72 @@ +//! Test support utilities shared between unit and integration tests. +//! +//! Gated behind `cfg(any(test, feature = "integration"))`. +//! Provides thin wrappers around `pub(crate)` server internals so integration +//! tests can start a real server on a random port without exposing internal APIs, +//! plus common helpers (temp dirs, cleanup) used across unit test modules. + +#![allow(clippy::unwrap_used, clippy::expect_used)] + +use crate::server::{AppState, run_with_listener}; +use anyhow::Result; +use std::path::{Path, PathBuf}; +use tokio::net::TcpListener; + +/// Start the HTTP server on the given listener, shutting down when `shutdown` resolves. +/// +/// The server behaves identically to production — same middleware, same handlers. +/// +/// # Errors +/// +/// Returns an error if the server encounters a fatal I/O error. +pub async fn run_server( + state: AppState, + listener: TcpListener, + shutdown: impl std::future::Future<Output = ()> + Send + 'static, +) -> Result<()> { + run_with_listener(state, listener, shutdown).await +} + +/// Install the SIGHUP configuration-reload handler for `state`. +/// +/// Call this before sending SIGHUP in tests that exercise hot-reload. +/// It replaces the default signal disposition (terminate) with the production +/// reload handler, so the process stays alive after receiving the signal. +pub fn setup_sighup_handler(state: &AppState) { + crate::server::setup_sighup_handler(state.clone()); +} + +/// Generate a unique ID for test isolation (timestamp + counter). +/// +/// # Panics +/// +/// Panics if the system clock is before the Unix epoch. +pub fn uuid() -> String { + use std::sync::atomic::{AtomicU64, Ordering}; + use std::time::{SystemTime, UNIX_EPOCH}; + static COUNTER: AtomicU64 = AtomicU64::new(0); + let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let count = COUNTER.fetch_add(1, Ordering::SeqCst); + format!( + "{}-{}-{}", + duration.as_secs(), + duration.subsec_nanos(), + count + ) +} + +/// Create a unique temporary directory for a test. +/// +/// # Panics +/// +/// Panics if the directory cannot be created. +pub async fn temp_dir(prefix: &str) -> PathBuf { + let dir = std::env::temp_dir().join(format!("witryna-{}-{}", prefix, uuid())); + tokio::fs::create_dir_all(&dir).await.unwrap(); + dir +} + +/// Remove a temporary directory (ignores errors). +pub async fn cleanup(dir: &Path) { + let _ = tokio::fs::remove_dir_all(dir).await; +} |
