Repository navigation
test: close the video-surface confidence gaps — capture E2E on both platforms + unit suites - #81
Merged
Merged
Conversation
…latforms + unit suites Pre-release audit of the video stack found the pure-logic core well covered (AnnexBStreamParser 98.8%, H264MuxingPipeline 89.0%, H264PassthroughRecorder 91.8%) but three blind spots: E2E: screenshot had no live suite on either platform, and Android record-video had none (stream-video landed with one in #80). Added: - ScreenshotTests (iOS runner): PNG-magic file capture, --json envelope whose path is verified on disk, directory-target stamping. - AndroidScreenshotTests: bridge capture to file, `--output -` raw PNG on stdout, top-level serial routing. - AndroidRecordVideoTests: AVAsset-loadable MP4 with a video track from both the android subcommand and the top-level route, plus a forced segment restart (SIM_USE_SCREENRECORD_TIME_LIMIT=2) that must still finalize one continuous MP4. Unit: VideoOutputFile was at 0% despite being pure path logic — now 95.7% (default stamping, tilde expansion, directory targets, stale-file replacement, intermediate dirs). VideoRecordingOptions boundary pins (93.8%), VideoFrameUtilities frame processing incl. the byte-for-byte pass-through fast path (the scale path renders via NSImage.lockFocus at the host's backing scale factor, so tests pin re-encode + aspect ratio, not absolute pixels), and ProcessControl primitives (66.2%; SignalObserver left to the live SIGTERM E2E paths). H264StreamRecorder's AVAssetWriter encoder body stays E2E-only: it is reachable only through the screencap/screenshot fallbacks, which cannot be forced without breaking screenrecord. 1252 unit tests green; all 12 new/E2E cases verified live against a booted iPhone 17 Pro simulator and emulator-5554. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
Review caught that the segment-restart case only proved "restart logged + file has a video track" — a muxer that dropped every post-restart frame would still pass. The suggested duration/isPlayable checks alone would not close that hole either: finish(stopHostTime:) re-appends the last access unit at the stop time, so a segment-1-only file still reports full wall-clock duration and stays playable. The discriminating pin reads the real muxed samples via a pass-through AVAssetReader: at least one sample PTS must land inside the post-restart window (2.5-5.5 s), where segment-1 frames (<= ~2.3 s) and the trailing re-append (~6 s) cannot reach; sample PTS must also be non-decreasing. Because screenrecord is VFR and a static screen can leave a segment frameless, the test drives adb input swipes for the whole recording so every segment has frames to contribute. duration > 3 s and isPlayable are asserted too, as supporting signals. Verified live against emulator-5554; 1252 unit tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: onevcat <onevcat@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Pre-release confidence pass over the video stack that just landed in #79/#80. The audit (per-file
llvm-covonmake test) found the pure-logic core in good shape but three blind spots worth closing before shipping.Audit result
AnnexBStreamParserH264MuxingPipelineH264PassthroughRecorderVideoOutputFileVideoRecordingOptionsProcessControlVideoCommandSupport(frame utils + encoder)The remainder of
VideoCommandSupportisH264StreamRecorder'sAVAssetWriterencoder body — reachable only through the screencap/screenshot fallback paths, which can't be forced without breaking screenrecord/FBSimulator capture; its policy pieces (estimateBitrate,waitUntilReadystall timeout) are unit-pinned and the happy paths run under live E2E.SignalObserveris likewise left to the live SIGTERM E2E paths. Command-orchestration files (backend verbs, forwarders) intentionally carry their weight in E2E, not unit numbers.E2E additions (the real gaps)
Screenshot had no live suite on either platform, and Android record-video had none:
ScreenshotTests(iOS runner): PNG-magic file capture,--jsonenvelope whosedata.pathis verified on disk, directory-target stamping.AndroidScreenshotTests: bridge capture to file,--output -raw PNG bytes on stdout, top-level serial routing.AndroidRecordVideoTests: AVAsset-loadable MP4 with a video track from bothandroid record-videoand the top-level route, plus a forced segment restart (SIM_USE_SCREENRECORD_TIME_LIMIT=2over a 6 s recording) that must still finalize one continuous MP4.With these, every capture surface (screenshot / record-video / stream-video) × platform (iOS / Android) has a live E2E suite; stream-video's landed in #80 (
StreamVideoTestsiOS,AndroidStreamVideoTests).Unit additions
VideoOutputFileTests(default stamping, tilde expansion, directory targets, stale-file replacement, intermediate dirs),VideoRecordingOptionsTests(range boundaries incl. the 30-vs-60 FPS stream/record split),VideoFrameProcessingTests(decode/dimension math, the byte-for-byte pass-through fast path, quality/scale re-encode — the scale path renders viaNSImage.lockFocusat the host's backing scale factor, so tests pin re-encode + aspect ratio rather than absolute pixels),ProcessControlTests(OnceFlag single-winner race, cancellableSleep early wake).Verification
make test: 1252 green (was 1222), zero warnings.emulator-5554(bridge installed viaandroid init).scripts/test-runner.sh/scripts/test-runner-android.shsomake e2e-ios/make e2e-androidpick them up.🤖 Generated with Claude Code