open-standards/wai/wai-rs/tests/cli_registry.rs
Transaction Science 05032bfef5 wai: give each CLI registry test its own payload directory
Three tests in tests/cli_registry.rs wrote their payload into one shared
directory, which scratch_dir empties before returning. Run in parallel,
one test removed the directory while another wrote into it, and the write
failed with EINVAL. Each test now names its own payload directory; the
carriage and CLI step passed three runs in a row.

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

177 lines
8.1 KiB
Rust

//! The `wai` binary's registry commands and its candidate refusal, run as a
//! user runs them. No codec feature is needed (`--test cli_registry`).
//!
//! - `wai registry export --check` passes on the committed tree and fails, writing
//! nothing, on a tree whose export has drifted; `wai registry export` repairs it.
//! - `wai wrap` refuses a candidate capability (SPEC §5, *Candidate capabilities*)
//! in every place an envelope can name one, and writes nothing.
//! - `wai inspect` and `wai capabilities` claim native decode only in a build that
//! has it (the `codecs` feature).
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
fn wai(args: &[&str]) -> Output {
Command::new(env!("CARGO_BIN_EXE_wai")).args(args).output().expect("run wai")
}
fn scratch_dir(name: &str) -> PathBuf {
let dir = Path::new(env!("CARGO_TARGET_TMPDIR")).join("cli_registry").join(name);
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
dir
}
fn wai_dir() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("..")
}
/// The files the export covers, relative to `wai/`.
const EXPORTED: &[&str] = &[
"registry/capabilities.json",
"registry/capabilities.schema.json",
"vocab/v2.ttl",
"vocab/v2.jsonld",
"vocab/v2.shapes.ttl",
"REGISTRY.md",
];
/// A copy of the exported files of the committed tree under a scratch root.
fn copy_tree(name: &str) -> PathBuf {
let root = scratch_dir(name);
for rel in EXPORTED {
let to = root.join(rel);
std::fs::create_dir_all(to.parent().unwrap()).unwrap();
std::fs::copy(wai_dir().join(rel), &to).unwrap();
}
root
}
#[test]
fn registry_export_check_passes_on_the_committed_tree() {
let run = wai(&["registry", "export", "--check"]);
assert!(run.status.success(), "{}{}", String::from_utf8_lossy(&run.stdout), String::from_utf8_lossy(&run.stderr));
}
#[test]
fn registry_export_check_fails_on_drift_and_export_repairs_it() {
let root = copy_tree("drift");
let root_s = root.to_str().unwrap();
let json = root.join("registry/capabilities.json");
let good = std::fs::read(&json).unwrap();
let edited = String::from_utf8(good.clone()).unwrap().replacen("\"patent-pool\"", "\"royalty-free\"", 1);
std::fs::write(&json, &edited).unwrap();
// The REGISTRY.md generated region drifts too.
let md = root.join("REGISTRY.md");
let md_good = std::fs::read_to_string(&md).unwrap();
std::fs::write(&md, md_good.replacen("| candidate |", "| registered |", 1)).unwrap();
let run = wai(&["registry", "export", "--root", root_s, "--check"]);
let stderr = String::from_utf8_lossy(&run.stderr);
assert_eq!(run.status.code(), Some(1), "drift exits 1: {stderr}");
assert!(stderr.contains("registry/capabilities.json") && stderr.contains("REGISTRY.md"), "{stderr}");
assert!(stderr.contains("registry export"), "the message says how to regenerate: {stderr}");
assert_eq!(std::fs::read_to_string(&json).unwrap(), edited, "--check writes nothing");
let run = wai(&["registry", "export", "--root", root_s]);
assert!(run.status.success(), "{}", String::from_utf8_lossy(&run.stderr));
assert_eq!(std::fs::read(&json).unwrap(), good, "export restores the committed bytes");
assert_eq!(std::fs::read_to_string(&md).unwrap(), md_good);
assert!(wai(&["registry", "export", "--root", root_s, "--check"]).status.success());
}
#[test]
fn registry_without_a_subcommand_is_refused() {
let run = wai(&["registry"]);
assert!(!run.status.success());
assert!(String::from_utf8_lossy(&run.stderr).contains("registry export"));
}
/// A payload file in a directory of the calling test's own: tests run in
/// parallel, and `scratch_dir` empties the directory it returns.
fn payload(test: &str) -> PathBuf {
let dir = scratch_dir(&format!("payload-{test}"));
let p = dir.join("bytes");
std::fs::write(&p, b"opaque payload bytes").unwrap();
p
}
#[test]
fn wrap_refuses_a_candidate_and_writes_nothing() {
let p = payload("wrap_refuses_a_candidate_and_writes_nothing");
let p = p.to_str().unwrap();
let companion = scratch_dir("companion").join("hdr");
std::fs::write(&companion, b"metadata").unwrap();
let companion = companion.to_str().unwrap();
let cases: [(&str, Vec<&str>); 6] = [
// WAI1: as the capability, with and without --intent, and as the fallback.
("wai.splat.sog", vec![]),
("wai.tensor.nnc", vec!["--intent", "improve"]),
("wai.image.png", vec!["--fallback", "wai.splat.sog"]),
// WAI2: as the base rendition, and as a companion in either intent.
("wai.splat.sog", vec!["--companion", "wai.meta.hdr10plus", companion]),
("wai.video.av1", vec!["--companion", "wai.splat.sog", companion]),
("wai.video.av1", vec!["--intent", "improve", "--companion", "wai.tensor.nnc", companion]),
];
for (i, (cap, extra)) in cases.iter().enumerate() {
let out = scratch_dir(&format!("refuse{i}")).join("out.wai");
let mut args = vec!["wrap", cap, p, "-o", out.to_str().unwrap()];
args.extend(extra.iter());
let run = wai(&args);
let stderr = String::from_utf8_lossy(&run.stderr);
assert!(!run.status.success(), "{cap} {extra:?}: wrap must refuse; stderr: {stderr}");
assert!(stderr.contains("is a candidate capability") && stderr.contains("SPEC"), "{cap} {extra:?}: {stderr}");
assert!(!out.exists(), "{cap} {extra:?}: a refused wrap must not write an envelope");
}
// A registered, pinned capability still wraps.
let out = scratch_dir("accept").join("out.wai");
let run = wai(&["wrap", "wai.pc.gpcc", p, "-o", out.to_str().unwrap()]);
assert!(run.status.success(), "{}", String::from_utf8_lossy(&run.stderr));
assert!(out.exists());
}
#[test]
fn wrap_writes_the_registry_media_class() {
let p = payload("wrap_writes_the_registry_media_class");
for (cap, media, extra) in [
("wai.mesh.draco", "volumetric", &[][..]),
("wai.neural.bmshj2018", "image", &["--intent", "improve"][..]),
("wai.film.reel", "video", &[][..]),
] {
let out = scratch_dir(&format!("media-{media}")).join("out.wai");
let mut args = vec!["wrap", cap, p.to_str().unwrap(), "-o", out.to_str().unwrap()];
args.extend(extra.iter());
let run = wai(&args);
assert!(run.status.success(), "{cap}: {}", String::from_utf8_lossy(&run.stderr));
let env = wai::container::Wai::read(&out).unwrap();
assert_eq!(env.media(), media, "{cap}");
}
}
/// `inspect` and `capabilities` take their native set from what the binary was
/// built with: without the `codecs` feature, `decode` is unavailable, so neither
/// may say a PNG envelope decodes here or list PNG as native.
#[test]
fn inspect_and_capabilities_claim_native_decode_only_with_codecs() {
let p = payload("inspect_and_capabilities_claim_native_decode_only_with_codecs");
let out = scratch_dir("inspect").join("png.wai");
let run = wai(&["wrap", "wai.image.png", p.to_str().unwrap(), "-o", out.to_str().unwrap(), "--intent", "improve"]);
assert!(run.status.success(), "{}", String::from_utf8_lossy(&run.stderr));
let run = wai(&["inspect", out.to_str().unwrap()]);
assert!(run.status.success(), "{}", String::from_utf8_lossy(&run.stderr));
let inspect = String::from_utf8_lossy(&run.stdout).into_owned();
let run = wai(&["capabilities"]);
assert!(run.status.success());
let caps = String::from_utf8_lossy(&run.stdout).into_owned();
let png_row = caps.lines().find(|l| l.trim_start().starts_with("wai.image.png ")).expect("a png row");
if cfg!(feature = "codecs") {
assert!(inspect.contains("DECODABLE via primary capability"), "{inspect}");
assert!(png_row.contains(" native "), "{png_row}");
} else {
assert!(!inspect.contains("DECODABLE"), "{inspect}");
assert!(!inspect.contains("this sink advertises it"), "{inspect}");
assert!(inspect.contains("decodes nothing natively"), "{inspect}");
assert!(png_row.contains("sink-supplied") && !png_row.contains(" native "), "{png_row}");
assert!(caps.contains("decodes nothing natively"), "{caps}");
}
}