Skip to content

test(ios): reuse ResizingProcessor instead of a second transcoding mock - #637

Closed
jkmassel wants to merge 1 commit into
docs/media-field-decode-invariantfrom
test/media-mock-cleanup
Closed

jkmassel wants to merge 1 commit into
docs/media-field-decode-invariantfrom
test/media-mock-cleanup

Conversation

@jkmassel

@jkmassel jkmassel commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #633. Follow-up from an adversarial review of #625.

What?

Deletes TranscodingProcessor and points its one call site at the existing ResizingProcessor. Drops @unchecked Sendable from two stateless mocks.

Why?

TranscodingProcessor was a duplicate of ResizingProcessor — same .processed(_, mimeType: "video/mp4", filename: "clip.mp4") result, one call site — and the weaker of the two on both counts that matter:

  • It wrote to a fixed $TMPDIR/clip.mp4 rather than a per-call UUID path inside the managed upload directory. processAndUpload's cleanup defer then deletes that path, so the mock unlinks a process-wide filename it does not own. Verified by planting a sentinel: before: exists=true → after: exists=false.
  • It swallowed the write with try? and still returned .processed(<URL>, …). Forcing the write to fail leaves the file absent and all four assertions still pass — the test cannot detect a regression where processing silently produces nothing. ResizingProcessor uses try.

@unchecked Sendable on ThrowingUploader and DecliningProcessor bought nothing — both are stateless final classes that satisfy the conformance on their own. The annotation belongs on the mocks holding NSLock-guarded state; carrying it on stateless ones normalizes it as boilerplate, which is how an unsynchronized property gets added later without a diagnostic.

How?

  • ios/Tests/GutenbergKitTests/Media/MediaUploadServerTests.swift: TranscodingProcessor deleted; processesForHostReleasedDelegate uses ResizingProcessor. @unchecked Sendable removed from ThrowingUploader and DecliningProcessor. ContentTypeDeleteClient keeps it — it subclasses an @unchecked Sendable class and must restate the conformance.

Mutation sensitivity is unchanged: against a weakly-held processor the swapped test still fails in all four places with the real symptom (passthroughUploadCalled → true).

Testing Instructions

  • swift test — 981 tests, host suite green
  • swift build --build-tests — zero warnings in the library and test targets
  • SwiftLint clean

Related

Two other findings from the same review are already fixed upstream in this stack: the off-main delegate release (HTTPServer.stop() now clears newConnectionHandler) and the #WeakMutability warning, both in #625.

EditorViewControllerMediaLifetimeTests — vacuous for the same class of reason, since it never loads the editor — has been deleted on #625, where the file lived. That also removed LifetimeProbeDelegate, so the mock cleanup in this PR is the remainder.

@github-actions github-actions Bot added the [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests. label Sep 8, 2026
@jkmassel jkmassel added the iOS label Sep 8, 2026
@jkmassel jkmassel self-assigned this Sep 8, 2026
@wpmobilebot

wpmobilebot commented Sep 8, 2026 •

Copy link
Copy Markdown

XCFramework Build

This PR's XCFramework is available for testing. Add the following to your Package.swift:

.package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/637")

Built from e6493f1

`TranscodingProcessor` duplicated `ResizingProcessor` — same
`.processed(_, mimeType: "video/mp4", filename: "clip.mp4")` result, one call
site — and was the weaker of the two. It wrote to a fixed `$TMPDIR/clip.mp4`
instead of a per-call UUID path inside the managed upload directory, and
swallowed the write with `try?`, so a failed write still returned
`.processed(<nonexistent URL>, …)` and the test passed green against a file
that never existed. `ResizingProcessor` uses `try` and a unique path.

Also drops `@unchecked Sendable` from `ThrowingUploader` and
`DecliningProcessor`, which are stateless. The escape hatch is only needed by
the mocks holding `NSLock`-guarded state; carrying it on stateless ones
normalizes it as boilerplate, which is how a real race gets hidden later.
`ContentTypeDeleteClient` keeps it — it subclasses an `@unchecked Sendable`
class and must restate the conformance.
@jkmassel
jkmassel force-pushed the docs/media-field-decode-invariant branch from 48e341f to 73aa209 Compare September 16, 2026 19:41
@jkmassel
jkmassel force-pushed the test/media-mock-cleanup branch from 96df139 to e6493f1 Compare September 16, 2026 19:41
@jkmassel jkmassel closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

iOS [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants