open-standards/wai/wai-pack/tests/refusals.rs
Transaction Science 39375763c7 wai-pack: an override never relaxes royalty_free_only; empty and unreadable directories refused; pack only into an empty --out; classic in any case; deep alterations never panic
Round 3 of the package review.

A. §3.2: an override only forces royalty_free_only on. Overrides.royalty_free_only is a
   bool (force on); Policy::effective ORs it in. Both verifiers read policy.json's
   royalty_free_only as that override, so a policy.json of false over a policy.toml of
   true is policy-json-mismatch. pack_verify.py parses policy.toml, applies the
   override, then checks §3.6 under the effective policy (§11.3 step 4), no longer
   refusing at the parse. Corpus case policy-json-relaxes-royalty-free (the review's
   pk-pol-rfo-false: a patent-pool floor relabelled through the objects and index,
   sealed with policy.json false). golden::reseal_as seals a policy.json given as bytes.
   The policy corpus's override case is now eq-defaults-a.toml forced on (example.toml
   forced off was a relaxation); packs.rs takes the line out of the policy instead.
B. pack_verify.py's strict walk raises on a directory it cannot read (os.walk onerror)
   and refuses it, as read_strict does.
C. Both verifiers refuse a directory below the package that holds nothing
   (unexpected-file); §11.1 says "no other file or directory". Corpus cases
   empty-directory, empty-dot-directory (.git/refs) and unreadable-directory (mode 0,
   or empty where the platform has no modes). Package cases are now written out and
   verified as directories by both verifiers (golden::package_case_verdict).
D. wai-pack pack refuses an --out that exists and is not empty (pack-out-not-empty,
   pack::out_dir_ready), before any work; §11.4 and §12. refusals.rs runs the command
   line: a stale claim left alone, a file in the way, an empty and a new directory
   packed and verified.
E. A class named classic in any case is pack-id (eq_ignore_ascii_case); corpus case
   class-named-classic-in-capitals.
F. review.rs deep_alterations_never_panic: 300 seeded rounds of floor-unit, framing,
   base-payload and index-field alterations through golden::replace_object and a
   re-seal; never a panic; anything accepted is in a stated equivalence class (AV1
   frame data, producer statements, equivalent WIV1 encodings) or the golden itself.

Floors: review 9, refusals 5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 09:09:09 -04:00

226 lines
11 KiB
Rust

