Security - Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged. CI / tooling - clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny dependency-audit gate with first-party git sources allowed (#15); audience-based comment-guard (#17). Docs - README (keydb ownership, BD-J parser count), drive-access transport/reset notes, mux timeline module-doc links.
3.2 KiB
src/testlog.rs — test-only tracing capture
Test-only capture of tracing events, so the crate's logging contract is
ENFORCED rather than merely commented.
Why this exists
The error contract is "Account / Log / Classify", and the round-2 audit
found the third leg unverifiable: three separate sites carry long comments
insisting they log the error's OWN code, not a fixed one — because
flattening a scratched sector (E6000) or an over-long allocation-descriptor
chain (E6016) into E6017 sends whoever triages them after authoring holes
and hides the population that actually exists. Nothing tested that. Putting
a literal back at bluray.rs's or hddvd.rs's warn sites broke no test, so
the guarantee was a convention one careless edit away from being false. Two
of those very sites were changed in round 1, and a third still carried a
hardcoded code = 6017.
Likewise "absence of a log is itself a bug": a refusal that returns the right error but says nothing produces the wrong population downstream (a residual-underrunning drive is indistinguishable from a scratched disc). That is only checkable by looking at what was emitted.
Why a hand-rolled subscriber and not tracing-subscriber
Same posture as crate::harness: this crate has exactly one dev-dependency
on purpose. tracing-subscriber would pull a tree of them to do what forty
lines of tracing::Subscriber does here. The capture is installed with
tracing::subscriber::with_default, which is THREAD-LOCAL — so it composes
with cargo test's parallel harness and two capturing tests cannot see
each other's events.
Field values are stringified through std::fmt::Debug/Display because
that is all the visitor API offers without a typed schema; tests compare
against the string form of the expected constant, which is exactly the
comparison that catches a hardcoded code.
capture(): why one global subscriber, not scoped with_default
tracing's per-callsite INTEREST CACHE is GLOBAL, but with_default is
thread-local. Under cargo test's parallel harness a rebuild of that cache
— triggered by ANY other thread registering any callsite for the first time
— re-evaluates the target callsite against the global dispatcher, which a
scoped subscriber is NOT part of, and can leave it cached "off" while a
capture is live, so the capture observes NOTHING. Serialising captures
against each other does not help: the poisoning thread is not itself
capturing. parse_playlist_unreadable_clip_icb_yields_no_title flaked ~1
run in 15 on exactly this — an empty event list.
The robust shape is a single subscriber installed globally for the whole
run, whose register_callsite returns sometimes (so no callsite is ever
hard-cached) and which routes each event to the emitting thread's own sink.
No scoped-dispatcher transitions, no cross-thread cache race, and concurrent
captures on different threads stay isolated by the thread-local sink.
capture_records_target_level_and_fields test rationale
The capture must actually see events and their field VALUES — if it silently recorded nothing, every logging assertion built on it would pass vacuously, which is worse than having no harness at all.
Mutation: an enabled() returning false, or an event() that drops
the visitor's fields, fails here.