No content:// input has ever reached a successful conversion, so the ffkitsaf bridge is untested #225

Closed
opened 2026-09-06 02:53:11 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-09-06 02:53:11 +00:00 (Migrated from github.com)

Filed from the 2026-09-05 e2e read of the instrumented suite on main @ 4b02294.

Every conversion a real user runs reads its input through FFmpegKitConfig.getSafParameterForRead. No passing test has ever taken that path.

The asymmetry

app/src/main/java/org/libremediaconverter/work/ConversionWorker.kt:228
app/src/main/java/org/libremediaconverter/ffmpeg/ConcatEngine.kt:36
if (uri.scheme == "content") FFmpegKitConfig.getSafParameterForRead(context, uri) else uri.path

Every convert and join test in the suite passes Uri.fromFile(...), which takes the uri.path arm. The content:// arm is exercised on the failure side only — UnopenableUriTest.aConversionInputThatCannotBeOpenedFailsCleanly points at a nonexistent authority, so it proves the error message, not the bridge.

So the ffkitsaf file-descriptor bridge — the thing standing between a SAF grant and the native process — has never been shown to work in either suite. It is on 100% of real conversions and 0% of tested ones.

What already exists

SafPickerRoundTripTest holds a real content:// URI with a live read grant, obtained through real DocumentsUI from FixtureDocumentsProvider, and asserts the file card fills in. It stops at ConversionState.Ready.

One more tap and an await on Converted closes this gap and covers Convert → Converting → Converted through the UI, which nothing does today. No new DocumentsUI interaction is needed — the expensive, flaky part is already done and paid for.

The blocker to resolve first

There is no GrantPermissionRule anywhere in app/src/androidTest. POST_NOTIFICATIONS is therefore denied for the whole instrumented suite, and ConverterScreen's Convert button does not call convert() directly — it launches requestNotifications and converts from the permission callback (ConverterScreen.kt:100). Tapping Convert in a test raises a system permission dialog.

That is fixable (GrantPermissionRule.grant(POST_NOTIFICATIONS), or uiAutomation.grantRuntimePermission), but it changes the conditions every other test in that class runs under, so it is a decision rather than a line.

Check the headless route before committing to the UI one. The instrumentation APK can call grantUriPermission to the target package for the fixture document URI, hand that URI straight to ConversionWorker.request(...), and skip the Activity entirely. If that works it is cheaper, deterministic, and does not pay #190's flake tax — and it covers the bridge, which is the actual subject. The UI route additionally covers the screen states, which is worth having but is a second thing.

Decide which of the two this ticket is, and say so, before writing it.

Mutation: make getSafParameterForRead return uri.toString(). FFmpeg cannot open it and the conversion fails. Nothing today notices.

Related

  • #190 — what a UI-driving test costs on the gating legs
  • SafPickerRoundTripTest's KDoc, on why the picker half was worth its trouble
_Filed from the 2026-09-05 e2e read of the instrumented suite on `main` @ `4b02294`._ Every conversion a real user runs reads its input through `FFmpegKitConfig.getSafParameterForRead`. No passing test has ever taken that path. ## The asymmetry ``` app/src/main/java/org/libremediaconverter/work/ConversionWorker.kt:228 app/src/main/java/org/libremediaconverter/ffmpeg/ConcatEngine.kt:36 ``` ```kotlin if (uri.scheme == "content") FFmpegKitConfig.getSafParameterForRead(context, uri) else uri.path ``` Every convert and join test in the suite passes `Uri.fromFile(...)`, which takes the `uri.path` arm. The `content://` arm is exercised on the **failure** side only — `UnopenableUriTest.aConversionInputThatCannotBeOpenedFailsCleanly` points at a nonexistent authority, so it proves the error message, not the bridge. So the ffkitsaf file-descriptor bridge — the thing standing between a SAF grant and the native process — has never been shown to work in either suite. It is on 100% of real conversions and 0% of tested ones. ## What already exists `SafPickerRoundTripTest` holds a **real `content://` URI with a live read grant**, obtained through real DocumentsUI from `FixtureDocumentsProvider`, and asserts the file card fills in. It stops at `ConversionState.Ready`. One more tap and an await on `Converted` closes this gap **and** covers Convert → Converting → Converted through the UI, which nothing does today. No new DocumentsUI interaction is needed — the expensive, flaky part is already done and paid for. ## The blocker to resolve first **There is no `GrantPermissionRule` anywhere in `app/src/androidTest`.** `POST_NOTIFICATIONS` is therefore denied for the whole instrumented suite, and `ConverterScreen`'s Convert button does not call `convert()` directly — it launches `requestNotifications` and converts from the permission **callback** (`ConverterScreen.kt:100`). Tapping Convert in a test raises a system permission dialog. That is fixable (`GrantPermissionRule.grant(POST_NOTIFICATIONS)`, or `uiAutomation.grantRuntimePermission`), but it changes the conditions every other test in that class runs under, so it is a decision rather than a line. **Check the headless route before committing to the UI one.** The instrumentation APK can call `grantUriPermission` to the target package for the fixture document URI, hand that URI straight to `ConversionWorker.request(...)`, and skip the Activity entirely. If that works it is cheaper, deterministic, and does not pay #190's flake tax — and it covers the bridge, which is the actual subject. The UI route additionally covers the screen states, which is worth having but is a second thing. **Decide which of the two this ticket is**, and say so, before writing it. *Mutation:* make `getSafParameterForRead` return `uri.toString()`. FFmpeg cannot open it and the conversion fails. Nothing today notices. ## Related - #190 — what a UI-driving test costs on the gating legs - `SafPickerRoundTripTest`'s KDoc, on why the picker half was worth its trouble
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMediaConverter#225