lac/tests/determinism.rs
Kamal Tufekcic 7862cb1d9d
All checks were successful
CI / lint (push) Successful in 5s
CI / fuzz-regression (push) Successful in 14s
CI / build (push) Successful in 4s
CI / test (push) Successful in 6m54s
CI / publish (push) Successful in 8s
initial commit
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
2026-04-23 14:58:32 +03:00

103 lines
3.9 KiB
Rust

//! Determinism fence: the encoder is contractually bit-exact on the
//! same input, and the decoder is contractually bit-exact on the same
//! bitstream. This file exists to catch a future change that would
//! quietly break either property — a parallel order search with a
//! race, a `HashMap` iteration order leaking into state, a
//! non-deterministic tie-break. All three would pass the round-trip
//! tests but fail here.
//!
//! Tests drive small deterministic inputs (LFSR noise, sine) so they
//! don't depend on corpus presence and run in milliseconds.
use lac::{decode_frame, encode_frame};
// ── Deterministic inputs ────────────────────────────────────────────────────
/// 32-bit Galois LFSR, mirrored from `tests/synthetic.rs`. Seeded
/// deterministically so repeated calls with the same `seed` produce
/// bit-identical outputs, which is the property we rely on below.
fn lfsr_noise(n: usize, bit_depth: u8, seed: u32) -> Vec<i32> {
assert!((1..=24).contains(&bit_depth));
let mut state = if seed == 0 { 0xACE1_ACE1 } else { seed };
let shift = 32 - bit_depth as u32;
let max: i32 = (1i32 << (bit_depth - 1)) - 1;
(0..n)
.map(|_| {
let lsb = state & 1;
state >>= 1;
if lsb != 0 {
state ^= 0x8020_0003;
}
((state as i32) >> shift).max(-max)
})
.collect()
}
// ── Tests ───────────────────────────────────────────────────────────────────
#[test]
fn encode_byte_equal_on_same_input_silence() {
let samples = vec![0i32; 4096];
let a = encode_frame(&samples);
let b = encode_frame(&samples);
assert_eq!(a, b, "encoder produced different bytes for identical input");
}
#[test]
fn encode_byte_equal_on_same_input_noise() {
// 16-bit noise — exercises the non-trivial LPC/Rice search path
// where any latent non-determinism (tie-break, parallelism, hash
// ordering) would be most likely to surface.
let samples = lfsr_noise(4096, 16, 0xDEAD);
let a = encode_frame(&samples);
let b = encode_frame(&samples);
assert_eq!(
a,
b,
"encoder produced different bytes on a noisy input (first {} bytes)",
a.len().min(16)
);
}
#[test]
fn encode_byte_equal_on_same_input_24bit_full_scale() {
// Full-scale content stresses the autocorrelation accumulator
// width; any non-determinism in coefficient quantization would
// show up differently from the silence and noise cases.
let samples = vec![(1 << 23) - 1; 2048];
let a = encode_frame(&samples);
let b = encode_frame(&samples);
assert_eq!(a, b);
}
#[test]
fn encode_byte_equal_across_many_repeats() {
// Ten encodes of the same input — catches an intermittent race
// that a two-shot comparison might miss by luck. LFSR seed chosen
// independently from the other tests to reduce correlation
// between failure modes.
let samples = lfsr_noise(2048, 20, 0xBEEF);
let reference = encode_frame(&samples);
for i in 1..10 {
let current = encode_frame(&samples);
assert_eq!(
current, reference,
"encode #{} differs from the reference encode",
i
);
}
}
#[test]
fn decode_byte_equal_on_same_input() {
// Decoder determinism: same bitstream, same samples, every time.
let samples = lfsr_noise(2048, 16, 0xF00D);
let bytes = encode_frame(&samples);
let a = decode_frame(&bytes).expect("decode a");
let b = decode_frame(&bytes).expect("decode b");
assert_eq!(
a, b,
"decoder produced different samples for identical bytes"
);
assert_eq!(a, samples, "decoder output doesn't match original samples");
}