crates/nornir-config/tests/pin_base.rs
//! The embedder seam, driven through the REAL process-global setter.
//!
//! `pin_nornir_base` is set-once per PROCESS, so this has to be an integration
//! test (its own binary) rather than a unit test sharing the lib's test process
//! with the `$HOME`-mutating ones. Its sibling `pin_after_read.rs` proves the
//! opposite order in a second process.
use std::path::{Path, PathBuf};
/// **The whole point.** After an embedder pins its own data root as the base,
/// EVERY nornir root hangs inside it — and `$HOME` no longer decides.
///
/// The `$HOME` half is the assertion that matters: before this seam existed the
/// only lever was `$HOME`, which also moves `~/.cargo`, `~/.rustup` and the
/// server's PATH injection. Moving `$HOME` here and watching the root NOT follow
/// is what proves the lever is gone.
///
/// RED WHEN REVERTED: make `nornir_home()` ignore `PINNED_BASE` (i.e. restore the
/// old one-line `nornir_home_from(&home::home_dir()…)`) and every assertion below
/// reports `/home/pin-test-home/.nornir…` instead of the pinned tree.
#[test]
fn a_pinned_base_owns_every_root_and_home_no_longer_moves_it() {
// A `$HOME` that is deliberately NOT the pinned base. If anything still reads
// it, the assertions below name this tree and fail.
// SAFETY: single-threaded test process; nothing else has read the root yet.
unsafe { std::env::set_var("HOME", "/home/pin-test-home") };
assert_eq!(nornir_config::pinned_nornir_base(), None, "nothing pinned yet");
let base = Path::new("/home/dwarves/.dwarves");
let root = nornir_config::pin_nornir_base(base).expect("pin the declared data root");
// The root is INSIDE the base — the property that lets the embedder delete its
// second declared root.
assert_eq!(root, PathBuf::from("/home/dwarves/.dwarves/.nornir"));
assert!(root.starts_with(base), "{} is not inside {}", root.display(), base.display());
assert_eq!(nornir_config::pinned_nornir_base().as_deref(), Some(base));
// Every composed root follows the pin, not `$HOME`.
assert_eq!(nornir_config::nornir_home(), PathBuf::from("/home/dwarves/.dwarves/.nornir"));
assert_eq!(
nornir_config::registry_root(),
PathBuf::from("/home/dwarves/.dwarves/.nornir/workspaces"),
);
assert_eq!(
nornir_config::warehouse_default_root(),
PathBuf::from("/home/dwarves/.dwarves/.nornir/warehouse"),
);
// …including the per-workspace warehouse the server actually opens — the
// 3.0 GB `nordisk/builds` tree, not just the bare root.
let loaded = nornir_config::Loaded {
nornir: nornir_config::Nornir::default(),
config_path: PathBuf::from("/ws/workspace_nordisk/release/nornir.toml"),
workspace_root: PathBuf::from("/ws"),
};
assert_eq!(
loaded.warehouse_root(),
PathBuf::from("/home/dwarves/.dwarves/.nornir/workspaces/nordisk/builds"),
);
// MOVE `$HOME` again. The root must not budge — that is the lever being gone.
// SAFETY: single-threaded test process.
unsafe { std::env::set_var("HOME", "/home/somewhere-else-entirely") };
assert_eq!(
nornir_config::nornir_home(),
PathBuf::from("/home/dwarves/.dwarves/.nornir"),
"the pinned root followed $HOME — the pin is not authoritative",
);
// Idempotent: the same base again is a no-op (an embedder may pin from more
// than one entry point).
assert_eq!(
nornir_config::pin_nornir_base(base).expect("re-pinning the same base is a no-op"),
root,
);
// A DIFFERENT base is the two-roots bug — refused, and it names both paths.
let err = nornir_config::pin_nornir_base(Path::new("/home/dwarves/.other"))
.expect_err("a second, different base must be refused");
assert_eq!(
err,
nornir_config::PinRefused::Conflict {
pinned: base.to_path_buf(),
attempted: PathBuf::from("/home/dwarves/.other"),
},
);
// …and the refusal did not change anything.
assert_eq!(nornir_config::nornir_home(), PathBuf::from("/home/dwarves/.dwarves/.nornir"));
}