FFmpegEngine reports progress without ever being asked for a job of unknown duration #265

Open
opened 2026-09-07 16:51:25 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-09-07 16:51:25 +00:00 (Migrated from github.com)

Found by the union coverage read of 2026-09-07 (E9 in docs/e2e-read-findings.md).

FFmpegEngine.kt:67   if (durationMs > 0) {

Inside the statistics callback:

{ stats ->
    if (durationMs > 0) {
        val percent = (stats.time / durationMs * 100).toInt().coerceIn(0, 100)
        onProgress(percent)
    }

The false arm — a job whose duration is unknown — is never taken by either suite. The guard is
what stops a divide-by-zero and a nonsense percentage, and nothing has ever asked it to.

Why this is reachable rather than defensive

MediaProbe returns durationMs = 0 when it cannot read one: info.getDuration()?.toDoubleOrNull() ?.times(MS_PER_SECOND)?.toLong() ?: 0L. So any input ffprobe cannot time — a stream, a truncated
file, a format with no duration in its header — reaches this callback with 0. That is a real user
input, not a second line of defence, which is what separates this from the F4 family.

Check whether it can be driven through the engine seam without a device before reaching for an
instrumented test; docs/coverage-read-findings.md records that ConversionDependencies.software()
is already a seam.

Acceptance

A test that runs a conversion whose probe reports durationMs == 0 and asserts no progress
callback fires
(not merely that the job succeeds).

Mutation: delete the if. With durationMs == 0 the division yields a non-finite value and
toInt() gives 0, so onProgress(0) fires — the test must go red on the callback count. Assert
the callback, not the output file: E1's lesson is that asserting the artefact passes quietly.

Found by the union coverage read of 2026-09-07 (E9 in `docs/e2e-read-findings.md`). ``` FFmpegEngine.kt:67 if (durationMs > 0) { ``` Inside the statistics callback: ```kotlin { stats -> if (durationMs > 0) { val percent = (stats.time / durationMs * 100).toInt().coerceIn(0, 100) onProgress(percent) } ``` The **false** arm — a job whose duration is unknown — is never taken by either suite. The guard is what stops a divide-by-zero and a nonsense percentage, and nothing has ever asked it to. ## Why this is reachable rather than defensive `MediaProbe` returns `durationMs = 0` when it cannot read one: `info.getDuration()?.toDoubleOrNull() ?.times(MS_PER_SECOND)?.toLong() ?: 0L`. So any input ffprobe cannot time — a stream, a truncated file, a format with no duration in its header — reaches this callback with `0`. That is a real user input, not a second line of defence, which is what separates this from the F4 family. Check whether it can be driven through the engine seam without a device before reaching for an instrumented test; `docs/coverage-read-findings.md` records that `ConversionDependencies.software()` is already a seam. ## Acceptance A test that runs a conversion whose probe reports `durationMs == 0` and asserts **no progress callback fires** (not merely that the job succeeds). **Mutation:** delete the `if`. With `durationMs == 0` the division yields a non-finite value and `toInt()` gives `0`, so `onProgress(0)` fires — the test must go red on the callback count. Assert the callback, not the output file: E1's lesson is that asserting the artefact passes quietly.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMediaConverter#265