use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
fn table_rows(design: &str) -> Vec<&str> {
design
.lines()
.skip_while(|l| !l.starts_with("## 12."))
.take_while(|l| !l.starts_with("## 13."))
.skip_while(|l| !l.starts_with("| `"))
.take_while(|l| l.starts_with("| `"))
.collect()
}
fn module_cell(row: &str) -> &str {
row.split('|').nth(1).unwrap_or_default()
}
fn expand(tok: &str) -> Vec<String> {
let Some((head, rest)) = tok.split_once('{') else {
return vec![tok.to_owned()];
};
let Some((body, tail)) = rest.split_once('}') else {
return vec![tok.to_owned()];
};
body.split(',')
.flat_map(|part| expand(&format!("{head}{part}{tail}")))
.collect()
}
fn entries(row: &str) -> Vec<String> {
module_cell(row)
.split('`')
.skip(1)
.step_by(2)
.flat_map(|tok| expand(tok.trim()))
.filter(|p| p.ends_with(".rs"))
.collect()
}
fn is_test_corpus(p: &Path) -> bool {
p.file_name().is_some_and(|n| n == "tests.rs")
|| p.parent()
.is_some_and(|d| d.components().any(|c| c.as_os_str() == "tests"))
}
fn names_test_module(p: &str) -> bool {
!p.starts_with("tests/") && is_test_corpus(Path::new(p))
}
fn sort_key(row: &str) -> String {
let first = entries(row).first().cloned().unwrap_or_default();
first.strip_suffix("mod.rs").unwrap_or(&first).to_owned()
}
fn duplicates(design: &str) -> Vec<String> {
let mut seen: BTreeMap<String, usize> = BTreeMap::new();
for path in table_rows(design).into_iter().flat_map(entries) {
*seen.entry(path).or_default() += 1;
}
seen.into_iter()
.filter(|(_, n)| *n > 1)
.map(|(path, _)| path)
.collect()
}
fn rust_files(dir: &Path, out: &mut Vec<PathBuf>) {
for entry in std::fs::read_dir(dir).into_iter().flatten().flatten() {
let p = entry.path();
if p.is_dir() {
rust_files(&p, out);
} else if p.extension().is_some_and(|e| e == "rs") {
out.push(p);
}
}
}
fn production_files() -> Vec<String> {
let mut files = Vec::new();
rust_files(Path::new("src"), &mut files);
files.retain(|p| !is_test_corpus(p));
let mut out: Vec<String> = files.iter().map(|p| p.display().to_string()).collect();
out.sort();
out
}
fn design() -> String {
std::fs::read_to_string("docs/DESIGN.md").unwrap_or_default()
}
#[test]
fn every_source_file_has_a_row() {
let design = design();
let mapped: BTreeSet<String> = table_rows(&design)
.into_iter()
.flat_map(entries)
.filter(|p| p.starts_with("src/"))
.collect();
let missing: Vec<String> = production_files()
.into_iter()
.filter(|p| !mapped.contains(p))
.collect();
assert!(
missing.is_empty(),
"tracked source files with no DESIGN §12 row — a split nobody \
recorded. Add the row (AGENTS.md: \"add the row to DESIGN §12\"):\n{}",
missing.join("\n")
);
}
#[test]
fn every_row_names_a_file_that_exists() {
let ghosts: Vec<String> = table_rows(&design())
.into_iter()
.flat_map(entries)
.filter(|p| (p.starts_with("src/") || p.starts_with("tests/")) && !Path::new(p).exists())
.collect();
assert!(
ghosts.is_empty(),
"DESIGN §12 rows naming paths that do not exist — a map of a tree that \
is not there:\n{}",
ghosts.join("\n")
);
}
#[test]
fn rows_stay_sorted_by_module_path() {
let design = design();
let keys: Vec<String> = table_rows(&design).into_iter().map(sort_key).collect();
let descents: Vec<String> = keys
.windows(2)
.filter(|w| w[1] < w[0])
.map(|w| format!("{} then {}", w[0], w[1]))
.collect();
assert!(
descents.is_empty(),
"DESIGN §12 rows out of sort order — an insert stacked at a subsystem \
boundary instead of distributing:\n{}",
descents.join("\n")
);
}
#[test]
fn no_row_names_a_test_module() {
let design = design();
let corpora: Vec<String> = table_rows(&design)
.into_iter()
.flat_map(entries)
.filter(|p| names_test_module(p))
.collect();
assert!(
corpora.is_empty(),
"DESIGN §12 cells naming test modules — §12: \"a test module … never \
earns one of its own\". Drop the entry; the row may still describe \
the corpus:\n{}",
corpora.join("\n")
);
}
#[test]
fn a_row_is_two_cells() {
let design = design();
let wide: Vec<String> = table_rows(&design)
.into_iter()
.filter(|row| row.split('|').count() != 4)
.map(|row| module_cell(row).trim().to_owned())
.collect();
assert!(
wide.is_empty(),
"DESIGN §12 rows with a third cell — that is where the line counts \
lived, and bl-273c subtracted them (160 of 389 had drifted). \
`make line-cap` is the one definition of the cap:\n{}",
wide.join("\n")
);
}
#[test]
fn no_path_is_mapped_twice() {
let dups = duplicates(&design());
assert!(
dups.is_empty(),
"DESIGN §12 paths in more than one row — two answers to one \
question:\n{}",
dups.join("\n")
);
}
#[test]
fn the_sweep_is_not_vacuous() {
let (rows, files) = (table_rows(&design()).len(), production_files().len());
assert!(
rows > 100 && files > 100,
"the sweep found {rows} rows over {files} files — it is broken, not \
the tree"
);
}
#[test]
fn braces_expand() {
assert_eq!(expand("src/a.rs"), ["src/a.rs"]);
assert_eq!(expand("src/x/{mod,y}.rs"), ["src/x/mod.rs", "src/x/y.rs"]);
assert_eq!(expand("src/x{.rs,/y.rs}"), ["src/x.rs", "src/x/y.rs"]);
assert_eq!(
expand("src/{a,b}/{c,d}.rs"),
["src/a/c.rs", "src/a/d.rs", "src/b/c.rs", "src/b/d.rs"]
);
}
#[test]
fn each_rule_sees_its_own_violation() {
let table = |rows: &str| {
format!("## 12. Module map\n\n| Module | Responsibility |\n|---|---|\n{rows}\n\n## 13. x\n")
};
let ordered = |doc: &str| {
table_rows(doc)
.windows(2)
.all(|w| sort_key(w[0]) <= sort_key(w[1]))
};
assert!(ordered(&table("| `src/a.rs` | a |\n| `src/b.rs` | b |")));
assert!(!ordered(&table("| `src/b.rs` | b |\n| `src/a.rs` | a |")));
assert!(ordered(&table(
"| `src/x/{mod,y}.rs` | x |\n| `src/x/z.rs` | z |"
)));
let corpus = |doc: &str| {
table_rows(doc)
.into_iter()
.flat_map(entries)
.any(|p| names_test_module(&p))
};
assert!(corpus(&table("| `src/a/{mod,tests}.rs` | a |")));
assert!(!corpus(&table("| `src/a/mod.rs` | a |")));
assert!(!names_test_module("tests/design_module_map.rs"));
let two_cells = |doc: &str| table_rows(doc).iter().all(|r| r.split('|').count() == 4);
assert!(!two_cells(&table("| `src/a.rs` | 120 | a |")));
assert!(two_cells(&table("| `src/a.rs` | a |")));
assert!(!duplicates(&table("| `src/a.rs` | one |\n| `src/a{.rs,/b.rs}` | two |")).is_empty());
assert!(duplicates(&table("| `src/a.rs` | one |\n| `src/b.rs` | two |")).is_empty());
let two = table(
"| `src/a.rs` | a |\n\n### 12.2 harness\n\n| File | Responsibility |\n\
|---|---|\n| `scripts/z.sh` | z |",
);
assert_eq!(table_rows(&two).len(), 1);
}