use std::fs;
use std::path::Path;
use std::process::Command;
fn run(dir: &Path, args: &[&str]) -> String {
let exe = env!("CARGO_BIN_EXE_rumdl");
let output = Command::new(exe)
.current_dir(dir)
.env("RUMDL_CACHE_DIR", dir.join(".rumdl_cache"))
.args(args)
.output()
.expect("failed to execute rumdl");
let mut combined = String::from_utf8_lossy(&output.stdout).to_string();
combined.push_str(&String::from_utf8_lossy(&output.stderr));
combined
}
fn delete_workspace_index(dir: &Path) {
let path = dir.join(".rumdl_cache").join("workspace_index.bin");
assert!(
path.exists(),
"expected workspace index cache at {} after first run",
path.display()
);
fs::remove_file(&path).expect("failed to remove workspace_index.bin");
}
fn write_target(dir: &Path) {
fs::write(dir.join("b.md"), "# Target\n\n## Real Heading\n").unwrap();
}
#[test]
fn cache_hit_respects_inline_disable_for_cross_file_rule() {
let temp = tempfile::tempdir().unwrap();
let dir = temp.path();
fs::write(dir.join(".rumdl.toml"), "").unwrap();
write_target(dir);
fs::write(
dir.join("a.md"),
"# Source\n\n\
<!-- rumdl-disable MD051 -->\n\
[link](b.md#nonexistent)\n\
<!-- rumdl-enable MD051 -->\n",
)
.unwrap();
let first = run(dir, &["check", "."]);
assert!(
!first.contains("MD051"),
"baseline: inline disable should suppress MD051, got:\n{first}"
);
delete_workspace_index(dir);
let second = run(dir, &["check", "."]);
assert!(
!second.contains("MD051"),
"MD051 must stay suppressed on a cache hit (inline disable), got:\n{second}"
);
}
#[test]
fn per_file_ignores_suppresses_cross_file_rule_without_cache() {
let temp = tempfile::tempdir().unwrap();
let dir = temp.path();
fs::write(dir.join(".rumdl.toml"), "[per-file-ignores]\n\"a.md\" = [\"MD051\"]\n").unwrap();
write_target(dir);
fs::write(dir.join("a.md"), "# Source\n\n[link](b.md#nonexistent)\n").unwrap();
let out = run(dir, &["check", ".", "--no-cache"]);
assert!(
!out.contains("MD051"),
"per-file-ignores must suppress cross-file MD051 for a.md, got:\n{out}"
);
}
#[test]
fn per_file_ignores_suppresses_cross_file_rule_on_cache_hit() {
let temp = tempfile::tempdir().unwrap();
let dir = temp.path();
fs::write(dir.join(".rumdl.toml"), "[per-file-ignores]\n\"a.md\" = [\"MD051\"]\n").unwrap();
write_target(dir);
fs::write(dir.join("a.md"), "# Source\n\n[link](b.md#nonexistent)\n").unwrap();
let _ = run(dir, &["check", "."]);
delete_workspace_index(dir);
let out = run(dir, &["check", "."]);
assert!(
!out.contains("MD051"),
"per-file-ignores must suppress cross-file MD051 on a cache hit, got:\n{out}"
);
}