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
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]>
140 lines
7.8 KiB
Rust
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, ¶ms)
|
|
}
|
|
|
|
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"));
|
|
}
|