//! The neural C ABI reports a refused pin as `WAI_ERR_PRIOR` with its reason first //! in `wai_last_error`, an unsound `replicate` under the strict flag as //! `WAI_ERR_UNSOUND_REPLICATE`, decodes a `WAI2` envelope through the //! rendition whose pin the registry holds, and reports the decode path that ran and //! whether a `WAI1` decoded through its fallback — all on the committed int_mlicpp //! vector, with no model to fetch. #![cfg(all(feature = "neural", feature = "ffi"))] use std::ffi::{CStr, CString}; use std::path::{Path, PathBuf}; use std::ptr; use wai::codecs::DeclaredTier; use wai::container::{Prior, Rendition, Supersedes, Wai, WaiMulti}; use wai::ffi::*; use wai::ffi_neural::*; fn dir() -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/vectors/int_mlicpp") } fn last_error() -> String { let p = wai_last_error(); if p.is_null() { String::new() } else { unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned() } } fn decoded() -> WaiDecoded { WaiDecoded { kind: 0, index: 0, data: WaiBuffer { data: ptr::null_mut(), len: 0, cap: 0 }, width: 0, height: 0, sample_rate: 0, n_frames: 0, fps_x_1000: 0, path: 0, fallback: 0, } } fn fnv_of(d: &WaiDecoded) -> String { let rgb = unsafe { std::slice::from_raw_parts(d.data.data, d.data.len) }; format!("{:016x}", wai::int_hyper_synth::fnv1a(rgb)) } #[test] fn tampered_model_is_wai_err_prior() { let env = std::fs::read(dir().join("stream.wai")).unwrap(); let tampered = std::env::temp_dir().join(format!("wai-ffi-tampered-{}.wmb", std::process::id())); let mut b = std::fs::read(dir().join("model.wmb")).unwrap(); b[20] ^= 1; std::fs::write(&tampered, &b).unwrap(); let path = CString::new(tampered.to_str().unwrap()).unwrap(); let mut rgb = WaiBuffer { data: ptr::null_mut(), len: 0, cap: 0 }; let (mut w, mut h) = (0u32, 0u32); let code = unsafe { wai_neural_decode_image(env.as_ptr(), env.len(), path.as_ptr(), &mut rgb, &mut w, &mut h) }; std::fs::remove_file(&tampered).ok(); assert_eq!(code, WAI_ERR_PRIOR); assert!(last_error().starts_with("prior_not_held: "), "{}", last_error()); // The true model decodes. let path = CString::new(dir().join("model.wmb").to_str().unwrap()).unwrap(); assert_eq!(unsafe { wai_neural_decode_image(env.as_ptr(), env.len(), path.as_ptr(), &mut rgb, &mut w, &mut h) }, WAI_OK); assert_eq!((w, h), (64, 64)); unsafe { wai_buffer_free(rgb) }; } /// A failed decode leaves `*out` empty, whatever it held before: a caller that /// frees `out->data` after any status frees nothing it did not get. #[test] fn failed_decode_ex_clears_out() { let env = std::fs::read(dir().join("stream.wai")).unwrap(); let empty = CString::new("{}").unwrap(); let mut out = WaiDecoded { kind: 7, index: 9, data: WaiBuffer { data: 0x5a5a as *mut u8, len: 5, cap: 5 }, width: 1, height: 1, sample_rate: 1, n_frames: 1, fps_x_1000: 1, path: 3, fallback: 1, }; let code = unsafe { wai_neural_decode_ex(env.as_ptr(), env.len(), empty.as_ptr(), 0, &mut out) }; assert_ne!(code, WAI_OK); assert_eq!((out.kind, out.index, out.width, out.height, out.path, out.fallback), (0, 0, 0, 0, 0, 0)); assert!(out.data.data.is_null() && out.data.len == 0 && out.data.cap == 0); unsafe { wai_buffer_free(out.data) }; // A bad argument after the null check clears it too. let mut out2 = WaiDecoded { kind: 3, ..decoded() }; let code = unsafe { wai_neural_decode_ex(env.as_ptr(), env.len(), ptr::null(), 0, &mut out2) }; assert_eq!(code, WAI_ERR_INVALID_ARG); assert_eq!(out2.kind, 0); } #[test] fn strict_replicate_is_wai_err_unsound_replicate() { let mut env = Wai::from_bytes(&std::fs::read(dir().join("stream.wai")).unwrap()).unwrap(); env.manifest.conditioning.prior = None; let bytes = env.to_bytes().unwrap(); let reg = CString::new(format!(r#"{{"wai.neural.int_mlicpp":["{}"]}}"#, dir().join("model.wmb").display())).unwrap(); let mut out = decoded(); let code = unsafe { wai_neural_decode_ex(bytes.as_ptr(), bytes.len(), reg.as_ptr(), WAI_DECODE_STRICT, &mut out) }; assert_eq!(code, WAI_ERR_UNSOUND_REPLICATE); assert!(last_error().contains("replicate_unpinned"), "{}", last_error()); // Without the strict flag the unpinned envelope decodes, through its own capability's // one decode path, and says so. assert_eq!(unsafe { wai_neural_decode_ex(bytes.as_ptr(), bytes.len(), reg.as_ptr(), 0, &mut out) }, WAI_OK); assert_eq!((out.kind, out.width, out.height), (WAI_DECODED_IMAGE, 64, 64)); assert_eq!((out.path, out.fallback), (WAI_DECODE_PATH_SOLE, 0)); unsafe { wai_buffer_free(out.data) }; } /// `wai_neural_decode_ex` reports the decode path that ran and whether a `WAI1` envelope /// decoded through its fallback (extensions/determinism-tiers.md §5), which a native sink /// states in its receipt (extensions/jwp-receipts.md §2.4.12, a decoder entry's `variant` /// and `path`). #[test] fn decode_ex_reports_the_path_and_the_fallback() { let mut env = Wai::from_bytes(&std::fs::read(dir().join("stream.wai")).unwrap()).unwrap(); env.manifest.conditioning.prior = None; let reg = CString::new(format!(r#"{{"wai.neural.int_mlicpp":["{}"]}}"#, dir().join("model.wmb").display())).unwrap(); let own = env.to_bytes().unwrap(); let mut out = decoded(); assert_eq!(unsafe { wai_neural_decode_ex(own.as_ptr(), own.len(), reg.as_ptr(), 0, &mut out) }, WAI_OK); assert_eq!((out.kind, out.path, out.fallback), (WAI_DECODED_IMAGE, WAI_DECODE_PATH_SOLE, 0)); let want = fnv_of(&out); unsafe { wai_buffer_free(out.data) }; // The same payload under a capability the registry does not hold, with int_mlicpp as // its fallback: the same picture, through the fallback, and the result says so. env.manifest.model_requirement.capability = "wai.neural.int_hyper".into(); env.manifest.model_requirement.fallback = Some("wai.neural.int_mlicpp".into()); let via = env.to_bytes().unwrap(); let mut out = decoded(); assert_eq!(unsafe { wai_neural_decode_ex(via.as_ptr(), via.len(), reg.as_ptr(), 0, &mut out) }, WAI_OK, "{}", last_error()); assert_eq!((out.kind, out.path, out.fallback), (WAI_DECODED_IMAGE, WAI_DECODE_PATH_SOLE, 1)); assert_eq!(fnv_of(&out), want); unsafe { wai_buffer_free(out.data) }; } #[test] fn wai2_decode_ex_picks_the_held_pin() { let pl = Wai::from_bytes(&std::fs::read(dir().join("stream.wai")).unwrap()).unwrap().payload; let committed = wai::pin::sha256_hex(&std::fs::read(dir().join("model.wmb")).unwrap()); let det = "int-rans/p16+int-mlicpp/i64"; let env = WaiMulti::new("image", "replicate", serde_json::Value::Null, vec![ Rendition::media("wai.neural.int_mlicpp", "int_mlicpp", pl.clone()) .with_prior(Prior::new("next", "5c".repeat(32), det).with_tier(DeclaredTier::DecodeEquivalence) .with_supersedes(Supersedes::new(committed.clone()))), Rendition::media("wai.neural.int_mlicpp", "int_mlicpp", pl) .with_prior(Prior::new("committed", committed, det).with_tier(DeclaredTier::DecodeEquivalence)), ]).to_bytes().unwrap(); let reg = CString::new(format!(r#"{{"wai.neural.int_mlicpp":["{}"]}}"#, dir().join("model.wmb").display())).unwrap(); let mut out = decoded(); let code = unsafe { wai_neural_decode_ex(env.as_ptr(), env.len(), reg.as_ptr(), WAI_DECODE_STRICT, &mut out) }; assert_eq!(code, WAI_OK, "{}", last_error()); assert_eq!((out.index, out.kind), (1, WAI_DECODED_IMAGE)); assert_eq!(fnv_of(&out), "7c0b9a4b3423d775"); unsafe { wai_buffer_free(out.data) }; // With no set held, nothing is picked. let empty = CString::new("{}").unwrap(); let mut out = decoded(); assert_eq!(unsafe { wai_neural_decode_ex(env.as_ptr(), env.len(), empty.as_ptr(), 0, &mut out) }, WAI_ERR_NO_RENDITION); }