use mbr_forensic::{
analyse,
findings::AnomalyKind,
wipe::{classify, FillPattern},
};
use std::io::Cursor;
#[test]
fn all_zero_is_zeros() {
assert_eq!(classify(&[0u8; 64]), FillPattern::Zeros);
}
#[test]
fn all_ff_is_ones() {
assert_eq!(classify(&[0xFFu8; 64]), FillPattern::Ones);
}
#[test]
fn single_repeated_byte_is_uniform() {
assert_eq!(classify(&[0xABu8; 64]), FillPattern::Uniform(0xAB));
}
#[test]
fn alternating_is_detected() {
let data: Vec<u8> = (0..64)
.map(|i| if i % 2 == 0 { 0x55 } else { 0xAA })
.collect();
assert_eq!(classify(&data), FillPattern::Alternating(0x55, 0xAA));
}
#[test]
fn full_range_ramp_is_high_entropy() {
let data: Vec<u8> = (0..1024u32).map(|i| (i % 256) as u8).collect();
assert_eq!(classify(&data), FillPattern::HighEntropy);
}
#[test]
fn structured_text_is_mixed() {
assert_eq!(
classify(b"the quick brown fox jumps over"),
FillPattern::Mixed
);
}
#[test]
fn deliberate_wipe_predicate() {
assert!(FillPattern::Ones.is_deliberate_wipe());
assert!(FillPattern::Uniform(0xAB).is_deliberate_wipe());
assert!(FillPattern::Alternating(0x55, 0xAA).is_deliberate_wipe());
assert!(!FillPattern::Zeros.is_deliberate_wipe());
assert!(!FillPattern::Mixed.is_deliberate_wipe());
}
fn entry(type_code: u8, lba_start: u32, lba_count: u32) -> [u8; 16] {
let mut e = [0u8; 16];
e[4] = type_code;
e[8..12].copy_from_slice(&lba_start.to_le_bytes());
e[12..16].copy_from_slice(&lba_count.to_le_bytes());
e
}
#[test]
fn ff_filled_gap_is_flagged_as_wiped() {
let mut disk = vec![0u8; 100 * 512];
disk[510] = 0x55;
disk[511] = 0xAA;
disk[446..462].copy_from_slice(&entry(0x83, 1, 10));
for b in disk.iter_mut().skip(11 * 512) {
*b = 0xFF;
}
let analysis = analyse(&mut Cursor::new(disk), 100 * 512).unwrap();
assert!(
analysis
.anomalies
.iter()
.any(|a| matches!(a.kind, AnomalyKind::WipedRegion { .. })),
"got: {:?}",
analysis
.anomalies
.iter()
.map(|a| a.code)
.collect::<Vec<_>>()
);
}
#[test]
fn zero_filled_gap_is_not_flagged() {
let mut disk = vec![0u8; 100 * 512];
disk[510] = 0x55;
disk[511] = 0xAA;
disk[446..462].copy_from_slice(&entry(0x83, 1, 10));
let analysis = analyse(&mut Cursor::new(disk), 100 * 512).unwrap();
assert!(!analysis
.anomalies
.iter()
.any(|a| matches!(a.kind, AnomalyKind::WipedRegion { .. })));
}