use proptest::prelude::*;
fn image() -> impl Strategy<Value = (usize, usize, Vec<u32>)> {
(1usize..=8, 1usize..=8).prop_flat_map(|(w, h)| {
prop::collection::vec(any::<u32>(), w * h).prop_map(move |px| (w, h, px))
})
}
proptest! {
#[test]
fn output_length_is_scale_squared((w, h, px) in image()) {
for (scale, run) in scalers() {
let mut dst = vec![0u32; scale * scale * w * h];
run(&px, &mut dst, w as u32, h as u32);
prop_assert_eq!(dst.len(), scale * scale * w * h);
}
}
#[test]
fn solid_input_yields_solid_output(color in any::<u32>(), w in 1usize..=6, h in 1usize..=6) {
let px = vec![color; w * h];
for (scale, run) in scalers() {
let mut dst = vec![0u32; scale * scale * w * h];
run(&px, &mut dst, w as u32, h as u32);
prop_assert!(dst.iter().all(|&p| p == color), "scale {}", scale);
}
}
#[test]
fn scaling_is_deterministic((w, h, px) in image()) {
for (scale, run) in scalers() {
let mut a = vec![0u32; scale * scale * w * h];
let mut b = vec![0u32; scale * scale * w * h];
run(&px, &mut a, w as u32, h as u32);
run(&px, &mut b, w as u32, h as u32);
prop_assert_eq!(a, b);
}
}
#[test]
fn extreme_corners_copy_source_corners((w, h, px) in image()) {
for (scale, run) in scalers() {
let dw = w * scale;
let dh = h * scale;
let mut dst = vec![0u32; dw * dh];
run(&px, &mut dst, w as u32, h as u32);
prop_assert_eq!(dst[0], px[0]);
prop_assert_eq!(dst[dw - 1], px[w - 1]);
prop_assert_eq!(dst[(dh - 1) * dw], px[(h - 1) * w]);
prop_assert_eq!(dst[dh * dw - 1], px[h * w - 1]);
}
}
}
type Scaler = fn(&[u32], &mut [u32], u32, u32);
fn scalers() -> Vec<(usize, Scaler)> {
vec![
(2, hqx::hq2x as Scaler),
(3, hqx::hq3x as Scaler),
(4, hqx::hq4x as Scaler),
]
}