use std::sync::{Mutex, MutexGuard}; /// Global mutex shared across all test modules to prevent parallel tests from /// interfering with each other when mutating environment variables. pub static ENV_MUTEX: Mutex<()> = Mutex::new(()); /// RAII guard that locks [`ENV_MUTEX`] and restores environment variables on drop. pub struct EnvGuard<'a> { _lock: MutexGuard<'a, ()>, vars: Vec<(String, Option)>, } impl<'a> EnvGuard<'a> { pub fn new(var_names: &[&str]) -> Self { let lock = ENV_MUTEX.lock().unwrap(); let vars = var_names .iter() .map(|&name| (name.to_string(), std::env::var(name).ok())) .collect(); Self { _lock: lock, vars } } pub fn set(&self, name: &str, value: &str) { debug_assert!( self.vars.iter().any(|(n, _)| n == name), "EnvGuard::set called with unregistered var: {name}" ); std::env::set_var(name, value); } pub fn remove(&self, name: &str) { debug_assert!( self.vars.iter().any(|(n, _)| n == name), "EnvGuard::remove called with unregistered var: {name}" ); std::env::remove_var(name); } } impl Drop for EnvGuard<'_> { fn drop(&mut self) { for (name, value) in &self.vars { match value { Some(v) => std::env::set_var(name, v), None => std::env::remove_var(name), } } } }