use super::*;
fn drift_test_config() -> crate::core::config::ResolvedCrateConfig {
let cfg: crate::core::config::NewAlefConfig = toml::from_str(
r#"
[workspace]
languages = ["rust"]
[[crates]]
name = "sample"
sources = ["src/lib.rs"]
"#,
)
.expect("valid config");
cfg.resolve().expect("resolvable").remove(0)
}
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 drifted_marked_paths_reports_a_marked_file_whose_body_no_longer_matches() {
let dir = tempfile::tempdir().expect("tempdir");
let old_file = gen_file("lib.rs", "pub fn greet() -> &'static str { \"old\" }\n");
let old_rendered = crate::cli::commands::adopt::managed_outputs(std::slice::from_ref(&old_file), dir.path());
std::fs::write(dir.path().join("lib.rs"), &old_rendered[0].content).unwrap();
let files = vec![gen_file("lib.rs", "pub fn greet() -> &'static str { \"new\" }\n")];
let (drifted, _stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert_eq!(
drifted,
vec![dir.path().join("lib.rs").display().to_string()],
"a marked file whose source changed since it was last written must be reported drifted"
);
}
#[test]
fn drifted_marked_paths_is_silent_once_the_marked_file_matches_the_fresh_render() {
let dir = tempfile::tempdir().expect("tempdir");
let file = gen_file("lib.rs", "pub fn greet() -> &'static str { \"new\" }\n");
let rendered = crate::cli::commands::adopt::managed_outputs(std::slice::from_ref(&file), dir.path());
std::fs::write(dir.path().join("lib.rs"), &rendered[0].content).unwrap();
let files = vec![file];
let (drifted, _stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert!(drifted.is_empty());
}
#[test]
fn drifted_marked_paths_ignores_a_declared_user_owned_file_even_when_it_still_has_an_old_marker() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::create_dir_all(dir.path().join("test")).expect("test directory");
std::fs::write(
dir.path().join("alef.toml"),
"[workspace]\nlanguages = [\"rust\"]\n\
[workspace.ownership]\nuser_owned = [\"test/manual.rs\"]\n\
[[crates]]\nname = \"sample\"\nsources = [\"src/lib.rs\"]\n",
)
.expect("ownership config");
let old_file = gen_file("test/manual.rs", "pub fn manual() -> u8 { 1 }\n");
let rendered = crate::cli::commands::adopt::managed_outputs(std::slice::from_ref(&old_file), dir.path());
std::fs::write(dir.path().join("test/manual.rs"), &rendered[0].content).expect("marked legacy file");
let fresh = vec![gen_file("test/manual.rs", "pub fn manual() -> u8 { 2 }\n")];
let (drifted, stats) = drifted_marked_paths(&fresh, dir.path(), &drift_test_config());
assert!(
drifted.is_empty(),
"a declared user-owned path is outside alef's drift verdict"
);
assert_eq!(stats, FormatDriftStats::default());
}
#[test]
fn drifted_marked_paths_ignores_a_file_that_carries_no_marker_at_all() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("lib.rs"), "pub fn greet() {}\n").unwrap();
let files = vec![gen_file("lib.rs", "pub fn greet() { /* changed */ }\n")];
let (drifted, _stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert!(drifted.is_empty());
}
#[test]
fn drifted_marked_paths_now_catches_a_toml_file_via_the_real_poly_fmt_pass() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let header = crate::core::hash::header(crate::core::hash::CommentStyle::Hash);
std::fs::write(
dir.path().join("pyproject.toml"),
format!("{header}\n[project]\nname = \"old\"\n"),
)
.unwrap();
let files = vec![gen_file("pyproject.toml", "[project]\nname=\"new\"\n")];
let (drifted, stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert_eq!(
drifted,
vec![dir.path().join("pyproject.toml").display().to_string()],
"a marked TOML file whose source changed must now be reported drifted via the real \
formatter pass, not silently predicted-and-missed"
);
assert_eq!(
stats.compared, 1,
"the real-formatter pass must have actually examined this file"
);
assert_eq!(stats.skipped_missing_formatter, 0);
}
#[test]
fn drifted_marked_paths_is_silent_once_a_toml_file_matches_the_real_formatters_output() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let header = crate::core::hash::header(crate::core::hash::CommentStyle::Hash);
let rendered_raw = "[project]\nname=\"same\"\n";
let scratch = dir.path().join("scratch.toml");
std::fs::write(&scratch, format!("{header}\n{rendered_raw}")).unwrap();
crate::cli::pipeline::poly_format_strict(std::slice::from_ref(&scratch), dir.path())
.expect("poly fmt must succeed");
let converged = std::fs::read_to_string(&scratch).unwrap();
std::fs::write(dir.path().join("pyproject.toml"), &converged).unwrap();
std::fs::remove_file(&scratch).ok();
let files = vec![gen_file("pyproject.toml", rendered_raw)];
let (drifted, stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert!(
drifted.is_empty(),
"an already up-to-date TOML file must not be reported drifted: {drifted:?}"
);
assert_eq!(stats.compared, 1);
}
#[test]
fn drifted_marked_paths_reports_a_self_marking_file_whose_body_no_longer_matches() {
let dir = tempfile::tempdir().expect("tempdir");
let header = crate::core::hash::header(crate::core::hash::CommentStyle::DoubleSlash);
std::fs::write(
dir.path().join("reference.md"),
format!("{header}Describes `greet`, which says hi.\n"),
)
.unwrap();
let files = vec![gen_file_unheadered(
"reference.md",
&format!("{header}Describes `greet`, which says hi warmly.\n"),
)];
let (drifted, _stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert_eq!(
drifted,
vec![dir.path().join("reference.md").display().to_string()],
"a self-marking file (marker baked into content, generated_header: false) whose body \
changed must still be reported drifted"
);
}
#[test]
fn drifted_marked_paths_is_silent_once_a_self_marking_file_matches() {
let dir = tempfile::tempdir().expect("tempdir");
let header = crate::core::hash::header(crate::core::hash::CommentStyle::DoubleSlash);
let content = format!("{header}Describes `greet`, which says hi warmly.\n");
std::fs::write(dir.path().join("reference.md"), &content).unwrap();
let files = vec![gen_file_unheadered("reference.md", &content)];
let (drifted, _stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert!(drifted.is_empty());
}
fn e2e_override_config() -> crate::core::config::ResolvedCrateConfig {
let cfg: crate::core::config::NewAlefConfig = toml::from_str(
r#"
[workspace]
languages = ["rust"]
[[crates]]
name = "sample"
sources = ["src/lib.rs"]
[crates.e2e]
fixtures = "fixtures"
output = "e2e"
[crates.e2e.call]
function = "run"
[crates.e2e.format]
dart = "cd {dir} && dart format ."
"#,
)
.expect("valid config");
cfg.resolve().expect("resolvable").remove(0)
}
#[test]
fn a_poly_excluded_path_is_silent_while_a_genuinely_drifted_one_is_still_reported() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(
dir.path().join("poly.toml"),
"[discovery]\nexclude = [\"**/pyproject.toml\"]\n",
)
.unwrap();
let excluded_render = "[project]\nname=\"same\"\n";
let excluded = gen_file("pyproject.toml", excluded_render);
let rendered = crate::cli::commands::adopt::managed_outputs(std::slice::from_ref(&excluded), dir.path());
std::fs::write(dir.path().join("pyproject.toml"), &rendered[0].content).unwrap();
let header = crate::core::hash::header(crate::core::hash::CommentStyle::DoubleSlash);
std::fs::write(
dir.path().join("lib.rs"),
format!("{header}\npub fn greet() -> &'static str {{\n \"old\"\n}}\n"),
)
.unwrap();
let drifted_rs = gen_file("lib.rs", "pub fn greet() -> &'static str {\n \"new\"\n}\n");
let files = vec![excluded, drifted_rs];
let (drifted, stats) = drifted_marked_paths(&files, dir.path(), &drift_test_config());
assert_eq!(
drifted,
vec![dir.path().join("lib.rs").display().to_string()],
"exactly the genuinely-drifted file must be reported: the poly-excluded one is not \
reformatted by anything alef runs, so its raw render IS its disk content"
);
assert_eq!(
stats.matched_render_exactly, 1,
"only the excluded file MATCHED the render; the drifted one was settled against the render \
too but did not match, which is why it is in `drifted` above and not counted here"
);
assert_eq!(
stats.compared, 1,
"only the Rust path poly owns may be staged; no temp copy may be staged for the excluded \
TOML path poly never reaches"
);
}
#[test]
fn a_file_owned_by_an_e2e_format_override_is_counted_rather_than_judged() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::create_dir_all(dir.path().join("e2e/dart/test")).unwrap();
let header = crate::core::hash::header(crate::core::hash::CommentStyle::DoubleSlash);
std::fs::write(
dir.path().join("e2e/dart/test/smoke_test.dart"),
format!("{header}\nvoid main() {{}}\n"),
)
.unwrap();
let files = vec![gen_file(
"e2e/dart/test/smoke_test.dart",
"void main() { print('x'); }\n",
)];
let (drifted, stats) = drifted_marked_paths(&files, dir.path(), &e2e_override_config());
assert!(
drifted.is_empty(),
"alef cannot predict what `dart format` leaves on disk, so it must not claim drift: {drifted:?}"
);
assert_eq!(
stats.skipped_no_faithful_prediction, 1,
"the path must be COUNTED as unexaminable, not dropped"
);
assert_eq!(stats.compared, 0);
assert_eq!(stats.matched_render_exactly, 0);
}