pub(crate) struct EnvVarGuard {
key: &'static str,
prev: Option<std::ffi::OsString>,
}
impl EnvVarGuard {
pub(crate) fn unset(key: &'static str) -> Self {
let prev = std::env::var_os(key);
unsafe { std::env::remove_var(key) };
Self { key, prev }
}
pub(crate) fn set(key: &'static str, value: impl AsRef<std::ffi::OsStr>) -> Self {
let prev = std::env::var_os(key);
unsafe { std::env::set_var(key, value) };
Self { key, prev }
}
}
impl Drop for EnvVarGuard {
fn drop(&mut self) {
unsafe {
match &self.prev {
Some(v) => std::env::set_var(self.key, v),
None => std::env::remove_var(self.key),
}
}
}
}
pub(crate) use trusty_common::credentials::test_sandbox::assert_secret_eq;
#[cfg(test)]
mod tests {
use serial_test::serial;
use super::*;
#[test]
fn a_failed_secret_assert_never_prints_the_value() {
let secret = "9121000000:fake-value-0123456789abcdef";
let panic = std::panic::catch_unwind(|| {
assert_secret_eq(Some(secret), Some("expected"), "probe");
})
.expect_err("a mismatch must panic");
let msg = panic
.downcast_ref::<String>()
.expect("assert! panics with a String payload");
assert!(!msg.contains(secret), "the message echoed the value");
assert!(!msg.contains("0123456789"), "the message echoed its tail");
assert!(msg.contains("expected"), "the message lost the expectation");
}
#[test]
#[serial]
fn env_var_guard_restores_the_prior_state() {
const VAR: &str = "TM_TEST_ENV_GUARD_9121";
let outer = EnvVarGuard::unset(VAR);
{
let _set = EnvVarGuard::set(VAR, "inner");
assert_eq!(std::env::var(VAR).as_deref(), Ok("inner"));
}
assert!(std::env::var_os(VAR).is_none(), "absent was not restored");
drop(outer);
}
}