81 lines
3.7 KiB
Rust
81 lines
3.7 KiB
Rust
//! `wai.live.compose` (extensions/live-compose.md): the committed corpus
|
|
//! `live-conformance/compose/vectors.json` regenerates byte for byte from its fixed seeds,
|
|
//! every case in it gets the outcome it states, every reason the extension adds refuses a
|
|
//! case of it, the cases §11 names are there, and the extension's §10 lists exactly the
|
|
//! reasons of the reference.
|
|
#![cfg(feature = "live_compose")]
|
|
|
|
use std::collections::BTreeSet;
|
|
use std::path::PathBuf;
|
|
use wai::live_compose::{corpus, Reason};
|
|
|
|
fn wai_dir() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
|
|
}
|
|
|
|
fn committed() -> String {
|
|
std::fs::read_to_string(wai_dir().join("live-conformance/compose/vectors.json")).expect("the committed corpus")
|
|
}
|
|
|
|
#[test]
|
|
fn the_committed_corpus_regenerates_from_its_seeds() {
|
|
assert!(committed() == corpus::generate(), "live-conformance/compose/vectors.json differs from `wai_live_compose_vectors gen`");
|
|
}
|
|
|
|
#[test]
|
|
fn every_case_gets_its_stated_outcome() {
|
|
let fails = corpus::verify(&committed());
|
|
assert!(fails.is_empty(), "{}", fails.join("\n"));
|
|
}
|
|
|
|
/// Every reason this extension adds refuses a case; grids of 0 to 12 tiles, every fill
|
|
/// mode, every corner under both behaviours, and both sessions are there; and the grid
|
|
/// session lays its room out anew at the guest's grant exchange.
|
|
#[test]
|
|
fn the_corpus_covers_every_reason_and_case() {
|
|
let doc: serde_json::Value = serde_json::from_str(&committed()).unwrap();
|
|
let mut seen: BTreeSet<String> = BTreeSet::new();
|
|
let mut names: BTreeSet<String> = BTreeSet::new();
|
|
for section in ["layouts", "mixes", "descriptors", "compositions", "receipts"] {
|
|
for v in doc[section].as_array().unwrap() {
|
|
names.insert(v["name"].as_str().unwrap().to_string());
|
|
if let Some(r) = v["reason"].as_str() {
|
|
seen.insert(r.into());
|
|
}
|
|
}
|
|
}
|
|
for r in Reason::ALL {
|
|
assert!(seen.contains(r.code()), "nothing in the corpus is refused {r}");
|
|
}
|
|
let mut want: Vec<String> = (0..=12).map(|n| format!("grid_{n}")).collect();
|
|
want.extend(["fill_fill", "fill_cover", "fill_contain", "featured_4", "featured_absent", "order_key_tie_break", "stopped_omitted"].map(String::from));
|
|
for c in ["top_left", "top_right", "bottom_left", "bottom_right"] {
|
|
for b in ["static", "dynamic"] {
|
|
want.push(format!("pip_{c}_{b}"));
|
|
}
|
|
}
|
|
want.extend(["pip_alone_static", "pip_alone_dynamic", "sum_saturates_high", "grid_session", "pip_session", "video", "audio"].map(String::from));
|
|
for n in &want {
|
|
assert!(names.contains(n), "no case {n}");
|
|
}
|
|
let session = doc["compositions"].as_array().unwrap().iter().find(|v| v["name"] == "grid_session").unwrap();
|
|
let frames = session["frames"].as_array().unwrap();
|
|
let at = |t: u64| frames.iter().find(|f| f["t"] == t).unwrap();
|
|
assert_ne!(at(4_000_000)["order"], at(5_000_000)["order"], "the guest's exchange at 5 s reorders the room");
|
|
assert_ne!(at(4_000_000)["set_digest"], at(5_000_000)["set_digest"]);
|
|
}
|
|
|
|
/// §10 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/live-compose.md")).expect("the extension");
|
|
let at = text.find("\n## 10. Reasons").expect("a §10");
|
|
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, "§10's table and Reason::ALL differ");
|
|
}
|