//! Every refusal of the packer this revision names (packaging §7.3, §11.4, §12), each from
//! the golden's inputs with one thing changed: the supplied floor's reasons, what this
//! revision does not pack yet, a meter that gives no figure, the encoder's caps, and an
//! output directory that is not empty.
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
type Files = BTreeMap<String, Vec<u8>>;
fn corpus() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../pack-conformance")
}
fn golden_policy() -> String {
String::from_utf8(std::fs::read(corpus().join("packs/video-base-01/policy.toml")).unwrap()).unwrap()
}
fn golden_floor() -> Vec<u8> {
std::fs::read(corpus().join("packs/video-base-01/floor/v.obu")).unwrap()
}
/// The golden policy with its floor pinned to the listing of `floor`, and `edit` applied.
fn policy_for(floor: &Files, edit: &dyn Fn(String) -> String) -> Vec<u8> {
let listing = wai_pack::floor::listing_sha256(floor).unwrap();
let p = golden_policy();
let at = p.find("supplied_listing = \"").unwrap() + "supplied_listing = \"".len();
let p = format!("{}{listing}{}", &p[..at], &p[at + 64..]);
edit(p).into_bytes()
}
fn pack(policy: &[u8], floor: Files, meter: Option<Box<dyn wai::energy_meter::Meter>>) -> String {
let mut o = wai_pack::pack::PackOpts::new(ed25519_dalek::SigningKey::from_bytes(&[0x5a; 32]), "did:key:test", floor);
o.meter = meter;
o.power_reader = "model".into();
o.issued_at = "2026-10-06T00:00:00Z".into();
let mut src = BTreeMap::new();
src.insert("v".to_string(), wai_pack::fixture::generate("video-base-01").unwrap());
match wai_pack::pack::pack(policy, &src, &mut o) {
Ok(_) => "ok".into(),
Err(e) => e.code,
}
}
fn units() -> Vec<Vec<u8>> {
wai_pack::av1::temporal_units(&golden_floor()).unwrap().iter().map(|t| t.bytes()).collect()
}
fn floor_of(stream: Vec<u8>) -> Files {
let mut f = BTreeMap::new();
f.insert("v.obu".to_string(), stream);
f
}
fn case(stream: Vec<u8>, edit: &dyn Fn(String) -> String) -> String {
let fl = floor_of(stream);
pack(&policy_for(&fl, edit), fl, None)
}
/// §7.3: each reason a supplied floor is refused with, before anything is written.
#[test]
fn every_floor_reason() {
let u = units();
let id = |p: String| p;
assert_eq!(case(golden_floor(), &id), "ok");
// No floor rung.
assert_eq!(
case(golden_floor(), &|p: String| p.replace("[[ladder]]\nid = \"f0\"\ncomponent = \"v\"\ncapability = \"wai.video.av1\"\nrole = \"floor\"\nparams = { source = \"supplied\" }\n", "")),
"floor-missing"
);
// A listing the policy does not pin.
let fl = floor_of(golden_floor());
let mut pol = String::from_utf8(policy_for(&fl, &id)).unwrap();
let at = pol.find("supplied_listing = \"").unwrap() + "supplied_listing = \"".len();
pol.replace_range(at..at + 64, &"0".repeat(64));
assert_eq!(pack(pol.as_bytes(), fl, None), "floor-listing-mismatch");
// No stream for the component.
let mut other = BTreeMap::new();
other.insert("w.obu".to_string(), golden_floor());
assert_eq!(pack(&policy_for(&other, &id), other, None), "floor-stream-missing");
// A stream cut inside its last unit; an empty stream.
let g = golden_floor();
assert_eq!(case(g[..g.len() - 3].to_vec(), &id), "floor-av1-malformed");
assert_eq!(case(Vec::new(), &id), "floor-av1-malformed");
// One unit short.
assert_eq!(case(u[..u.len() - 1].concat(), &id), "floor-frame-count");
// The piece of frames 85 to 134 opening on an inter frame, with no key frame
// anywhere in it.
let mut inter = u.clone();
inter[85] = u[86].clone();
assert_eq!(case(inter.concat(), &id), "floor-keyframe-mismatch");
// A key frame inside piece 2: refused, unless extra key frames are allowed.
let mut extra = u.clone();
extra[86] = u[85].clone();
assert_eq!(case(extra.concat(), &id), "floor-keyframe-mismatch");
assert_eq!(case(extra.concat(), &|p: String| p.replace("[floor]\n", "[floor]\nextra_keyframes = true\n")), "ok");
}
/// §11.4: what this revision does not pack yet is refused by name, every
/// `pack-capability-unsupported` naming its capability.
#[test]
fn what_this_revision_does_not_pack() {
let fl = floor_of(golden_floor());
let run = |edit: &dyn Fn(String) -> String| pack(&policy_for(&fl, edit), fl.clone(), None);
// Another medium, and two components.
assert_eq!(run(&|p: String| p.replace("media = \"video\"", "media = \"image\"")), "pack-media-unsupported");
assert_eq!(
run(&|p: String| p.replace("[segmentation]", "[[component]]\nid = \"a\"\nmedia = \"audio\"\n\n[component.timebase]\nnum = 48000\nden = 1\n\n[[ladder]]\nid = \"ab\"\ncomponent = \"a\"\ncapability = \"wai.audio.flac\"\nrole = \"base\"\n\n[segmentation]")),
"pack-media-unsupported"
);
// A refinement rung.
assert_eq!(
run(&|p: String| p.replace("[floor]", "[[ladder]]\nid = \"r1\"\ncomponent = \"v\"\ncapability = \"wai.video.int_refine\"\nrole = \"refinement\"\nrefines = \"b0\"\nparams = { q = 6 }\n\n[live]\nlayer_lag_ms = [0, 200]\n\n[floor]")),
"pack-refinement-unsupported"
);
// A rule's ladder subset.
assert_eq!(
run(&|p: String| format!("{p}\n[[rule]]\nid = \"s\"\nwhen = {{ piece_kind = [\"static\"] }}\nthen = {{ ladder = [\"b0\", \"f0\"] }}\n")),
"pack-rule-ladder-unsupported"
);
// A floor to encode.
assert_eq!(run(&|p: String| p.replace("params = { source = \"supplied\" }", "params = { source = \"encode\" }")), "pack-floor-encode-unsupported");
// A base of another capability; two bases; a floor of another capability.
assert_eq!(
run(&|p: String| p.replace("capability = \"wai.video.int_motion\"\nrole = \"base\"\nparams = { block = 16, search = 4, mv_precision = 1, q_candidates = [16, 12, 8], max_sse_px_milli = 30000 }", "capability = \"wai.image.png\"\nrole = \"base\"")),
"pack-capability-unsupported:wai.image.png"
);
assert_eq!(
run(&|p: String| p.replace("[floor]", "[[ladder]]\nid = \"b1\"\ncomponent = \"v\"\ncapability = \"wai.image.png\"\nrole = \"base\"\n\n[floor]")),
"pack-capability-unsupported:wai.image.png"
);
assert_eq!(
run(&|p: String| p.replace("capability = \"wai.video.av1\"\nrole = \"floor\"\nparams = { source = \"supplied\" }", "capability = \"wai.image.png\"\nrole = \"floor\"")),
"pack-capability-unsupported:wai.image.png"
);
}
/// A meter that was asked for and gives no figure refuses the pack: a model past its
/// range, and one whose figure rounds to nothing.
#[test]
fn a_meter_with_no_figure_refuses_the_pack() {
let fl = floor_of(golden_floor());
let pol = policy_for(&fl, &|p: String| p);
let clock = |step: u64| {
let mut t = 0u64;
move || {
let v = t;
t += step;
v
}
};
let huge = wai::energy_meter::ModelMeter::new(clock(1_000_000), u64::MAX / 2);
assert_eq!(pack(&pol, fl.clone(), Some(Box::new(huge))), "pack-meter");
let tiny = wai::energy_meter::ModelMeter::new(clock(1), 1);
assert_eq!(pack(&pol, fl.clone(), Some(Box::new(tiny))), "pack-meter");
let fine = wai::energy_meter::ModelMeter::new(clock(1_000_000), 500);
assert_eq!(pack(&pol, fl, Some(Box::new(fine))), "ok");
}
/// The encoder's caps (the review's clipcap): a 4K piece of 50 frames is past the clip
/// cap (more than 2^30 samples), refused for that before anything is allocated or any
/// frame is read; the packer reports it `pack-encode`.
#[test]
fn the_encoder_refuses_a_piece_past_its_caps() {
let (h, w) = (2160u32, 3840u32);
let frames: Vec<Vec<u8>> = (0..50).map(|_| Vec::new()).collect();
let p = wai_pack::encode::MotionParams { block: 16, search: 7, mv_precision: 2, q_candidates: vec![8], max_sse_px_milli: 0 };
let e = wai_pack::encode::choose_q(&frames, h, w, &p).map(|q| q.q).unwrap_err();
assert_eq!((e.code(), e.detail()), ("too_large", "the clip exceeds the clip cap"));
// One frame fewer than the cap allows passes the caps (and is then refused for its
// frames, which hold nothing).
let n = ((1u64 << 30) / (3 * h as u64 * w as u64)) as usize;
let e = wai_pack::encode::choose_q(&frames[..n], h, w, &p).map(|q| q.q).unwrap_err();
assert_ne!(e.code(), "too_large", "{e}");
}
/// §11.4: `wai-pack pack` writes a package only into a new or empty directory. Into one
/// that holds a file (a measurement claim of an earlier pack, here) it refuses with
/// `pack-out-not-empty` before any work, and leaves the directory as it was; into an
/// empty one it packs a package that verifies.
#[test]
fn the_packer_refuses_an_out_directory_that_is_not_empty() {
let bin = env!("CARGO_BIN_EXE_wai-pack");
let dir = std::env::temp_dir().join(format!("wai-pack-out-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
let src = dir.join("v.y4m");
std::fs::write(&src, wai_pack::fixture::generate("video-base-01").unwrap()).unwrap();
let golden = corpus().join("packs/video-base-01");
let run = |out: &Path| {
std::process::Command::new(bin)
.arg("pack")
.arg("--policy")
.arg(golden.join("policy.toml"))
.arg("--out")
.arg(out)
.arg("--key")
.arg(golden.join("key.hex"))
.arg("--source")
.arg(format!("v={}", src.display()))
.output()
.unwrap()
};
// A directory holding an earlier pack's measurement claim.
let stale = dir.join("stale");
std::fs::create_dir_all(stale.join("claims")).unwrap();
std::fs::write(stale.join("claims/old.measurement.json"), b"{}").unwrap();
let o = run(&stale);
assert!(!o.status.success());
let err = String::from_utf8_lossy(&o.stderr);
assert!(err.contains("pack-out-not-empty"), "{err}");
let left = wai_pack::verify::read_strict(&stale).unwrap();
assert_eq!(left.keys().collect::<Vec<_>>(), ["claims/old.measurement.json"], "nothing written");
// A file where the directory would be.
let file = dir.join("a-file");
std::fs::write(&file, b"x").unwrap();
assert!(String::from_utf8_lossy(&run(&file).stderr).contains("pack-out-not-empty"));
// An empty directory, and one that does not exist yet.
std::fs::create_dir_all(dir.join("empty")).unwrap();
for out in [dir.join("empty"), dir.join("new")] {
let o = run(&out);
assert!(o.status.success(), "{}", String::from_utf8_lossy(&o.stderr));
assert!(wai_pack::verify::verify_dir(&out).is_ok(), "the package verifies");
}
let _ = std::fs::remove_dir_all(&dir);
}