MediaProbe: three pure helpers have no test, while the rest is device-bound and fine #84
Closed
opened 2026-08-25 03:21:49 +00:00 by JMR-dev
·
2 comments
No Branch/Tag Specified
main
fix/102-picker-back-press-overshoot
fix/268-saf-picker-determinism
feat/ogg-vorbis-libvorbis
feat/expedited-conversion-work
fix/gate-cache-in-worktrees
chore/gate-runs-shellcheck
test/publish-delete-arm-real-provider
docs/e8-instrumented-coverage
docs/api37-carrier-count-drift
docs/e7-second-constraint
test/publish-to-a-real-saf-destination
fix/api37-report-match-line
fix/api37-task-snapshot-crash
test/join-failure-message-on-device
docs/e2e-read-findings-e7
test/cancelling-a-running-export
test/reattach-to-a-running-job
test/content-uri-reaches-ffmpeg
fix/launcher-wiring-waits-for-the-pick
fix/cancel-tests-need-a-slower-encode
test/cancelling-a-running-join
test/cancelling-a-running-session
test/notification-cancel-action
test/ffmpeg-progress-is-observed
test/fallback-asserts-the-path
test/flac-and-opus-assert-their-format
docs/e2e-read-findings
docs/wave4-coverage-numbers
fix/injectable-startup-sweep-scope
test/session-outcome-seam
test/launcher-callback-identity
test/theme-follows-system-dark
test/audio-drop-arm
fix/rotation-waits-for-recreation
fix/convert-guards-on-ready
test/retry-save-mime
test/hardware-progress-reaches-workmanager
test/ffprobe-mapping-seam
test/device-codec-enumeration-seam
test/unknown-container-row
test/null-message-fallbacks
test/cancel-reaches-workmanager
docs/coverage-wave3-recovery
test/concat-engine-seam
docs/coverage-wave3
test/mediaprobe-merge-seam
test/adaptive-shell-wiring
test/aac-audio-args
test/notification-progress-text
test/media3-muxer-guard
test/hardware-fallback-and-cancellation
test/unprobeable-join-clip
test/one-branch-outcomes
test/foreground-type-regimes
fix/bound-wedge-diagnostics
docs/coverage-wave2
test/screen-wiring
test/viewmodel-setters
test/join-state-mapping
test/conversion-state-mapping
test/dedupe-user-messages
fix/restore-stack-merges
test/refused-jobs
test/concatworker-failure-arms
test/container-capabilities-audio
test/readspec-enum-fallbacks
test/outputpublisher-seams
test/mediaprobe-track-seam
test/outputpublisher-partial-branches
test/fake-provider-scaffolding
docs/coverage-read-findings
chore/gitignore-kotlin
test/bound-the-hangs
docs/coverage-remeasure
ci/baseline-counter-precision
fix/invalid-suggestion-chip
ci/wedged-leg-report
fix/reattachment-overwrites-pick
test/theme-live-branches
fix/failed-save-retry
fix/empty-composition-crash
ci/advisory-failure-report
docs/seven-run-counts
test/release-permission-guard
ci/build-workflow-permissions
docs/api37-point-release
docs/benchmark-populate-path
fix/dead-assertion-probe-test
ci/actionlint
test/device-codecs-encode-consequence
fix/sdkmanager-pipefail
docs/readme-restart-claim
fix/saf-picker-root-discovery
fix/probe-dispatcher-seam
test/media3engine-mime-tables
test/mediaprobe-pure-helpers
fix/codec-vocabulary-drift
docs/robolectric-rationale-correction
docs/api37-advisory-counts
test/r38-8-saf-e2e
test/r38-7-join-states
test/r38-6-conversion-states
test/r38-5-state-seam
fix/jacoco-robolectric-coverage
docs/instrumented-tests-correction
test/r38-2-filecard
test/r38-4-advanced-picker
test/r38-3-pickers
tools/file-issue-script
tools/api-37-emulator
fix/review-app-gaps
docs/review-corrections
No results found.
Labels
Clear labels
above-cut
accessibility
backlog
bug
confirmed
documentation
duplicate
enhancement
good first issue
help wanted
invalid
plausible
question
sev:high
sev:low
sev:medium
wontfix
Worked autonomously overnight: local, JVM-verifiable, no product decision
Barrier affecting people with disabilities
Held for manual review: product/UX call, CI/workflow, hardware, or unverifiable here
Something isn't working
Reviewer demonstrated the defect
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Good for newcomers
Extra attention is needed
This doesn't seem right
Reviewer could not fully demonstrate it; treat as unproven
Further information is requested
High severity
Low severity
Medium severity
This will not be worked on
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: JMR-dev/LibreMediaConverter#84
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Filed from a coverage read on
ad28293, but the number is not the reason — see the last section.MediaProbeis 75/145 lines on the JVM. What is missing splits cleanly into two halves, and only one of them is a gap worth closing.Genuinely untested, and unit-testable today
shortName(mime)whenoverMediaFormat.MIMETYPE_*constants -> short names, withmime.substringAfter('/')as the fallbackisImageFormat(formatName),, matchesimage2or a_pipesuffixintOrAll three are
private. #57 established the precedent for widening exactly this way —internal, with the JVM test source set as a friend ofmain(MainActivity.ktcarries the reasoning).shortNameis a lookup table over Android MIME constants, which is the shape that rots silently: nothing today would notice a wrong or missing arm.isImageFormat's_pipesuffix rule is the kind of thing that looks arbitrary until it breaks.Device- or native-bound, and NOT a gap
readMediaInformation(14/14) spawns FFprobe;probeWithExtractor(13/25) drivesMediaExtractor;probe,probeWithFFprobeandprobeForConcatare the orchestration over those. These are exercised byRemuxTest,ConcatEngineTestandRealMediaBenchmarkinandroidTest— which JaCoCo does not measure at all, because the report coverstestDebugUnitTestonly.Do not read their 0% as untested, and do not try to fix it by mocking FFprobe.
MediaProbeFormatTestandMediaProbeNativeLoadTestalready cover the parsing and the native-failure edge at the seams that exist.Done means
The three pure helpers have tests that name their cases — every arm of
shortNameincluding the fallback, and both halves ofisImageFormat's rule.Mutation: delete one arm of
shortName(sayMIMETYPE_VIDEO_HEVC -> "hevc") and the test must go red naming that mime; changeendsWith("_pipe")tocontains("pipe")and theisImageFormattest must go red.On the coverage number
This will move it barely at all — 17 lines of 2246. That is not the point and must not become the acceptance. JaCoCo was found on 2026-08-24 never to have counted a Robolectric test in this repo (#75, fixed in #76), and #52's entire premise turned out to be an artifact of that. The reason to write these is that three lookup tables have no test, not that a percentage moves.
#87 and #74 landed together in PR #90, and it leaves a join point here rather than a fifth table.
MediaProbe.ktis untouched — that is this ticket's file, deliberately left alone. What changedunderneath it:
CodecNames.videoFromName/audioFromNameare no longerwhenexpressions. The vocabulary isnow
internal val CodecNames.VIDEO_ALIASES: Map<String, VideoCodec>andCodecNames.AUDIO_ALIASES: Map<String, AudioCodec>. That is the load-bearing part: awhencannot be enumerated, so no test could ask one table what another one knows. A map can.
app/src/test/java/org/libremediaconverter/codec/CodecVocabularyTest.ktis the cross-check. Itwalks
CodecNames.VIDEO_ALIASES.keysagainstAndroidDeviceCodecs.NAME_TO_MIME.keysin bothdirections, and asserts the two agree on each name's meaning, not merely that both know it.
Adding an alias to one side alone fails it — measured, with the whole 386-test suite green
except that file.
shortNameis the third table and the one this ticket owns. The cheap way to bring it in is anarm in
CodecVocabularyTest, not a table of its own: every short nameshortNamecan emit mustbe a key in
CodecNames.VIDEO_ALIASESorAUDIO_ALIASES, or be listed as a documentedexception the way
AndroidDeviceCodecs.DECODE_ONLY_NAMESlistsmpeg4. That exception list isitself checked in both directions in #90, because otherwise it is an escape hatch — any future
divergence could be waved through by adding the name to it.
Two things worth copying rather than reinventing:
AndroidDeviceCodecs.mimeFor,mimeForCodecName,NAME_TO_MIMEandDECODE_ONLY_NAMESwerewidened from
privatetointernalso the JVM test source set (a friend ofmain) can reachthem.
MainActivity.kt:36-38carries the precedent and #57 established it.CodecVocabularyTestasserts one literal MIME ("video/avc") on purpose. Without it, if theMediaFormatconstants ever stopped being inlined into the unit-test classpath, every MIMEcomparison would be
null == nulland green.Revisiting the boundary this ticket drew — with new evidence, not a re-reading of the old.
This ticket closed on:
Two claims there, and they have aged differently.
Still exactly right: the FFprobe half, and the measurement boundary.
readMediaInformationis native, JaCoCo measurestestDebugUnitTestonly, and mocking FFprobe would have been the wrong fix. Nothing here touches any of that.Not right: that the extractor half is only orchestration. It is a branch matrix — first-track-wins per type,
maxOfduration across tracks, thecontainsKey(KEY_DURATION)guard, and track ordering.RemuxTestandConcatEngineTestreach those lines, but only through whatever the committed fixtures happen to contain, so none of the rules is chosen by any test. A two-video-track file, a track that omits its duration, or an audio-before-video ordering is not something a device test produces on purpose.Addressed in #141 / PR #150 by cutting the walk into
extractedFrom(List<MediaFormat>)andconcatInputFrom(List<MediaFormat>)— the pure-seam patternwork/FailureOutcome.ktdocuments — rather than by mocking anything. What is left needing a device issetDataSource/getTrackFormat/release, three lines, which is the thin edgeandroidTestshould be covering. Eleven tests, six mutations, all six red.MediaProbe's missed branches went 91 → 70.Recorded here rather than only in the PR because this ticket is what a future coverage read will find first, and re-deriving the distinction cost a full spike. The
ShadowMediaExtractorroute was also checked and is genuinely available — Robolectric 4.16.1 shadows the exactsetDataSource(Context, Uri, Map)overload — so if the seam is ever reverted, that is the fallback rather than a dead end.Leaving this closed; #141 carries the work.