High-performance Testing Pyramid for Tier 1. We are going to test it exactly like a AAA game engine.
The biggest mistake web-assembly developers make is only compiling to .wasm.
Tier 1 is standard C++17. You must configure your CMakeLists.txt to compile Tier 1 as a native desktop executable (macOS/Linux/Windows) for testing.
When you run tests, you run a native C++ binary. It executes in milliseconds. No V8 engine, no Emscripten, no browser.
Tool: Catch2 or GoogleTest (Native C++) Speed: 10,000 tests per second.
You test the logic of the engine without drawing a single pixel. You allocate the memory_pool, feed it a fake Command Buffer array, and assert the state.
What to test:
[CMD_SET_BOUNDS, 42, 10, 10, 100, 100]. Assert that memory_pool[42].x == 10.ed_hit_test(15, 15).CMD_COMMIT_SCENE with OP_PUSH_CLIP and OP_POP. Assert that the internal C++ display list matches the expected hierarchy.Handle = 9999999 (out of bounds). Assert that the engine ignores it and doesn’t segfault.Tool: Catch2 + Skia CPU Rasterizer (Native C++) Speed: 100 tests per second.
How do you test that CMD_SET_LINEAR_GRADIENT actually draws a gradient, without using Playwright?
You use Skia’s CPU Backend. Skia does not require WebGPU or a monitor to draw. It can draw directly into a block of system RAM.
The Test Lifecycle:
SkSurface::MakeRasterN32Premul(800, 600). (This creates a headless, CPU-only canvas).ed_render_frame(current_time_ms), passing the current frame timestamp while rendering into the CPU canvas instead of the WebGPU canvas.surface->makeImageSnapshot()->encodeToData()..png and do a pixel-diff against a “Golden Image” stored in your repo.Verdict: This replaces 90% of your Playwright tests. You are testing the exact Skia drawing code that will run in the browser, but you are doing it natively in C++ in milliseconds.
Tool: libFuzzer or AFL++ (Native C++) Speed: Millions of iterations per minute.
Because Tier 1 accepts a raw u32 array from the JS Bridge, it is vulnerable to malicious or corrupted data. If Tier 2 has a bug and sends a malformed Command Buffer, Tier 1 must not crash.
You write a Fuzzer that feeds completely random garbage bytes into ed_execute_command_buffer(). You let it run on a CI server for an hour. If Tier 1 segfaults, you fix the bounds-checking. If it survives, your Kernel is bulletproof.
Tool: Playwright + Headless Chromium Speed: ~2-5 seconds per test.
You only use Playwright to test the things that cannot be tested natively in C++. You keep these to an absolute minimum (maybe 5 to 10 tests total).
What to test:
GPUAdapter and boot the WASM module without throwing a JS error?ed_create_node(), does it return a valid Handle?page.screenshot() to ensure the WebGPU canvas actually displays pixels in the browser.page.mouse.click(). Assert that the JS Bridge catches it and successfully routes it to the WASM module.If you rely on Playwright to test if a button is red, you will hate working on this project.
By leveraging the fact that Tier 1 is just a C++ library:
This is exactly how Google tests Chrome (Blink/Skia) and how Epic Games tests Unreal Engine. You build the engine natively, test it natively, and treat the browser as just another “compile target.”