use netcdf_reader::NcFile;
use peak_alloc::PeakAlloc;
use proptest::prelude::*;
#[global_allocator]
static PEAK: PeakAlloc = PeakAlloc;
const SEED: &[u8] = &[
0x43, 0x44, 0x46, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x74, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x73, 0x65, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x67, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x67, 0x72, 0x69, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x75, 0x6e, 0x69, 0x74,
0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x6f, 0x62, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x48, 0x3f, 0x80, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x14,
0x00, 0x15, 0x00, 0x16,
];
const MAX_OPEN_ALLOC: f32 = 8.0 * 1024.0 * 1024.0;
proptest! {
#![proptest_config(ProptestConfig::with_cases(400))]
#[test]
fn mutated_classic_file_never_panics_or_over_allocates(
mutations in prop::collection::vec((0usize..SEED.len(), any::<u8>()), 0..8)
) {
let mut bytes = SEED.to_vec();
for (index, value) in mutations {
bytes[index] = value;
}
PEAK.reset_peak_usage();
let before = PEAK.current_usage() as f32;
if let Ok(file) = NcFile::from_bytes(&bytes) {
let _ = file.global_attributes();
let _ = file.dimensions();
if let Ok(variables) = file.variables() {
let names: Vec<String> = variables.iter().map(|v| v.name.clone()).collect();
for name in names {
let _ = file.read_variable::<f64>(&name);
}
}
}
let peak = PEAK.peak_usage() as f32 - before;
prop_assert!(
peak < MAX_OPEN_ALLOC,
"mutated open allocated {peak} bytes (> {MAX_OPEN_ALLOC})"
);
}
}