use std::collections::BTreeSet;
use std::fmt::Write as _;
use std::io::Write as _;
use std::path::PathBuf;
use std::process::{Command, Stdio};
const BINARY: &str = env!("CARGO_BIN_EXE_ids-le");
const POLICY: &str = include_str!("../src/extract/policy.rs");
const FORMAT: &str = include_str!("../src/extract/format.rs");
const VERSIONS: [i64; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
fn documents() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures/documents")
}
fn scan(path: &PathBuf) -> Vec<serde_json::Value> {
let output = Command::new(BINARY)
.arg(path)
.output()
.expect("the binary runs");
assert!(
matches!(output.status.code(), Some(0 | 1)),
"the scan did not finish: {}",
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8_lossy(&output.stdout)
.lines()
.filter(|line| !line.trim().is_empty())
.map(|line| serde_json::from_str(line).expect("stdout carries only JSON"))
.collect()
}
fn scan_stdin(document: &str, format: &str) -> serde_json::Value {
let mut child = Command::new(BINARY)
.args(["--stdin", "--format", format])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("the binary runs");
child
.stdin
.as_mut()
.expect("stdin")
.write_all(document.as_bytes())
.expect("the child is still reading");
drop(child.stdin.take());
let output = child.wait_with_output().expect("the child finishes");
assert!(
matches!(output.status.code(), Some(0 | 1)),
"the scan did not finish: {}",
String::from_utf8_lossy(&output.stderr)
);
serde_json::from_slice(&output.stdout).expect("stdout carries JSON")
}
fn rows(reports: &[serde_json::Value]) -> Vec<serde_json::Value> {
reports
.iter()
.flat_map(|report| report["ids"].as_array().expect("rows").clone())
.collect()
}
fn variants_of(source: &str, name: &str) -> Vec<String> {
let declaration = format!("enum {name} {{");
let start = source
.find(&declaration)
.unwrap_or_else(|| panic!("{name} is not declared where this test looks for it"));
let body = &source[start + declaration.len()..];
let end = body
.find("\n}")
.unwrap_or_else(|| panic!("{name} has no closing brace"));
body[..end]
.lines()
.map(str::trim)
.filter(|line| !line.is_empty() && !line.starts_with("//") && !line.starts_with('#'))
.map(|line| line.trim_end_matches(',').to_string())
.collect()
}
fn snake_case(name: &str) -> String {
let mut out = String::with_capacity(name.len() + 4);
for (index, character) in name.chars().enumerate() {
if character.is_ascii_uppercase() && index > 0 {
out.push('_');
}
out.extend(character.to_lowercase());
}
out
}
fn offered_formats() -> Vec<String> {
let start = FORMAT
.find("SUPPORTED_FORMATS")
.expect("the offered list is declared");
let list = &FORMAT[start..];
let assigned = list.find('=').expect("an assignment");
let open = list[assigned..].find('[').expect("a list") + assigned;
let close = list[open..].find(']').expect("a closing bracket") + open;
list[open + 1..close]
.split(',')
.map(|entry| entry.trim().trim_matches('"').to_string())
.filter(|entry| !entry.is_empty())
.collect()
}
#[test]
fn every_kind_reason_version_and_format_is_reachable_from_a_fixture() {
let reports = scan(&documents());
assert!(!reports.is_empty(), "the fixture directory was not walked");
let rows = rows(&reports);
let named: BTreeSet<String> = rows
.iter()
.filter(|row| row["valid"] == true)
.filter_map(|row| row["kind"].as_str().map(str::to_string))
.collect();
let kinds: Vec<String> = variants_of(POLICY, "Kind")
.iter()
.map(|variant| variant.to_lowercase())
.collect();
assert_eq!(kinds.len(), 5, "a kind arrived or left: {kinds:?}");
for kind in &kinds {
assert!(
named.contains(kind),
"no fixture document produces a {kind}: named {named:?}"
);
}
assert!(
named.iter().all(|kind| kinds.contains(kind)),
"a kind was reported that the enum does not declare: {named:?} against {kinds:?}"
);
let refused: BTreeSet<String> = rows
.iter()
.filter_map(|row| row["refused"].as_str().map(str::to_string))
.collect();
let reasons: Vec<String> = variants_of(POLICY, "Reason")
.iter()
.map(|variant| snake_case(variant))
.collect();
assert_eq!(reasons.len(), 5, "a reason arrived or left: {reasons:?}");
for reason in &reasons {
assert!(
refused.contains(reason),
"no fixture document produces {reason}: refused {refused:?}"
);
}
assert!(
refused.iter().all(|reason| reasons.contains(reason)),
"a reason was reported that the enum does not declare: {refused:?}"
);
let variants: BTreeSet<String> = rows
.iter()
.filter_map(|row| row["variant"].as_str().map(str::to_string))
.collect();
let declared: Vec<String> = variants_of(POLICY, "Variant")
.iter()
.map(|variant| snake_case(variant))
.collect();
assert_eq!(declared.len(), 4, "a variant arrived or left: {declared:?}");
for variant in &declared {
assert!(
variants.contains(variant),
"no fixture document reports the {variant} variant: {variants:?}"
);
}
let versions: BTreeSet<i64> = rows
.iter()
.filter(|row| row["valid"] == true && row["kind"] == "uuid")
.filter_map(|row| row["version"].as_i64())
.collect();
for version in VERSIONS {
assert!(
versions.contains(&version),
"no fixture document holds a named UUID v{version}: {versions:?}"
);
}
assert!(
versions.iter().all(|version| VERSIONS.contains(version)),
"a version outside RFC 9562's range was named: {versions:?}"
);
let productive: BTreeSet<String> = reports
.iter()
.filter(|report| !report["ids"].as_array().expect("rows").is_empty())
.filter_map(|report| report["format"].as_str().map(str::to_string))
.collect();
let offered = offered_formats();
assert_eq!(offered.len(), 8, "a format arrived or left: {offered:?}");
for format in &offered {
assert!(
productive.contains(format),
"no fixture document is read as {format} and produces a row: {productive:?}"
);
}
println!(
"coverage-matrix: complete — {} kinds, {} reasons, {} variants, {} uuid versions, \
{} formats, from {} fixture documents",
kinds.len(),
reasons.len(),
declared.len(),
VERSIONS.len(),
offered.len(),
reports.len()
);
}
#[test]
fn no_hash_in_prose_is_named_and_the_residual_under_an_id_key_is_measured() {
let bare = rows(&scan(&documents().join("hashes.txt")));
let hex24: Vec<&serde_json::Value> = bare
.iter()
.filter(|row| row["value"].as_str().is_some_and(|value| value.len() == 24))
.collect();
assert!(
hex24.len() >= 500,
"the fixture stopped holding enough 24-hex runs to measure: {}",
hex24.len()
);
let named = hex24.iter().filter(|row| row["valid"] == true).count();
for row in &hex24 {
assert_eq!(row["refused"], "ambiguous_kind", "{row}");
assert!(row["kind"].is_null(), "a kind was named anyway: {row}");
assert!(
row["timestamp"].is_string(),
"a 24-hex verdict came without the decode behind it: {row}"
);
}
let mut document = String::new();
for (index, row) in hex24.iter().enumerate() {
let value = row["value"].as_str().expect("a value");
let _ = writeln!(document, "k{index}_id: {value}");
}
let keyed = rows(&[scan_stdin(&document, "yaml")]);
assert_eq!(keyed.len(), hex24.len(), "a run went missing under a key");
let residual = keyed.iter().filter(|row| row["valid"] == true).count();
let share = |count: usize| {
f64::from(u32::try_from(count).expect("a count"))
/ f64::from(u32::try_from(hex24.len()).expect("a count"))
};
println!(
"coverage-matrix: 24-hex naming rate {:.1}% ({named} of {}) in prose, {:.1}% \
({residual} of {}) under a key ending in id, against a window covering {:.1}% of the \
32-bit second space",
share(named) * 100.0,
hex24.len(),
share(residual) * 100.0,
hex24.len(),
window_share() * 100.0
);
assert_eq!(
named, 0,
"a hash in prose was named an ObjectId — the context requirement has been relaxed"
);
assert!(
residual > 0,
"not one digest was named even under an id key, so this measures nothing and the \
timestamp filter has changed"
);
assert!(
(share(residual) - window_share()).abs() <= 0.10,
"under an id key the rate {:.4} is nowhere near the window's {:.4} — the timestamp \
filter changed, or the fixture is no longer random hex",
share(residual),
window_share()
);
}
fn window_share() -> f64 {
const EARLIEST_PLAUSIBLE_S: u64 = 631_152_000;
const FUTURE_ALLOWANCE_S: u64 = 365 * 86_400;
const SECOND_SPACE: f64 = 4_294_967_296.0;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("a clock")
.as_secs();
let upper = (now + FUTURE_ALLOWANCE_S).min(4_294_967_295);
let width = u32::try_from(upper.saturating_sub(EARLIEST_PLAUSIBLE_S)).expect("a 32-bit width");
f64::from(width) / SECOND_SPACE
}