open-standards/wai/wai-rs/tests/avatar_face.rs
Transaction Science 46e081ab8f wai.avatar.face: an integer talking-head generator, its records and its verification (avatar_face)
Registers wai.avatar.face (GenerativeDeterministic, ops face-int/1, one-file parameter set):
the WFG1 generator, WFI1 identity prior and WFK1 keypoint segment readers and writers; the
driver's integer warp and keypoint maps; the lowering face-int/1 to one wai-ops/1-i32 graph,
with the same arithmetic written out loop by loop for the tests; the identity and track
records; verification over them and synthesis's claims, log and label policy; the corpus
generator (bin wai_avatar_face_vectors) and the corpus and GPU tests. Registry export
regenerated.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-22 10:57:20 -04:00

125 lines
5.9 KiB
Rust

//! `wai.avatar.face` (extensions/avatars.md §6 to §13): the committed corpus
//! `live-conformance/avatar-face/` regenerates byte for byte from its fixed seeds and its pinned
//! inputs, holds no other file, every vector in it gets what it states, the extension's §10 lists
//! exactly the reasons the reference reports and the codes its files are refused with, and §7.9's
//! measurement is the training tool's report. The generator itself asserts that the corpus gives
//! every one of the reasons.
#![cfg(feature = "avatar_face")]
use std::collections::BTreeMap;
use std::path::PathBuf;
use wai::avatar_face::{self, corpus, FormError, Reason};
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn committed() -> BTreeMap<String, Vec<u8>> {
let dir = wai_dir().join("live-conformance/avatar-face");
let mut files = BTreeMap::new();
for sub in ["", "identities", "tracks"] {
for e in std::fs::read_dir(dir.join(sub)).expect("the committed corpus").flatten() {
let name = e.file_name().to_string_lossy().into_owned();
if e.path().is_dir() || (sub.is_empty() && name == "README.md") {
continue;
}
let key = if sub.is_empty() { name } else { format!("{sub}/{name}") };
files.insert(key, std::fs::read(e.path()).expect("a file"));
}
}
files
}
fn inputs(files: &BTreeMap<String, Vec<u8>>) -> BTreeMap<String, Vec<u8>> {
corpus::INPUTS.iter().filter_map(|(n, _)| files.get(*n).map(|b| (n.to_string(), b.clone()))).collect()
}
fn section<'a>(text: &'a str, heading: &str) -> &'a str {
let at = text.find(heading).unwrap_or_else(|| panic!("{heading}"));
let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e);
&text[at..end]
}
fn extension() -> String {
std::fs::read_to_string(wai_dir().join("extensions/avatars.md")).expect("the extension")
}
#[test]
fn the_inputs_are_the_pinned_ones() {
assert_eq!(corpus::check_inputs(&inputs(&committed())), Vec::<String>::new());
}
#[test]
fn the_committed_corpus_regenerates_from_its_seeds() {
let files = committed();
let mut generated: BTreeMap<String, Vec<u8>> = corpus::generate(&inputs(&files)).into_iter().collect();
generated.extend(inputs(&files));
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_avatar_face_vectors gen`");
}
#[test]
fn every_vector_gets_what_it_states() {
let fails = corpus::verify(&committed());
assert!(fails.is_empty(), "{}", fails.join("\n"));
}
/// §10 lists, in its first table, exactly the codes `Reason::ALL` has, in order, and in its
/// second exactly the codes the files are refused with.
#[test]
fn the_extension_lists_the_reasons() {
let text = extension();
let s = section(&text, "\n## 10. Reasons");
let tables: Vec<Vec<String>> = s
.split("\n\n")
.filter(|b| b.lines().any(|l| l.starts_with("| `")))
.map(|b| b.lines().filter(|l| l.starts_with("| `")).filter_map(|l| l.split('`').nth(1).map(String::from)).collect())
.collect();
assert_eq!(tables.len(), 2, "§10 has two tables of codes");
let want: Vec<String> = Reason::ALL.iter().map(|r| r.code().to_string()).collect();
assert_eq!(tables[0], want, "§10's first table and Reason::ALL differ");
let forms: Vec<String> = FormError::ALL.iter().map(|r| r.code().to_string()).collect();
assert_eq!(tables[1], forms, "§10's second table and FormError::ALL differ");
}
/// §7.9's tables state the training tool's report, `training.json`, figure for figure.
#[test]
fn the_measurement_is_the_reports() {
let text = extension();
let s = section(&text, "\n### 7.9 ");
let files = committed();
let report: serde_json::Value = serde_json::from_slice(&files["training.json"]).expect("training.json");
let m = &report["measurement"];
let f = |v: &serde_json::Value| match v.as_f64() {
Some(x) if x.fract() == 0.0 => format!("{x:.1}"),
_ => v.to_string(),
};
for (key, what) in [("int_float", "integer, float"), ("int_truth", "integer, rendered"), ("float_truth", "float, rendered"), ("warp_truth", "warp alone, rendered")] {
let p = &m["psnr_db"][key];
let q = &m["ssim"][key];
let row = format!("| {what} | {} | {} | {} | {} |", f(&p["mean"]), f(&p["min"]), f(&q["mean"]), f(&q["min"]));
assert!(s.contains(&row), "§7.9 lacks the row `{row}`");
}
for (key, what) in [("truth", "the rendered faces"), ("float", "the float network's"), ("int", "the integer generator's")] {
let row = format!("| {what} | {} | {} |", f(&m["keypoint_rms_px"][key]), f(&m["mouth_keypoint_rms_px"][key]));
assert!(s.contains(&row), "§7.9 lacks the row `{row}`");
}
for (key, what) in [("truth_step4", "rendered, step 4"), ("truth_step1", "rendered, step 1"), ("detected_step4", "detected, step 4"), ("detected_step1", "detected, step 1")] {
let row = format!("| {what} | {} |", f(&m["track_kbit_s"][key]));
assert!(s.contains(&row), "§7.9 lacks the row `{row}`");
}
let g = &report["generator"];
assert_eq!(g["sha256"].as_str(), Some(corpus::INPUTS[0].1), "the report's generator is the corpus's");
}
/// The registered generator's graph meets `acc64` and not `acc32` (§7.6), and its frames are
/// §7.6's arithmetic written out loop by loop.
#[test]
fn the_registered_generator_meets_acc64_only() {
let files = committed();
let g = &files["generator.wfg"];
assert!(avatar_face::load(g).is_ok());
assert!(!avatar_face::meets_acc32(g), "a 16-bit activation times a 16-bit weight over hundreds of terms passes i32");
}