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 e2e_poly_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.registry]
output = "test_apps"
"#,
)
.expect("valid config");
cfg.resolve().expect("resolvable").remove(0)
}
#[test]
fn poly_probe_roots_match_the_e2e_writers_per_language_working_directories() {
let dir = tempfile::tempdir().expect("tempdir");
for relative in ["e2e/java", "e2e/python", "test_apps/java"] {
std::fs::create_dir_all(dir.path().join(relative)).unwrap();
}
assert_eq!(
poly_probe_roots(&e2e_poly_config(), dir.path()),
vec![
dir.path().to_path_buf(),
dir.path().join("e2e/java"),
dir.path().join("e2e/python"),
dir.path().join("test_apps/java"),
]
);
}
fn real_formatter_drift(
candidates: Vec<RealFormatCandidate>,
base_dir: &std::path::Path,
) -> (Vec<String>, FormatDriftStats) {
real_formatter_drift_with(candidates, base_dir, &crate::cli::pipeline::is_tool_available)
}
fn candidate(full_path: &std::path::Path, disk_content: &str, rendered_content: &str) -> RealFormatCandidate {
RealFormatCandidate {
full_path: full_path.to_path_buf(),
disk_content: disk_content.to_string(),
rendered_content: rendered_content.to_string(),
format_context: full_path.parent().unwrap_or(full_path).to_path_buf(),
}
}
#[test]
fn skips_and_counts_every_candidate_when_poly_is_unavailable() {
let dir = tempfile::tempdir().expect("tempdir");
let candidates = vec![
candidate(&dir.path().join("a.toml"), "[a]\nx = 1\n", "[a]\nx=1\n"),
candidate(&dir.path().join("b.py"), "x = 1\n", "x=1\n"),
];
let (drifted, stats) = real_formatter_drift_with(candidates, dir.path(), &|_tool| false);
assert!(
drifted.is_empty(),
"a skipped comparison must never manufacture a drift finding: {drifted:?}"
);
assert_eq!(
stats,
FormatDriftStats {
compared: 0,
skipped_missing_formatter: 2,
skipped_staging_error: 0,
skipped_no_faithful_prediction: 0,
matched_render_exactly: 0,
},
"every candidate must be counted as skipped, never silently dropped, when poly is absent"
);
}
#[test]
fn is_a_trivial_no_op_on_an_empty_candidate_list() {
let dir = tempfile::tempdir().expect("tempdir");
let (drifted, stats) = real_formatter_drift_with(Vec::new(), dir.path(), &|_tool| true);
assert!(drifted.is_empty());
assert_eq!(stats, FormatDriftStats::default());
}
#[test]
fn catches_a_toml_file_whose_rendered_value_genuinely_differs_from_disk() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let real_path = dir.path().join("pyproject.toml");
std::fs::write(&real_path, "[project]\nname = \"old\"\n").unwrap();
let candidates = vec![candidate(
&real_path,
"[project]\nname = \"old\"\n",
"[project]\nname=\"new\"\n",
)];
let (drifted, stats) = real_formatter_drift(candidates, dir.path());
assert_eq!(drifted, vec![real_path.display().to_string()]);
assert_eq!(
stats,
FormatDriftStats {
compared: 1,
skipped_missing_formatter: 0,
skipped_staging_error: 0,
skipped_no_faithful_prediction: 0,
matched_render_exactly: 0,
}
);
}
#[test]
fn is_silent_once_poly_fmt_converges_the_render_to_match_disk() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let real_path = dir.path().join("pyproject.toml");
let rendered = "[project]\nname=\"same\"\n";
let (_drifted, _stats) = real_formatter_drift(
vec![candidate(&real_path, "placeholder -- overwritten below", rendered)],
dir.path(),
);
let formatted_once = format_once_for_test(rendered, dir.path());
std::fs::write(&real_path, &formatted_once).unwrap();
let (drifted, stats) = real_formatter_drift(vec![candidate(&real_path, &formatted_once, rendered)], dir.path());
assert!(
drifted.is_empty(),
"an already-converged file must not be reported drifted: {drifted:?}"
);
assert_eq!(stats.compared, 1);
}
#[test]
fn formatter_managed_e2e_manifests_verify_after_generation_formatting() {
let dir = tempfile::tempdir().expect("tempdir");
let cases = [
"test_apps/csharp/Xberg.E2eTests.csproj",
"test_apps/java/pom.xml",
"test_apps/zig/build.zig.zon",
];
let mut candidates = Vec::new();
for relative in cases {
let path = dir.path().join(relative);
std::fs::create_dir_all(path.parent().expect("manifest parent")).expect("create manifest parent");
std::fs::write(&path, "formatted\n").expect("write formatted manifest");
candidates.push(candidate(&path, "formatted\n", "raw render\n"));
}
let run_filename_keyed_formatter = |paths: &[std::path::PathBuf], _base: &std::path::Path| {
let mut formatted = 0usize;
for path in paths {
let name = path.file_name().and_then(|name| name.to_str()).unwrap_or_default();
if matches!(name, "Xberg.E2eTests.csproj" | "pom.xml" | "build.zig.zon") {
std::fs::write(path, "formatted\n")?;
formatted += 1;
}
}
anyhow::ensure!(
formatted == paths.len(),
"formatter reached {formatted} of {} canonical manifest names",
paths.len()
);
Ok(())
};
let (drifted, stats) = real_formatter_drift_with_runner(
candidates,
dir.path(),
&|tool| tool == "poly",
&run_filename_keyed_formatter,
);
assert!(
drifted.is_empty(),
"freshly generated and formatted E2E manifests must verify without false drift: {drifted:?}"
);
assert_eq!(
stats.compared, 3,
"all three formatter-managed manifests must be compared"
);
}
#[test]
fn formatter_candidates_run_in_the_same_language_context_as_the_e2e_writer() {
let dir = tempfile::tempdir().expect("tempdir");
let language_root = dir.path().join("e2e/java");
let real_path = language_root.join("src/test/java/io/example/e2e/SmokeTest.java");
std::fs::create_dir_all(real_path.parent().expect("test parent")).unwrap();
std::fs::write(&real_path, "formatted\n").unwrap();
let mut item = candidate(&real_path, "formatted\n", "raw render\n");
item.format_context = language_root.clone();
let runner = |paths: &[std::path::PathBuf], context: &std::path::Path| {
anyhow::ensure!(
context == language_root,
"wrong formatter context: {}",
context.display()
);
anyhow::ensure!(paths.len() == 1, "expected one staged path, got {}", paths.len());
std::fs::write(&paths[0], "formatted\n")?;
Ok(())
};
let (drifted, stats) = real_formatter_drift_with_runner(vec![item], dir.path(), &|tool| tool == "poly", &runner);
assert!(
drifted.is_empty(),
"writer-context formatting must converge: {drifted:?}"
);
assert_eq!(stats.compared, 1);
}
#[test]
fn real_poly_formats_a_gitignored_staged_e2e_render() {
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 = [\"**/e2e/**\"]\n").unwrap();
std::fs::write(dir.path().join(".gitignore"), "e2e/python/alef-verify-drift-*/\n").unwrap();
let language_root = dir.path().join("e2e/python");
let real_path = language_root.join("test_smoke.py");
std::fs::create_dir_all(real_path.parent().expect("test parent")).unwrap();
let raw = "value=1\n";
std::fs::write(&real_path, raw).unwrap();
for args in [
vec!["init", "--quiet"],
vec!["config", "user.email", "alef-tests@example.invalid"],
vec!["config", "user.name", "Alef Tests"],
vec!["add", "poly.toml", ".gitignore"],
vec!["add", "e2e/python/test_smoke.py"],
vec!["commit", "--quiet", "-m", "fixture"],
] {
let status = std::process::Command::new("git")
.args(args)
.current_dir(dir.path())
.status()
.expect("git must run");
assert!(status.success(), "git fixture setup must succeed");
}
crate::cli::pipeline::poly_format_strict(&[std::path::PathBuf::from(".")], &language_root)
.expect("the writer-context formatter must run");
let formatted = std::fs::read_to_string(&real_path).unwrap();
assert_ne!(formatted, raw, "fixture must prove the real Python formatter ran");
let mut item = candidate(&real_path, &formatted, raw);
item.format_context = language_root;
let saw_ignored_staging_path = std::cell::Cell::new(false);
let runner = |paths: &[std::path::PathBuf], context: &std::path::Path| {
assert_eq!(paths.len(), 1, "one staged candidate must reach poly");
let ignored = std::process::Command::new("git")
.args(["check-ignore", "--quiet", "--"])
.arg(&paths[0])
.current_dir(dir.path())
.status()?;
assert!(ignored.success(), "the staging directory must be gitignored");
saw_ignored_staging_path.set(true);
crate::cli::pipeline::poly_format_strict_including_excluded(paths, context)
};
let (drifted, stats) = real_formatter_drift_with_runner(vec![item], dir.path(), &|tool| tool == "poly", &runner);
assert!(
drifted.is_empty(),
"a gitignored staged copy must converge to the writer's real output: {drifted:?}"
);
assert!(
saw_ignored_staging_path.get(),
"the gitignore negative control must run"
);
assert_eq!(stats.compared, 1);
}
#[test]
fn unchanged_stamped_render_bypasses_the_formatter_prediction() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let file = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("pyproject.toml"),
content: "[build-system]\nrequires=[\"setuptools>=68\",\"wheel\"]\n".to_owned(),
generated_header: true,
};
let rendered = crate::cli::commands::adopt::managed_outputs(std::slice::from_ref(&file), dir.path())
.pop()
.expect("one managed output")
.content;
let probe_dir = dir.path().join("probe");
std::fs::create_dir_all(&probe_dir).unwrap();
let probe = probe_dir.join("pyproject.toml");
std::fs::write(&probe, &rendered).unwrap();
crate::cli::pipeline::poly_format_strict(std::slice::from_ref(&probe), &probe_dir)
.expect("poly must format the negative-control render");
assert_ne!(
std::fs::read_to_string(&probe).unwrap(),
rendered,
"negative control must prove that formatting the unstamped render changes it"
);
let hash = crate::core::hash::hash_content(&rendered);
std::fs::write(
dir.path().join(&file.path),
crate::core::hash::inject_hash_line(&rendered, &hash),
)
.unwrap();
let (drifted, stats) =
drifted_marked_paths_with(std::slice::from_ref(&file), dir.path(), &drift_test_config(), &|tool| {
tool == "poly"
});
assert!(
drifted.is_empty(),
"an unchanged writer input cannot be formatter drift"
);
assert_eq!(stats.matched_render_exactly, 1);
assert_eq!(stats.compared, 0, "the impossible formatter pass must not run");
}
#[test]
fn drift_check_ignores_create_once_seeds_even_if_an_older_copy_has_a_marker() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join(".gitattributes");
let old = "# Generated by alef scaffold.\nold/** linguist-generated=true\n";
let old = crate::cli::pipeline::ensure_generated_header(&path, old);
let hash = crate::core::hash::compute_file_hash(&old);
std::fs::write(&path, crate::core::hash::inject_hash_line(&old, &hash)).unwrap();
let seed = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from(".gitattributes"),
content: "# Generated by alef scaffold.\nnew/** linguist-generated=true\n".to_string(),
generated_header: false,
};
assert!(
!crate::cli::commands::adopt::is_create_once_seed(&seed),
"fixture must reproduce the self-marker that defeats the generic seed classifier"
);
let (drifted, stats) = drifted_marked_paths_with(
std::slice::from_ref(&seed),
dir.path(),
&drift_test_config(),
&|_tool| false,
);
assert!(
drifted.is_empty(),
"create-once content is consumer-owned after creation"
);
assert_eq!(stats, FormatDriftStats::default());
}
fn format_once_for_test(content: &str, base_dir: &std::path::Path) -> String {
let scratch = base_dir.join("scratch.toml");
std::fs::write(&scratch, content).unwrap();
crate::cli::pipeline::poly_format_strict(std::slice::from_ref(&scratch), base_dir).expect("poly fmt must succeed");
let formatted = std::fs::read_to_string(&scratch).unwrap();
std::fs::remove_file(&scratch).ok();
formatted
}
#[test]
fn leaves_no_temp_file_behind_after_comparing() {
let Some(_poly) = crate::test_support::tool_available_with_stable_path("poly") else {
return;
};
let dir = tempfile::tempdir().expect("tempdir");
let real_path = dir.path().join("pyproject.toml");
std::fs::write(&real_path, "[project]\nname = \"old\"\n").unwrap();
let candidates = vec![candidate(
&real_path,
"[project]\nname = \"old\"\n",
"[project]\nname=\"new\"\n",
)];
let _ = real_formatter_drift(candidates, dir.path());
let leftovers: Vec<_> = std::fs::read_dir(dir.path())
.unwrap()
.filter_map(Result::ok)
.map(|entry| entry.file_name())
.filter(|name| name != "pyproject.toml")
.collect();
assert!(
leftovers.is_empty(),
"no temp file may survive a comparison call, found: {leftovers:?}"
);
}
#[test]
fn render_predicts_final_bytes_clears_rust_and_markdown_only_without_poly() {
let cases = [
("lib.rs", false, true),
("reference.md", false, true),
("pyproject.toml", false, false),
("bindings.go", false, false),
("noextension", false, false),
];
for (name, with_poly, without_poly) in cases {
assert_eq!(
render_predicts_final_bytes(std::path::Path::new(name), true),
with_poly,
"render_predicts_final_bytes({name:?}) with poly present must be {with_poly}"
);
assert_eq!(
render_predicts_final_bytes(std::path::Path::new(name), false),
without_poly,
"render_predicts_final_bytes({name:?}) with poly absent must be {without_poly}"
);
}
}
#[test]
fn managed_toml_drift_preview_preserves_the_existing_provenance_header() {
let dir = tempfile::tempdir().expect("tempdir");
let existing = "# This file is auto-generated by alef — DO NOT EDIT.\n\
# alef:hash:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\
# To regenerate: alef generate\n\
# To verify freshness: alef verify --exit-code\n\n\
[discovery]\nexclude = [\"generated/**\", \"consumer/**\"]\n";
let file = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("poly.toml"),
content: "[discovery]\nexclude = [\"generated/**\"]\n".to_string(),
generated_header: true,
};
let output = managed_output_for_drift(&file, existing, dir.path())
.into_iter()
.next()
.expect("managed output");
assert!(
output
.content
.contains("# To verify freshness: alef verify --exit-code")
);
assert!(output.content.contains("\"consumer/**\""));
assert!(
crate::cli::pipeline::matches_alef_output(&dir.path().join("poly.toml"), existing, &output.content),
"verification must predict the merge writer's fixed point, including its preserved header"
);
}
#[test]
fn ordinary_generated_toml_uses_the_fresh_render_without_merge_semantics() {
let dir = tempfile::tempdir().expect("tempdir");
let existing = "# This file is auto-generated by alef — DO NOT EDIT.\n\
# alef:hash:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\
# To regenerate: alef generate\n\
# To verify freshness: alef verify\n\n\
[build]\ntarget-dir = \"consumer-target\"\n";
let file = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from(".cargo/config.toml"),
content: "[build]\ntarget-dir = \"generated-target\"\n".to_string(),
generated_header: true,
};
let output = managed_output_for_drift(&file, existing, dir.path())
.into_iter()
.next()
.expect("managed output");
assert!(output.content.contains("generated-target"));
assert!(!output.content.contains("consumer-target"));
}
#[test]
fn drift_preview_preserves_an_existing_marker_for_an_unheadered_render() {
let dir = tempfile::tempdir().expect("tempdir");
let cases = [
("test_apps/csharp/Xberg.E2eTests.csproj", "<Project />\n"),
(
"test_apps/java/pom.xml",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project />\n",
),
("test_apps/zig/build.zig.zon", ".{ .name = .e2e }\n"),
];
for (relative, raw) in cases {
let path = dir.path().join(relative);
let marked = crate::cli::pipeline::ensure_generated_header(&path, raw);
let file_hash = crate::core::hash::compute_file_hash(&marked);
let existing = crate::core::hash::inject_hash_line(&marked, &file_hash);
let file = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from(relative),
content: raw.to_owned(),
generated_header: false,
};
let output = managed_output_for_drift(&file, &existing, dir.path())
.into_iter()
.next()
.expect("managed output");
assert!(
crate::cli::pipeline::matches_alef_output(&path, &existing, &output.content),
"{relative}: verify must mirror the writer's disk-aware header preservation"
);
}
}
#[test]
fn drifted_marked_paths_compares_an_rs_candidate_on_the_fast_path_when_poly_is_unavailable() {
let dir = tempfile::tempdir().expect("tempdir");
let file = crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("lib.rs"),
content: "pub fn greet() -> &'static str { \"old\" }\n".to_string(),
generated_header: true,
};
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 (drifted, stats) = drifted_marked_paths_with(
std::slice::from_ref(&file),
dir.path(),
&drift_test_config(),
&|_tool| false,
);
assert!(
drifted.is_empty(),
"an up-to-date .rs file must be compared and found clean without poly, not reported: {drifted:?}"
);
assert_eq!(
stats,
FormatDriftStats {
matched_render_exactly: 1,
..FormatDriftStats::default()
},
"a fast-path file must be counted as settled against the render, never as a real-formatter \
skip just because poly is absent"
);
let changed = vec![crate::core::backend::GeneratedFile {
path: std::path::PathBuf::from("lib.rs"),
content: "pub fn greet() -> &'static str { \"new\" }\n".to_string(),
generated_header: true,
}];
let (drifted, stats) = drifted_marked_paths_with(&changed, dir.path(), &drift_test_config(), &|_tool| false);
assert_eq!(
drifted,
vec![dir.path().join("lib.rs").display().to_string()],
"a genuinely stale .rs file must be REPORTED with poly absent -- this is the finding the \
alef#458 gate suppressed on the no-poly CI leg"
);
assert_eq!(stats, FormatDriftStats::default());
}
#[test]
fn rust_binding_bytes_on_disk_match_a_fresh_render_with_no_poly() {
if !crate::cli::pipeline::is_tool_available("rustfmt") {
return;
}
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path().canonicalize().unwrap_or_else(|_| temp.path().to_path_buf());
write_first_run_fixture(&root);
assert!(
!root.join("rustfmt.toml").exists(),
"fixture setup: this run must start with no committed rustfmt.toml, or it is not \
exercising a project's first `alef all` run at all"
);
let _cargo_guard = crate::test_support::RealCargoGuard::acquire();
let _no_poly = crate::test_support::PathWithoutToolGuard::exclude("poly");
let _cwd = crate::test_support::CwdGuard::enter(&root);
let context = crate::bin_cli::dispatch::DispatchContext {
config_path: root.join("alef.toml"),
crate_filter: Vec::new(),
};
crate::bin_cli::all_commands::handle(first_run_all_command(), &context)
.expect("alef all must succeed against a plain python fixture");
let mut compared = 0usize;
let mut mismatches = Vec::new();
for entry in walkdir::WalkDir::new(&root).into_iter().filter_map(Result::ok) {
let path = entry.path();
if !path.is_file() || path.extension().and_then(|extension| extension.to_str()) != Some("rs") {
continue;
}
let Ok(disk) = std::fs::read_to_string(path) else {
continue;
};
if !crate::core::hash::content_has_alef_marker(&disk) {
continue;
}
compared += 1;
let rerendered = crate::cli::pipeline::normalize_content(&root, path, &disk);
if rerendered != disk {
mismatches.push(format!(
"{}\n--- on disk ---\n{}\n--- fresh render ---\n{}",
path.display(),
first_differing_lines(&disk, &rerendered),
first_differing_lines(&rerendered, &disk)
));
}
}
assert!(
compared > 0,
"no marked .rs file was produced by this run, so every byte comparison above was \
vacuous -- this check examined nothing"
);
assert!(
mismatches.is_empty(),
"{compared} marked .rs file(s) compared; {} differ from a fresh in-memory render on a \
first run with no poly, so the .rs fast-path prediction is still unsound:\n{}",
mismatches.len(),
mismatches.join("\n\n")
);
}
fn first_differing_lines(left: &str, right: &str) -> String {
let start = left
.lines()
.zip(right.lines())
.position(|(l, r)| l != r)
.unwrap_or_else(|| left.lines().count().min(right.lines().count()));
left.lines().skip(start).take(6).collect::<Vec<_>>().join("\n")
}
const FIRST_RUN_FIXTURE_SOURCE: &str = "pub fn compute_widget_totals(\n \
alpha: String,\n bravo: String,\n charlie: String,\n delta: String,\n echo: String,\n \
foxtrot: String,\n golf: String,\n hotel: String,\n india: String,\n juliett: String,\n\
) -> String {\n \
format!(\"{alpha}{bravo}{charlie}{delta}{echo}{foxtrot}{golf}{hotel}{india}{juliett}\")\n\
}\n";
const FIRST_RUN_FIXTURE_CARGO_TOML: &str = "[package]\nname = \"test-lib\"\nversion = \"0.1.0\"\nedition = \"2024\"\n";
const FIRST_RUN_FIXTURE_ALEF_TOML: &str = r#"
[workspace]
languages = ["python"]
[[crates]]
name = "test-lib"
sources = ["src/lib.rs"]
version_from = "Cargo.toml"
[crates.python]
module_name = "test_lib"
[crates.python.stubs]
output = "packages/python/test_lib"
"#;
fn write_first_run_fixture(root: &std::path::Path) {
std::fs::create_dir_all(root.join("src")).expect("create fixture src directory");
std::fs::write(root.join("src/lib.rs"), FIRST_RUN_FIXTURE_SOURCE).expect("write fixture source");
std::fs::write(root.join("Cargo.toml"), FIRST_RUN_FIXTURE_CARGO_TOML).expect("write fixture Cargo.toml");
std::fs::write(root.join("alef.toml"), FIRST_RUN_FIXTURE_ALEF_TOML).expect("write fixture alef.toml");
}
fn first_run_all_command() -> crate::bin_cli::args::Commands {
crate::bin_cli::args::Commands::All {
clean: false,
clobber_create_once_seeds: false,
strict: false,
skip_frb: false,
skip_snippet_validation: false,
skip_compile: true,
}
}