#!/usr/bin/env bash # # scripts/tests/test-mouse.sh — automated PS/2 mouse round-trip test. # # Boots QEMU headless, injects mouse movement via the QEMU monitor, # verifies the on-screen cursor tracks it, and tests the mouse stream # routing command. # # Usage: ./scripts/tests/test-mouse.sh # Env: SYSTEM_IMG, OVMF, QEMU (see scripts/lib.sh) # set -euo pipefail TNAME="mouse" # shellcheck source=../lib.sh source "$(dirname "$0")/../lib.sh" # cursor_state — one-shot `cursor` command, parsed to "x y buttons". cursor_state() { sendkeys "cursor" sleep 0.5 sed -n 's/.*cursor: x=\([0-9]*\) y=\([0-9]*\) buttons=\([A-Za-z-]*\).*/\1 \2 \3/p' "$LOG" | tail -1 } echo "==> 1/6 build (kernel + bins)" build_all echo "==> 2/6 stage system image" stage_image --force echo "==> 3/6 boot QEMU (headless)" test_boot grep -aq "ps2: mouse ready" "$LOG" || fail "mouse driver did not come up at boot" wait_log "$LOG" "cursor: task " 10 || fail "cursor task did not spawn" echo "==> 4/6 cursor position tracks injected movement" INIT=$(cursor_state) [ -n "$INIT" ] || fail "no initial cursor position" IX=$(echo "$INIT" | awk '{print $1}') IY=$(echo "$INIT" | awk '{print $2}') IB=$(echo "$INIT" | awk '{print $3}') echo " initial: x=$IX y=$IY buttons=$IB" [ "$IB" = "---" ] || fail "expected no buttons at boot, got $IB" qemu_hmp "mouse_move 20 7" S1=$(cursor_state) X1=$(echo "$S1" | awk '{print $1}') Y1=$(echo "$S1" | awk '{print $2}') [ "$X1" -eq $((IX + 20)) ] || fail "x did not move +20 (was $IX, now $X1)" [ "$Y1" -eq $((IY + 7)) ] || fail "y did not move +7 (was $IY, now $Y1)" echo " moved: x=$X1 y=$Y1 (delta +20,+7)" echo "==> 5/6 left button edge detection" qemu_hmp "mouse_button 1" S2=$(cursor_state) IB2=$(echo "$S2" | awk '{print $3}') [ "$IB2" = "L--" ] || fail "expected L--, got $IB2" qemu_hmp "mouse_button 0" S3=$(cursor_state) IB3=$(echo "$S3" | awk '{print $3}') [ "$IB3" = "---" ] || fail "expected --- after release, got $IB3" echo " button: $IB2 → $IB3" echo "==> 6/6 mouse stream routing to msgrecv's task" # The spawned task id shifts with the task table (wm-input took slot 3) — # parse it rather than hardcoding. sendkeys "msgrecv" sleep 1 MID="$(sed -n 's/.*msgrecv: task \([0-9][0-9]*\) listening.*/\1/p' "$LOG" | tail -1)" [ -n "$MID" ] || fail "msgrecv did not spawn" echo " msgrecv task id: $MID" sendkeys "mouse $MID" qemu_hmp "mouse_move 20 7" qemu_hmp "mouse_button 1" sleep 0.5 qemu_hmp "mouse_button 0" sleep 0.5 sendkeys "ctrl-c" sleep 0.5 grep -aq "Mouse(+20,+7" "$LOG" || fail "routed mouse move not logged" echo "" echo "PASS — mouse round trip"