50 lines
1.4 KiB
Rust
50 lines
1.4 KiB
Rust
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<String>)>,
|
|
}
|
|
|
|
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),
|
|
}
|
|
}
|
|
}
|
|
}
|