use super::*;
fn gen_file(rel: &str, content: &str) -> crate::core::backend::GeneratedFile {
crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from(rel),
content: content.to_string(),
generated_header: true,
}
}
fn gen_file_unheadered(rel: &str, content: &str) -> crate::core::backend::GeneratedFile {
crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from(rel),
content: content.to_string(),
generated_header: false,
}
}
#[test]
fn frozen_managed_paths_reports_an_unmarked_pre_existing_file() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("SomeType.java"), "final class SomeType {}\n").unwrap();
let files = vec![gen_file("SomeType.java", "final class SomeType {}\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert_eq!(frozen[0].path, dir.path().join("SomeType.java").display().to_string());
assert_eq!(
frozen[0].remedy.as_deref(),
Some("// This file is auto-generated by alef — DO NOT EDIT.")
);
assert_eq!(
frozen[0].near_miss, None,
"plain hand-written content has no near miss to report"
);
}
#[test]
fn frozen_managed_paths_reports_a_near_miss_when_one_is_present() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(
dir.path().join("SomeType.java"),
"// This alef-generated file should not be edited.\nfinal class SomeType {}\n",
)
.unwrap();
let files = vec![gen_file("SomeType.java", "final class SomeType {}\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert_eq!(
frozen[0].near_miss.as_deref(),
Some("// This alef-generated file should not be edited.")
);
}
#[test]
fn frozen_managed_paths_reports_nothing_when_the_existing_file_already_carries_the_marker() {
let dir = tempfile::tempdir().expect("tempdir");
let marked = format!(
"{}final class SomeType {{}}\n",
crate::core::hash::header(crate::core::hash::CommentStyle::DoubleSlash)
);
std::fs::write(dir.path().join("SomeType.java"), &marked).unwrap();
let files = vec![gen_file("SomeType.java", "final class SomeType {}\n")];
assert!(frozen_managed_paths(&files, dir.path(), &[]).is_empty());
}
#[test]
fn frozen_managed_paths_reports_nothing_when_the_file_does_not_exist() {
let dir = tempfile::tempdir().expect("tempdir");
let files = vec![gen_file("SomeType.java", "final class SomeType {}\n")];
assert!(frozen_managed_paths(&files, dir.path(), &[]).is_empty());
}
#[test]
fn frozen_managed_paths_ignores_a_hand_written_scaffold_file() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("Cargo.toml"), "[package]\nname = \"demo\"\n").unwrap();
let files = vec![gen_file_unheadered("Cargo.toml", "[package]\nname = \"demo\"\n")];
assert!(frozen_managed_paths(&files, dir.path(), &[]).is_empty());
}
#[test]
fn frozen_managed_paths_reads_the_remedy_from_self_marked_content() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("Foo.swift"), "struct Foo {}\n").unwrap();
let files = vec![gen_file_unheadered(
"Foo.swift",
"// Generated by alef. Do not edit by hand.\nstruct Foo {}\n",
)];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert_eq!(
frozen[0].remedy.as_deref(),
Some("// Generated by alef. Do not edit by hand.")
);
}
#[test]
fn frozen_managed_paths_reports_no_remedy_for_an_unmarkable_extension() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("manifest.json"), "{}\n").unwrap();
let files = vec![gen_file("manifest.json", "{}\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert_eq!(frozen[0].remedy, None);
}
#[test]
fn frozen_managed_paths_reports_nothing_for_an_unmarkable_extension_with_a_committed_ownership_record() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("manifest.json");
std::fs::write(&path, "{}\n").unwrap();
crate::cli::cache::record_scaffold_owned_path(dir.path(), &path).expect("record ownership");
let files = vec![gen_file("manifest.json", "{}\n")];
assert!(
frozen_managed_paths(&files, dir.path(), &[]).is_empty(),
"a path the committed ownership record already proves alef owns must agree with \
the write guard, which would happily overwrite it"
);
}
#[test]
fn frozen_managed_paths_offers_a_real_remedy_for_clang_format() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join(".clang-format"), "---\nBasedOnStyle: LLVM\n").unwrap();
let files = vec![gen_file(".clang-format", "---\nBasedOnStyle: LLVM\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert_eq!(
frozen[0].remedy.as_deref(),
Some("# This file is auto-generated by alef — DO NOT EDIT.")
);
}
#[test]
fn frozen_managed_paths_reports_an_unmarkable_generated_header_false_file_with_no_ownership_record() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("config.m4"), "dnl old content\n").unwrap();
let files = vec![gen_file_unheadered(
"config.m4",
"dnl Configuration for Rust-based PHP extension via ext-php-rs.\n",
)];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(
frozen.len(),
1,
"an unmarkable, generated_header: false, unmarked-content file the write guard would \
refuse must be surfaced by alef verify too"
);
assert_eq!(frozen[0].path, dir.path().join("config.m4").display().to_string());
assert_eq!(
frozen[0].remedy, None,
"`.m4` has no comment syntax alef stamps, so there is no literal marker line to hand back"
);
}
#[test]
fn frozen_managed_paths_reports_nothing_for_an_unmarkable_generated_header_false_file_with_a_committed_ownership_record()
{
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("config.m4");
std::fs::write(&path, "dnl old content\n").unwrap();
crate::cli::cache::record_scaffold_owned_path(dir.path(), &path).expect("record ownership");
let files = vec![gen_file_unheadered(
"config.m4",
"dnl Configuration for Rust-based PHP extension via ext-php-rs.\n",
)];
assert!(
frozen_managed_paths(&files, dir.path(), &[]).is_empty(),
"a path the committed ownership record already proves alef owns must agree with the \
write guard, which would happily overwrite it"
);
}
#[test]
fn every_frozen_path_is_actually_accepted_by_the_adopt_invocation_its_create_once_flag_implies() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
std::fs::write(base.join("config.m4"), "dnl old content\n").unwrap();
let seed_file = gen_file_unheadered(
"config.m4",
"dnl Configuration for Rust-based PHP extension via ext-php-rs.\n",
);
std::fs::write(base.join("SomeType.java"), "final class SomeType {}\n").unwrap();
let marker_rail_file = gen_file("SomeType.java", "final class SomeType {}\n");
let files = vec![seed_file, marker_rail_file];
let frozen = frozen_managed_paths(&files, base, &[]);
assert_eq!(
frozen.len(),
2,
"fixture precondition: both paths must be reported frozen"
);
let seed = frozen
.iter()
.find(|f| f.path.ends_with("config.m4"))
.expect("config.m4 must be in the frozen report");
assert!(
seed.create_once,
"an unmarkable, unrecorded seed must classify as create-once"
);
let adoptable = frozen
.iter()
.find(|f| f.path.ends_with("SomeType.java"))
.expect("SomeType.java must be in the frozen report");
assert!(
!adoptable.create_once,
"a marker-rail file must never classify as create-once"
);
let managed = crate::cli::commands::adopt::managed_outputs(&files, base);
let plain_write = crate::cli::commands::adopt::AdoptOptions {
target: "config.m4".to_owned(),
base_dir: base.to_path_buf(),
write: true,
converged_only: false,
clobber_create_once_seeds: false,
};
assert!(
crate::cli::commands::adopt::run(&plain_write, &managed).is_err(),
"a plain `alef adopt --write` must still refuse a create-once seed -- if this ever \
passes, `is_create_once_seed` and this fixture's `config.m4` have drifted apart"
);
let clobbering = crate::cli::commands::adopt::AdoptOptions {
clobber_create_once_seeds: true,
..plain_write
};
let seed_report = crate::cli::commands::adopt::run(&clobbering, &managed)
.expect("the exact remedy `alef verify` prints for a create-once seed must be accepted");
assert_eq!(seed_report.adopted, vec![std::path::PathBuf::from("config.m4")]);
let adopt_marker_rail = crate::cli::commands::adopt::AdoptOptions {
target: "SomeType.java".to_owned(),
base_dir: base.to_path_buf(),
write: true,
converged_only: false,
clobber_create_once_seeds: false,
};
let adoptable_report = crate::cli::commands::adopt::run(&adopt_marker_rail, &managed).expect(
"the remedy `alef verify` prints for a genuinely adoptable frozen file must be accepted \
under a plain --write",
);
assert_eq!(
adoptable_report.adopted,
vec![std::path::PathBuf::from("SomeType.java")]
);
}
#[test]
fn has_adoptable_frozen_files_is_true_when_one_of_several_frozen_files_is_adoptable() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("seed.zzz"), "old seed content\n").unwrap();
std::fs::write(dir.path().join("SomeType.java"), "final class SomeType {}\n").unwrap();
let files = vec![
gen_file_unheadered("seed.zzz", "fresh seed content\n"),
gen_file("SomeType.java", "final class SomeType {}\n"),
];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 2, "fixture precondition: both paths must be frozen");
assert!(
has_adoptable_frozen_files(&frozen),
"a genuinely adoptable frozen file must still be detected even alongside a \
create-once seed that must not gate the exit code on its own"
);
}
#[test]
fn has_adoptable_frozen_files_is_false_for_an_empty_list() {
assert!(!super::has_adoptable_frozen_files(&[]));
}
#[test]
fn has_adoptable_frozen_files_is_false_when_every_frozen_file_is_a_create_once_seed() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("seed.zzz"), "old seed content\n").unwrap();
let files = vec![crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("seed.zzz"),
content: "fresh seed content\n".to_string(),
generated_header: false,
}];
let frozen = super::frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(
frozen.len(),
1,
"fixture precondition: exactly one frozen create-once seed"
);
assert!(
frozen[0].create_once,
"fixture precondition: the seed must classify as create-once"
);
assert!(
!super::has_adoptable_frozen_files(&frozen),
"a frozen list of only create-once seeds has nothing `alef adopt --write` accepts, so \
verify must not gate its exit code on it"
);
}
#[test]
fn has_adoptable_frozen_files_is_true_when_a_real_adoptable_frozen_file_remains() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("binding.rs"), "fn hand_written() {}\n").unwrap();
let files = vec![crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("binding.rs"),
content: "fn generated() {}\n".to_string(),
generated_header: true,
}];
let frozen = super::frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1, "fixture precondition: exactly one frozen file");
assert!(
!frozen[0].create_once,
"fixture precondition: this one is on the marker rail"
);
assert!(super::has_adoptable_frozen_files(&frozen));
}
#[test]
fn report_lines_omits_a_create_once_seed_and_never_names_the_clobber_flag() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("LICENSE"), "Copyright the consumer\n").unwrap();
let files = vec![gen_file_unheadered("LICENSE", "Copyright <holder>\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1, "the seed is still classified");
assert!(
frozen[0].create_once,
"an unmarked seed with unmarked content is create-once"
);
let report = super::report_lines(&frozen);
assert!(
report.is_empty(),
"a create-once seed must not be reported as frozen: {report:?}"
);
assert_eq!(super::unmarked_create_once_seeds(&frozen).len(), 1);
}
#[test]
fn report_lines_still_reports_a_genuinely_adoptable_frozen_file() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("SomeType.java"), "final class SomeType {}\n").unwrap();
let files = vec![gen_file("SomeType.java", "final class SomeType {}\n")];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
let report = super::report_lines(&frozen).join("\n");
assert!(report.contains("Frozen generated files detected"), "{report}");
assert!(report.contains("SomeType.java"), "{report}");
assert!(report.contains("alef adopt <path> --write"), "{report}");
assert!(
!report.contains("add marker:"),
"the report must never instruct a reader to hand-paste the marker -- that is the exact \
workflow the write guard warns against: {report}"
);
assert!(super::unmarked_create_once_seeds(&frozen).is_empty());
}
#[test]
fn frozen_managed_paths_marks_a_frozen_file_whose_body_differs_as_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(
dir.path().join("Widget.java"),
"final class Widget { String v = \"1.2.1\"; }\n",
)
.unwrap();
let files = vec![gen_file(
"Widget.java",
"final class Widget { String v = \"1.4.2\"; }\n",
)];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert!(
frozen[0].drifted,
"the file on disk is not what alef would write, and the report has to be able to say so"
);
}
#[test]
fn frozen_managed_paths_does_not_mark_a_body_identical_frozen_file_as_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let body = "final class Widget { String v = \"1.4.2\"; }\n";
std::fs::write(dir.path().join("Widget.java"), body).unwrap();
let files = vec![gen_file("Widget.java", body)];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1, "still frozen: alef cannot prove it owns the file");
assert!(
!frozen[0].drifted,
"but not stale -- the only withheld difference is the header alef would add"
);
}
#[test]
fn frozen_managed_paths_does_not_mark_a_converged_shell_script_as_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let body = "#!/usr/bin/env bash\nset -euo pipefail\nrun\n";
std::fs::write(dir.path().join("run_tests.sh"), body).unwrap();
let files = vec![gen_file("run_tests.sh", body)];
let frozen = frozen_managed_paths(&files, dir.path(), &[]);
assert_eq!(frozen.len(), 1);
assert!(
!frozen[0].drifted,
"the header goes below the shebang, which is a header-only difference like any other"
);
}
#[test]
fn report_lines_distinguish_a_stale_frozen_file_from_a_settled_one() {
let lines = report_lines(&[
adoptable_frozen("/repo/Stale.java", true),
adoptable_frozen("/repo/Settled.java", false),
])
.join("\n");
assert!(
lines.contains("/repo/Stale.java"),
"the drifted file must be named, since no count identifies which file went stale"
);
assert!(
lines.contains("content DIFFERS from what alef would generate"),
"and must be described as differing, not merely as unowned: {lines}"
);
assert!(
lines.contains("content already matches what alef would generate"),
"the settled file must read as benign -- otherwise a reader has to open every file to \
find the one that matters: {lines}"
);
}
fn adoptable_frozen(path: &str, drifted: bool) -> FrozenFile {
FrozenFile {
path: path.to_owned(),
remedy: None,
near_miss: None,
create_once: false,
drifted,
rewritten_every_run: true,
}
}
#[test]
fn a_markable_unmarked_seed_under_a_rewritten_root_is_reported_as_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let root = dir.path().join("e2e");
std::fs::create_dir_all(root.join("php")).unwrap();
std::fs::write(root.join("php/install.sh"), "#!/usr/bin/env bash\nVERSION=1.2.1\n").unwrap();
let files = vec![gen_file_unheadered(
"e2e/php/install.sh",
"#!/usr/bin/env bash\nVERSION=1.4.2\n",
)];
let frozen = frozen_managed_paths(&files, dir.path(), &[root]);
assert_eq!(frozen.len(), 1, "the file must reach the frozen walk at all");
assert!(frozen[0].drifted && frozen[0].create_once && frozen[0].rewritten_every_run);
assert_eq!(
drifted_frozen_seeds(&frozen),
vec![dir.path().join("e2e/php/install.sh").display().to_string()],
"a seed alef re-renders every run, whose content differs, is the withheld-and-stale case"
);
let report = drifted_seed_report_lines(&frozen).join("\n");
assert!(
report.contains("install.sh"),
"the report must name the file, not only count it: {report}"
);
}
#[test]
fn a_markable_unmarked_seed_under_a_rewritten_root_that_matches_is_not_reported_as_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let root = dir.path().join("e2e");
std::fs::create_dir_all(root.join("php")).unwrap();
let body = "#!/usr/bin/env bash\nVERSION=1.4.2\n";
std::fs::write(root.join("php/install.sh"), body).unwrap();
let files = vec![gen_file_unheadered("e2e/php/install.sh", body)];
let frozen = frozen_managed_paths(&files, dir.path(), &[root]);
assert_eq!(
frozen.len(),
1,
"still an unmarked seed alef makes no content claim about"
);
assert!(!frozen[0].drifted);
assert!(drifted_frozen_seeds(&frozen).is_empty());
assert!(
drifted_seed_report_lines(&frozen).is_empty(),
"a benign frozen seed must produce no heading at all"
);
}
#[test]
fn the_same_drifted_seed_outside_a_rewritten_root_is_not_reported() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::create_dir_all(dir.path().join("packages/php")).unwrap();
std::fs::write(
dir.path().join("packages/php/install.sh"),
"#!/usr/bin/env bash\nVERSION=1.2.1\n",
)
.unwrap();
let files = vec![gen_file_unheadered(
"packages/php/install.sh",
"#!/usr/bin/env bash\nVERSION=1.4.2\n",
)];
assert!(
frozen_managed_paths(&files, dir.path(), &[dir.path().join("e2e")]).is_empty(),
"a create-once seed alef never re-attempts is not frozen and not drifted"
);
}
#[test]
fn sign_off_line_is_not_the_unqualified_up_to_date_sentence_when_seeds_have_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let root = dir.path().join("e2e");
std::fs::create_dir_all(root.join("php")).unwrap();
std::fs::create_dir_all(root.join("node")).unwrap();
std::fs::write(root.join("php/install.sh"), "#!/usr/bin/env bash\nVERSION=1.2.1\n").unwrap();
std::fs::write(root.join("node/install.sh"), "#!/usr/bin/env bash\nVERSION=1.2.1\n").unwrap();
let files = vec![
gen_file_unheadered("e2e/php/install.sh", "#!/usr/bin/env bash\nVERSION=1.4.2\n"),
gen_file_unheadered("e2e/node/install.sh", "#!/usr/bin/env bash\nVERSION=1.4.2\n"),
];
let frozen = frozen_managed_paths(&files, dir.path(), &[root]);
let drifted = drifted_frozen_seeds(&frozen);
assert_eq!(
drifted.len(),
2,
"both version-bearing fixtures must be counted as drifted create-once seeds: {drifted:?}"
);
let sign_off = report_sign_off_line(drifted.len());
assert_ne!(
sign_off, "All bindings and versions are up to date.",
"a run that just reported drifted frozen paths must never also assert the unqualified \
sign-off for the same run: {sign_off}"
);
assert_eq!(
sign_off,
"2 frozen path(s) drifted and not enforced (see the DRIFTED block above); everything \
else is up to date.",
"the sign-off must state the exact count and stay honest about what it does and does \
not cover"
);
}
#[test]
fn sign_off_line_stays_the_unqualified_sentence_when_nothing_has_drifted() {
assert_eq!(report_sign_off_line(0), "All bindings and versions are up to date.");
}