//! `wai.live.events` (extensions/live-events.md): the committed corpus //! `live-conformance/events/vectors.json` regenerates byte for byte from its fixed seeds, //! every case in it gets the outcome it states, it covers every kind and every reason, //! and the extension's §9 lists exactly the reasons the reference reports. #![cfg(feature = "live_events")] use std::collections::BTreeSet; use std::path::PathBuf; use wai::live_events::{corpus, kind_name, Reason, KINDS}; fn wai_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..") } fn committed() -> String { std::fs::read_to_string(wai_dir().join("live-conformance/events/vectors.json")).expect("the committed corpus") } #[test] fn the_committed_corpus_regenerates_from_its_seeds() { assert!(committed() == corpus::generate(), "live-conformance/events/vectors.json differs from `wai_live_events_vectors gen`"); } #[test] fn every_case_gets_its_stated_outcome() { let fails = corpus::verify(&committed()); assert!(fails.is_empty(), "{}", fails.join("\n")); } /// Every kind has an accepted event, every refusal reason a vector, policy case or binding /// case refused with it, and the gap outcome a vector. #[test] fn the_corpus_covers_every_kind_and_reason() { let doc: serde_json::Value = serde_json::from_str(&committed()).unwrap(); let mut kinds = BTreeSet::new(); let mut reasons = BTreeSet::new(); for v in doc["vectors"].as_array().unwrap() { if let Some(r) = v["reason"].as_str() { reasons.insert(r.to_string()); } if v["outcome"] == "accept" { for e in v["events"].as_array().unwrap() { let h = e.as_str().unwrap(); let at = 2 * (4 + 1 + 32 + 32 + 8 + 32 + 8); let flag = u8::from_str_radix(&h[at..at + 2], 16).unwrap(); let k = 2 * (4 + 1 + 32 + 32 + 8 + 32 + 8 + 1 + 48 * flag as usize); kinds.insert(u8::from_str_radix(&h[k..k + 2], 16).unwrap()); } } } for c in doc["policy_cases"].as_array().unwrap().iter().chain(doc["binding_cases"].as_array().unwrap()) { if let Some(r) = c["reason"].as_str() { reasons.insert(r.to_string()); } } for (k, name) in KINDS { assert!(kinds.contains(&k), "no accepted {name} event"); } for r in Reason::ALL { assert!(reasons.contains(r.code()), "nothing in the corpus is refused with {r}"); } assert!(kinds.iter().all(|k| kind_name(*k).is_some())); } /// §9 of the extension lists exactly the codes `Reason` has, each once. #[test] fn the_extension_lists_the_reasons() { let text = std::fs::read_to_string(wai_dir().join("extensions/live-events.md")).expect("the extension"); let at = text.find("\n## 9. Reasons").expect("a §9"); let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e); let listed: Vec = text[at..end] .lines() .filter(|l| l.starts_with("| `")) .filter_map(|l| l.split('`').nth(1).map(String::from)) .collect(); let want: Vec = Reason::ALL.iter().map(|r| r.code().to_string()).collect(); assert_eq!(listed, want, "§9's table and Reason::ALL differ"); }