use super::*;
fn ask(command: &str) -> Option<(&'static str, String)> {
match structured(command) {
OperandVerdict::Ask { tail, target } => Some((tail, target)),
_ => None,
}
}
fn unresolvable(target: &str) -> Option<(&'static str, String)> {
Some((TAIL_UNRESOLVABLE, target.to_string()))
}
fn critical(target: &str) -> Option<(&'static str, String)> {
Some((TAIL_CRITICAL, target.to_string()))
}
#[test]
fn the_unresolvable_arm_reads_each_of_its_shapes_in_turn() {
assert_eq!(ask("rm -rf a/../*"), unresolvable("a/../*"));
assert_eq!(ask("rm -rf $D/*"), unresolvable("__TRACKED_VAR__/*"));
assert_eq!(
ask("rm -rf $(id -u)/*"),
unresolvable("__CMDSUB_OUTPUT__/*")
);
assert_eq!(ask("rm -rf ~/x/*"), unresolvable("~/x/*"));
assert_eq!(
ask("rm -rf //server/share/*"),
unresolvable("//server/share/*")
);
assert_eq!(ask("rm -rf ../*"), unresolvable("../*"));
assert_eq!(ask("rmdir -p a/*"), unresolvable("a/*"));
assert_eq!(structured("rmdir -p a/*/"), OperandVerdict::NeedsFs);
assert_eq!(structured("rm -p a/*"), OperandVerdict::NeedsFs);
assert_eq!(structured("rm -rf build/*"), OperandVerdict::NeedsFs);
assert_eq!(structured("rm -rf $D/build"), OperandVerdict::NeedsFs);
}
#[test]
fn a_cd_anywhere_turns_a_relative_glob_into_an_ask_by_itself() {
assert_eq!(ask("cd /tmp && rm -rf build/*"), unresolvable("build/*"));
assert_eq!(
structured("cd /tmp && rm -rf /tmp/build/*"),
OperandVerdict::NeedsFs
);
}
#[test]
fn the_critical_path_arm_answers_for_a_root_a_drive_and_a_top_level_name() {
assert_eq!(ask("rm -rf /tmp"), critical("/tmp"));
assert_eq!(
ask("rm -rf /*"),
critical("/*"),
"the glob resolves to the root"
);
assert_eq!(ask("rm -rf C:"), critical("C:"));
assert_eq!(ask("rm -rf C:/x"), critical("C:/x"));
assert_eq!(ask("rm ~"), critical("~"));
assert_eq!(ask("rm ~/"), critical("~/"));
assert_eq!(ask("rm -rf /tmp*"), critical("/tmp*"));
assert_eq!(structured("rm -rf /tmp/build"), OperandVerdict::NeedsFs);
assert_eq!(structured("rm -rf C:x"), OperandVerdict::NeedsFs);
}
#[test]
fn an_environment_resolved_expansion_answers_needs_fs() {
assert_eq!(structured("rm -rf $HOME/*"), OperandVerdict::NeedsFs);
assert_eq!(structured("rm -rf ${TMPDIR}/x"), OperandVerdict::NeedsFs);
assert_eq!(ask("rm -rf $TMP/*"), unresolvable("__TRACKED_VAR__/*"));
}
#[test]
fn an_interior_glob_reaches_the_arm_that_counts_what_it_would_enumerate() {
assert_eq!(structured("rm -rf a/*/b/*"), OperandVerdict::NeedsFs);
}
#[test]
fn an_ask_from_any_operand_outranks_a_needs_fs_from_another() {
assert_eq!(
ask("rm -rf /tmp/build $D/*"),
unresolvable("__TRACKED_VAR__/*")
);
assert_eq!(structured("ls -la /"), OperandVerdict::Clear);
assert_eq!(structured("rm -rf"), OperandVerdict::Clear);
assert_eq!(structured(""), OperandVerdict::Clear);
}
#[test]
fn the_trailing_glob_fixpoint_strips_only_a_trailing_run() {
assert_eq!(trailing_glob_fixpoint("/a/b/*"), "/a/b");
assert_eq!(trailing_glob_fixpoint("/a/*/b/*"), "/a/*/b");
assert_eq!(trailing_glob_fixpoint("/a/**/"), "/a");
assert_eq!(
trailing_glob_fixpoint("/*"),
"/",
"an empty strip becomes the root"
);
assert_eq!(trailing_glob_fixpoint("/a/b"), "/a/b");
assert_eq!(trailing_glob_fixpoint("/a//b/*"), "/a/b");
assert_eq!(trailing_glob_fixpoint("/a/b/../*"), "/a");
assert_eq!(trailing_glob_fixpoint(&format!("{CWD}/*")), CWD);
assert_eq!(relative_z(&format!("{CWD}/a/*/b")), "a/*/b");
assert_eq!(relative_z("/a/b"), "/a/b");
}
#[test]
fn the_critical_path_test_answers_for_a_glob_a_root_and_a_top_level_name() {
assert!(is_critical_path("*"));
assert!(is_critical_path("/x/*"));
assert!(is_critical_path("/"));
assert!(is_critical_path("//"));
assert!(is_critical_path("\\"));
assert!(is_critical_path("C:"));
assert!(is_critical_path("C:/"));
assert!(is_critical_path("/tmp"));
assert!(is_critical_path("/tmp/"));
assert!(is_critical_path("C:/x"));
assert!(!is_critical_path("/tmp/build"));
assert!(!is_critical_path("C:x"));
assert!(!is_critical_path("C:/x/y"));
}
#[test]
fn normalize_is_the_node_posix_path_normalize() {
assert_eq!(normalize("/a//b/./c"), "/a/b/c");
assert_eq!(normalize("a/b/../c"), "a/c");
assert_eq!(normalize("../a"), "../a");
assert_eq!(normalize("../../a"), "../../a");
assert_eq!(normalize("/../a"), "/a");
assert_eq!(normalize("a/.."), ".");
assert_eq!(normalize("/a/.."), "/");
assert_eq!(normalize(""), ".");
}
#[test]
fn the_path_helpers_are_the_node_ones_they_are_named_for() {
assert_eq!(dirname("/a/b"), "/a");
assert_eq!(dirname("/a"), "/");
assert_eq!(dirname("a"), ".", "no separator at all");
assert_eq!(collapse_slashes("a\\\\b//c"), "a/b/c");
assert_eq!(collapse_slashes("a"), "a");
assert!(has_dotdot_after_segment("a/../b"));
assert!(has_dotdot_after_segment("a/./../b"));
assert!(!has_dotdot_after_segment("../b"));
assert!(!has_dotdot_after_segment("../../b"));
assert!(!has_dotdot_after_segment("a/b"));
assert!(!has_dotdot_after_segment("/../b"));
assert!(!has_dotdot_after_segment("./../b"));
assert!(has_dotdot_segment("../b"));
assert!(!has_dotdot_segment("a/..b"));
assert!(ends_with_star_slash("a/*/"));
assert!(!ends_with_star_slash("a/*"));
assert!(!ends_with_star_slash("a/b/"));
}