Skip to main content

vissue_core/
process_env.rs

1//! Process environment with a thread-local overlay for tests.
2//!
3//! Production reads `std::env`. Tests call [`override_var`] so they never
4//! need `set_var` / `remove_var`, which are unsafe in edition 2024.
5
6use std::cell::RefCell;
7use std::collections::HashMap;
8use std::env::VarError;
9
10thread_local! {
11    static OVERLAY: RefCell<HashMap<String, Option<String>>> = RefCell::new(HashMap::new());
12}
13
14/// Read `key`, honouring a test overlay if one is set on this thread.
15///
16/// # Errors
17///
18/// Returns [`VarError::NotPresent`] when the overlay unsets `key` or when
19/// the real process environment has no such variable.
20pub fn var(key: &str) -> Result<String, VarError> {
21    if let Some(over) = OVERLAY.with(|m| m.borrow().get(key).cloned()) {
22        return over.ok_or(VarError::NotPresent);
23    }
24    std::env::var(key)
25}
26
27/// Pretend `key` is `value` (`None` means unset) on this thread.
28///
29/// Used by tests. Production code never calls this.
30pub fn override_var(key: &str, value: Option<&str>) {
31    OVERLAY.with(|m| {
32        m.borrow_mut()
33            .insert(key.to_string(), value.map(str::to_string));
34    });
35}
36
37/// Drop the overlay for `key` so later reads use the real process environment.
38pub fn clear_override(key: &str) {
39    OVERLAY.with(|m| {
40        m.borrow_mut().remove(key);
41    });
42}