open-standards/wai/wai-rs/tests/int_payload.rs
Transaction Science 946f3beda9
All checks were successful
joule-moq-remote host agent / joule-moq-remote · does this change touch it (pull_request) Successful in 6s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 7s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
wai-app and Create / wai-app · does this change touch it (pull_request) Successful in 6s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 6s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 6s
WAI operation catalogue / does this change touch it (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 6s
WAI energy receipts / does this change touch it (pull_request) Successful in 5s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 6s
wai-fleet service / does this change touch it (pull_request) Successful in 6s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 7s
wai-ledger service / does this change touch it (pull_request) Successful in 6s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Successful in 1m25s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 6s
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 6s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 6s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 6s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 6s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m57s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m7s
WAI Studio / does this change touch it (pull_request) Successful in 6s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-web wasm32 / does this change touch it (pull_request) Successful in 6s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Successful in 29s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 2m1s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m59s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 1m1s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 26s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m19s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 16s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m4s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Successful in 1m15s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 5m15s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 6m19s
wai-fleet service / service · macos (pull_request) Successful in 1m2s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 2m46s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 1m43s
wai-ledger service / service · macos (pull_request) Successful in 1m24s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m2s
WAI operation catalogue / the catalogue and every door · linux (pull_request) Successful in 4m18s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 9m19s
wai-pack / wai-pack · macos (pull_request) Successful in 3m8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 30s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 7m49s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 3m23s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m39s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m9s
wai-fleet service / service · linux (pull_request) Successful in 2m5s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 3m28s
wai-ledger service / service · linux (pull_request) Successful in 1m43s
wai-pack / wai-pack · linux (pull_request) Successful in 1m55s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 3m0s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 1m10s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 16m12s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m32s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 4m51s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 13m12s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 15m2s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m3s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 16m34s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m40s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 17m22s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m44s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m46s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 34s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 17s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 9m28s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m7s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 14m49s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m34s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m16s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 11m4s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 13m6s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m58s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 10m55s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 9m51s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 10m15s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 9m21s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 30m14s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h4m7s
Changelog entries and the conformance workflow's lists move into files a change adds
Every change to WAI added an entry at the head of wai/CHANGELOG.md, and every new module
appended to the hand-kept lists of .github/workflows/wai-conformance.yml. So any two
branches conflicted on those lines and had to merge one after another. This moves both into
files a change adds.

- Changelog entries: a change adds wai/changes/<yyyy-mm-dd>-<slug>.md holding the entry
  text. scripts/changelog-assemble.py renders the entries into CHANGELOG.md's Unreleased
  section for a release, in a stable order. scripts/check-changelog-fragment.py, run by
  repo-checks on every pull request, fails a pull request that changes wai/ and adds or
  edits no entry file directly in wai/changes/ (a release passes, and so does a commit
  with the trailer line "Changelog: none"). A pull request opened before the check reached
  main passes as it is; one opened after it that adds its entry to the head of Unreleased
  fails and is told where the entry goes. wai breaking reads breaking changes from entry
  files too.
- The conformance workflow: each per-module verifier step is a file in
  .github/wai-conformance/verifiers/, each corpus a file in corpora/, and the
  integer-kernel tests carry a tag line. scripts/wai-conformance-lists.py derives every
  list the workflow kept by hand (WAI_FEATURES, the union --bin and --test lists, the
  features-alone lists, the kernel and corpus steps) from those files when the workflow
  runs. Its `selftest --exact` holds the derived lists to the hand lists of the commit
  before this one, and its dry-run prints every command each job runs: the dry-runs before
  and after this change differ only in the gate's path list, which gains the two paths this
  change adds.
- What stays shared, and how to insert there, is written in wai/CONTRIBUTING.md and
  wai/changes/README.md: wai-rs Cargo.toml features and [[test]] entries, lib.rs, registry
  rows, wai/.gitattributes and the live corpus table take an insert beside the related
  entry, never at the end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 01:41:29 -05:00

140 lines
7.8 KiB
Rust

// wai-conformance: int-kernels
//! The payloads of the WAI-native integer codecs (`extensions/integer-payloads.md`)
//! against the committed corpus `wai/int-payload-conformance/`:
//!
//! - every refusal fixture is refused with the code its index states, at the layer it
//! states (parsing alone, or the decode);
//! - every strict prefix of every committed payload is refused, and every changed byte
//! in a sweep over each payload is refused or decoded — never a panic, in either
//! profile (CI runs this file with overflow checks on and off);
//! - a tool's JSON output carried as an envelope's payload under each pinned string is
//! refused (`bad_magic`) by the framing check `wai wrap` runs and by `decode_int`.
#![cfg(all(feature = "video_int", feature = "audio_int", feature = "splat_int"))]
use std::collections::BTreeMap;
use std::path::PathBuf;
use serde_json::Value;
use wai::container::{Conditioning, Manifest, ModelRequirement, Rendition, Wai, WaiMulti};
use wai::int_payload::{decode_int, wire, IntParams, Refusal};
use wai::pin::HeldBytes;
fn wai_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..")
}
fn read(rel: &str) -> Vec<u8> {
let p = wai_dir().join(rel);
std::fs::read(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()))
}
fn index() -> Value {
serde_json::from_slice(&read("int-payload-conformance/vectors.json")).expect("the index parses")
}
/// The set an index entry names, read: member name → bytes.
fn set_of(entry: &Value) -> BTreeMap<String, Vec<u8>> {
entry["set"].as_object().into_iter().flatten().map(|(k, v)| (k.clone(), read(v.as_str().unwrap()))).collect()
}
fn decode(cap: &str, payload: &[u8], set: &BTreeMap<String, Vec<u8>>) -> Result<wai::int_payload::IntDecoded, wai::int_payload::IntPayloadError> {
let view: BTreeMap<String, &[u8]> = set.iter().map(|(k, v)| (k.clone(), v.as_slice())).collect();
let params = wai::int_payload::resolve(cap, None, &[HeldBytes::Set { listing: b"", files: &view }], None)
.unwrap_or_else(|_| IntParams::none());
decode_int(cap, payload, &params)
}
fn parse_err(cap: &str, p: &[u8]) -> Option<wire::WireError> {
match wai::codecs::pinned_int_payload(cap)? {
wire::MAGIC_WIV1 => wire::parse_wiv1(p, Some((cap == wai::codecs::CAP_VIDEO_INT_HYPER) as u8)).err(),
wire::MAGIC_WIH1 => wire::parse_wih1(p).err(),
wire::MAGIC_WIA1 => wire::parse_wia1(p).err(),
_ => wire::parse_wis1(p).err(),
}
}
/// Every fixture is refused with its code, at its layer; and every code a payload's
/// bytes can cause has a fixture.
#[test]
fn every_refusal_fixture_is_refused_with_its_code() {
let idx = index();
let mut seen = std::collections::BTreeSet::new();
for f in idx["refusals"].as_array().unwrap() {
let (name, cap, code) = (f["name"].as_str().unwrap(), f["capability"].as_str().unwrap(), f["code"].as_str().unwrap());
let payload = read(f["payload"].as_str().unwrap());
let parsed = parse_err(cap, &payload);
match f["layer"].as_str().unwrap() {
"parse" => assert_eq!(parsed.map(|e| e.code()), Some(code), "{name}: refused by parsing alone"),
_ => assert_eq!(parsed, None, "{name}: parses, and is refused by the decode"),
}
let r = decode(cap, &payload, &set_of(f));
assert_eq!(r.as_ref().map(|_| ()).map_err(|e| e.code()), Err(code), "{name}");
seen.insert(code);
}
for code in ["bad_magic", "format_capability_mismatch", "keyframe_capability_mismatch", "version", "reserved_nonzero",
"field_range", "too_large", "cdf_malformed", "stream_length", "nested_length", "trailing",
"stream_exhausted", "stream_noncanonical", "geometry_mismatch", "model_mismatch"] {
assert!(Refusal::from_code(code).is_some(), "{code} is a code");
assert!(seen.contains(code), "no fixture is refused with {code}");
}
}
/// Every strict prefix of every committed payload is refused; a sweep of single-byte
/// changes over each is refused or decoded, and nothing panics. The sweep changes
/// every byte of the fixed header and 96 bytes spread evenly over the rest (low bit
/// and high bit by turns), so each payload's tables, length fields and stream are
/// all reached while the decodes stay few enough for a build with overflow checks.
#[test]
fn every_prefix_and_byte_change_is_refused_or_decoded() {
let idx = index();
for v in idx["vectors"].as_array().unwrap() {
let (name, cap) = (v["name"].as_str().unwrap(), v["capability"].as_str().unwrap());
let payload = read(v["payload"].as_str().unwrap());
let set = set_of(v);
assert!(decode(cap, &payload, &set).is_ok(), "{name}: the committed payload decodes");
for n in 0..payload.len() {
assert!(parse_err(cap, &payload[..n]).is_some(), "{name}: the {n}-byte prefix parses");
}
let (mut refused, mut decoded) = (0, 0);
const HEADER: usize = 48;
let stride = (payload.len() - HEADER).div_ceil(96).max(1);
for (n, at) in (0..payload.len()).filter(|&i| i < HEADER || (i - HEADER) % stride == 0).enumerate() {
let mut p = payload.clone();
p[at] ^= if n % 2 == 0 { 0x01 } else { 0x80 };
match decode(cap, &p, &set) {
Ok(_) => decoded += 1,
Err(_) => refused += 1,
}
}
assert!(refused > 0, "{name}: no change was refused");
println!("{name}: {refused} changes refused, {decoded} decoded, no panic");
}
}
/// A tool's JSON output wrapped as the payload under each pinned string: the framing
/// check (`Wai::check_int_payload_framing`, `WaiMulti::check_int_payload_framing`,
/// which `wai wrap` and `wai inspect` run) and `decode_int` both refuse it as
/// `bad_magic`; its binary conversion passes both.
#[test]
fn a_json_form_in_an_envelope_is_refused() {
use wai::codecs as c;
for (cap, json, bin) in [
(c::CAP_VIDEO_INT_MOTION, "wai-rs/tests/vectors/int_video/int_video_bitstream.json", "wai-rs/tests/vectors/int_video/int_video_bitstream.wiv1"),
(c::CAP_VIDEO_INT_HYPER, "wai-rs/tests/vectors/int_video/video_nk_bitstream.json", "wai-rs/tests/vectors/int_video/video_nk_bitstream.wiv1"),
(c::CAP_NEURAL_INT_HYPER, "wai-rs/tests/vectors/int_hyper/tiny_bitstream.json", "wai-rs/tests/vectors/int_hyper/tiny_bitstream.wih1"),
(c::CAP_AUDIO_INT_CODEC, "wai-rs/tests/vectors/int_audio/audio_bitstream.json", "wai-rs/tests/vectors/int_audio/audio_bitstream.wia1"),
(c::CAP_SPLAT_INT_CODEC, "wai-rs/tests/vectors/int_splat/splat.json", "wai-rs/tests/vectors/int_splat/splat.wis1"),
] {
let wrap = |payload: Vec<u8>| Wai::new(Manifest::new("binary", "improve", ModelRequirement::new(cap), Conditioning::new("bytes")), payload);
let env = Wai::from_bytes(&wrap(read(json)).to_bytes().unwrap()).unwrap();
assert_eq!(env.check_int_payload_framing().map_err(|e| e.code), Err("bad_magic"), "{cap}");
assert_eq!(decode_int(cap, &env.payload, &IntParams::none()).map(|_| ()).map_err(|e| e.code()), Err("bad_magic"), "{cap}");
assert_eq!(wrap(read(bin)).check_int_payload_framing(), Ok(()), "{cap}: the binary form");
let multi = WaiMulti::new("binary", "improve", Value::Null, vec![Rendition::media(cap, "bytes", read(json))]);
assert_eq!(multi.check_int_payload_framing().map_err(|(i, e)| (i, e.code)), Err((0, "bad_magic")), "{cap}");
}
// The fallback decodes the same payload (SPEC §4 step 5), so its framing is checked too.
let env = Wai::new(
Manifest::new("video", "improve", ModelRequirement::new(c::CAP_VIDEO_AV1).with_fallback(c::CAP_VIDEO_INT_MOTION), Conditioning::new("bytes")),
read("wai-rs/tests/vectors/int_video/int_video_bitstream.json"));
assert_eq!(env.check_int_payload_framing().map_err(|e| e.code), Err("bad_magic"));
}