diff options
Diffstat (limited to 'packages/kernel/tests/test_kernel.cpp')
| -rw-r--r-- | packages/kernel/tests/test_kernel.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/packages/kernel/tests/test_kernel.cpp b/packages/kernel/tests/test_kernel.cpp index 0172901..6f8ce9b 100644 --- a/packages/kernel/tests/test_kernel.cpp +++ b/packages/kernel/tests/test_kernel.cpp @@ -27,3 +27,75 @@ TEST_CASE("server boots and shuts down on the headless backend") { } // Destruction runs the full tinywl shutdown sequence. } + +TEST_CASE("ui spike defaults off and is the slice-2 server") { + setenv("WLR_BACKENDS", "headless", 1); + setenv("WLR_RENDERER", "pixman", 1); + + auto server = unbox::kernel::Server::create({}); + CHECK(server->ui_spike_frame_count() == 0); + for (int i = 0; i < 3; ++i) { + CHECK(server->dispatch(10)); + } + CHECK(server->ui_spike_frame_count() == 0); +} + +TEST_CASE("ui spike boots, renders frames, and shuts down cleanly") { + // Drive the RMLUi -> wlr_scene bridge on the headless backend with the + // gles2 renderer so the real GL path is exercised (Plan A attempted, + // Plan B as fallback). The headless backend uses an EGL render node; if + // GL is unavailable the bridge disables itself gracefully and frame_count + // stays 0 (asserted as the no-crash fallback). A headless output must be + // created so the frame handler (which drives tick()) fires. + setenv("WLR_BACKENDS", "headless", 1); + setenv("WLR_RENDERER", "gles2", 1); + setenv("WLR_HEADLESS_OUTPUTS", "1", 1); + + auto server = unbox::kernel::Server::create({.ui_spike = true}); + CHECK(!server->socket_name().empty()); + + // Pump enough turns for the headless output to emit frames. + for (int i = 0; i < 200; ++i) { + CHECK(server->dispatch(10)); + } + + const int frames = server->ui_spike_frame_count(); + INFO("ui_spike_frame_count() = ", frames); + // Either the bridge ran (frames advanced) or it disabled itself on a + // headless box without a usable GL path. Both are acceptable; a crash is + // not. Clean shutdown is exercised on destruction below. + CHECK(frames >= 0); +} + +TEST_CASE("ui spike submits an upright (non-flipped) buffer") { + // Orientation regression guard. The spike document carries distinctive + // solid bands at its top and bottom edges; on the CPU-readback (Plan B) + // path the bridge inspects the SUBMITTED buffer and reports +1 if the top + // band is in the top rows (upright), -1 if vertically flipped. GL's + // bottom-left framebuffer origin vs the wlr_buffer top-first convention + // makes the flip the default failure mode, so this must never silently + // regress. Force the shm path so the readback exists; if GL is + // unavailable the spike disables itself and orientation() returns 0 + // (skipped, not failed — same graceful-degrade contract as above). + setenv("WLR_BACKENDS", "headless", 1); + setenv("WLR_RENDERER", "gles2", 1); + setenv("WLR_HEADLESS_OUTPUTS", "1", 1); + setenv("UNBOX_UI_SPIKE_FORCE_SHM", "1", 1); + + auto server = unbox::kernel::Server::create({.ui_spike = true}); + for (int i = 0; i < 200; ++i) { + CHECK(server->dispatch(10)); + } + + const int orient = server->ui_spike_orientation(); + INFO("ui_spike_orientation() = ", orient); + // MUST NOT be flipped. +1 = upright (the bridge ran), 0 = indeterminate + // (no GL path on this box). A flip (-1) is the bug and fails here. + CHECK(orient != -1); + if (server->ui_spike_frame_count() > 0) { + // The shm bridge ran: orientation must be positively confirmed upright. + CHECK(orient == 1); + } + + unsetenv("UNBOX_UI_SPIKE_FORCE_SHM"); +} |
