use super::*;
struct EnvGuard {
name: &'static str,
previous: Option<std::ffi::OsString>,
}
impl EnvGuard {
fn set(name: &'static str, value: &str) -> Self {
let previous = std::env::var_os(name);
unsafe { std::env::set_var(name, value) }
Self { name, previous }
}
fn unset(name: &'static str) -> Self {
let previous = std::env::var_os(name);
unsafe { std::env::remove_var(name) }
Self { name, previous }
}
}
impl Drop for EnvGuard {
fn drop(&mut self) {
unsafe {
match self.previous.take() {
Some(value) => std::env::set_var(self.name, value),
None => std::env::remove_var(self.name),
}
}
}
}
fn temp_home(tag: &str) -> std::path::PathBuf {
let dir = std::env::temp_dir().join(format!("moadim-machine-{tag}-{}", uuid::Uuid::new_v4()));
std::fs::create_dir_all(&dir).expect("create temp home");
dir
}
#[test]
fn resolve_from_prefers_env() {
let (name, source) = resolve_from(
Some("from-env".to_string()),
Some("from-file".to_string()),
"from-host".to_string(),
);
assert_eq!(name, "from-env");
assert_eq!(source, MachineSource::Env);
}
#[test]
fn resolve_from_uses_file_when_no_env() {
let (name, source) = resolve_from(None, Some("from-file".to_string()), "from-host".to_string());
assert_eq!(name, "from-file");
assert_eq!(source, MachineSource::File);
}
#[test]
fn resolve_from_falls_back_to_hostname() {
let (name, source) = resolve_from(None, None, "from-host".to_string());
assert_eq!(name, "from-host");
assert_eq!(source, MachineSource::Hostname);
}
#[test]
fn resolve_from_treats_blank_env_and_file_as_absent() {
let (name, source) = resolve_from(
Some(" ".to_string()),
Some("\t\n".to_string()),
"from-host".to_string(),
);
assert_eq!(name, "from-host");
assert_eq!(source, MachineSource::Hostname);
}
#[test]
fn resolve_from_trims_winning_value() {
let (name, source) = resolve_from(Some(" padded ".to_string()), None, "host".to_string());
assert_eq!(name, "padded");
assert_eq!(source, MachineSource::Env);
}
#[test]
fn non_empty_filters_blank_and_none() {
assert_eq!(non_empty(None), None);
assert_eq!(non_empty(Some(" ".to_string())), None);
assert_eq!(non_empty(Some(" ok ".to_string())), Some("ok".to_string()));
}
#[test]
fn hostname_is_non_empty() {
assert!(!hostname().is_empty());
}
#[test]
fn targets_matches_only_named_machine() {
assert!(targets(&["a".to_string(), "b".to_string()], "b"));
assert!(!targets(&["a".to_string()], "b"));
assert!(!targets(&[], "a"));
}
#[test]
fn targets_glob_entry_matches_any_or_a_family() {
assert!(targets(&["*".to_string()], "anything"));
let machines = vec!["box-*".to_string()];
assert!(targets(&machines, "box-1"));
assert!(!targets(&machines, "other-1"));
assert!(!targets(&machines, "prefix-box-1"));
}
#[test]
fn glob_match_without_star_is_exact() {
assert!(glob_match("box", "box"));
assert!(!glob_match("box", "boxes"));
assert!(!glob_match("box", ""));
}
#[test]
fn glob_match_star_matches_prefix_middle_suffix_and_everything() {
assert!(glob_match("*", "anything at all"));
assert!(glob_match("box-*", "box-1"));
assert!(glob_match("box-*", "box-"));
assert!(!glob_match("box-*", "other"));
assert!(glob_match("*-work", "m4-work"));
assert!(!glob_match("*-work", "m4-personal"));
assert!(glob_match("a*z", "abcz"));
assert!(!glob_match("a*z", "abcy"));
assert!(glob_match("a**b", "axxxb")); assert!(glob_match("*bc", "abcbc"));
assert!(!glob_match("*bc", "abcd"));
}
#[test]
fn source_labels_are_distinct() {
assert_eq!(MachineSource::Env.label(), "MOADIM_MACHINE env");
assert_eq!(MachineSource::File.label(), "machine.local.toml");
assert_eq!(
MachineSource::Generated.label(),
"auto-generated (first run)"
);
assert_eq!(MachineSource::Hostname.label(), "system hostname");
}
include!("read_machine_file_absent_is_none_tests.rs");