use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
const DOCS_WITH_PATH_CLAIMS: &[&str] = &[
"README.md",
"README.pt-BR.md",
"CONTRIBUTING.md",
"CONTRIBUTING.pt-BR.md",
"SECURITY.md",
"SECURITY.pt-BR.md",
"INTEGRATIONS.md",
"INTEGRATIONS.pt-BR.md",
"docs/AGENTS.md",
"docs/AGENTS.pt-BR.md",
"docs/COOKBOOK.md",
"docs/COOKBOOK.pt-BR.md",
"docs/HOW_TO_USE.md",
"docs/HOW_TO_USE.pt-BR.md",
"docs/CROSS_PLATFORM.md",
"docs/CROSS_PLATFORM.pt-BR.md",
"docs/MIGRATION.md",
"docs/MIGRATION.pt-BR.md",
"docs/TESTING.md",
"docs/TESTING.pt-BR.md",
"docs/RELEASE_CHECKLIST.md",
"docs/RELEASE_CHECKLIST.pt-BR.md",
"docs/schemas/README.md",
"llms.txt",
"llms-full.txt",
"llms.pt-BR.txt",
];
const TRACKED_ROOTS: &[&str] = &[
"tests/",
"scripts/",
"src/",
"docs/",
"benches/",
"examples/",
];
fn code_spans(line: &str) -> Vec<String> {
if line.trim_start().starts_with("```") {
return Vec::new();
}
let chars: Vec<char> = line.chars().collect();
let mut spans = Vec::new();
let mut i = 0;
while i < chars.len() {
if chars[i] != '`' {
i += 1;
continue;
}
let start = i + 1;
let mut end = start;
while end < chars.len() && chars[end] != '`' {
end += 1;
}
if end >= chars.len() {
break;
}
spans.push(chars[start..end].iter().collect());
i = end + 1;
}
spans
}
fn is_concrete_repo_path(span: &str) -> bool {
if !TRACKED_ROOTS.iter().any(|r| span.starts_with(r)) {
return false;
}
if span.ends_with('/') {
return false;
}
if span.contains('*') || span.contains('<') || span.contains('{') || span.contains(' ') {
return false;
}
Path::new(span).extension().is_some()
}
#[test]
fn every_repository_path_a_document_names_exists() {
let root = root();
let mut missing: Vec<String> = Vec::new();
for doc in DOCS_WITH_PATH_CLAIMS {
let path = root.join(doc);
let text = match std::fs::read_to_string(&path) {
Ok(t) => t,
Err(e) => panic!("{doc} is catalogued here but unreadable: {e}"),
};
for (idx, line) in text.lines().enumerate() {
for span in code_spans(line) {
if !is_concrete_repo_path(&span) {
continue;
}
if !root.join(&span).exists() {
missing.push(format!("{doc}:{} names `{span}`", idx + 1));
}
}
}
}
assert!(
missing.is_empty(),
"documents name repository files that do not exist:\n{}",
missing.join("\n")
);
}
#[test]
fn every_suite_on_disk_is_catalogued_in_testing() {
let root = root();
let mut on_disk: BTreeSet<String> = BTreeSet::new();
let entries = std::fs::read_dir(root.join("tests")).expect("tests/ must be readable");
for entry in entries.flatten() {
let name = entry.file_name().to_string_lossy().to_string();
if name.ends_with(".rs") {
on_disk.insert(format!("tests/{name}"));
}
}
for doc in ["docs/TESTING.md", "docs/TESTING.pt-BR.md"] {
let text = std::fs::read_to_string(root.join(doc)).expect("TESTING must be readable");
let uncatalogued: Vec<&String> = on_disk.iter().filter(|s| !text.contains(*s)).collect();
assert!(
uncatalogued.is_empty(),
"{doc} omits suites that exist on disk:\n{}",
uncatalogued
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join("\n")
);
}
}
#[test]
fn the_extractor_reads_spans_and_ignores_sets() {
assert_eq!(
code_spans("see `tests/a.rs` and `scripts/b.sh` now"),
vec!["tests/a.rs".to_string(), "scripts/b.sh".to_string()]
);
assert!(code_spans("```bash").is_empty());
assert!(code_spans("a `dangling span").is_empty());
assert!(is_concrete_repo_path(
"tests/gaps_v070_doc_reference_reach.rs"
));
assert!(is_concrete_repo_path("docs/schemas/exec.schema.json"));
assert!(!is_concrete_repo_path("tests/*.rs"));
assert!(!is_concrete_repo_path("docs/<NAME>.md"));
assert!(!is_concrete_repo_path("src/"));
assert!(!is_concrete_repo_path("ssh-cli exec"));
assert!(!is_concrete_repo_path("/tmp/hosts.toml"));
}