libfreemkv 0.31.4: prune 144 vacuous tests (keep spec-grounded subset)
This commit is contained in:
@@ -631,27 +631,6 @@ mod tests {
|
||||
|
||||
// --- YCbCr → RGB green channel + neutral chroma ---
|
||||
|
||||
#[test]
|
||||
fn ycbcr_green_channel_formula() {
|
||||
// G = Y - 0.344*(Cb-128) - 0.714*(Cr-128). For pure-ish green choose
|
||||
// Y=145, Cb=54, Cr=34: G should be high, R and B low. (Full-range BT.601
|
||||
// per the module's deliberate convention.)
|
||||
let [r, g, b] = ycbcr_to_rgb(&[0x00, 145, 54, 34]);
|
||||
assert!(g > 200, "G high for green, got {g}");
|
||||
assert!(r < 80, "R low for green, got {r}");
|
||||
assert!(b < 80, "B low for green, got {b}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ycbcr_neutral_chroma_is_grey() {
|
||||
// Cb=Cr=128 (neutral) → R=G=B=Y for any Y. (Confirms the chroma terms
|
||||
// vanish at 128.)
|
||||
for y in [0u8, 64, 128, 200, 255] {
|
||||
let [r, g, b] = ycbcr_to_rgb(&[0x00, y, 128, 128]);
|
||||
assert_eq!([r, g, b], [y, y, y], "neutral chroma → grey at Y={y}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ycbcr_blue_channel_clamps_high() {
|
||||
// B = Y + 1.772*(Cb-128). Y=128, Cb=255 → 128 + 1.772*127 ≈ 353 → clamp 255.
|
||||
|
||||
@@ -1518,17 +1518,6 @@ mod tests {
|
||||
|
||||
// --- IRAP keyframe boundary values ---
|
||||
|
||||
#[test]
|
||||
fn irap_lower_boundary_type_16_is_keyframe() {
|
||||
// BLA_W_LP = 16, the inclusive lower boundary of NAL_BLA_W_LP..=23.
|
||||
let mut parser = HevcParser::new();
|
||||
let mut data = vec![0x00, 0x00, 0x01];
|
||||
data.extend_from_slice(&hevc_nal_header(16));
|
||||
data.extend_from_slice(&[0x10, 0x20]);
|
||||
let f = parser.parse(&make_pes(data, Some(0)));
|
||||
assert!(f[0].keyframe);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_15_just_below_irap_not_keyframe() {
|
||||
// Type 15 (RASL_R) is one below the IRAP range and must NOT be a keyframe.
|
||||
|
||||
@@ -225,17 +225,6 @@ mod tests {
|
||||
assert_eq!(f[0].data, vec![0xAB], "5 BD bytes → 1 PCM byte");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bd_exactly_four_bytes_dropped() {
|
||||
// Exactly 4 bytes = header only: `len <= offset` (4 <= 4) → dropped.
|
||||
let mut parser = LpcmParser::new();
|
||||
assert!(
|
||||
parser
|
||||
.parse(&make_pes(vec![0x00, 0x01, 0x00, 0x91], Some(0)))
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bd_three_bytes_dropped() {
|
||||
// Fewer than the 4-byte header → dropped, no panic / no underflow slice.
|
||||
|
||||
@@ -803,20 +803,6 @@ mod tests {
|
||||
assert_eq!(f2[0].pts_ns, 0, "no PTS/DTS → 0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_data_is_whole_pes_not_just_picture() {
|
||||
// The emitted frame data is the ENTIRE PES payload (pes.data.clone()),
|
||||
// not just the picture NAL — MPEG-2 ES is muxed as-is. Confirm a seq
|
||||
// header + picture PES emits the whole buffer.
|
||||
let mut parser = Mpeg2Parser::new();
|
||||
let mut data = make_seq_header(720, 480, 3, 4);
|
||||
data.extend_from_slice(&make_picture_header(PICTURE_TYPE_I));
|
||||
data.extend_from_slice(&[0x12, 0x34]);
|
||||
let f = parser.parse(&make_pes(data.clone(), Some(0)));
|
||||
assert_eq!(f.len(), 1);
|
||||
assert_eq!(f[0].data, data, "frame data = whole PES payload");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parser_resolution_method() {
|
||||
let mut parser = Mpeg2Parser::new();
|
||||
|
||||
@@ -433,17 +433,6 @@ mod tests {
|
||||
|
||||
// --- duration computation and clamping ---
|
||||
|
||||
#[test]
|
||||
fn duration_is_clear_minus_display() {
|
||||
// BlockDuration = clear_pts - display_pts (in ns). display @ 90000 (1s),
|
||||
// clear @ 450000 (5s) → duration 4s.
|
||||
let mut parser = PgsParser::new();
|
||||
let _ = parser.parse(&make_pes(pcs_bytes(1), Some(90000)));
|
||||
let f = parser.parse(&make_pes(pcs_bytes(0), Some(450000)));
|
||||
assert_eq!(f[0].pts_ns, 1_000_000_000);
|
||||
assert_eq!(f[0].duration_ns, Some(4_000_000_000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duration_clamps_to_zero_when_clear_precedes_display() {
|
||||
// A clear PTS earlier than the display PTS (corrupt/out-of-order stream)
|
||||
|
||||
@@ -163,15 +163,6 @@ mod tests {
|
||||
|
||||
// --- skip_start_code: boundary / form selection ---
|
||||
|
||||
#[test]
|
||||
fn skip_4byte_preferred_over_3byte_when_extra_zero_present() {
|
||||
// `00 00 00 01`: the function must recognise the 4-byte form (return
|
||||
// pos+4), not stop at a phantom 3-byte interpretation. data[pos+2]==0x00
|
||||
// and data[pos+3]==0x01 select the 4-byte branch.
|
||||
let data = [0x00, 0x00, 0x00, 0x01, 0x42];
|
||||
assert_eq!(skip_start_code(&data, 0), Some(4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_start_code_at_nonzero_pos() {
|
||||
// skip must honour pos: a 3-byte code at offset 2 returns 2+3 = 5.
|
||||
|
||||
@@ -526,12 +526,6 @@ mod tests {
|
||||
assert_eq!(truehd_channels(1 << 20), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truehd_channels_71_layout_low5_bits() {
|
||||
// Standard 7.1: 8ch bits 0-4 = L/R(2)+C(1)+LFE(1)+Ls/Rs(2)+Lb/Rb(2) = 8.
|
||||
assert_eq!(truehd_channels(0x1F), Some(8));
|
||||
}
|
||||
|
||||
// --- truehd_channels_from_stream: major-sync variant bit + scan ---
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -588,47 +588,6 @@ mod tests {
|
||||
assert_eq!(parse_vc1_resolution(&sh), Some((8192, 8192)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolution_field_is_12_bits_no_higher() {
|
||||
// Asserting the field width: a width one step above the max (8194 →
|
||||
// coded_w 4096) overflows the 12-bit MAX_CODED_WIDTH field (4096 & 0xFFF
|
||||
// = 0), so it cannot encode 8194 — it wraps to (0+1)*2 = 2. This proves
|
||||
// the 12-bit masking in the parser, i.e. it never reads a 13th bit.
|
||||
let sh = make_ap_seq_header(8194, 720);
|
||||
assert_eq!(
|
||||
parse_vc1_resolution(&sh),
|
||||
Some((2, 720)),
|
||||
"coded_w field is masked to 12 bits → 4096 wraps to 0 → width 2"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolution_deescapes_emulation_prevention() {
|
||||
// VC-1 Annex-B EBDU payload may carry an emulation-prevention 0x03 after
|
||||
// a 00 00 run. The resolution parser must de-escape before bit
|
||||
// extraction; an EP byte in the first few payload bytes would otherwise
|
||||
// shift every later bit and corrupt the dimensions. Build a header whose
|
||||
// de-escaped payload encodes 1280x720, then splice 00 00 03 into the raw
|
||||
// payload and confirm it still decodes 1280x720.
|
||||
let base = make_ap_seq_header(1280, 720);
|
||||
// base = [00 00 01 0F][5 payload bytes]. Insert a benign EP run that
|
||||
// de-escapes away: find a spot where two zeros precede our inserted 0x03.
|
||||
// Construct payload manually: prepend 00 00 03 then the real 5 bytes; the
|
||||
// de-escaper drops the 0x03, leaving 00 00 + the 5 bytes → but that
|
||||
// shifts the fields. Instead, the real coverage: the de-escaper collects
|
||||
// 5 bytes skipping EP. Put the EP at the very front so after stripping we
|
||||
// still recover the 5 meaningful bytes... that changes leading bits.
|
||||
// Simpler grounded check: a payload with a trailing EP byte (after the 5
|
||||
// needed bytes) must not change the result, since only 5 are collected.
|
||||
let mut sh = base.clone();
|
||||
sh.extend_from_slice(&[0x00, 0x00, 0x03, 0xFF]); // trailing EP run
|
||||
assert_eq!(
|
||||
parse_vc1_resolution(&sh),
|
||||
Some((1280, 720)),
|
||||
"trailing EP bytes beyond the 5 collected must not affect parsing"
|
||||
);
|
||||
}
|
||||
|
||||
// --- codec_private BITMAPINFOHEADER field layout ---
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -551,14 +551,6 @@ mod tests {
|
||||
assert!(!starts_with_start_code(&[]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_byte_start_code_only_buffer_passes_through() {
|
||||
// A buffer that is exactly a 3-byte start code prefix is passed through
|
||||
// (the probe wins before length parsing).
|
||||
let raw = [0x00, 0x00, 0x01, 0x40, 0x01];
|
||||
assert_eq!(length_prefixed_to_annex_b(&raw), raw);
|
||||
}
|
||||
|
||||
// --- HevcMux: params-once + error semantics ---
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -2036,20 +2036,6 @@ mod tests {
|
||||
// element ID bytes.
|
||||
// ============================================================
|
||||
|
||||
#[test]
|
||||
fn seekhead_seek_id_values_match_target_element_ids() {
|
||||
let tracks = [make_video_track(), make_audio_track()];
|
||||
let (data, _) = mux_to_bytes(&tracks, &[], &frames_for(10.0, 1.0));
|
||||
let entries = parse_seekhead(&data);
|
||||
// The decoded SeekID for each entry must equal a real Matroska element
|
||||
// ID (Info, Tracks, Cues). parse_seekhead reads SeekID as a uint; the
|
||||
// value is the big-endian element ID.
|
||||
let ids: Vec<u32> = entries.iter().map(|(id, _)| *id).collect();
|
||||
assert!(ids.contains(&ebml::INFO));
|
||||
assert!(ids.contains(&ebml::TRACKS));
|
||||
assert!(ids.contains(&ebml::CUES));
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// dolby_vision_config (dvcC / DOVIDecoderConfigurationRecord) bit
|
||||
// packing. Byte 2: profile(7 bits) << 1 | level high bit. Byte 3:
|
||||
|
||||
@@ -1210,14 +1210,6 @@ mod tests {
|
||||
// 0x1100 + (tnum-2) formula).
|
||||
// ============================================================
|
||||
|
||||
#[test]
|
||||
fn ts_pid_for_track_mid_range_formula() {
|
||||
// tnum 10 → 0x1100 + 8 = 0x1108.
|
||||
assert_eq!(ts_pid_for_track(10).unwrap(), 0x1108);
|
||||
// tnum 0x100 → 0x1100 + 0xFE = 0x11FE.
|
||||
assert_eq!(ts_pid_for_track(0x100).unwrap(), 0x11FE);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// CLUSTER_TIMESTAMP overflow guard — a value above i64::MAX would cast
|
||||
// to a large negative i64 and poison every block PTS in the cluster.
|
||||
|
||||
@@ -231,16 +231,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_seek_blanket_impl_covers_cursor() {
|
||||
// WriteSeek is the MKV sink bound (Write + Seek). The blanket impl
|
||||
// must opt in any T: Write+Seek; Cursor<Vec<u8>> is the canonical
|
||||
// in-memory seekable sink. Compile-time proof via a generic fn.
|
||||
fn assert_writeseek<T: super::super::WriteSeek>(_: &T) {}
|
||||
let cur = std::io::Cursor::new(Vec::<u8>::new());
|
||||
assert_writeseek(&cur);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_matching_scheme_wins_no_double_prefix_confusion() {
|
||||
// A path component that itself looks like another scheme must be
|
||||
|
||||
@@ -87,30 +87,4 @@ mod tests {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,21 +889,6 @@ mod tests {
|
||||
assert_eq!(parse_pts(&encode_pts(max, 0x20)), max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_pts_ignores_marker_bits_in_value() {
|
||||
// The marker bits (LSB of bytes 0,2,4) are NOT part of the 33-bit
|
||||
// value. Two encodings differing only in marker bits decode equal.
|
||||
let v = 0x1_2345_6789u64 & ((1 << 33) - 1);
|
||||
let a = encode_pts(v, 0x20);
|
||||
let mut b = a;
|
||||
// markers are already 1; the value bits must dominate regardless.
|
||||
b[0] |= 0x01;
|
||||
b[2] |= 0x01;
|
||||
b[4] |= 0x01;
|
||||
assert_eq!(parse_pts(&a), v);
|
||||
assert_eq!(parse_pts(&b), v);
|
||||
}
|
||||
|
||||
// ── pack header (0xBA) framing ────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
@@ -1151,14 +1136,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_feed_then_flush_is_empty() {
|
||||
// No input at all → nothing to emit, no panic.
|
||||
let mut demuxer = PsDemuxer::new();
|
||||
assert!(demuxer.feed(&[]).is_empty());
|
||||
assert!(demuxer.flush().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pes_header_data_length_skips_pts_when_flag_unset() {
|
||||
// If pts_dts_flags == 0 the 5 "PTS" bytes after the fixed header are
|
||||
|
||||
@@ -700,13 +700,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// output() to null:// must succeed (it's the canonical write sink).
|
||||
#[test]
|
||||
fn output_null_succeeds() {
|
||||
let t = DiscTitle::empty();
|
||||
assert!(output("null://", &t).is_ok());
|
||||
}
|
||||
|
||||
/// output() to an unknown scheme must surface StreamUrlInvalid
|
||||
/// (E9002 → InvalidInput).
|
||||
#[test]
|
||||
@@ -964,23 +957,4 @@ mod tests {
|
||||
);
|
||||
assert!(res.is_err(), "zero batch_sectors must be rejected");
|
||||
}
|
||||
|
||||
/// info() on the assembled pipeline returns the title it was built with —
|
||||
/// the consumer reads stream layout from here before muxing.
|
||||
#[test]
|
||||
fn build_iso_pipeline_info_returns_title() {
|
||||
let mut title = aac_audio_title(0x1100);
|
||||
title.playlist = "PipelineTitle".into();
|
||||
let stream = build_iso_pipeline(
|
||||
MemSource { data: Vec::new() },
|
||||
title,
|
||||
DecryptKeys::None,
|
||||
8192,
|
||||
ContentFormat::BdTs,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(stream.info().playlist, "PipelineTitle");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,13 +231,6 @@ mod tests {
|
||||
assert_eq!(s.codec_private(99), None);
|
||||
}
|
||||
|
||||
/// info() on the write side reflects the supplied title.
|
||||
#[test]
|
||||
fn output_info_reflects_title() {
|
||||
let s = StdioStream::output(&title_with_codec_privates());
|
||||
assert_eq!(s.info().playlist, "StdioTitle");
|
||||
}
|
||||
|
||||
/// A fresh input stream defaults to an empty title until a header is
|
||||
/// parsed — info() must not invent stream metadata.
|
||||
#[test]
|
||||
|
||||
@@ -885,27 +885,4 @@ mod tests {
|
||||
assert_eq!(got.len(), big.len(), "no bytes lost in the PES split");
|
||||
assert_eq!(got, big, "split audio reassembles byte-for-byte");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn af_plus_payload_always_fills_184() {
|
||||
// Invariant from write_pes_chain: af_bytes + payload_len == 184 on
|
||||
// every packet (so the 192-byte frame is exact). Verify for a video
|
||||
// keyframe (which forces an RAI adaptation field on packet 1).
|
||||
let mut sink: Vec<u8> = Vec::new();
|
||||
{
|
||||
let mut mux = TsMuxer::new(&mut sink, &[VIDEO_PID]);
|
||||
let idr = fake_hevc_nal(19, 400);
|
||||
mux.write_frame(0, 0, true, &idr).unwrap();
|
||||
mux.finish().unwrap();
|
||||
}
|
||||
let packets = parse_bd_ts(&sink);
|
||||
for p in packets.iter().filter(|p| p.pid == VIDEO_PID) {
|
||||
let af_total = p.af.as_ref().map(|a| a.len() + 1).unwrap_or(0); // +1 length byte
|
||||
assert_eq!(
|
||||
af_total + p.payload.len(),
|
||||
184,
|
||||
"AF area + payload must fill the 184-byte TS body"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user