use disk_forensic::container::{open, ContainerFormat, OpenError};
use std::io::{Read, Seek, SeekFrom};
const AFF4_VIRTUAL_SIZE: u64 = 512;
fn write_temp(name: &str, bytes: &[u8]) -> (tempfile::TempDir, std::path::PathBuf) {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join(name);
std::fs::write(&path, bytes).unwrap();
(dir, path)
}
#[test]
fn opens_and_reads_physical_aff4_disk() {
let payload: &[u8] = b"AFF4-PHYSICAL-DISK-PAYLOAD\x00\x01\x02\x03\xfe\xff";
let bytes = aff4::testutil::test_aff4(payload);
let (_dir, path) = write_temp("physical.aff4", &bytes);
let mut opened = open(&path).unwrap();
assert_eq!(opened.format, ContainerFormat::Aff4);
assert_eq!(opened.size, AFF4_VIRTUAL_SIZE, "decoded virtual disk size");
let mut buf = vec![0u8; payload.len()];
opened.reader.seek(SeekFrom::Start(0)).unwrap();
opened.reader.read_exact(&mut buf).unwrap();
assert_eq!(buf, payload, "decoded disk bytes at offset 0");
let mut tail = [0u8; 4];
opened
.reader
.seek(SeekFrom::Start(AFF4_VIRTUAL_SIZE - 4))
.unwrap();
opened.reader.read_exact(&mut tail).unwrap();
assert_eq!(tail, [0u8; 4], "zero fill at end of the virtual disk");
}
#[test]
fn logical_aff4_is_reported_as_logical_container_not_a_disk() {
let bytes =
aff4::testutil::test_aff4_logical("evidence.txt", b"hello logical", &"0".repeat(32));
let (_dir, path) = write_temp("logical.aff4", &bytes);
let err = open(&path).unwrap_err();
assert!(
matches!(err, OpenError::LogicalContainer(ContainerFormat::Aff4)),
"got {err:?}"
);
assert!(
err.to_string().contains("logical"),
"message should name the logical path: {err}"
);
}
#[test]
fn truncated_aff4_errors_without_panic() {
let bytes = aff4::testutil::test_aff4(b"payload-to-be-truncated");
let truncated = &bytes[..bytes.len() / 2];
let (_dir, path) = write_temp("truncated.aff4", truncated);
let err = open(&path).unwrap_err();
assert!(
matches!(
err,
OpenError::Decode(ContainerFormat::Aff4, _) | OpenError::Io(_)
),
"got {err:?}"
);
}