use std::path::{Path, PathBuf};
fn plan_refs(text: &str) -> Vec<String> {
let mut refs = Vec::new();
let mut from = 0;
while let Some(pos) = text[from..].find("plans/") {
let slug_start = from + pos + "plans/".len();
let slug_end = text[slug_start..]
.find(|c: char| !(c.is_ascii_alphanumeric() || c == '-'))
.map_or(text.len(), |o| slug_start + o);
let slug = &text[slug_start..slug_end];
if !slug.is_empty() {
refs.push(slug.to_string());
}
from = slug_end.max(slug_start);
}
refs.sort();
refs.dedup();
refs
}
fn walk(dir: &Path, visit: &mut impl FnMut(&Path)) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.file_name().is_some_and(|n| n == "target") {
continue;
}
if path.is_dir() {
walk(&path, visit);
} else {
visit(&path);
}
}
}
fn check_file(root: &Path, path: &Path, problems: &mut Vec<String>) {
if path.file_name().is_some_and(|n| n == "docs_refs.rs") {
return;
}
let Ok(text) = std::fs::read_to_string(path) else {
return;
};
for slug in plan_refs(&text) {
let plan = root.join("docs/plans").join(format!("{slug}.md"));
if !plan.exists() {
problems.push(format!(
"{}: cites plan '{slug}' but {} does not exist",
path.display(),
plan.display()
));
}
}
}
fn stale_plan_refs(root: &Path) -> Vec<String> {
let mut problems = Vec::new();
for dir in ["crates", "tools", ".githooks"] {
walk(&root.join(dir), &mut |path| {
check_file(root, path, &mut problems)
});
}
check_file(root, &root.join("Cargo.toml"), &mut problems);
problems.sort();
problems
}
fn repo_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.canonicalize()
.unwrap()
}
#[test]
fn the_repo_cites_only_plans_that_still_exist() {
let problems = stale_plan_refs(&repo_root());
assert!(
problems.is_empty(),
"stale plan citations:\n{}",
problems.join("\n")
);
}
#[test]
fn a_citation_of_a_retired_plan_is_caught() {
let dir = std::env::temp_dir().join(format!("arris-docs-refs-lint-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(dir.join("docs/plans")).unwrap();
std::fs::write(dir.join("docs/plans/still-open.md"), "# Plan: still-open\n").unwrap();
std::fs::create_dir_all(dir.join("crates/fake/src")).unwrap();
std::fs::write(
dir.join("crates/fake/src/lib.rs"),
"//! see docs/plans/still-open.md for the design\n\
//! and (plans/retired-plan step 3) for why this exists\n",
)
.unwrap();
let problems = stale_plan_refs(&dir);
assert_eq!(problems.len(), 1, "{problems:?}");
assert!(problems[0].contains("retired-plan"), "{problems:?}");
assert!(!problems[0].contains("still-open"), "{problems:?}");
std::fs::remove_dir_all(&dir).unwrap();
}
#[test]
fn the_roadmap_holds_the_committed_tier_histogram() {
use arris_debug::histogram::{COMMITTED_TIER, Histogram};
let mut histogram = Histogram::new();
for name in COMMITTED_TIER {
let fixture = arris_debug::part::load(&arris_debug::fixtures::corpus_root().join(name))
.unwrap_or_else(|e| panic!("{name}: {e}"));
histogram
.add_part(&fixture)
.unwrap_or_else(|e| panic!("{e}"));
}
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
let roadmap = std::fs::read_to_string(root.join("docs/ROADMAP.md")).unwrap();
let open = "<!-- histogram: committed -->\n";
let start = roadmap
.find(open)
.expect("the committed tier's histogram block")
+ open.len();
let end = start
+ roadmap[start..]
.find("<!-- /histogram -->")
.expect("the block's end");
assert_eq!(
&roadmap[start..end],
histogram.markdown(),
"print it again: cargo run -p arris-debug --example real_parts -- --committed"
);
}