use std::process::Command;
use assert_cmd::prelude::*;
fn snapdir_clean_env() -> Command {
let mut cmd = Command::cargo_bin("snapdir").expect("snapdir binary built");
cmd.env_clear();
if let Ok(path) = std::env::var("PATH") {
cmd.env("PATH", path);
}
cmd.env("HOME", "/tmp/snapdir-defaults-test-home");
cmd
}
fn defaults_lines(cmd: &mut Command) -> Vec<String> {
let out = cmd.arg("defaults").output().expect("run snapdir defaults");
assert!(
out.status.success(),
"snapdir defaults failed ({:?})\nstderr: {}",
out.status.code(),
String::from_utf8_lossy(&out.stderr),
);
String::from_utf8(out.stdout)
.expect("utf8 stdout")
.lines()
.map(ToOwned::to_owned)
.collect()
}
#[test]
fn defaults_command_exits_zero() {
snapdir_clean_env().arg("defaults").assert().success();
}
#[test]
fn defaults_command_reports_env_set_knobs_with_value_and_source() {
let mut cmd = snapdir_clean_env();
cmd.env("SNAPDIR_CACHE_DIR", "/tmp/x")
.env("SNAPDIR_CATALOG", "foo")
.env("SNAPDIR_VERSION", "9.9.9")
.env("UNRELATED_VAR", "should-not-appear");
let lines = defaults_lines(&mut cmd);
assert!(
lines
.iter()
.any(|l| l.contains("cache-dir") && l.contains("/tmp/x") && l.contains("env")),
"expected an env-tagged cache-dir=/tmp/x line in:\n{}",
lines.join("\n"),
);
assert!(
lines
.iter()
.any(|l| l.contains("catalog") && l.contains("foo") && l.contains("env")),
"expected an env-tagged catalog=foo line in:\n{}",
lines.join("\n"),
);
assert!(
!lines.iter().any(|l| l.to_lowercase().contains("version")),
"no VERSION line may appear:\n{}",
lines.join("\n"),
);
assert!(
!lines.iter().any(|l| l.contains("should-not-appear")),
"non-SNAPDIR vars must not appear:\n{}",
lines.join("\n"),
);
}
#[test]
fn defaults_command_legacy_manifest_vars_not_live_knobs() {
let mut cmd = snapdir_clean_env();
cmd.env("SNAPDIR_CACHE_DIR", "/tmp/x");
let lines = defaults_lines(&mut cmd);
for legacy in ["SNAPDIR_MANIFEST_CONTEXT", "SNAPDIR_MANIFEST_EXCLUDE"] {
assert!(
!lines.iter().any(|l| l.trim() == format!("{legacy}=")),
"the old empty `{legacy}=` legacy line must not appear in:\n{}",
lines.join("\n"),
);
}
}
#[test]
fn defaults_command_legacy_manifest_var_when_set_is_labeled_legacy() {
let mut cmd = snapdir_clean_env();
cmd.env("SNAPDIR_CACHE_DIR", "/tmp/x")
.env("SNAPDIR_MANIFEST_CONTEXT", "mykey");
let lines = defaults_lines(&mut cmd);
let manifest_line = lines
.iter()
.find(|l| l.contains("SNAPDIR_MANIFEST_CONTEXT"))
.expect("a set SNAPDIR_MANIFEST_CONTEXT must still be surfaced");
assert!(
manifest_line.contains("mykey"),
"the surfaced legacy line must carry its value: {manifest_line:?}",
);
assert!(
manifest_line.to_lowercase().contains("legacy"),
"the surfaced legacy line must be labeled legacy: {manifest_line:?}",
);
}
#[test]
fn defaults_command_is_deterministic() {
let mut a = snapdir_clean_env();
a.env("SNAPDIR_CACHE_DIR", "/tmp/x")
.env("SNAPDIR_STORE", "file:///tmp/store");
let out_a = a.arg("defaults").output().expect("run a");
let mut b = snapdir_clean_env();
b.env("SNAPDIR_CACHE_DIR", "/tmp/x")
.env("SNAPDIR_STORE", "file:///tmp/store");
let out_b = b.arg("defaults").output().expect("run b");
assert_eq!(
out_a.stdout, out_b.stdout,
"two `defaults` runs on the same env must be byte-identical",
);
}
#[test]
fn defaults_command_reports_store_env_var() {
let mut cmd = snapdir_clean_env();
cmd.env("SNAPDIR_CACHE_DIR", "/tmp/x")
.env("SNAPDIR_STORE", "file:///tmp/store");
let lines = defaults_lines(&mut cmd);
assert!(
lines
.iter()
.any(|l| l.contains("store") && l.contains("file:///tmp/store") && l.contains("env")),
"expected an env-tagged store=file:///tmp/store line in:\n{}",
lines.join("\n"),
);
}