#![allow(clippy::unwrap_used, clippy::expect_used)]
use apfs_core::container::{NxSuperblock, NX_MAGIC};
use apfs_core::ApfsError;
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 nxsb_magic_constant_is_nxsb_little_endian() {
assert_eq!(NX_MAGIC, 0x4253_584E);
assert_eq!(&NX_MAGIC.to_le_bytes(), b"NXSB");
}
#[test]
fn parse_decodes_real_container_geometry() {
let nx = NxSuperblock::parse(block(0)).expect("parse NXSB block 0");
assert_eq!(nx.block_size, 4096); assert_eq!(nx.block_count, 32758);
assert_eq!(nx.xid, 2);
assert_eq!(nx.omap_oid, 343);
assert_eq!(nx.fs_oids, vec![1026]); assert_eq!(
nx.uuid,
[
0x40, 0x11, 0x50, 0x33, 0x95, 0x23, 0x44, 0x96, 0x96, 0xa2, 0x0e, 0xda, 0xde, 0xec,
0xa5, 0x65
]
);
}
#[test]
fn parse_decodes_checkpoint_area_fields() {
let nx = NxSuperblock::parse(block(0)).expect("parse NXSB block 0");
assert_eq!(nx.xp_desc_base, 1);
assert_eq!(nx.xp_desc_blocks, 8);
assert_eq!(nx.xp_data_base, 9);
assert_eq!(nx.xp_data_blocks, 304);
assert!(!nx.xp_desc_is_tree());
assert!(!nx.xp_data_is_tree());
}
#[test]
fn parse_rejects_bad_magic_loudly() {
let mut blk = block(0).to_vec();
blk[32] ^= 0xff; match NxSuperblock::parse(&blk) {
Err(ApfsError::NoValidSuperblock { last_magic, .. }) => {
assert_ne!(last_magic, NX_MAGIC);
}
other => panic!("expected NoValidSuperblock, got {other:?}"),
}
}
#[test]
fn parse_rejects_bad_checksum_loudly() {
let mut blk = block(0).to_vec();
blk[200] ^= 0xff;
match NxSuperblock::parse(&blk) {
Err(ApfsError::ChecksumMismatch {
stored, computed, ..
}) => assert_ne!(stored, computed),
other => panic!("expected ChecksumMismatch, got {other:?}"),
}
}
#[test]
fn parse_rejects_short_block_without_panicking() {
assert!(NxSuperblock::parse(&[0u8; 64]).is_err());
assert!(NxSuperblock::parse(&[]).is_err());
}