use std::io::Read;
use std::path::PathBuf;
use ewf::EwfReader;
fn data(name: &str) -> PathBuf {
PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data")).join(name)
}
#[test]
fn concurrent_positioned_reads_match_serial() {
let path = data("nps-2010-emails.E01");
let mut serial = EwfReader::open(&path).expect("open serial");
let size = serial.total_size() as usize;
let mut baseline = vec![0u8; size];
serial.read_exact(&mut baseline).expect("serial read_exact");
let reader = EwfReader::open(&path).expect("open concurrent");
let nthreads = 8usize;
let block = size.div_ceil(nthreads);
std::thread::scope(|s| {
let baseline = &baseline;
let reader = &reader; for t in 0..nthreads {
s.spawn(move || {
let start = t * block;
if start >= size {
return;
}
let len = block.min(size - start);
let mut buf = vec![0u8; len];
let n = reader.read_at(&mut buf, start as u64).expect("read_at");
assert_eq!(n, len, "thread {t}: short read");
assert_eq!(
&buf[..],
&baseline[start..start + len],
"thread {t}: concurrent read differs from serial baseline"
);
});
}
});
}
#[test]
fn concurrent_reads_of_same_chunk_are_stable() {
let path = data("nps-2010-emails.E01");
let mut serial = EwfReader::open(&path).expect("open serial");
let want_len = 4096usize.min(serial.total_size() as usize);
let mut want = vec![0u8; want_len];
serial.read_exact(&mut want).expect("serial read");
let reader = EwfReader::open(&path).expect("open concurrent");
std::thread::scope(|s| {
let want = &want;
let reader = &reader;
for _ in 0..16 {
s.spawn(move || {
let mut buf = vec![0u8; want_len];
let n = reader.read_at(&mut buf, 0).expect("read_at");
assert_eq!(n, want_len);
assert_eq!(&buf[..], &want[..], "same-chunk concurrent read diverged");
});
}
});
}