open-standards/wai/wai-rs/tests/timeliness.rs
Transaction Science e6a38c6b82 wai: timeliness fallback ladder, and the reference sink scheduler that runs §7 plans
An entry's fallback is an ordered ladder: null, one rung as an object, or two to eight rungs as an
array in strictly falling value, no object named twice (§4.2 rule 3.4, timeliness_ladder_invalid).
One rung has one form, the object, so an entry with one fallback object is a ladder of one rung and
reads, judges and plans as it did; the cache-authority corpus regenerates unchanged.

§5.3 states which rung applies: at by_ms the primary held, else the first rung held; holding
neither, the sink has passed every rung, states `passed`, presents the primary late at its value at
arrival, and at the end, having presented nothing, abandons and states `ended`. §6.3 and §7.3 take
the ladder, and a plan's choice names its rung.

§7.5 and timeliness::scheduler run a sink's plans against the instants it first held each object:
fetch, abandon, present, passed and ended by exact steps, a function of those inputs alone. A later
plan replaces the one in force wholly. plans_invalid and arrivals_invalid refuse a run's inputs.

The corpus gains the group E, ladder claims, verdicts and plans, and runs, each outcome declared in
the generator. timeliness_verify.py writes the ladder and the run from the text, with mutations and
weakenings for both, and claim_verify.py holds rule 3.4.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:05:46 -05:00

108 lines
4.9 KiB
Rust

//! `wai.delivery.timeliness` (extensions/timeliness.md): the committed corpus
//! `live-conformance/timeliness/` regenerates byte for byte from its fixed seeds, holds no other
//! file, every case in it gets the outcome it states, §9 lists exactly the reasons the reference
//! reports, §6.3 exactly its outcomes and §7.5.3 its run's actions, jwp-receipts §3.1 lists the
//! class codes at their steps, and delivery-telemetry §5.1 lists the switch reason of §8.6.
#![cfg(feature = "timeliness")]
use std::collections::BTreeMap;
use std::path::PathBuf;
use wai::timeliness::{corpus, scheduler, CODES, OUTCOMES};
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn read(path: &str) -> String {
std::fs::read_to_string(wai_dir().join(path)).unwrap_or_else(|e| panic!("{path}: {e}"))
}
fn committed() -> BTreeMap<String, String> {
let dir = wai_dir().join("live-conformance/timeliness");
std::fs::read_dir(&dir)
.expect("the committed corpus")
.flatten()
.map(|e| (e.file_name().to_string_lossy().into_owned(), e.path()))
.filter(|(n, _)| n != "README.md")
.map(|(n, p)| (n, std::fs::read_to_string(p).expect("a text file")))
.collect()
}
/// The text of the section of `text` that starts at the line `heading`, to the next heading of
/// the same level.
fn section<'a>(text: &'a str, heading: &str) -> &'a str {
let at = text.find(&format!("\n{heading}")).unwrap_or_else(|| panic!("no {heading}"));
let level = heading.split(' ').next().expect("a heading's hashes");
let end = text[at + 1..].find(&format!("\n{level} ")).map_or(text.len(), |e| at + 1 + e);
&text[at..end]
}
/// The first code of each table row of a section: `| \`code\` | …`.
fn listed(section: &str) -> Vec<String> {
section.lines().filter(|l| l.starts_with("| `")).filter_map(|l| l.split('`').nth(1).map(String::from)).collect()
}
#[test]
fn the_committed_corpus_regenerates_from_its_seeds() {
let files = committed();
let generated: BTreeMap<String, String> = corpus::generate().into_iter().collect();
let extra: Vec<&String> = files.keys().filter(|k| !generated.contains_key(*k)).collect();
let missing: Vec<&String> = generated.keys().filter(|k| !files.contains_key(*k)).collect();
let differ: Vec<&String> = generated.iter().filter(|(k, v)| files.get(*k).is_some_and(|f| f != *v)).map(|(k, _)| k).collect();
assert!(extra.is_empty() && missing.is_empty() && differ.is_empty(), "extra {extra:?}, missing {missing:?}, differ {differ:?}: run `wai_timeliness_vectors gen`");
}
#[test]
fn every_case_gets_its_stated_outcome() {
let fails = corpus::verify(&committed());
assert!(fails.is_empty(), "{}", fails.join("\n"));
}
/// §9 of the extension lists exactly the codes `CODES` has, each once, in order.
#[test]
fn the_extension_lists_the_reasons() {
let text = read("extensions/timeliness.md");
let want: Vec<String> = CODES.iter().map(|c| c.to_string()).collect();
assert_eq!(listed(section(&text, "## 9. Reasons")), want, "§9's table and CODES differ");
}
/// §6.3's table lists exactly the outcomes `OUTCOMES` has, in order.
#[test]
fn the_extension_lists_the_outcomes() {
let text = read("extensions/timeliness.md");
let want: Vec<String> = OUTCOMES.iter().map(|c| c.to_string()).collect();
assert_eq!(listed(section(&text, "### 6.3 Lines")), want, "§6.3's table and OUTCOMES differ");
}
/// §7.5.3 states each action a run decides, in backticks.
#[test]
fn the_extension_states_the_runs_actions() {
let text = read("extensions/timeliness.md");
let steps = section(&text, "#### 7.5.3 Decisions");
for action in scheduler::ACTIONS {
assert!(steps.contains(&format!("`{action}`")), "§7.5.3 does not state {action}");
}
}
/// jwp-receipts §3.1's table lists the class's codes: its rules at step 4, its checks against the
/// group, its objects and their rungs at step 6.
#[test]
fn jwp_receipts_lists_the_class_codes() {
let text = read("extensions/jwp-receipts.md");
let class: Vec<&str> = CODES.iter().copied().filter(|c| c.starts_with("timeliness_") && *c != "timeliness_contradicted").collect();
assert_eq!(class.len(), 14, "the class's codes");
for (k, code) in class.iter().enumerate() {
let step = if k < 6 { 4 } else { 6 };
assert!(text.contains(&format!("| {step} | `{code}` |")), "jwp-receipts §3.1 does not list {code} at step {step}");
}
}
/// delivery-telemetry §5.1 lists the switch reason a sink records when it presents a fallback
/// (§8.6), and the reference's list of switch reasons has it.
#[test]
fn delivery_telemetry_lists_the_switch_reason() {
let text = read("extensions/delivery-telemetry.md");
let reasons = section(&text, "## 5. Switch reasons");
assert!(reasons.contains("`not-held-by-deadline`"), "delivery-telemetry §5.1 does not list not-held-by-deadline");
assert!(wai::delivery_terms::SWITCH_REASONS.contains(&"not-held-by-deadline"));
}