libfreemkv 0.31.2: comprehensive spec-grounded test suite (~950 tests)

Test-hardening release, no runtime changes. Adds spec-grounded unit tests
across the silent-corruption surfaces — UDF/MPLS/CLPI/IFO parsing, BD/DVD
title + extent assembly, AACS/CSS key handling, TS/PS demux + codec parsers,
MKV/EBML container output, the mux pipeline, sector prefetch + decrypt
decorator, drive/SCSI sense decoding, label extraction, and core I/O. Each
test is grounded in the format spec or real on-disc behavior and verified to
fail under a targeted source mutation. No behavior changed.
This commit is contained in:
Matthew Jackson
2026-06-07 22:28:29 -07:00
parent 2a55bab3ed
commit 8000bae177
85 changed files with 22998 additions and 1 deletions
+47
View File
@@ -66,4 +66,51 @@ mod tests {
let err = Stream::read(&mut sink).expect_err("read on a sink must error");
assert_eq!(err.kind(), io::ErrorKind::Unsupported);
}
/// finish() must be idempotent and safe to call repeatedly — a benchmark
/// driver may finish more than once. Each must be Ok(()), and writes
/// after finish must still succeed (NullStream has no terminal state).
#[test]
fn finish_is_idempotent_and_write_after_finish_ok() {
let title = DiscTitle::empty();
let mut sink = NullStream::new(&title);
sink.finish().unwrap();
sink.finish().unwrap();
let frame = crate::pes::PesFrame {
track: 3,
pts: 42,
keyframe: false,
data: vec![0xFF; 4096],
duration_ns: Some(1000),
};
// Discard-sink contract: write always returns Ok regardless of frame
// size, track index, or post-finish state.
sink.write(&frame).unwrap();
}
/// info() must return the title the sink was constructed with, unchanged
/// — the Stream trait contract requires info() be stable and reflect the
/// supplied metadata (the muxer reads stream layout from it).
#[test]
fn info_reflects_constructed_title() {
let mut title = DiscTitle::empty();
title.playlist = "BenchTitle".into();
title.playlist_id = 7;
let sink = NullStream::new(&title);
assert_eq!(sink.info().playlist, "BenchTitle");
assert_eq!(sink.info().playlist_id, 7);
}
/// The write-only read() guard must hold on EVERY call, not just the
/// first — a caller that retries read() after the initial error must
/// keep getting StreamWriteOnly, never a stale Ok(None).
#[test]
fn read_stays_write_only_across_repeated_calls() {
let title = DiscTitle::empty();
let mut sink = NullStream::new(&title);
for _ in 0..3 {
let err = Stream::read(&mut sink).expect_err("read on a sink must always error");
assert_eq!(err.kind(), io::ErrorKind::Unsupported);
}
}
}