//! `wai.asset.c2pa` (extensions/c2pa-binding.md): the committed corpus //! `live-conformance/c2pa-envelope/` regenerates byte for byte from its fixed seeds, holds no other //! file, every vector in it gets the outcome it states, every reason of §7 refuses a vector, and §7 //! lists exactly the reasons the reference reports with the C2PA code it gives each. #![cfg(feature = "c2pa_envelope")] use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use wai::c2pa_envelope::{corpus, Reason}; fn wai_dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..") } fn read_tree(root: &Path, dir: &Path, out: &mut BTreeMap>) { for e in std::fs::read_dir(dir).expect("the committed corpus").flatten() { let p = e.path(); if p.is_dir() { read_tree(root, &p, out); } else { let rel = p.strip_prefix(root).expect("under the root").to_string_lossy().replace('\\', "/"); if rel != "README.md" { out.insert(rel, std::fs::read(&p).expect("a file")); } } } } fn committed() -> BTreeMap> { let dir = wai_dir().join("live-conformance/c2pa-envelope"); let mut out = BTreeMap::new(); read_tree(&dir, &dir, &mut out); out } #[test] fn the_committed_corpus_regenerates_from_its_seeds() { let files = committed(); let generated: BTreeMap> = corpus::generate().into_iter().collect(); let extra: Vec<&String> = files.keys().filter(|k| !generated.contains_key(*k)).collect(); let missing: Vec<&String> = generated.keys().filter(|k| !files.contains_key(*k)).collect(); let differ: Vec<&String> = generated.iter().filter(|(k, v)| files.get(*k).is_some_and(|f| f != *v)).map(|(k, _)| k).collect(); assert!( extra.is_empty() && missing.is_empty() && differ.is_empty(), "extra {extra:?}, missing {missing:?}, differ {differ:?}: run `wai_c2pa_envelope_vectors gen`" ); } #[test] fn every_vector_gets_its_stated_outcome_and_every_reason_refuses_one() { let fails = corpus::verify_files(&committed()); assert!(fails.is_empty(), "{}", fails.join("\n")); } /// §7 of the extension lists exactly the codes `Reason::ALL` has, each once, in order, with the /// C2PA code the reference reports. #[test] fn the_extension_lists_the_reasons() { let text = std::fs::read_to_string(wai_dir().join("extensions/c2pa-binding.md")).expect("the extension"); let at = text.find("\n## 7. Reasons").expect("a §7"); let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e); let rows: Vec> = text[at..end] .lines() .filter(|l| l.starts_with("| `")) .map(|l| l.split('|').map(|c| c.trim().trim_matches('`').to_string()).collect()) .collect(); let listed: Vec<&str> = rows.iter().map(|r| r[1].as_str()).collect(); let want: Vec<&str> = Reason::ALL.iter().map(|r| r.code()).collect(); assert_eq!(listed, want, "§7's table and Reason::ALL differ"); for (r, row) in Reason::ALL.iter().zip(&rows) { let code = if row[3] == "—" { None } else { Some(row[3].clone()) }; assert_eq!(code, r.c2pa().map(String::from), "{}: the C2PA code", r.code()); } }