#![allow(clippy::unwrap_used)]
use std::path::Path;
use dxcontainer::{checksum, chunks};
fn container(parts: &[(&[u8; 4], &[u8])]) -> Vec<u8> {
let directory = 32 + 4 * parts.len();
let mut offsets = Vec::new();
let mut body = Vec::new();
for (kind, data) in parts {
offsets.push((directory + body.len()) as u32);
body.extend_from_slice(*kind);
body.extend_from_slice(&(data.len() as u32).to_le_bytes());
body.extend_from_slice(data);
}
let mut out = b"DXBC".to_vec();
out.extend_from_slice(&[0; 16]);
out.extend_from_slice(&1u32.to_le_bytes());
out.extend_from_slice(&((directory + body.len()) as u32).to_le_bytes());
out.extend_from_slice(&(parts.len() as u32).to_le_bytes());
for offset in offsets {
out.extend_from_slice(&offset.to_le_bytes());
}
out.extend_from_slice(&body);
out
}
fn set(bytes: &mut [u8], at: usize, value: u32) {
bytes[at..at + 4].copy_from_slice(&value.to_le_bytes());
}
fn refusal(bytes: &[u8]) -> String {
chunks(bytes).unwrap_err().to_string()
}
#[test]
fn parts_are_read_in_the_directorys_order_with_their_bytes() {
let bytes = container(&[(b"ISG1", &[1, 2, 3]), (b"DXIL", &[4, 5, 6, 7, 8]), (b"EMPT", &[])]);
let parts = chunks(&bytes).unwrap();
let read: Vec<_> = parts.iter().map(|p| (p.kind, p.data.to_vec())).collect();
assert_eq!(
read,
[
(*b"ISG1", vec![1, 2, 3]),
(*b"DXIL", vec![4, 5, 6, 7, 8]),
(*b"EMPT", vec![])
]
);
assert!(chunks(&container(&[])).unwrap().is_empty());
}
#[test]
fn what_compilers_never_write_is_refused_by_name() {
let good = container(&[(b"AAAA", &[1, 1, 1, 1]), (b"BBBB", &[2, 2])]);
chunks(&good).unwrap();
let mut bad = good.clone();
bad[0] = b'X';
assert!(refusal(&bad).contains("not DXBC"));
let mut bad = good.clone();
set(&mut bad, 20, 2);
assert!(refusal(&bad).contains("version is not 1"));
let mut bad = good.clone();
set(&mut bad, 24, good.len() as u32 + 1);
assert!(refusal(&bad).contains("states a size of"));
let mut bad = good.clone();
set(&mut bad, 28, u32::MAX);
assert!(refusal(&bad).contains("does not fit the container"));
let mut bad = good.clone();
let first = u32::from_le_bytes(good[32..36].try_into().unwrap());
set(&mut bad, 36, first + 4);
assert!(refusal(&bad).contains("overlapping parts: part 1"));
set(&mut bad, 36, first + 100);
assert!(refusal(&bad).contains("part 1") && !refusal(&bad).contains("overlapping"));
let mut bad = good.clone();
bad.push(0);
let size = bad.len() as u32;
set(&mut bad, 24, size);
assert!(refusal(&bad).contains("1 bytes after the last part"));
let mut bad = good.clone();
set(&mut bad, first as usize + 4, 1000);
assert!(refusal(&bad).contains("part 0 (AAAA)"));
let mut gap = container(&[(b"AAAA", &[1])]);
gap.splice(36..36, [0u8; 4]);
let size = gap.len() as u32;
set(&mut gap, 24, size);
set(&mut gap, 32, 40);
assert!(refusal(&gap).contains("bytes between parts: part 0"));
let twice = container(&[(b"AAAA", &[1]), (b"AAAA", &[2])]);
assert!(refusal(&twice).contains("a part kind twice: AAAA"));
}
#[test]
fn every_truncation_is_refused() {
let bytes = container(&[(b"AAAA", &[1, 1, 1, 1]), (b"BBBB", &[2, 2])]);
for n in 0..bytes.len() {
assert!(chunks(&bytes[..n]).is_err(), "prefix {n}");
}
}
#[test]
fn the_committed_fixtures_of_both_bytecodes_are_read_to_their_end() {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut read = 0;
for crate_dir in ["dxbc-reader", "dxil-reader"] {
for entry in std::fs::read_dir(root.join(crate_dir).join("tests/fixtures")).unwrap() {
let path = entry.unwrap().path();
if !path.extension().is_some_and(|e| e == "dxbc" || e == "dxil") {
continue;
}
let bytes = std::fs::read(&path).unwrap();
let parts = chunks(&bytes).unwrap_or_else(|e| panic!("{}: {e}", path.display()));
let total: usize = 32 + 4 * parts.len() + parts.iter().map(|p| 8 + p.data.len()).sum::<usize>();
assert_eq!(total, bytes.len(), "{}", path.display());
read += 1;
}
}
assert!(read > 100, "{read} fixtures");
}
#[test]
fn the_digest_is_md5_of_the_bytes_from_20_as_the_compiler_pads_it() {
let empty = container(&[]);
let digest = checksum(&empty).unwrap();
assert_eq!(checksum(&empty[..19]), None);
assert_ne!(digest, [0; 16]);
let mut other = empty.clone();
other[28] = 1;
assert_ne!(checksum(&other), Some(digest));
}
#[test]
fn the_digest_equals_the_one_every_committed_fixture_stores() {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut checked = 0;
for crate_dir in ["dxbc-reader", "dxil-reader"] {
for entry in std::fs::read_dir(root.join(crate_dir).join("tests/fixtures")).unwrap() {
let path = entry.unwrap().path();
if !path.extension().is_some_and(|e| e == "dxbc" || e == "dxil") {
continue;
}
let bytes = std::fs::read(&path).unwrap();
let stored: [u8; 16] = bytes[4..20].try_into().unwrap();
assert_eq!(checksum(&bytes), Some(stored), "{}", path.display());
checked += 1;
}
}
assert!(checked > 100, "{checked} fixtures");
}