const MANIFEST: &str = include_str!("../Cargo.toml");
const ARCH_README: &str = include_str!("../docs/architecture/README.md");
const REGISTER: &str = include_str!("../docs/architecture/s13-decision-register.md");
const README: &str = include_str!("../README.md");
fn crate_version() -> String {
MANIFEST
.lines()
.map(str::trim)
.find_map(|l| l.strip_prefix("version = \""))
.and_then(|rest| rest.split('"').next())
.expect("Cargo.toml has a package version")
.to_string()
}
fn revision_rows() -> Vec<Vec<String>> {
let after = ARCH_README
.split_once("## Revision history")
.expect("the architecture README has a revision history")
.1;
after
.lines()
.skip_while(|l| !l.starts_with('|'))
.take_while(|l| l.starts_with('|'))
.filter(|l| !l.starts_with("|---"))
.map(|l| {
l.trim_matches('|')
.split('|')
.map(|c| c.trim().to_string())
.collect::<Vec<String>>()
})
.filter(|r| r.first().map(String::as_str) != Some("Version"))
.collect()
}
fn highest_decision() -> u32 {
REGISTER
.match_indices("<a id=\"d-")
.filter_map(|(i, _)| {
let rest = ®ISTER[i + 9..];
let n: String = rest.chars().take_while(char::is_ascii_digit).collect();
n.parse::<u32>().ok()
})
.max()
.expect("the register defines decisions")
}
fn readme_dep_pin() -> Option<String> {
README
.lines()
.map(str::trim)
.find_map(|l| l.strip_prefix("macrame-db = \""))
.and_then(|rest| rest.split('"').next())
.map(str::to_string)
}
fn crate_series() -> String {
let v = crate_version();
let mut parts = v.split('.');
let major = parts.next().expect("a version has a major");
let minor = parts.next().expect("a version has a minor");
format!("{major}.{minor}")
}
#[test]
fn the_readme_pins_the_series_the_crate_is_at() {
let series = crate_series();
let pin = readme_dep_pin().expect("the README's quick start pins a version");
assert_eq!(
pin, series,
"the README's quick start says `macrame-db = \"{pin}\"` while the crate \
is at {}. That line is not internal documentation: `README.md` is this \
package's front page on crates.io and PyPI, so it is the first \
instruction a new user follows, and a stale pin sends them to a series \
this repository has stopped changing. It read \"0.13\" when 0.15.0 was \
tagged and was caught by a reader rather than by a gate — the version \
sweep that release ran searched for `0.13.0` and `0.14.0`, and a \
two-component pin matches neither.",
crate_version()
);
}
#[test]
fn the_revision_history_reaches_the_release_the_crate_is_at() {
let version = crate_version();
let rows = revision_rows();
let last = rows.last().expect("the table has rows");
assert!(
last[0].contains(&version),
"the last revision-history row covers {:?}, and the crate is at {version}. \
Every release is a row or an extended range in \
`docs/architecture/README.md`; a release that does not appear there is \
one nobody can find the substance of later. Extend the last row's \
version span, or add a row (D-209, closing §6.1).",
last[0]
);
}
#[test]
fn the_header_names_the_version_the_document_describes() {
let version = crate_version();
let row = ARCH_README
.lines()
.find(|l| l.starts_with("| Document version |"))
.expect("the architecture README declares its version");
assert!(
row.contains(&version),
"the architecture README calls itself {row:?} while the crate is at \
{version}. The header is the first thing a reader checks against the \
code in front of them, and it said 0.9.0 for twenty-six releases \
(D-209)."
);
}
#[test]
fn the_file_table_offers_the_decisions_the_register_actually_holds() {
let highest = highest_decision();
let want = format!("D-001…D-{highest:03}");
assert!(
ARCH_README.contains(&want),
"the file table in the architecture README does not say {want:?}, and \
the register's highest entry is D-{highest:03}. That cell is the \
register's advertised range; a reader who trusts it stops looking at \
the number it names (D-209)."
);
}
#[test]
fn the_documents_are_shaped_the_way_these_tests_assume() {
let rows = revision_rows();
assert!(
rows.len() > 20,
"only {} revision-history rows parsed; the table's format changed and \
these tests are measuring nothing",
rows.len()
);
assert!(
rows.iter().all(|r| r.len() >= 3),
"a revision-history row has fewer than three cells; the columns changed"
);
assert_eq!(rows[0][0], "0.1.0", "the table no longer starts at 0.1.0");
assert!(highest_decision() >= 208);
assert!(crate_version().starts_with("0."));
assert!(
readme_dep_pin().is_some(),
"the README no longer contains a `macrame-db = \"x.y\"` line; the \
quickstart moved and the pin test is measuring nothing"
);
}