Files
libfreemkv/docs/testlog.md
T
Matthew Jackson 6e14fc0c0c libfreemkv: 1.7.0 groundwork — sector-recycle soundness + CI hardening
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.
2026-09-02 12:40:55 -07:00

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.