use super::*;
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(),
}
}
#[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,
},
"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() {
if !crate::cli::pipeline::is_tool_available("poly") {
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,
}
);
}
#[test]
fn is_silent_once_poly_fmt_converges_the_render_to_match_disk() {
if !crate::cli::pipeline::is_tool_available("poly") {
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);
}
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() {
if !crate::cli::pipeline::is_tool_available("poly") {
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_is_gated_on_poly_availability() {
let cases = [
("lib.rs", true, true),
("reference.md", true, true),
("pyproject.toml", true, false),
("lib.rs", false, false),
("reference.md", false, false),
("pyproject.toml", false, false),
];
for (name, poly_available, expected) in cases {
assert_eq!(
render_predicts_final_bytes(std::path::Path::new(name), poly_available),
expected,
"render_predicts_final_bytes({name:?}, poly_available={poly_available}) must be {expected}"
);
}
}
#[test]
fn drifted_marked_paths_routes_an_rs_candidate_to_the_counted_skip_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 files = vec![file];
let (drifted, stats) = drifted_marked_paths_with(&files, dir.path(), &|_tool| false);
assert!(
drifted.is_empty(),
"an unprovable fast-path prediction must never manufacture a drift finding when poly is \
unavailable: {drifted:?}"
);
assert_eq!(
stats,
FormatDriftStats {
compared: 0,
skipped_missing_formatter: 1,
skipped_staging_error: 0,
},
"the .rs candidate must be counted as a loud, explicit skip -- not silently dropped, and \
not folded into a clean-looking zero"
);
}