1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::ffi::OsString;
use std::sync::{Mutex, MutexGuard, OnceLock};
/// Acquire the process-wide environment mutation guard shared by tests that mutate or depend on PATH.
/// 获取由修改或依赖 PATH 的测试共享的进程级环境变量保护锁。
pub(crate) fn process_env_test_guard() -> MutexGuard<'static, ()> {
/// Process-wide lock that serializes tests touching executable discovery environment.
/// 用于串行化触碰可执行文件发现环境的测试的进程级锁。
static GUARD: OnceLock<Mutex<()>> = OnceLock::new();
GUARD
.get_or_init(|| Mutex::new(()))
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
}
/// Restore one process environment variable after a test mutates it.
/// 在测试修改环境变量后恢复单个进程环境变量。
fn restore_test_env_var(name: &str, previous: Option<OsString>) {
match previous {
Some(value) => unsafe { std::env::set_var(name, value) },
None => unsafe { std::env::remove_var(name) },
}
}
/// Restore one batch of mutated environment variables when a PATH-sensitive test finishes.
/// 当依赖 PATH 的测试结束时,恢复一批被修改过的环境变量。
pub(crate) struct TestEnvRestoreGuard {
/// Recorded previous values keyed by variable name.
/// 按变量名记录的旧值集合。
entries: Vec<(String, Option<OsString>)>,
}
impl TestEnvRestoreGuard {
/// Capture one named environment variable before the current test mutates it.
/// 在当前测试修改环境变量前,捕获单个具名环境变量。
pub(crate) fn capture(name: &str) -> Self {
Self {
entries: vec![(name.to_string(), std::env::var_os(name))],
}
}
/// Capture one additional named environment variable before the current test mutates it.
/// 在当前测试修改环境变量前,再额外捕获一个具名环境变量。
#[cfg(windows)]
pub(crate) fn and_capture(mut self, name: &str) -> Self {
self.entries
.push((name.to_string(), std::env::var_os(name)));
self
}
}
impl Drop for TestEnvRestoreGuard {
/// Restore every captured environment variable in reverse order on drop.
/// 在释放时按逆序恢复所有已捕获的环境变量。
fn drop(&mut self) {
while let Some((name, previous)) = self.entries.pop() {
restore_test_env_var(&name, previous);
}
}
}