open-standards/wai/wai-rs/tests/platform_encode.rs

91 lines
5 KiB
Rust

//! `wai.video.encode` (extensions/platform-encode.md): the committed corpus
//! `encode-conformance/` regenerates byte for byte from its pinned fixture streams, every case
//! gets the outcome it states, every record reason of §12 is in it, and §12 lists exactly the
//! reasons the reference reports. Where the platform's media framework is built in (macOS), an
//! encode through it of each codec holds to §4.3, signs a record that verifies, and decodes in
//! the platform's decoder to one picture per frame; a host with no hardware engine fails that
//! test rather than skipping it.
#![cfg(feature = "platform_encode")]
use std::collections::{BTreeMap, BTreeSet};
use std::path::PathBuf;
use wai::platform_encode::{corpus, record::Reason, sha256_hex};
fn dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../encode-conformance")
}
fn streams() -> BTreeMap<String, Vec<u8>> {
corpus::FIXTURES.iter().map(|f| (f.file.to_string(), std::fs::read(dir().join("streams").join(f.file)).expect("a fixture stream"))).collect()
}
#[test]
fn the_fixture_streams_are_the_pinned_bytes() {
let pins: serde_json::Value = serde_json::from_slice(&std::fs::read(dir().join("streams.json")).expect("streams.json")).expect("JSON");
let s = streams();
assert_eq!(pins.as_object().expect("an object").len(), s.len(), "streams.json pins every fixture and nothing else");
for (k, v) in &s {
assert_eq!(pins[k].as_str(), Some(sha256_hex(v).as_str()), "{k} is not the bytes streams.json pins");
}
}
#[test]
fn the_committed_corpus_regenerates_byte_for_byte() {
let generated = corpus::generate(&streams());
for (p, b) in &generated {
assert_eq!(std::fs::read(dir().join(p)).ok().as_ref(), Some(b), "{p} does not regenerate: run `wai_encode_vectors gen`");
}
for sub in ["records", "mutated"] {
for e in std::fs::read_dir(dir().join(sub)).expect("the corpus").flatten() {
let rel = format!("{sub}/{}", e.file_name().to_string_lossy());
assert!(generated.contains_key(&rel), "{rel} is not generated");
}
}
}
#[test]
fn every_case_gets_its_outcome_and_every_reason_appears() {
assert!(corpus::check(&dir()).is_ok(), "{:?}", corpus::check(&dir()));
let cases = corpus::cases(&streams());
let seen: BTreeSet<&str> = cases.iter().filter_map(|c| c.expect.map(Reason::code)).collect();
// The rendition's reason is the packager's corpus's (wai-pack tests/encode_rung.rs).
let want: BTreeSet<&str> = Reason::ALL.iter().map(|r| r.code()).filter(|c| *c != "encode-package-mismatch").collect();
assert_eq!(seen, want, "every record reason but the rendition's has a case");
assert!(cases.iter().filter(|c| c.expect.is_none()).count() >= corpus::FIXTURES.len(), "every fixture is accepted");
}
#[test]
fn the_reasons_table_is_the_references() {
let text = std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../extensions/platform-encode.md")).expect("the extension");
let at = text.find("## 12. Reasons").expect("§12");
let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e);
let table: BTreeSet<String> = text[at..end]
.lines()
.filter(|l| l.starts_with("| `") && !l.contains("| producer |"))
.filter_map(|l| l.split('`').nth(1).map(String::from))
.collect();
let code: BTreeSet<String> = Reason::ALL.iter().map(|r| r.code().to_string()).collect();
assert_eq!(table, code, "§12's record reasons are exactly Reason::ALL");
}
/// The media framework's encoders, each codec, on this host: §4.3 holds, a signed record
/// verifies with the stream and the source held, and the platform's decoder gives one
/// picture per frame.
#[cfg(target_vendor = "apple")]
#[test]
fn the_platform_encoder_makes_a_stream_that_holds_and_decodes() {
use wai::platform_encode::{self as pe, Api, Codec, Options, record};
let src = corpus::source();
for codec in [Codec::Avc, Codec::Hevc] {
let p = pe::prepare(&src, codec, None, 400).expect("the corpus source");
let e = pe::encode(Api::Platform, &p.cfg, &Options::default(), p.frames.iter().map(Vec::as_slice), &corpus::PLAN).unwrap_or_else(|e| panic!("{}: {e}", codec.name()));
assert!(e.identity.hardware, "{}: the framework chose its software encoder: {:?}", codec.name(), e.identity);
let body = record::body(&e, &p.cfg, &p.source, &corpus::PLAN, None, None, corpus::ISSUED_AT);
let text = record::to_text(&record::sign(body, &ed25519_dalek::SigningKey::from_bytes(&corpus::SEED)));
let (hd, frames) = pe::y4m::read_all(&src).expect("the source");
let planes = frames.concat();
record::verify(&text, &record::Held { stream: Some(&e.stream), source: Some((&hd, &planes)) }).unwrap_or_else(|r| panic!("{}: {r}", codec.name()));
let n = pe::platform_decode(codec, &e.stream, &e.units, |f| if f.len() == p.cfg.picture_len() { Ok(()) } else { Err("a picture of another size".into()) }).expect("the platform decodes it");
assert_eq!(n, corpus::FRAMES, "{}: one picture per frame", codec.name());
}
}