use std::path::{Path, PathBuf};
#[test]
fn conform_source_matches_build_time_integrity_hash() {
let Some(expected) = option_env!("VYRE_CONFORM_SRC_INTEGRITY")
.map(str::to_owned)
.or_else(|| std::env::var("VYRE_CONFORM_SRC_INTEGRITY").ok())
else {
eprintln!(
"skipping conform/src integrity check: VYRE_CONFORM_SRC_INTEGRITY is not configured"
);
return;
};
let actual = source_integrity_hash(Path::new(env!("CARGO_MANIFEST_DIR")).join("src"));
assert_eq!(
actual, expected,
"conform/src integrity mismatch. Fix: rebuild tests from the reviewed source tree."
);
}
fn source_integrity_hash(root: PathBuf) -> String {
let mut files = Vec::new();
collect_rs_files(&root, &mut files);
files.sort();
let mut hash = 0xcbf2_9ce4_8422_2325u64;
for path in files {
let rel = path.strip_prefix(&root).unwrap_or(&path).to_string_lossy();
fnv1a_update(&mut hash, rel.as_bytes());
fnv1a_update(&mut hash, &[0]);
let bytes = std::fs::read(&path).unwrap_or_default();
fnv1a_update(&mut hash, &bytes);
fnv1a_update(&mut hash, &[0xff]);
}
format!("{hash:016x}")
}
fn collect_rs_files(dir: &Path, out: &mut Vec<PathBuf>) {
for entry in std::fs::read_dir(dir).unwrap().flatten() {
let path = entry.path();
if path.is_dir() {
collect_rs_files(&path, out);
} else if path.extension().and_then(|s| s.to_str()) == Some("rs") {
out.push(path);
}
}
}
fn fnv1a_update(hash: &mut u64, bytes: &[u8]) {
for &byte in bytes {
*hash ^= u64::from(byte);
*hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
}
}