Merge branch 'codeaudit/tg-busy-2' into codeaudit/land

This commit is contained in:
Matthew Jackson
2026-09-29 20:45:04 -07:00
12 changed files with 297 additions and 15 deletions
+30
View File
@@ -4155,6 +4155,12 @@ mod tests {
assert!(d.contains("redacted"), "AacsState missing marker: {d}");
for k in [
Key::Device(vec![crate::aacs::types::DeviceKey {
key: [0xD5; 16],
node: 0,
uv: 0,
u_mask_shift: 0,
}]),
Key::Unit(vec![(1, [0xD5; 16])]),
Key::Volume([0xD5; 16]),
Key::Processing(vec![[0xD5; 16]]),
@@ -7097,6 +7103,30 @@ mod tests {
);
}
// Many ranges: sorted largest-first, capped at 50 with the overflow counted.
// Input is ascending, so a flipped sort keeps the smallest and reports its gap.
// bps = 2048 B/s, so range i (i+1 sectors) lasts (i+1) * 1000 ms.
#[test]
fn locate_ranges_sorts_largest_first_and_truncates_at_fifty() {
let mut title = title_with_size(204_800, vec![]);
title.duration_secs = 100.0;
let raw: Vec<(u64, u64)> = (0..53u64)
.map(|i| (i * 100 * 2048, (i + 1) * 2048))
.collect();
let r = locate_ranges(&raw, &title);
assert_eq!(r.num_ranges, 53);
assert_eq!(r.truncated, 3);
assert_eq!(r.ranges.len(), 50);
assert_eq!(r.largest_gap_ms, 53_000.0);
assert_eq!(r.ranges[0].count, 53);
assert_eq!(r.ranges[49].count, 4, "the three smallest were dropped");
assert!(
r.ranges
.windows(2)
.all(|w| w[0].duration_ms > w[1].duration_ms)
);
}
// bps computed exactly 0.0: duration_ms/main_at_risk_ms must stay 0.0,
// never inf/NaN. Kills `bps > 0.0` flipped to `>=` at both sites (the
// boundary exactly zero would wrongly take the division branch).
+20
View File
@@ -2114,6 +2114,26 @@ mod tests {
}
}
// A truncated run may still assert "not forced" (positive evidence: a non-forced set was
// seen) when the shape gate allows demotion, but never a forced verdict (an absence claim).
#[test]
fn a_truncated_run_asserts_only_a_demotable_not_forced_verdict() {
let full = TrackEvidence {
observed: true,
non_forced: true,
displays: 20,
..Default::default()
};
let flagged = TrackEvidence {
observed: true,
forced_seen: true,
displays: 20,
..Default::default()
};
let ev = HashMap::from([(0x1200u16, full), (0x1201u16, flagged)]);
assert_eq!(verdicts(&ev, false), HashMap::from([(0x1200u16, false)]));
}
// Coverage is what makes a memo replayable: an entry from a thin sample must not answer a
// question needing a thorough one.
#[test]
+25 -2
View File
@@ -1772,10 +1772,26 @@ fn resolve_retains_no_source_and_nothing_asks_after() {
let mut buf = vec![0u8; 30 * 2048];
w.read_sectors(b, 30, &mut buf, true).unwrap();
}
let _ = crate::mux::mux_with_keys(
// The mux needs a stream to run at all; with none it returns E6009 before reading.
let mut title = fx.disc.titles[0].clone();
title
.streams
.push(crate::disc::Stream::Video(crate::disc::VideoStream {
pid: 0x1011,
codec: crate::disc::Codec::Mpeg2,
resolution: crate::disc::Resolution::R1080p,
frame_rate: crate::disc::FrameRate::F23_976,
hdr: crate::disc::HdrFormat::Sdr,
color_space: crate::disc::ColorSpace::Bt709,
display_aspect: None,
secondary: false,
label: String::new(),
measured_cicp: None,
}));
let r = crate::mux::mux_with_keys(
crate::mux::MuxSource::Live {
reader: Box::new(src.clone()),
title: fx.disc.titles[0].clone(),
title,
format: ContentFormat::BdTs,
},
Some(&set),
@@ -1787,6 +1803,13 @@ fn resolve_retains_no_source_and_nothing_asks_after() {
&Halt::new(),
Arc::new(crate::mux::driver::NoopEvents),
);
// The fixture TS carries no muxable frames, so a mux that read every unit through the
// held keys ends E6008 (MkvInvalid); E6009 would mean it never read.
let e = r.expect_err("no muxable frames");
assert_eq!(
crate::error::error_code(&e),
Some(crate::error::E_MKV_INVALID)
);
assert_eq!(Arc::strong_count(&f), 1);
assert_eq!(calls.len(), asked, "nothing asks after resolve");
}
+77
View File
@@ -376,6 +376,83 @@ mod tests {
assert_eq!(set, None);
}
// A UDF with `/BDMV/META/DL/` holding `files` (name, contents), or no DL dir when `dl` is false.
fn disc_with_dl(files: &[(&str, Vec<u8>)], dl: bool) -> (crate::udf::fixture::MemDisc, UdfFs) {
use crate::udf::fixture::*;
let dl_files = files
.iter()
.enumerate()
.map(|(i, (n, c))| file_with(n, 30 + i as u32, 100 + 2_000 * i as u32, c.clone(), true))
.collect();
let dir = |name: &str, icb, data, files, subdirs| DirSpec {
name: name.into(),
icb_lba: icb,
dir_data_lba: data,
files,
subdirs,
};
let leaf = if dl {
dir("DL", 16, 17, dl_files, vec![])
} else {
dir("OTHER", 16, 17, dl_files, vec![])
};
let meta = dir("META", 14, 15, vec![], vec![leaf]);
let bdmv = dir("BDMV", 12, 13, vec![], vec![meta]);
let root = dir("", 10, 11, vec![], vec![bdmv]);
let mut disc = MemDisc::new();
build_udf_skeleton(&mut disc, 10);
lay_dir(&mut disc, &root);
let udf = crate::udf::read_filesystem(&mut disc).expect("fs");
(disc, udf)
}
#[test]
fn parse_aggregates_languages_and_first_disc_set_wins() {
let xml = |name: &str, set: u32| {
format!(
"<d><di:name>{name}</di:name><di:setNumber>{set}</di:setNumber>\
<di:numSets>2</di:numSets></d>"
)
.into_bytes()
};
let mut fra = xml("Titre", 2);
fra.extend_from_slice(b"<di:description>Suite.</di:description>");
let mut big = xml("Too Big", 1);
big.resize(MAX_BDMT_BYTES as usize + 1, b' ');
let (mut disc, udf) = disc_with_dl(
&[
("bdmt_eng.xml", xml("Title", 1)),
("bdmt_fra.xml", fra),
("bdmt_deu.xml", big),
("bdmt_xx.xml", xml("Bad Lang", 1)),
("notes.xml", xml("Not BDMT", 1)),
],
true,
);
assert!(detect(&udf));
let meta = parse(&mut disc, &udf).expect("titles found");
let titles: Vec<_> = meta
.titles
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect();
assert_eq!(titles, [("eng", "Title"), ("fra", "Titre")]);
assert_eq!(meta.descriptions.len(), 1);
assert_eq!(meta.descriptions["fra"], "Suite.");
assert_eq!(meta.disc_number, Some((1, 2)), "the first file's set wins");
}
#[test]
fn parse_and_detect_are_none_without_bdmt_files() {
let (mut disc, udf) = disc_with_dl(&[("bdmt_eng.xml", b"<d/>".to_vec())], false);
assert!(!detect(&udf));
assert!(parse(&mut disc, &udf).is_none());
// A DL dir with only a title-less bdmt file: detected, but nothing to parse.
let (mut disc, udf) = disc_with_dl(&[("bdmt_eng.xml", b"<d/>".to_vec())], true);
assert!(detect(&udf));
assert!(parse(&mut disc, &udf).is_none());
}
#[test]
fn multiple_languages_keyed_correctly() {
// Drive parse_bdmt_xml from two synthetic XML blobs and aggregate
+4 -7
View File
@@ -809,12 +809,9 @@ mod tests {
/// Mutation: skip lowercase normalization → "ENG" stays "ENG" in the label.
#[test]
fn normalize_language_lowercases_and_trims() {
assert_eq!(
// trim + lowercase, mirroring production normalize_language
super::super::mpls_universal::language_display_name(
&" ENG ".trim().to_ascii_lowercase(),
),
"English"
);
assert_eq!(normalize_language(" ENG "), "eng");
assert_eq!(normalize_language(" "), "");
// An unknown code keeps its trimmed lowercase form.
assert_eq!(normalize_language(" XYZ "), "xyz");
}
}
+47 -4
View File
@@ -762,8 +762,8 @@ mod tests {
assert_eq!(codec("dts"), "dts");
}
/// Spec: all 36 bare-lang entries must resolve correctly.
/// Mutation: swap two entries in BARE_LANGS → wrong code returned.
/// Spec: every BARE_LANGS entry must resolve to its code.
/// Mutation: swap two entries' codes in BARE_LANGS -> wrong code returned.
#[test]
fn lang_bare_all_entries_spot_check() {
let cases = [
@@ -774,17 +774,48 @@ mod tests {
("Italian", "ita"),
("Japanese", "jpn"),
("Chinese", "zho"),
("Korean", "kor"),
("Mandarin", "zho"),
("Cantonese", "zho"),
("Portuguese", "por"),
("Polish", "pol"),
("Czech", "ces"),
("Hungarian", "hun"),
("Dutch", "nld"),
("Korean", "kor"),
("Arabic", "ara"),
("Russian", "rus"),
("Hindi", "hin"),
("Turkish", "tur"),
("Thai", "tha"),
("Swedish", "swe"),
("Norwegian", "nor"),
("Danish", "dan"),
("Finnish", "fin"),
("Hebrew", "heb"),
("Russian", "rus"),
("Greek", "ell"),
("Vietnamese", "vie"),
("Indonesian", "ind"),
("Malay", "msa"),
("Ukrainian", "ukr"),
("Romanian", "ron"),
("Bulgarian", "bul"),
("Croatian", "hrv"),
("Serbian", "srp"),
("Slovak", "slk"),
("Slovenian", "slv"),
("Estonian", "est"),
("Latvian", "lav"),
("Lithuanian", "lit"),
("Icelandic", "isl"),
("Basque", "eus"),
("Catalan", "cat"),
("Galician", "glg"),
];
assert_eq!(
cases.len(),
BARE_LANGS.len(),
"table and cases must stay in step"
);
for (name, code) in cases {
let r = lang(name).unwrap_or_else(|| panic!("lang({:?}) must be Some", name));
assert_eq!(r.code, code, "wrong code for {}", name);
@@ -792,6 +823,18 @@ mod tests {
}
}
/// Needles embedded in longer words must not match in qualifier/purpose/lang.
/// Mutation: has_word -> contains() in any of the three -> a false hit.
#[test]
fn embedded_needles_do_not_match_word_classifiers() {
assert_eq!(qualifier("xsdhx"), LabelQualifier::None);
assert_eq!(qualifier("uncaptions"), LabelQualifier::None);
assert_eq!(purpose("uncommentary"), LabelPurpose::Normal);
assert_eq!(purpose("scorecard"), LabelPurpose::Normal);
assert_eq!(lang("englishman"), None);
assert_eq!(lang("thaiwan"), None);
}
/// Word boundary: "sdh" inside "lambdash" must not match.
/// Mutation: use `contains("sdh")` → "lambdash" falsely triggers SDH.
#[test]
+11
View File
@@ -1476,6 +1476,17 @@ mod tests {
compositions
}
// A visible PCS with no duration has no known wipe time: neither write nor finish adds a clear.
#[test]
fn pgs_sup_visible_pcs_without_duration_gets_no_clear_at_finish() {
let mut writer = PgsSupWriter::default();
let mut bytes = Vec::new();
let f = sup_frame(1_000_000_000, None, true);
writer.write_frame(&mut bytes, &f, f.pts).unwrap();
writer.finish(&mut bytes).unwrap();
assert_eq!(sup_compositions(&bytes), [(90_000, 1)]);
}
#[test]
fn pgs_sup_preserves_original_clear_without_a_duplicate_or_later_clear() {
let mut writer = PgsSupWriter::default();
+23 -1
View File
@@ -1319,6 +1319,27 @@ mod tests {
.count()
}
/// The declared-only warning check must cover finish() too; captures are thread-local, so the
/// sink is finished on the capturing thread instead of the consumer thread.
#[test]
fn declared_only_mp2_extension_gives_no_warning_at_finish() {
let title = mp2_ext_title();
let dir = tempfile::tempdir().expect("tempdir");
let d = dir.path().display();
for url in [
format!("mkv://{d}/o.mkv"),
format!("m2ts://{d}/o.m2ts"),
format!("demux://{d}/demux"),
format!("audio://{d}/audio"),
] {
let mut sink = crate::mux::resolve::output(&url, &title, None).expect("sink opens");
let (res, ev) = crate::testlog::capture(|| sink.finish());
let _ = res;
assert_eq!(mp2_extension_warnings(&ev), 0, "{url}: declared only");
assert!(sink.undelivered_streams().is_empty(), "{url}");
}
}
/// Guard (mpg design §7): every sink but mpg/network/stdio lists an MPEG-2 multichannel
/// extension track as excluded once its packets arrive, so lost surround is never silent;
/// IFO coding mode 3 alone (no `0xD0|n` packet) gives no warning and no note.
@@ -2181,7 +2202,8 @@ mod tests {
assert!(mkv.set_codec_private(i + 1, cp).expect("patch"));
assert!(!mkv.set_codec_private(i + 1, cp).expect("second patch"));
}
assert!(!mkv.set_codec_private(1, &[0; 14]).expect("too big"));
// Track 4 still holds its reserve, so this reaches the size guard.
assert!(!mkv.set_codec_private(4, &[0; 14]).expect("too big"));
mkv.write(&frame(1)).expect("audio frame");
mkv.finish().expect("finish");
let back = crate::mux::mkvstream::MkvStream::open(std::fs::File::open(&path).unwrap())
+16
View File
@@ -1240,6 +1240,22 @@ mod tests {
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
}
#[test]
fn read_size_truncated_inside_the_vint_errors_at_every_width() {
// A width-w size VINT needs w bytes; supply one fewer, never a decoded size.
for w in 2..=8usize {
let mut bytes = vec![0u8; w - 1];
bytes[0] = 0x80 >> (w - 1);
let e = read_size(&mut Cursor::new(&bytes)).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof, "width {w}");
}
let mut buf = Vec::new();
write_id(&mut buf, SIMPLE_BLOCK).unwrap();
buf.push(0x40);
let e = read_element_header(&mut Cursor::new(&buf)).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::UnexpectedEof);
}
// write_size — every declared width-boundary, asserting the exact VINT bytes.
// Width W encodes 7*W payload bits; the highest value of each width is reserved.
+30 -1
View File
@@ -5550,6 +5550,31 @@ mod tests {
);
}
// Several EBML size deltas in a row, mixed signs: each is relative to the PREVIOUS size,
// and a delta that drives a size below zero rejects the whole lace.
#[test]
fn an_ebml_lace_accumulates_signed_deltas_and_rejects_negative_sizes() {
// Sizes 3, +2, -3, +2 = 3, 5, 2, 4; the last frame is the remainder (6).
// 1-octet svint: 0x80 | (delta + 63).
let mut body = vec![0x04, 0x83, 0xC1, 0xBC, 0xC1];
let sizes = [3usize, 5, 2, 4, 6];
for (i, n) in sizes.iter().enumerate() {
body.extend(std::iter::repeat_n(i as u8 + 1, *n));
}
let frames = split_lacing(LACING_EBML, &body).expect("well-formed lace");
assert_eq!(frames.len(), 5);
for (i, (f, n)) in frames.iter().zip(sizes).enumerate() {
assert_eq!(*f, vec![i as u8 + 1; n].as_slice(), "frame {i}");
}
// 3 then -4 = -1: negative size.
assert_eq!(
split_lacing(LACING_EBML, &[0x02, 0x83, 0xBB, 0, 0, 0]),
None
);
// The delta VINT is missing.
assert_eq!(split_lacing(LACING_EBML, &[0x02, 0x83]), None);
}
// The shortest usable (Simple)Block is 4 bytes (track VINT + rel-ts + flags,
// empty payload) — exactly the boundary of the short-block guards, where an
// off-by-one drops a legal frame or indexes past the buffer end.
@@ -5925,7 +5950,11 @@ mod tests {
ebml::write_binary(&mut group, ebml::DISCARD_PADDING, &[0; 9]).unwrap();
ebml::write_binary(&mut cluster, ebml::BLOCK_GROUP, &group).unwrap();
let bytes = mkv_with_tracks_and_cluster(&[TrackSpec::new(1, 2)], &cluster);
assert!(MkvStream::open(Cursor::new(bytes)).unwrap().read().is_err());
let e = MkvStream::open(Cursor::new(bytes))
.unwrap()
.read()
.unwrap_err();
assert!(is_mkv_source_invalid(&e), "{e:?}");
}
fn av_frame(track: usize, pts: i64, keyframe: bool, data: Vec<u8>) -> crate::pes::PesFrame {
+4
View File
@@ -1124,8 +1124,10 @@ mod tests {
.unwrap();
tx.send(DemuxBatch::Eof).unwrap();
let mut out = Vec::new();
let mut pts = Vec::new();
while let Some(f) = stream.read().unwrap() {
out.push(f.data);
pts.push(f.pts);
}
assert_eq!(
out,
@@ -1135,6 +1137,8 @@ mod tests {
au[4].clone()
]
);
// A merged pair keeps its FIRST field's PTS; only the PTS-less frame reads 0.
assert_eq!(pts, [9_000, 12_003, 0]);
}
// Single-video-stream title on `codec` + CountingParser; feeds three 0xE0
+10
View File
@@ -497,6 +497,16 @@ impl ScsiTransport for SptiTransport {
mod tests {
use super::*;
// A drive root like `D:\` must open the volume, not the root directory.
#[test]
fn normalize_device_path_maps_drive_forms_to_the_volume_path() {
assert_eq!(normalize_device_path("D:"), r"\\.\D:");
assert_eq!(normalize_device_path(r"D:\"), r"\\.\D:");
assert_eq!(normalize_device_path(r"\\.\D:"), r"\\.\D:");
assert_eq!(normalize_device_path(r"\\.\CdRom0"), r"\\.\CdRom0");
assert_eq!(normalize_device_path("CdRom0"), r"\\.\CdRom0");
}
// Regression guard: `StorageAdapterDescriptor` must match `STORAGE_ADAPTER_DESCRIPTOR`
// (winioctl.h) field-for-field.
#[test]