From f245917570e47c9b2f9398291d27cf610b5012c7 Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 3 Sep 2026 11:50:20 -0600 Subject: [PATCH] qemu: drive scripted UI scenarios ui-shot.sh proves touch reaches the UI in one tap. Verifying a UI change needs a SEQUENCE -- swipe through the app rows, open a submenu, tap a tab, bring up the keyboard -- and booting per step costs about a minute under TCG, so: - qmp.py gains a `drive` mode: one connection, one boot, a script of tap/swipe/fling/shot/sleep steps in PANEL PIXELS rather than the raw 0..32767 tablet axis. Swipes interpolate their motion, because LVGL decides a gesture from the movement between indev polls and a press-then-release with nothing in between is a click, not a scroll. - ui-drive.sh runs such a script against a booted VM and collects the screenshots. It also FAILS on a UI that died mid-script. warden-ui crashing leaves its last frame in the framebuffer, so screendumps keep returning a plausible picture of a program that no longer exists; stage-2 init now announces the exit and its status on the console, and ui-drive.sh greps for that after the run. This is what caught the SIGSEGV behind flare-edge#125. Stage-2 init also mounts devpts. The UI's Terminal page opens a PTY, so without it that page could only ever report "no PTY available" -- it rendered, which made a screenshot scenario look fine while the one thing the page does was untestable. tests/scripts/nav-stress.txt is the first committed drive script: the navigation sequence that reproduces flare-edge#125. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn --- qemu/README.md | 1 + qemu/rootfs/sbin/init | 22 ++++- qemu/tests/qmp.py | 136 ++++++++++++++++++++++++++---- qemu/tests/scripts/nav-stress.txt | 55 ++++++++++++ qemu/tests/ui-drive.sh | 132 +++++++++++++++++++++++++++++ 5 files changed, 330 insertions(+), 16 deletions(-) create mode 100644 qemu/tests/scripts/nav-stress.txt create mode 100755 qemu/tests/ui-drive.sh diff --git a/qemu/README.md b/qemu/README.md index 8b7810a..23607bf 100644 --- a/qemu/README.md +++ b/qemu/README.md @@ -68,6 +68,7 @@ All take the virt-fragment ``; `FLARE_EDGE=` where noted. | `portal-scenario.sh` | `FLARE_EDGE` | real flared against the desk mock portal: authenticated check-in, desired-state pull, signed tier-1 `.wfw` download; verify/stage/APPLYING as a dry run (no `WARDEN_FW_ALLOW_APPLY`) | | `ota-apply.sh` | `FLARE_EDGE` | the FULL apply: the `.wfw`'s bootable rootfs payload is written to rootfs_b (`run.sh --allow-apply` gates it per boot), the AvbABData in `misc` flips, and slot `_b` boots the applied version | | `ui-shot.sh` | - | display+touch, headless: QMP-screendumps the 720x720 UI, taps the Metrics tab via `input-send-event`, asserts the frame changed (`qmp.py` is the QMP client) | +| `ui-drive.sh