Skip to content

chore(🐙): unit test the surface registry and the frame rate vote's cadence on the host - #550

Open
YevheniiKotyrlo wants to merge 3 commits into
wcandillon:mainfrom
YevheniiKotyrlo:test/native-unit-tiers
Open

YevheniiKotyrlo wants to merge 3 commits into
wcandillon:mainfrom
YevheniiKotyrlo:test/native-unit-tiers

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Most Android bugs land in two places: the surface registry, which carries a canvas's frames across attach, detach, resize and present, and the native code that tells a SurfaceView canvas it animates, for its refresh rate vote. Neither has a unit test, so the e2e suite on a device is the only check on them. This adds a host unit tier for both, run by the CI job that builds that code.

The surface registry

packages/webgpu/tests/cpp compiles SurfaceRegistry.h for the host and links FakeWebGPU.cpp in place of Dawn: the WebGPU C functions the registry calls, which keep what each surface, device and queue was asked to do and record every call Dawn would reject, such as a present without an acquired texture. Every test ends with no rejected call and no leaked object.

The tests cover the frame lifecycle: a canvas renders offscreen until a surface attaches; an attached surface is adopted only at a frame boundary, including from the JS thread's flush while another thread renders; the frame rendered before a surface attaches is copied onto it and presented; a frame whose surface is destroyed mid-frame is dropped; an outdated surface is reconfigured once and a failed acquire falls back offscreen; reconfigure resizes the drawing buffer; a pending surface replaced before adoption, and every window the entry holds when it dies, are released exactly once. The registry tests cover find-or-create, the entry React's StrictMode retires while its context still holds it, and an entry whose view owns a surface.

The frame rate vote's cadence

AnimationReporter's timing rule moves unchanged into android/cpp/AnimationCadence.h: a frame presented within 25 ms of its predecessor is an animation frame, the first of an animation is reported once, and releaseIfIdle re-arms the report once no animation frame came for the idle time Java asks about. It takes the time as an argument where AnimationReporter read the clock, so the tests drive it with fixed times; AnimationReporter keeps the clock and the call into Java.

yarn test:cpp configures both with CMake (GoogleTest 1.18.0 from its release tarball, Dawn's headers from react-native-webgpu-dawn), builds them into node_modules/.cache/cpp-tests and runs them with ctest. The Android job runs it before the Gradle build. The hardware-buffer pool and the Metal scheduling wait stay with the e2e suite.

Verification

  • yarn test:cpp on Ubuntu 24.04 (g++ 13.3, CMake 3.28): 26 passed. Breaking SurfaceRegistry.h at any of nine single places, or AnimationCadence.h at any of six, fails at least one test.
  • yarn lint · yarn tsc · yarn turbo run build --filter='./packages/*' · the Expo template's web build · yarn test:plugin · yarn check-dawn · yarn build:docs, the package's cpplint command, and the example's Android build.
  • CI's Android e2e step (debug build, Metro with CI=true) on an Android 15 emulator: 219 of 221, as on main; the two failures, the YUV cases of ExternalTextureColorSpace and NativeBufferWrapper, fail on main there too.

Not run here: the workflow itself, which runs on this PR.

@YevheniiKotyrlo

YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

yarn test:cpp on Ubuntu 24.04 (g++ 13.3, CMake 3.28), from a clean build directory, on main 46f42a6b:

100% tests passed, 0 tests failed out of 26

Each test was also run against a deliberately broken registry or cadence: every one of nine single-place breaks of SurfaceRegistry.h, and of six of AnimationCadence.h, fails at least one test.

…dence on the host

SurfaceRegistry.h and AnimationReporter had no unit tests: CI built them
and the e2e suite on a device was the only check. tests/cpp compiles the
registry for the host against FakeWebGPU.cpp, a stand-in for the WebGPU C
functions it calls that records every call Dawn would reject, and
`yarn test:cpp` builds and runs it with CMake and GoogleTest.
AnimationReporter's timing rule moves unchanged into AnimationCadence,
which takes the time as an argument, so the same tests drive it. The
Android CI job runs them before the Gradle build.
@YevheniiKotyrlo YevheniiKotyrlo changed the title chore(🐙): unit test the surface registry on the host and the Android library on the JVM chore(🐙): unit test the surface registry and the frame rate vote's cadence on the host Oct 16, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant