diff --git a/src-gossamer/src/boj/commands.rs b/src-gossamer/src/boj/commands.rs index e3e40fe..a95c733 100644 --- a/src-gossamer/src/boj/commands.rs +++ b/src-gossamer/src/boj/commands.rs @@ -106,6 +106,7 @@ mod tests { #[test] fn boj_url_default_and_override() { + let _env = crate::test_env::lock(); std::env::remove_var("BOJ_URL"); assert_eq!(boj_url(), DEFAULT_BOJ_URL); let custom = "http://boj.local:9999/v2"; diff --git a/src-gossamer/src/boj_live.rs b/src-gossamer/src/boj_live.rs index 46b43c1..1127734 100644 --- a/src-gossamer/src/boj_live.rs +++ b/src-gossamer/src/boj_live.rs @@ -122,6 +122,7 @@ mod tests { /// Verify the endpoint builder respects BOJ_URL and strips trailing slashes. #[test] fn boj_endpoint_default_and_override() { + let _env = crate::test_env::lock(); std::env::remove_var("BOJ_URL"); let ep = boj_endpoint(); assert_eq!(ep.base_url, DEFAULT_BOJ_URL); diff --git a/src-gossamer/src/governance/commands.rs b/src-gossamer/src/governance/commands.rs index aa2c38a..cd49d85 100644 --- a/src-gossamer/src/governance/commands.rs +++ b/src-gossamer/src/governance/commands.rs @@ -134,12 +134,14 @@ mod tests { #[test] fn boj_url_default() { + let _env = crate::test_env::lock(); std::env::remove_var("BOJ_URL"); assert_eq!(boj_url(), DEFAULT_BOJ_URL); } #[test] fn boj_url_override() { + let _env = crate::test_env::lock(); let custom = "http://nesy.local:8800/v2"; std::env::set_var("BOJ_URL", custom); assert_eq!(boj_url(), custom); diff --git a/src-gossamer/src/hypatia/commands.rs b/src-gossamer/src/hypatia/commands.rs index bfcb72d..bf09ac0 100644 --- a/src-gossamer/src/hypatia/commands.rs +++ b/src-gossamer/src/hypatia/commands.rs @@ -117,6 +117,7 @@ mod tests { /// Verify the default Hypatia URL is the expected localhost endpoint. #[test] fn smoke_hypatia_url_default() { + let _env = crate::test_env::lock(); // Unset the env var to ensure we get the hardcoded default. std::env::remove_var("HYPATIA_URL"); let url = hypatia_url(); @@ -126,6 +127,7 @@ mod tests { /// Verify that HYPATIA_URL env var overrides the default. #[test] fn smoke_hypatia_url_override() { + let _env = crate::test_env::lock(); std::env::set_var("HYPATIA_URL", "http://custom-host:9999/api/v2"); let url = hypatia_url(); assert_eq!(url, "http://custom-host:9999/api/v2"); diff --git a/src-gossamer/src/lib.rs b/src-gossamer/src/lib.rs index 97328a3..c1c5ac0 100644 --- a/src-gossamer/src/lib.rs +++ b/src-gossamer/src/lib.rs @@ -95,6 +95,23 @@ pub mod watcher; pub mod wiring_inspector; pub mod workspace; +/// Serialises the tests that set or remove process environment variables +/// (`BOJ_URL`, `OVERLAY_URL`, `HYPATIA_URL`, `TYPELL_URL`). `cargo test` runs +/// tests on parallel threads and the environment is process-wide, so without +/// this lock one test can read the value another has just set. +#[cfg(test)] +pub(crate) mod test_env { + use std::sync::{Mutex, MutexGuard}; + + static LOCK: Mutex<()> = Mutex::new(()); + + /// Hold the guard for the whole test. A test that panics while holding it + /// poisons the lock; the next test takes it anyway. + pub(crate) fn lock() -> MutexGuard<'static, ()> { + LOCK.lock().unwrap_or_else(|e| e.into_inner()) + } +} + /// Cross-module integration tests. These exercise the public command-backed /// functions end-to-end. They live in the lib (not `tests/`) so they run via /// `cargo test --lib` without cargo also force-building the GTK-linked diff --git a/src-gossamer/src/overlay/commands.rs b/src-gossamer/src/overlay/commands.rs index 1adfe9c..33c4426 100644 --- a/src-gossamer/src/overlay/commands.rs +++ b/src-gossamer/src/overlay/commands.rs @@ -273,6 +273,7 @@ mod tests { #[test] fn overlay_url_default_and_override() { + let _env = crate::test_env::lock(); std::env::remove_var("OVERLAY_URL"); assert_eq!(overlay_url(), DEFAULT_OVERLAY_URL); let custom = "http://overlay.local:9999/v2"; diff --git a/src-gossamer/src/typell/commands.rs b/src-gossamer/src/typell/commands.rs index f4043d5..90a8369 100644 --- a/src-gossamer/src/typell/commands.rs +++ b/src-gossamer/src/typell/commands.rs @@ -104,6 +104,7 @@ mod tests { #[test] fn typell_url_default_and_override() { + let _env = crate::test_env::lock(); std::env::remove_var("TYPELL_URL"); assert_eq!(typell_url(), DEFAULT_TYPELL_URL); let custom = "http://typell.local:9999/v2";