runMedia3OrFallBack was eleven lines at 0%, and isCancellation reported ci=0 — never called by any JVM test, not merely a missed branch.
Why it stayed cold when the seam already existed
ConversionDependencies.hardware has been there all along and no unit test had ever set it. Two things kept the path unreachable in practice, and both are now stated in setUp rather than inherited:
every existing worker test uses EnginePreference.FORCE_SOFTWARE, which never enters the function;
InputProbe() defaults to UNPARSEABLE, which PERMISSIVE.canDecode refuses — so even AUTO would have routed straight to FFmpeg for a reason no assertion mentioned.
Four behaviours, five mutations, all confirmed red
The cancellation case is why this ticket led the group.runMedia3OrFallBack catches Throwable, so without that re-throw a user cancelling a hardware transcode has the app quietly start a second conversion in software — the one thing cancelling is supposed to prevent. ForcedFailureTest covers the failure half on a device and does not cover this half at all.
The clean-staging assertion is made where it is observable rather than by reading the file: the software fake records whether the output existed when it was entered, so a missing delete surfaces as FFmpeg finding a half-written hardware output at the path it is about to write.
#169 rides along because it is the same file and the same fixture. The value it protects is not only the notification title — it feeds outputNameFor, so it is also the filename offered in the user's save dialog.
Gate
Full gate green. 556 → 560 JVM tests, 0 failures. No production code changed. ConversionWorker: 22 → 9 missed lines, 14 → 7 missed branches. Line 2090/2348 → 2103/2348, branch 1022/1340 → 1029/1340.
Closes #168. Closes #169. Stacked on #181.
`runMedia3OrFallBack` was eleven lines at 0%, and `isCancellation` reported `ci=0` — **never called by any JVM test**, not merely a missed branch.
### Why it stayed cold when the seam already existed
`ConversionDependencies.hardware` has been there all along and no unit test had ever set it. Two things kept the path unreachable in practice, and both are now stated in `setUp` rather than inherited:
- every existing worker test uses `EnginePreference.FORCE_SOFTWARE`, which never enters the function;
- `InputProbe()` defaults to `UNPARSEABLE`, which `PERMISSIVE.canDecode` refuses — so even `AUTO` would have routed straight to FFmpeg for a reason no assertion mentioned.
### Four behaviours, five mutations, all confirmed red
| behaviour | mutation |
|---|---|
| a hardware failure falls back to software | delete the fallback call |
| …onto a **clean** staging file | delete `staged.delete()` before it |
| a cancellation is rethrown, not fallen back | delete `if (isCancellation(e)) throw e` |
| `engine.close()` runs either way | empty the `finally` block |
| the display-name fallback (#169) | change `"input"` to anything else |
**The cancellation case is why this ticket led the group.** `runMedia3OrFallBack` catches `Throwable`, so without that re-throw a user cancelling a hardware transcode has the app quietly start a *second* conversion in software — the one thing cancelling is supposed to prevent. `ForcedFailureTest` covers the failure half on a device and does not cover this half at all.
The clean-staging assertion is made where it is observable rather than by reading the file: the software fake records whether the output existed when it was entered, so a missing delete surfaces as FFmpeg finding a half-written hardware output at the path it is about to write.
#169 rides along because it is the same file and the same fixture. The value it protects is not only the notification title — it feeds `outputNameFor`, so it is also the filename offered in the user's save dialog.
### Gate
Full gate green. 556 → 560 JVM tests, 0 failures. **No production code changed.**
`ConversionWorker`: 22 → 9 missed lines, 14 → 7 missed branches. Line 2090/2348 → 2103/2348, branch 1022/1340 → 1029/1340.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Closes #168. Closes #169. Stacked on #181.
runMedia3OrFallBackwas eleven lines at 0%, andisCancellationreportedci=0— never called by any JVM test, not merely a missed branch.Why it stayed cold when the seam already existed
ConversionDependencies.hardwarehas been there all along and no unit test had ever set it. Two things kept the path unreachable in practice, and both are now stated insetUprather than inherited:EnginePreference.FORCE_SOFTWARE, which never enters the function;InputProbe()defaults toUNPARSEABLE, whichPERMISSIVE.canDecoderefuses — so evenAUTOwould have routed straight to FFmpeg for a reason no assertion mentioned.Four behaviours, five mutations, all confirmed red
staged.delete()before itif (isCancellation(e)) throw eengine.close()runs either wayfinallyblock"input"to anything elseThe cancellation case is why this ticket led the group.
runMedia3OrFallBackcatchesThrowable, so without that re-throw a user cancelling a hardware transcode has the app quietly start a second conversion in software — the one thing cancelling is supposed to prevent.ForcedFailureTestcovers the failure half on a device and does not cover this half at all.The clean-staging assertion is made where it is observable rather than by reading the file: the software fake records whether the output existed when it was entered, so a missing delete surfaces as FFmpeg finding a half-written hardware output at the path it is about to write.
#169 rides along because it is the same file and the same fixture. The value it protects is not only the notification title — it feeds
outputNameFor, so it is also the filename offered in the user's save dialog.Gate
Full gate green. 556 → 560 JVM tests, 0 failures. No production code changed.
ConversionWorker: 22 → 9 missed lines, 14 → 7 missed branches. Line 2090/2348 → 2103/2348, branch 1022/1340 → 1029/1340.🤖 Generated with Claude Code