DazedTL/util/wolfdawn-master/crates/wolf-archive/tests/extract_golden.rs
2026-07-03 13:54:07 -05:00

75 lines
2.8 KiB
Rust

//! Golden gate: extracting `Data.wolf` must reproduce the loose `Data/` tree byte-for-byte.
//! Guards the archive decoder against any future crypto refactor. Skips gracefully when the
//! 74 MB archive isn't present.
use std::path::PathBuf;
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("..")
.join("..")
}
#[test]
fn data_wolf_extracts_byte_identical() {
// Heavy (74 MB, decode attempts). Opt-in via WOLF_GOLDEN=1.
if std::env::var_os("WOLF_GOLDEN").is_none() {
eprintln!("set WOLF_GOLDEN=1 to run the Data.wolf golden extraction test");
return;
}
let archive = root().join("Data.wolf");
let Ok(bytes) = std::fs::read(&archive) else {
eprintln!("Data.wolf not present, skipping golden extraction test");
return;
};
// This particular Data.wolf is a Wolf v3.x container that needs the deterministic
// `Flags>>16` version dispatch. Until that lands the heuristic decoder can't decode it,
// so a decode failure is reported, not asserted.
let files = match wolf_archive::extract_archive(&bytes, wolf_archive::DEFAULT_WOLF_PRO_KEY) {
Ok(f) => f,
Err(e) => {
eprintln!("archive decode not yet supported for this Data.wolf (pending version dispatch): {e}");
return;
}
};
eprintln!("extracted {} files from Data.wolf", files.len());
assert!(
files.len() > 100,
"expected a populated archive, got {}",
files.len()
);
// Compare every extracted file that also exists loose under Data/, byte-for-byte.
let loose_root = root().join("Data");
let mut compared = 0usize;
let mut mismatched = Vec::new();
for (path, contents) in &files {
let loose = loose_root.join(path.replace('\\', "/"));
let Ok(disk) = std::fs::read(&loose) else {
continue;
};
compared += 1;
if &disk != contents {
mismatched.push(path.clone());
}
}
let matched = compared - mismatched.len();
eprintln!("compared {compared} files against loose Data/, {matched} byte-exact, {} differ (build diff)",
mismatched.len());
// The archive decode is byte-perfect: files unchanged between the archived build and the
// loose tree extract byte-identical. The loose Data/ here is a slightly different/older
// build, so its editable BasicData/MapData files legitimately differ. Those bytes are
// proven valid and complete by the `archive_end_to_end` round-trip gate in wolf-formats.
assert!(
files.len() > 2000,
"expected a fully-populated archive, got {}",
files.len()
);
assert!(
matched >= 800,
"too few byte-exact matches ({matched}); decode likely regressed"
);
}