#![allow(clippy::unwrap_used, clippy::expect_used)]
use apfs_core::object::{fletcher64_checksum, ObjPhys, OBJ_PHYS_LEN};
const HEAD: &[u8] = include_bytes!("../../tests/data/apfs_nxsb_head.bin");
const BLOCK_SIZE: usize = 4096;
fn block(n: usize) -> &'static [u8] {
&HEAD[n * BLOCK_SIZE..(n + 1) * BLOCK_SIZE]
}
#[test]
fn obj_phys_header_decodes_real_nxsb_block0() {
let h = ObjPhys::parse(block(0)).expect("parse block 0 header");
assert_eq!(h.cksum, 0x2d03_fdf6_5e3d_b5e6);
assert_eq!(h.oid, 1);
assert_eq!(h.xid, 2);
assert_eq!(h.obj_type_raw, 0x8000_0001);
assert_eq!(h.subtype, 0x0);
assert_eq!(h.obj_type(), 0x1);
}
#[test]
fn obj_phys_parse_rejects_short_slice() {
assert!(ObjPhys::parse(&[0u8; OBJ_PHYS_LEN - 1]).is_none());
assert!(ObjPhys::parse(&[]).is_none());
}
#[test]
fn fletcher64_recomputes_real_stored_checksum_block0() {
let blk = block(0);
let stored = u64::from_le_bytes(blk[0..8].try_into().unwrap());
assert_eq!(stored, 0x2d03_fdf6_5e3d_b5e6);
assert_eq!(fletcher64_checksum(blk), stored);
}
#[test]
fn fletcher64_validates_every_real_object_in_the_descriptor_ring() {
let mut checked = 0;
for n in 0..HEAD.len() / BLOCK_SIZE {
let blk = block(n);
let stored = u64::from_le_bytes(blk[0..8].try_into().unwrap());
let oid = u64::from_le_bytes(blk[8..16].try_into().unwrap());
if stored == 0 && oid == 0 {
continue; }
assert_eq!(
fletcher64_checksum(blk),
stored,
"block {n} checksum mismatch"
);
checked += 1;
}
assert!(checked >= 10, "expected >=10 real objects, got {checked}");
}
#[test]
fn fletcher64_detects_a_corrupted_object() {
let mut blk = block(0).to_vec();
let stored = u64::from_le_bytes(blk[0..8].try_into().unwrap());
blk[100] ^= 0xff;
assert_ne!(fletcher64_checksum(&blk), stored);
}
#[test]
fn fletcher64_does_not_panic_on_unaligned_or_short_input() {
for len in [0usize, 1, 3, 7, 31, 33, 4095, 4097] {
let _ = fletcher64_checksum(&vec![0xABu8; len]);
}
}