open-standards/wai/wai-rs/tests/exploration.rs
Transaction Science bcef9a5671 wai.media.exploration: descriptors, archives that replay, default-distance, collection statements, taste priors, rankings and picks (CO2, CO3)
The extension, the wai-rs module behind the feature exploration, the corpus
live-conformance/exploration/ written by wai_exploration_vectors gen, its second
implementation exploration_verify.py, the CI step, and the registry, SPEC and
CHANGELOG entries.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 13:41:14 -04:00

73 lines
3.3 KiB
Rust

//! `wai.media.exploration` (extensions/exploration.md): the committed corpus
//! `live-conformance/exploration/` regenerates byte for byte from its fixed seeds, holds no other
//! file, every generation, descriptor vector and case in it gets the outcome it states, and the
//! extension's §13 lists exactly the reasons the reference reports. The generator itself asserts
//! that the corpus gives every one of them.
#![cfg(feature = "exploration")]
use std::collections::BTreeMap;
use std::path::PathBuf;
use wai::exploration::{corpus, Reason, DESCRIPTORS};
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn committed() -> BTreeMap<String, String> {
let dir = wai_dir().join("live-conformance/exploration");
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()
}
fn section(text: &str, heading: &str) -> String {
let at = text.find(heading).unwrap_or_else(|| panic!("a section {heading}"));
let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e);
text[at..end].to_string()
}
#[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_exploration_vectors gen`");
}
#[test]
fn every_case_gets_its_stated_outcome() {
let fails = corpus::verify(&committed());
assert!(fails.is_empty(), "{}", fails.join("\n"));
}
/// §13 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/exploration.md")).expect("the extension");
let listed: Vec<String> = section(&text, "\n## 13. Reasons")
.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, "§13's table and Reason::ALL differ");
}
/// §3.2's table names the descriptors `DESCRIPTORS` holds, in its order.
#[test]
fn the_extension_names_the_descriptors() {
let text = std::fs::read_to_string(wai_dir().join("extensions/exploration.md")).expect("the extension");
let s = section(&text, "\n### 3.2 ");
let named: Vec<String> = s
.lines()
.filter(|l| l.starts_with("| ") && l.split('|').nth(1).is_some_and(|c| c.trim().parse::<u32>().is_ok()))
.filter_map(|l| l.split('`').nth(1).map(String::from))
.collect();
assert_eq!(named, DESCRIPTORS.map(String::from).to_vec(), "§3.2's table and DESCRIPTORS differ");
}