joeylib2/scripts/verify-amiga-input.sh

120 lines
4.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# verify-amiga-input.sh - Typed-character acceptance gate for the Amiga
# port. Boots the Keys example off a directory hard drive in FS-UAE
# under Xvfb, types the RetroNet definition-of-done string with xdotool
# (real X key events, so ':' goes through the emulated shift and
# keymap.library's MapRawKey), then presses Escape. On exit Keys logs
# its full received-character history as hex to joeylog.txt on the boot
# volume -- which is the staged host directory -- and the harness
# compares that against the typed ASCII.
#
# Usage: scripts/verify-amiga-input.sh
# Requires: fs-uae, Xvfb, xdotool; build/amiga/bin/Keys (make amiga);
# toolchains/emulators/support/kickstart.rom.
set -euo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
bin_dir=$repo/build/amiga/bin
kickstart=$repo/toolchains/emulators/support/kickstart.rom
target="192.168.1.10:6510"
[ -f "$bin_dir/Keys" ] || { echo "verify-amiga-input: build Keys first (make amiga)" >&2; exit 2; }
[ -f "$kickstart" ] || { echo "verify-amiga-input: missing $kickstart" >&2; exit 2; }
work=$(mktemp -d -t joeylib-amiga-input.XXXXXX)
display_num=$((RANDOM % 500 + 300))
cleanup() {
[ -n "${fsuae_pid:-}" ] && kill "$fsuae_pid" 2>/dev/null
[ -n "${xvfb_pid:-}" ] && kill "$xvfb_pid" 2>/dev/null
rm -rf "$work"
}
trap cleanup EXIT
mkdir -p "$work/hd/s"
cp "$bin_dir/Keys" "$work/hd/"
echo ":Keys" > "$work/hd/s/startup-sequence"
Xvfb ":$display_num" -screen 0 1024x768x24 >/dev/null 2>&1 &
xvfb_pid=$!
sleep 1
# --fullscreen=1 is REQUIRED under a WM-less Xvfb: SDL only accepts
# keyboard input once its window has input focus, no window manager
# ever grants it to a plain window, and xdotool's windowfocus/
# XSendEvent routes are ignored by SDL. A fullscreen SDL window takes
# focus itself, after which plain XTEST typing (xdotool without
# --window) lands in the emulated Amiga.
DISPLAY=":$display_num" fs-uae \
--amiga_model=A500 \
--fast_memory=2048 \
--kickstart_file="$kickstart" \
--hard_drive_0="$work/hd" \
--hard_drive_0_label=JOEYLIB \
--fullscreen=1 \
--initial_input_grab=1 \
--floppy_drive_speed=800 \
>/dev/null 2>&1 &
fsuae_pid=$!
# Boot AmigaDOS off the directory HD and let startup-sequence launch
# Keys. No sentinel channel here, so give it a generous fixed wait.
sleep 28
# XTEST keyboard events land in whatever window HAS focus, and under
# a WM-less Xvfb the fullscreen SDL window latches it on its own
# schedule -- so wait until getwindowfocus actually reports the FS-UAE
# window before typing, nudging with windowfocus while waiting.
win=$(DISPLAY=":$display_num" xdotool search --name -- "FS-UAE" | head -1)
for i in $(seq 1 30); do
focus=$(DISPLAY=":$display_num" xdotool getwindowfocus 2>/dev/null || true)
[ -n "$win" ] && [ "$focus" = "$win" ] && break
[ -n "$win" ] && DISPLAY=":$display_num" xdotool windowfocus --sync "$win" 2>/dev/null || true
sleep 1
[ -z "$win" ] && win=$(DISPLAY=":$display_num" xdotool search --name -- "FS-UAE" | head -1)
done
# Up to three attempts: type, press Escape, then look for the typed=
# line Keys logs on exit. The verdict compares the history's SUFFIX
# against the target, so a partially-delivered early attempt can't
# poison a complete later one -- the proof is that the final 17
# characters arrived in order through the queue.
log="$work/hd/joeylog.txt"
delivered=""
for attempt in 1 2 3; do
DISPLAY=":$display_num" xdotool type --delay 200 -- "$target"
sleep 2
# Hold Escape across several emulated frames: an instantaneous
# down+up can land inside ONE drainMessages pass, where set-then-
# clear in the same poll is invisible to the edge predicate.
DISPLAY=":$display_num" xdotool keydown Escape
sleep 0.5
DISPLAY=":$display_num" xdotool keyup Escape
for i in $(seq 1 10); do
if [ -f "$log" ] && grep -q "typed=" "$log"; then
delivered=1
break 2
fi
sleep 1
done
done
if [ -z "$delivered" ]; then
echo "verify-amiga-input: FAIL - no typed= line in joeylog.txt (keystrokes never landed?)" >&2
ls -la "$work/hd" >&2
exit 1
fi
typedHex=$(grep -o "typed=[0-9A-Fa-f]*" "$log" | tail -1 | cut -d= -f2)
expect=$(printf '%s' "$target" | od -A n -t x1 | tr -d ' \n' | tr 'a-f' 'A-F')
echo "VERIFY-AMIGA-INPUT typed=$typedHex"
case "$typedHex" in
*"$expect")
echo "verify-amiga-input: PASS (typed \"$target\", all ${#target} chars arrived via jlInputGetChar)"
;;
*)
echo "verify-amiga-input: FAIL" >&2
echo " expected suffix: $expect" >&2
echo " got: $typedHex" >&2
exit 1
;;
esac