use super::*;
static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
fn with_var<T>(name: &str, value: Option<&str>, body: impl FnOnce() -> T) -> T {
let _guard = ENV_LOCK
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
let previous = std::env::var_os(name);
match value {
Some(value) => std::env::set_var(name, value),
None => std::env::remove_var(name),
}
let outcome = body();
match previous {
Some(previous) => std::env::set_var(name, previous),
None => std::env::remove_var(name),
}
outcome
}
const PROBE: &str = "RUNNING_PROCESS_ENV_VARS_PROBE";
#[test]
fn an_owned_flag_is_on_only_for_a_recognised_affirmative() {
for on in ["1", "true", "TRUE", " True ", "yes", "on"] {
assert!(
with_var(PROBE, Some(on), || flag_owned(PROBE)),
"{on:?} must turn an owned switch on"
);
}
for off in ["", "0", "false", "no", "off", "OFF", " 0 "] {
assert!(
!with_var(PROBE, Some(off), || flag_owned(PROBE)),
"{off:?} must leave an owned switch off"
);
}
for unknown in ["maybe", "2", "y", "enabled", "tru"] {
assert!(
!with_var(PROBE, Some(unknown), || flag_owned(PROBE)),
"{unknown:?} is not a spelling we defined, so the switch stays off"
);
}
assert!(!with_var(PROBE, None, || flag_owned(PROBE)), "unset is off");
}
#[test]
fn a_foreign_flag_is_off_only_for_a_recognised_negative() {
for off in ["", "0", "false", "no", "off", " OFF "] {
assert!(
!with_var(PROBE, Some(off), || flag_foreign(PROBE)),
"{off:?} must turn a foreign switch off"
);
}
for on in ["1", "true", "yes", "on", "maybe", "2", "enabled"] {
assert!(
with_var(PROBE, Some(on), || flag_foreign(PROBE)),
"{on:?} is not a falsy spelling, so the switch reads as on"
);
}
}
#[test]
fn an_unset_foreign_flag_is_off() {
assert!(!with_var(PROBE, None, || flag_foreign(PROBE)));
}
#[test]
fn the_two_flag_semantics_differ_only_on_unrecognised_values() {
for agreed in ["1", "true", "yes", "on", "0", "false", "no", "off", ""] {
assert_eq!(
with_var(PROBE, Some(agreed), || flag_owned(PROBE)),
with_var(PROBE, Some(agreed), || flag_foreign(PROBE)),
"{agreed:?} is a recognised spelling; both semantics must agree"
);
}
for disputed in ["maybe", "2", "enabled"] {
assert!(
!with_var(PROBE, Some(disputed), || flag_owned(PROBE)),
"owned: unknown is off"
);
assert!(
with_var(PROBE, Some(disputed), || flag_foreign(PROBE)),
"foreign: unknown is on"
);
}
}
#[test]
fn an_exact_value_guard_refuses_plausible_misspellings() {
assert!(with_var(BROKER_ALLOW_PRIVILEGED.name, Some("1"), || {
BROKER_ALLOW_PRIVILEGED.is_set()
}));
for refused in ["true", "yes", "on", "TRUE", " 1 "] {
assert!(
!with_var(BROKER_ALLOW_PRIVILEGED.name, Some(refused), || {
BROKER_ALLOW_PRIVILEGED.is_set()
}),
"{refused:?} must not open a privilege guard"
);
}
}
#[test]
fn scanning_a_value_agrees_with_reading_the_variable() {
for value in ["1", "true", "maybe", "0", "false", "off", ""] {
assert_eq!(
value_is_affirmative_foreign(value),
with_var(PROBE, Some(value), || flag_foreign(PROBE)),
"{value:?} must read the same scanned as it does read directly"
);
}
}
#[test]
fn declarations_are_sorted_and_unique() {
let names: Vec<&str> = DECLARED.iter().map(|var| var.name).collect();
let mut sorted = names.clone();
sorted.sort_unstable();
assert_eq!(names, sorted, "declarations must stay alphabetical");
let mut unique = sorted.clone();
unique.dedup();
assert_eq!(unique, sorted, "a variable must be declared once");
}
#[test]
fn declarations_are_documented() {
for var in DECLARED {
assert!(!var.name.is_empty());
assert!(
!var.default.is_empty(),
"{} has no documented default",
var.name
);
assert!(!var.summary.is_empty(), "{} has no summary", var.name);
match var.owner {
Owner::Crate => assert!(
var.name.starts_with("RUNNING_PROCESS_"),
"{} is declared as ours but is not namespaced",
var.name
),
Owner::Foreign => assert!(!var.name.is_empty()),
}
}
}
#[test]
fn declaration_table_covers_every_variable() {
let declared: std::collections::BTreeSet<&str> = DECLARED.iter().map(|var| var.name).collect();
let mut undeclared: std::collections::BTreeSet<String> = Default::default();
for path in source_files() {
let text = std::fs::read_to_string(&path).expect("read source file");
for found in literal_env_names(&text) {
if !declared.contains(found.as_str()) {
undeclared.insert(format!("{found} (in {})", path.display()));
}
}
}
assert!(
undeclared.is_empty(),
"these variables are read but not declared in DECLARED:\n {}",
undeclared.into_iter().collect::<Vec<_>>().join("\n ")
);
}
const NOT_ENVIRONMENT_READS: &[&str] = &[
"RUNNING_PROCESS_TEST_CLIENT_ONLY_ENV",
"RUNNING_PROCESS_TEST_DAEMON_ONLY_ENV",
"RUNNING_PROCESS_MATERIALIZE_CANARY",
"RUNNING_PROCESS_BASELINE_CANARY",
"RUNNING_PROCESS_ENV_VARS_PROBE",
];
const PREFIX: &str = "RUNNING_PROCESS_";
const READS: &[&str] = &["env::var(\"", "env::var_os(\""];
fn literal_env_names(text: &str) -> Vec<String> {
let mut found = Vec::new();
for read in READS {
let mut index = 0;
while let Some(start) = text[index..].find(read) {
let open = index + start + read.len();
let Some(len) = text[open..].find('"') else {
break;
};
let name = &text[open..open + len];
let is_a_name = !name.is_empty()
&& name != PREFIX
&& name
.chars()
.all(|ch| ch.is_ascii_uppercase() || ch.is_ascii_digit() || ch == '_');
if is_a_name && !NOT_ENVIRONMENT_READS.contains(&name) {
found.push(name.to_owned());
}
index = open + len;
}
}
found
}
fn source_files() -> Vec<std::path::PathBuf> {
let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
let mut files = Vec::new();
let mut stack = vec![root];
while let Some(dir) = stack.pop() {
let Ok(entries) = std::fs::read_dir(&dir) else {
continue;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
stack.push(path);
} else if path.extension().is_some_and(|ext| ext == "rs") {
files.push(path);
}
}
}
assert!(!files.is_empty(), "the crate must have sources to scan");
files
}
#[test]
fn an_unset_flag_matches_its_declared_default() {
for var in DECLARED {
let declared_on = match var.kind {
EnvKind::OwnedFlag | EnvKind::ForeignFlag | EnvKind::OptOutFlag => {
describes_an_enabled_default(var.default)
}
EnvKind::ExactValue(_) => describes_an_enabled_default(var.default),
_ => continue,
};
let actually_on = with_var(var.name, None, || var.is_set());
assert_eq!(
actually_on,
declared_on,
"{}: declared default {:?} says {}, but reading it unset gives {}",
var.name,
var.default,
if declared_on { "on" } else { "off" },
actually_on
);
}
}
fn describes_an_enabled_default(default: &str) -> bool {
match default {
"broker-owned bind is used" => true,
"privileged startup is refused"
| "the broker is used"
| "processes are tracked"
| "the guard does not run"
| "the process is not a daemon"
| "a dev-build daemon relocates itself"
| "not running under GitHub Actions" => false,
other => panic!(
"default {other:?} is not a phrasing this check recognises; \
add it rather than letting the assertion pass vacuously"
),
}
}
#[test]
fn zero_means_what_each_numeric_variable_declares() {
let mut checked = 0;
for var in DECLARED {
let EnvKind::Number {
zero_selects_default,
} = var.kind
else {
continue;
};
checked += 1;
let sentinel = std::time::Duration::from_millis(9_999);
let read = with_var(var.name, Some("0"), || var.millis_or(sentinel));
if zero_selects_default {
assert_eq!(
read, sentinel,
"{}: zero must fall back to the caller's default",
var.name
);
} else {
assert_eq!(
read,
std::time::Duration::ZERO,
"{}: zero must be honoured as zero",
var.name
);
}
}
assert!(checked >= 8, "expected the numeric variables to be checked");
}
#[test]
fn an_unparseable_number_falls_back_to_the_default() {
let sentinel = std::time::Duration::from_millis(4_242);
for var in DECLARED {
if !matches!(var.kind, EnvKind::Number { .. }) {
continue;
}
for junk in ["", " ", "abc", "12ms", "-1", "1.5"] {
assert_eq!(
with_var(var.name, Some(junk), || var.millis_or(sentinel)),
sentinel,
"{}: {junk:?} is not a number and must not be read as one",
var.name
);
}
}
}
#[test]
fn a_number_is_read_through_surrounding_whitespace() {
let sentinel = std::time::Duration::from_millis(1);
assert_eq!(
with_var(CLIENT_RPC_TIMEOUT_MS.name, Some(" 250 "), || {
CLIENT_RPC_TIMEOUT_MS.millis_or(sentinel)
}),
std::time::Duration::from_millis(250)
);
}
#[test]
fn a_path_is_taken_verbatim_and_an_empty_one_is_absent() {
assert_eq!(
with_var(MANIFEST_DIR.name, Some("/tmp/manifests"), || MANIFEST_DIR
.path()),
Some(std::path::PathBuf::from("/tmp/manifests"))
);
assert_eq!(
with_var(MANIFEST_DIR.name, Some(""), || MANIFEST_DIR.path()),
None
);
assert_eq!(
with_var(MANIFEST_DIR.name, None, || MANIFEST_DIR.path()),
None
);
}
#[test]
fn empty_text_is_absent() {
assert_eq!(
with_var(DAEMON_SCOPE.name, Some("dev"), || DAEMON_SCOPE.text()),
Some("dev".to_owned())
);
assert_eq!(
with_var(DAEMON_SCOPE.name, Some(""), || DAEMON_SCOPE.text()),
None
);
}
#[test]
fn no_literal_environment_read_lives_outside_this_module() {
let mut offenders: Vec<String> = Vec::new();
for path in source_files() {
let name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or_default();
if name == "env_vars.rs" {
continue;
}
let text = std::fs::read_to_string(&path).expect("read source file");
for read in READS {
let mut index = 0;
while let Some(start) = text[index..].find(read) {
let open = index + start + read.len();
let Some(len) = text[open..].find('"') else {
break;
};
let named = &text[open..open + len];
if !NOT_ENVIRONMENT_READS.contains(&named) {
offenders.push(format!("{}: {read}{named}\")", path.display()));
}
index = open + len;
}
}
}
offenders.sort();
assert!(
offenders.is_empty(),
"read these through `crate::env_vars` instead, so the variable is \
declared and parsed one way:\n {}",
offenders.join("\n ")
);
}
#[test]
fn the_combined_inventory_is_sorted_unique_and_documented() {
let all = all_declared();
let names: Vec<&str> = all.iter().map(|var| var.name).collect();
let mut sorted = names.clone();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(names, sorted, "all_declared() must be sorted and unique");
for var in &all {
assert!(
!var.summary.trim().is_empty(),
"{} has no summary",
var.name
);
assert!(
!var.default.trim().is_empty(),
"{} has no default",
var.name
);
}
for var in DECLARED.iter().chain(platform::DECLARED_PLATFORM) {
assert!(
names.contains(&var.name),
"{} is declared but missing from all_declared()",
var.name
);
}
}
#[test]
fn a_name_in_both_tables_is_one_declaration() {
let mut shared = 0;
for ours in DECLARED {
let Some(theirs) = platform::DECLARED_PLATFORM
.iter()
.find(|theirs| theirs.name == ours.name)
else {
continue;
};
shared += 1;
assert!(
ours.summary == theirs.summary
&& ours.default == theirs.default
&& ours.kind == theirs.kind
&& ours.owner == theirs.owner,
"{} is declared twice; refer to the platform declaration with `use` instead",
ours.name
);
}
assert!(shared > 0, "expected variables read by both crates");
}
#[test]
fn production_code_calls_std_env_only_through_declarations() {
let mut offenders = Vec::new();
for path in source_files() {
let in_test_tree = path.components().any(|part| part.as_os_str() == "tests");
let name = path
.file_name()
.and_then(|name| name.to_str())
.unwrap_or_default();
if in_test_tree
|| name == "env_vars.rs"
|| name == "tests.rs"
|| name.ends_with("_tests.rs")
{
continue;
}
let text = std::fs::read_to_string(&path).expect("read source file");
let lines: Vec<&str> = text.lines().collect();
let cut = lines
.iter()
.enumerate()
.position(|(index, line)| {
let line = line.trim_start();
(line.starts_with("#[cfg(test)]") || line.starts_with("#[cfg(all(test"))
&& lines[index + 1..]
.iter()
.map(|next| next.trim())
.find(|next| !next.is_empty() && !next.starts_with("#["))
.is_some_and(|next| next.starts_with("mod ") && next.ends_with('{'))
})
.unwrap_or(lines.len());
for (index, line) in lines[..cut].iter().enumerate() {
let direct = [
"env::var(",
"env::var_os(",
"env::set_var(",
"env::remove_var(",
]
.iter()
.any(|call| line.contains(call));
if direct && !line.trim_start().starts_with("//") {
offenders.push(format!("{}:{}", path.display(), index + 1));
}
}
}
assert!(
offenders.is_empty(),
"read these through a declared `crate::env_vars` constant: {offenders:#?}"
);
}
#[cfg(feature = "probe")]
#[test]
fn the_probe_table_shares_no_name_with_the_running_process_or_platform_tables() {
let below: Vec<&str> = DECLARED
.iter()
.chain(platform::DECLARED_PLATFORM)
.map(|var| var.name)
.collect();
for var in running_process_probe::env_vars::DECLARED_PROBE {
assert!(
!below.contains(&var.name),
"{} is declared by both the probe crate and a lower table",
var.name
);
}
let all = all_declared();
for var in running_process_probe::env_vars::DECLARED_PROBE {
assert!(
all.iter().any(|listed| listed.name == var.name),
"{} is missing from all_declared()",
var.name
);
}
}