//! An edited kernel is caught: each mutant below changes one expression of a shipped //! kernel (a tie rule, a rounding addend, a clamp bound, a square, a rotation, a flag), //! and the cases of `kernels.rs` must find a result that differs from the reference on //! every adapter. A mutant they did not catch would be a part of a kernel the tests do //! not hold. mod support; use support::*; use wai_pack_gpu::Sources; struct Mutant { name: &'static str, kernel: &'static str, from: &'static str, to: &'static str, } const MUTANTS: &[Mutant] = &[ Mutant { name: "the earlier vector loses a tie", kernel: "motion", from: "return i < bi;", to: "return i > bi;" }, Mutant { name: "the longer vector wins a tie", kernel: "motion", from: "return l < bl;", to: "return l > bl;" }, Mutant { name: "a horizontal half-pel truncates", kernel: "motion", from: "return (px(iy, ix, c) + px(iy, ix + 1, c) + 1) >> 1u;", to: "return (px(iy, ix, c) + px(iy, ix + 1, c)) >> 1u;" }, Mutant { name: "a diagonal half-pel rounds by 1", kernel: "motion", from: "px(iy + 1, ix + 1, c) + 2) >> 2u;", to: "px(iy + 1, ix + 1, c) + 1) >> 2u;" }, Mutant { name: "a column past the frame is read", kernel: "motion", from: "clamp(xx, 0, i32(P.w) - 1)", to: "clamp(xx, 0, i32(P.w))" }, Mutant { name: "the reduction skips a lane", kernel: "motion", from: "for (var s = WG / 2u; s > 0u; s = s >> 1u)", to: "for (var s = WG / 2u; s > 1u; s = s >> 1u)" }, Mutant { name: "the absolute difference, not its square", kernel: "sse", from: "acc = acc + u32(d * d);", to: "acc = acc + u32(abs(d));" }, Mutant { name: "a rotation by 11", kernel: "blake3", from: "v[b] = rotr(v[b] ^ v[c], 12u);", to: "v[b] = rotr(v[b] ^ v[c], 11u);" }, Mutant { name: "a permutation entry swapped", kernel: "blake3", from: "m[0] = o[2];\n m[1] = o[6];", to: "m[0] = o[6];\n m[1] = o[2];" }, Mutant { name: "the root flag of a parent's value", kernel: "blake3", from: "const ROOT: u32 = 8u;", to: "const ROOT: u32 = 4u;" }, Mutant { name: "every chunk counted as the first", kernel: "blake3", from: "v[12] = job.counter_lo;", to: "v[12] = 0u;" }, Mutant { name: "a short last block counted whole", kernel: "blake3", from: "v[14] = block_len;", to: "v[14] = 64u;" }, ]; fn edited(m: &Mutant) -> Sources { let mut s = Sources::shipped(); let k = match m.kernel { "motion" => &mut s.motion, "sse" => &mut s.sse, _ => &mut s.blake3, }; assert_eq!(k.matches(m.from).count(), 1, "{}: the expression is in the kernel once", m.name); *k = k.replacen(m.from, m.to, 1); s } /// Whether the kernel cases find a difference from the reference on `g`. fn caught(g: &wai_pack_gpu::Gpu, kernel: &str) -> bool { match kernel { "motion" => { let mut rng = Rng(0x5eed_0001); MOTION_CASES.iter().any(|&(h, w, block, range, prec)| { frame_pairs(&mut rng, h, w).into_iter().any(|(_, src, rf)| g.motion_frame(&src, &rf, h, w, block, range, prec).ok() != Some(search(&src, &rf, h, w, block, range, prec))) }) } "sse" => { let mut rng = Rng(0x5eed_0002); [1usize, 4097, 65_537].iter().any(|&n| { let (a, b) = (rng.bytes(n), rng.bytes(n)); g.sse(&a, &b).ok() != Some(sse(&a, &b)) }) } _ => { let inputs: Vec> = BLAKE3_LENGTHS.iter().map(|&n| blake3_input(n)).collect(); let refs: Vec<&[u8]> = inputs.iter().map(|v| v.as_slice()).collect(); match g.blake3_many(&refs) { Ok(hs) => refs.iter().zip(hs).any(|(m, h)| &h != blake3::hash(m).as_bytes()), Err(_) => true, } } } } #[test] fn every_mutant_is_caught() { if gpus().is_empty() { return; } for m in MUTANTS { let found = gpus_with(&edited(m), m.name); assert!(!found.is_empty(), "{}: the mutant did not compile, so it proves nothing", m.name); for g in &found { assert!(caught(g, m.kernel), "{}: {} not caught", g.adapter().label(), m.name); } eprintln!("caught: {} ({})", m.name, m.kernel); } }