#![allow(unused_imports)]
use std::collections::HashMap;
use crate::gates::{GateTable, HostFacts};
use crate::handlers::HandlerConfig;
use crate::packs::Pack;
use crate::rules::{Rule, Scanner};
use crate::testing::TempEnvironment;
use super::{default_rules, host_pair, make_pack};
#[test]
fn gate_passing_strips_suffix_and_routes_to_handler() {
let env = TempEnvironment::builder()
.pack("mac")
.file("install._darwin.sh", "#!/bin/sh\necho mac-only")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("mac", env.dotfiles_root.join("mac"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
let m = &matches[0];
assert_eq!(m.handler, "install");
assert_eq!(m.relative_path.to_string_lossy(), "install.sh");
assert!(m
.absolute_path
.to_string_lossy()
.ends_with("install._darwin.sh"));
}
#[test]
fn gate_failing_emits_gate_handler_match() {
let env = TempEnvironment::builder()
.pack("cross")
.file("install._linux.sh", "#!/bin/sh\napt-get foo")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("cross", env.dotfiles_root.join("cross"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
let m = &matches[0];
assert_eq!(m.handler, crate::handlers::HANDLER_GATE);
assert_eq!(m.relative_path.to_string_lossy(), "install._linux.sh");
assert_eq!(m.options.get("gate_label"), Some(&"linux".to_string()));
assert_eq!(
m.options.get("gate_predicate"),
Some(&"os=linux".to_string())
);
assert_eq!(m.options.get("gate_host"), Some(&"os=darwin".to_string()));
}
#[test]
fn gate_unknown_label_is_hard_error() {
let env = TempEnvironment::builder()
.pack("typo")
.file("install._darwn.sh", "#!/bin/sh") .done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("typo", env.dotfiles_root.join("typo"));
let (gates, host) = host_pair("darwin", "aarch64");
let err = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap_err();
let msg = err.to_string();
assert!(msg.contains("darwn"), "missing label: {msg}");
assert!(msg.contains("typo"), "missing pack: {msg}");
assert!(msg.contains("install._darwn.sh"), "missing file: {msg}");
}
#[test]
fn gate_compound_user_label_evaluates_and() {
let env = TempEnvironment::builder()
.pack("p")
.file("setup._arm-mac.sh", "x")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("p", env.dotfiles_root.join("p"));
let mut user = HashMap::new();
let mut arm_mac = HashMap::new();
arm_mac.insert("os".into(), "darwin".into());
arm_mac.insert("arch".into(), "aarch64".into());
user.insert("arm-mac".into(), arm_mac);
let mut gates = GateTable::with_builtins();
gates.merge_user(&user).unwrap();
let host = HostFacts::for_tests("darwin", "aarch64");
let mut rules = default_rules();
rules.push(Rule {
pattern: "setup.sh".into(),
handler: "shell".into(),
priority: 10,
case_insensitive: false,
options: HashMap::new(),
});
let matches = scanner
.match_entries(
&scanner.walk_pack(&pack.path, &[], &gates, &host).unwrap(),
&rules,
&pack.name,
&gates,
&host,
&HashMap::new(),
)
.unwrap();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].handler, "shell");
assert_eq!(matches[0].relative_path.to_string_lossy(), "setup.sh");
let host_intel = HostFacts::for_tests("darwin", "x86_64");
let matches = scanner
.match_entries(
&scanner
.walk_pack(&pack.path, &[], &gates, &host_intel)
.unwrap(),
&rules,
&pack.name,
&gates,
&host_intel,
&HashMap::new(),
)
.unwrap();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].handler, crate::handlers::HANDLER_GATE);
}
#[test]
fn gate_composes_with_template_extension() {
let env = TempEnvironment::builder()
.pack("p")
.file("aliases._darwin.sh.tmpl", "alias x=y")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("p", env.dotfiles_root.join("p"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
let m = &matches[0];
assert_eq!(m.relative_path.to_string_lossy(), "aliases.sh.tmpl");
assert_eq!(m.handler, "symlink");
}
#[test]
fn gate_composes_with_home_routing_prefix() {
let env = TempEnvironment::builder()
.pack("p")
.file("home.bashrc._darwin", "# bashrc")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("p", env.dotfiles_root.join("p"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
let m = &matches[0];
assert_eq!(m.relative_path.to_string_lossy(), "home.bashrc");
assert_eq!(m.handler, "symlink");
}
#[test]
fn gate_mixed_files_in_one_pack() {
let env = TempEnvironment::builder()
.pack("cross")
.file("install._darwin.sh", "#!/bin/sh\necho mac")
.file("install._linux.sh", "#!/bin/sh\necho linux")
.file("vimrc", "set nocompatible")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("cross", env.dotfiles_root.join("cross"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
let by_handler: HashMap<&str, Vec<String>> =
matches.iter().fold(HashMap::new(), |mut acc, m| {
acc.entry(m.handler.as_str())
.or_default()
.push(m.relative_path.to_string_lossy().to_string());
acc
});
assert_eq!(
by_handler.get("install"),
Some(&vec!["install.sh".to_string()])
);
assert_eq!(
by_handler.get(crate::handlers::HANDLER_GATE),
Some(&vec!["install._linux.sh".to_string()])
);
assert_eq!(by_handler.get("symlink"), Some(&vec!["vimrc".to_string()]));
}
#[test]
fn gate_brewfile_extensionless() {
let env = TempEnvironment::builder()
.pack("brew")
.file("Brewfile._darwin", "brew \"ripgrep\"")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("brew", env.dotfiles_root.join("brew"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].handler, "homebrew");
assert_eq!(matches[0].relative_path.to_string_lossy(), "Brewfile");
}
#[test]
fn gate_arch_label_uses_arm64_alias() {
let env = TempEnvironment::builder()
.pack("p")
.file("aliases._arm64.sh", "alias x=y")
.done()
.build();
let scanner = Scanner::new(env.fs.as_ref());
let pack = make_pack("p", env.dotfiles_root.join("p"));
let (gates, host) = host_pair("darwin", "aarch64");
let matches = scanner
.scan_pack(&pack, &default_rules(), &[], &gates, &host, &HashMap::new())
.unwrap();
assert_eq!(matches.len(), 1);
let m = &matches[0];
assert_eq!(m.relative_path.to_string_lossy(), "aliases.sh");
assert_eq!(m.handler, "shell");
}