use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
fn alef_binary() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_alef"))
}
fn run_alef(root: &Path, args: &[&str]) -> Output {
Command::new(alef_binary())
.current_dir(root)
.args(args)
.output()
.unwrap_or_else(|error| panic!("run alef {args:?}: {error}"))
}
fn context(output: &Output) -> String {
format!(
"stdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
)
}
fn write_snippet_root(root: &Path) -> PathBuf {
let snippets = root.join("snippets");
fs::create_dir_all(&snippets).expect("create snippets directory");
fs::write(snippets.join("hello.md"), "```json\n{\"hello\": \"world\"}\n```\n").expect("write snippet fixture");
snippets
}
#[test]
fn audit_names_the_missing_snippets_root_instead_of_a_coverage_ledger_walk() {
let dir = tempfile::tempdir().expect("temporary workspace");
let missing = dir.path().join("snippets-never-created");
let output = run_alef(
dir.path(),
&["snippets", "audit", "--snippets", &missing.to_string_lossy()],
);
assert!(
!output.status.success(),
"a snippets root that does not exist must fail the audit.\n{}",
context(&output)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("configured snippet directory does not exist"),
"the diagnostic must name the real cause -- a configured directory that is not there -- \
not the coverage-ledger walk that happened to trip over it first.\n{}",
context(&output)
);
assert!(
stderr.contains(&missing.display().to_string()),
"the diagnostic must name the missing path.\n{}",
context(&output)
);
}
#[test]
fn audit_fails_on_a_missing_docs_root_instead_of_reporting_it_clean() {
let dir = tempfile::tempdir().expect("temporary workspace");
let snippets = write_snippet_root(dir.path());
let missing = dir.path().join("docs-never-created");
let output = run_alef(
dir.path(),
&[
"snippets",
"audit",
"--snippets",
&snippets.to_string_lossy(),
"--docs",
&missing.to_string_lossy(),
],
);
assert!(
!output.status.success(),
"a documentation root that does not exist must fail the audit -- reporting it clean \
means claiming a tree was audited when not one file in it was opened.\n{}",
context(&output)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("configured documentation directory does not exist"),
"the diagnostic must name the missing documentation root.\n{}",
context(&output)
);
assert!(
stderr.contains(&missing.display().to_string()),
"the diagnostic must name the missing path.\n{}",
context(&output)
);
}
#[test]
fn gaps_names_the_missing_docs_root_instead_of_reporting_every_snippet_unreferenced() {
let dir = tempfile::tempdir().expect("temporary workspace");
let snippets = write_snippet_root(dir.path());
let missing = dir.path().join("docs-never-created");
let output = run_alef(
dir.path(),
&[
"snippets",
"gaps",
"--snippets",
&snippets.to_string_lossy(),
"--docs",
&missing.to_string_lossy(),
],
);
assert!(
!output.status.success(),
"a documentation root that does not exist must fail the gap report.\n{}",
context(&output)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("configured documentation directory does not exist"),
"the gap report used to fail for the wrong reason -- with no docs tree to walk, every \
snippet reads as unreferenced -- which points the user at their snippets instead of at \
the path that is not there.\n{}",
context(&output)
);
assert!(
!String::from_utf8_lossy(&output.stdout).contains("Unreferenced snippets"),
"the misleading unreferenced-snippet finding must not be reported for a docs root that \
was never walked.\n{}",
context(&output)
);
}
#[test]
fn an_existing_empty_docs_root_still_audits_clean() {
let dir = tempfile::tempdir().expect("temporary workspace");
let snippets = write_snippet_root(dir.path());
let docs = dir.path().join("docs");
fs::create_dir_all(&docs).expect("create empty docs directory");
let output = run_alef(
dir.path(),
&[
"snippets",
"audit",
"--snippets",
&snippets.to_string_lossy(),
"--docs",
&docs.to_string_lossy(),
],
);
assert!(
output.status.success(),
"an existing but empty documentation root is not a misconfiguration.\n{}",
context(&output)
);
}
const FIXTURE_SOURCE: &str = "pub fn greet(name: String) -> String {\n name\n}\n";
const FIXTURE_CARGO_TOML: &str =
"[package]\nname = \"verify-missing-dir-fixture\"\nversion = \"0.1.0\"\nedition = \"2024\"\n";
const FIXTURE_ALEF_TOML: &str = r#"
[workspace]
languages = ["python"]
[workspace.docs.snippets]
dirs = ["snippets"]
inline_dirs = ["docs/guides-removed-after-generation"]
[[crates]]
name = "verify-missing-dir-fixture"
sources = ["src/lib.rs"]
version_from = "Cargo.toml"
[crates.python]
module_name = "verify_missing_dir_fixture"
[crates.python.stubs]
output = "packages/python/verify_missing_dir_fixture"
"#;
#[test]
fn verify_reports_a_configured_snippet_root_that_does_not_exist() {
let dir = tempfile::tempdir().expect("temporary workspace");
let root = dir.path().canonicalize().unwrap_or_else(|_| dir.path().to_path_buf());
fs::create_dir_all(root.join("src")).expect("create fixture src directory");
fs::write(root.join("src/lib.rs"), FIXTURE_SOURCE).expect("write fixture source");
fs::write(root.join("Cargo.toml"), FIXTURE_CARGO_TOML).expect("write fixture Cargo.toml");
fs::write(root.join("alef.toml"), FIXTURE_ALEF_TOML).expect("write fixture alef.toml");
write_snippet_root(&root);
let removed_root = root.join("docs/guides-removed-after-generation");
fs::create_dir_all(&removed_root).expect("create the root that generation requires");
let generated = run_alef(&root, &["all", "--skip-frb"]);
assert!(
generated.status.success(),
"alef all must succeed against the fixture.\n{}",
context(&generated)
);
fs::remove_dir_all(&removed_root).expect("remove the configured root after generation");
let output = run_alef(&root, &["verify"]);
assert!(
!output.status.success(),
"verify must fail on a configured docs.snippets root that does not exist -- passing \
means every snippet check that walks it was graded against nothing.\n{}",
context(&output)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("docs/guides-removed-after-generation"),
"verify must name the configured entry that does not resolve.\n{}",
context(&output)
);
assert!(
stdout.contains("Configured docs.snippets roots that do not exist"),
"the finding must have its own section, distinct from coverage-ledger staleness.\n{}",
context(&output)
);
let report_only = run_alef(&root, &["verify", "--report-only"]);
assert!(
report_only.status.success(),
"--report-only must keep a successful exit status, as it does for every other verify \
finding.\n{}",
context(&report_only)
);
assert!(
String::from_utf8_lossy(&report_only.stdout).contains("docs/guides-removed-after-generation"),
"--report-only must still print the finding.\n{}",
context(&report_only)
);
}