open-standards/wai/wai-rs/tests/capture_take.rs
Transaction Science 6538c563b0 wai: capture_take, the take manifest, commitments, receipts, consent and verifier (WIP)
capture-binding.md drafts wai.capture.take. The room's recording policy gains
commit_interval_ms and jitter_ms (live-rooms §3.7), and the output tree exposes its
RFC 6962 hash and RFC 9162 consistency proofs for the take tree to reuse.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 04:30:48 -04:00

77 lines
3.3 KiB
Rust

//! `wai.capture.take` (extensions/capture-binding.md): the committed corpus
//! `live-conformance/takes/vectors.json` regenerates byte for byte from its fixed seeds,
//! every vector in it gets the outcome it states, every reason the extension adds appears
//! in it, and the extension's §12 lists exactly those reasons.
#![cfg(feature = "capture_take")]
use std::collections::BTreeSet;
use std::path::PathBuf;
use wai::capture_take::{corpus, Reason, DELIVERY_GAP};
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn committed() -> String {
std::fs::read_to_string(wai_dir().join("live-conformance/takes/vectors.json")).expect("the committed corpus")
}
#[test]
fn the_committed_corpus_regenerates_from_its_seeds() {
assert!(committed() == corpus::generate(), "live-conformance/takes/vectors.json differs from `wai_capture_take_vectors gen`");
}
#[test]
fn every_vector_gets_its_stated_outcome() {
let fails = corpus::verify(&committed());
assert!(fails.is_empty(), "{}", fails.join("\n"));
}
/// Every reason this extension adds, and `delivery_gap`, is a vector's refusal or one of
/// its verdicts; the three good takes §13 names stand, and `single-take` holds of the
/// missing chunk while `complete` fails.
#[test]
fn the_corpus_covers_every_reason_and_take() {
let doc: serde_json::Value = serde_json::from_str(&committed()).unwrap();
let vectors = doc["vectors"].as_array().unwrap();
let mut seen: BTreeSet<String> = BTreeSet::new();
for v in vectors {
if let Some(r) = v["reason"].as_str() {
seen.insert(r.into());
}
let verdicts = &v["verdicts"];
for k in ["single_take", "aligned", "complete"] {
if let Some(r) = verdicts[k].as_str() {
seen.insert(r.into());
}
}
if let Some(p) = verdicts["publishable"].as_object() {
seen.extend(p.values().filter_map(|r| r.as_str()).map(String::from));
}
}
for r in Reason::ALL.iter().copied().chain([DELIVERY_GAP]) {
assert!(seen.contains(r.code()), "nothing in the corpus gives {r}");
}
for name in ["lesson", "resumed_upload", "minor_guardian"] {
let v = vectors.iter().find(|v| v["name"] == name).unwrap_or_else(|| panic!("no vector {name}"));
assert_eq!(v["stands"], true, "{name}");
}
let missing = vectors.iter().find(|v| v["name"] == "missing_chunk").expect("the missing chunk");
assert_eq!(missing["verdicts"]["single_take"], "holds");
assert_eq!(missing["verdicts"]["complete"], "chunk_missing");
}
/// §12 of the extension lists exactly the codes `Reason::ALL` has, each once, in order.
#[test]
fn the_extension_lists_the_reasons() {
let text = std::fs::read_to_string(wai_dir().join("extensions/capture-binding.md")).expect("the extension");
let at = text.find("\n## 12. Reasons").expect("a §12");
let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e);
let listed: Vec<String> = text[at..end]
.lines()
.filter(|l| l.starts_with("| `"))
.filter_map(|l| l.split('`').nth(1).map(String::from))
.collect();
let want: Vec<String> = Reason::ALL.iter().map(|r| r.code().to_string()).collect();
assert_eq!(listed, want, "§12's table and Reason::ALL differ");
}