joeylib2/scripts/verify-all.sh

266 lines
12 KiB
Bash
Executable file

#!/usr/bin/env bash
# verify-all.sh - Run JoeyLib's gates, one kind or all of them, and summarise.
#
# Driven by `make verify` (all), `make verify-audio` and `make verify-serial`.
#
# Kinds, in the order `all` runs them:
# host the shared layer on the host, no emulator: the new-port
# template (blank), file roots, the dirty-band marker, input,
# millis, save, serial, sfxmix, tilebank
# golden UBER on each port, its 51 per-op surface hashes against
# tests/goldens/uber (x68000 against the IIgs's, its own gate;
# dvx against the DOS port's, whose stage it shows)
# atarist: also the dirty-band marker the three 68000 ports share
# (src/m68k/stageBands.s), held to the per-row widen under Hatari
# visual iigs: every launchable example on joey.2mg boots and draws
# dvx: full screen -- UBER's hashes through a suspend and a
# resume, and KEYS's row read off the 320x200 VGA screen, then
# in its window, then on the whole screen again
# dvx: also the display -- UBER's probe build on nine desktop
# depths and scales and the full screen, every displayed pixel
# checked against the stage
# x68000: the SCB -- every text-palette reload of a 147-change
# screen lands in the blanking before its band, timed on the beam
# tilebank each port: examples/tilebank loads the port's own .tbk bake
# of the host fixture both ways, pixel-exact and with the host
# gate's surface hash, and refuses every other target's bake (the
# host half is check-tilebank.sh under `host`)
# input each port: a typed string reaches jlInputGetChar byte-exact
# (dvx: and the present shows it, decoded from the desktop, also
# at 8/15/32 bpp and 2x/3x; Ctrl+Esc must not end the program)
# x68000 and dvx: also both joysticks -- every direction, both
# buttons and every release, read back from examples/joy's display
# audio six gates, two kinds (the IIgs and X68000 on AUDIOPRB, AUDIO
# pressing its own keys; the rest drive AUDIO's keys):
# iigs DOC wavetable + sound IRQ vector (register tap)
# x68000 YM2151 noise + PPI port C + ADPCM rate (register tap)
# atarist YM2149 write trace, with the pc (register tap)
# amiga recorded sound, four loudness phases (Paula has no tap)
# dos recorded sound, four loudness phases (SB has no tap)
# dvx recorded sound, four loudness phases (DVX's mixer, SB)
# serial the host check of the shared layer, then each port's loopback
# (banner out, probe echoed back):
# host scripts/check-serial.sh (no emulator)
# iigs SCC modem port -> MAME null_modem
# x68000 SCC channel A -> MAME null_modem
# atarist Modem port -> Hatari pty
# amiga serial.device -> FS-UAE TCP
# dos COM1 -> DOSBox nullmodem
# dvx COM1 through DVX's rs232 library -> DOSBox nullmodem
# mouse x68000: deltas, clamps and buttons through the IOCS mouse
# (and with serial streaming both ways on the same SCC)
# save iigs: a SAVES/ blob written and read back through GS/OS
# loss iigs: 4096 bytes through full-screen presents, lossless on the
# modem port at 9600 and a Super Serial Card at 2400
# x68000: both serial streams byte-exact and the mouse right while
# the SCB changes palette on every line of a run (9600, 19200, 38400)
# disk iigs: a one-program boot volume (DRAW's) boots, launches the
# program and draws: as a 2048KB volume off a CFFA2 card, then as
# an 800KB floppy on ROM 3 and on ROM 01
#
# `all` first BUILDS every selected port (make <port>, and iigs-disk plus the
# loss probes and game disks for the IIgs), stopping on a build failure, then
# runs every kind. A gate for a port that was not selected is left out.
#
# SEQUENTIAL, deliberately. The recording audio gates drive the emulator on
# wall-clock sleeps and grade fixed time windows of the capture, so a
# second emulator competing for CPU can slide a phase boundary and fail a
# gate that is actually fine. Running several emulators at once also makes
# the timing-sensitive register gates noisier.
#
# Exit codes, distinguishing "it works" from "it did not run":
# 0 every selected gate PASSED
# 1 at least one gate FAILED (a real defect), or an `all` build failed
# 3 no failures, but at least one gate SKIPPED for a missing
# prerequisite -- an unbuilt port or absent emulator. Non-zero on
# purpose: a run that quietly tested nothing must not look green.
# A gate reached through make cannot tell a skip from a failure (make
# exits 2 for both), so those count as failures; `all` builds their
# prerequisites first, so a missing one is a real problem anyway.
#
# Each gate already reports its own evidence line; this only adds the
# roll-up. Gate stdout/stderr is echoed as it happens, so a failure shows
# its diagnosis here and not just a verdict.
#
# Usage: scripts/verify-all.sh KIND|all [port ...]
# with no ports, every port the kind has. Ports: host iigs
# x68000 atarist amiga dos dvx
# Env: VERIFY_ALL_LOG also append the full transcript to this file
# Requires: whatever each selected gate requires; missing ones SKIP.
set -uo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
kind=${1:-}
shift || true
label="verify-all $kind"
KINDS="host golden visual tilebank input audio serial mouse save loss disk"
ALL_PORTS="host iigs x68000 atarist amiga dos dvx"
# UBER on the Amiga needs longer than bench-amiga.sh's interactive default.
AMIGA_UBER_SECONDS=400
# kind port name command...: every gate, in run order within its kind.
GATES=$(cat <<EOF
host host blank scripts/check-blank.sh
host host roots scripts/check-fileroots.sh
host host marks scripts/check-dirtymark.sh
host host input scripts/check-input.sh
host host millis scripts/check-millis.sh
host host save scripts/check-save.sh
host host serial scripts/check-serial.sh
host host sfxmix scripts/check-sfxmix.sh
host host tilebank scripts/check-tilebank.sh
golden iigs uber scripts/bench-iigs.sh && tools/diff-uber-hashes tests/goldens/uber/iigs.txt build/iigs/bin/joeylog.txt
golden x68000 uber scripts/verify-x68000-golden.sh
golden atarist uber scripts/bench-atarist.sh && tools/diff-uber-hashes tests/goldens/uber/atarist.txt build/atarist/bin/joeylog.txt
golden atarist marks scripts/verify-atarist-dirtymark.sh
golden amiga uber TIMEOUT=$AMIGA_UBER_SECONDS scripts/bench-amiga.sh && tools/diff-uber-hashes tests/goldens/uber/amiga.txt build/amiga/bin/joeylog.txt
golden dos uber scripts/bench-dos.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/dos/bin/JOEYLOG.TXT
golden dvx uber scripts/bench-dvx.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/dvx/bin/joeylog.txt
visual iigs examples scripts/verify-iigs-all.sh
visual dvx full scripts/verify-dvx-fullscreen.sh
visual dvx display scripts/verify-dvx-display.sh
visual x68000 scb scripts/verify-x68000-scb.sh
tilebank iigs tilebank make -s -f make/iigs.mk iigs-verify-tilebank || exit 1
tilebank x68000 tilebank scripts/verify-x68000-tilebank.sh
tilebank atarist tilebank scripts/verify-atarist-tilebank.sh
tilebank amiga tilebank scripts/verify-amiga-tilebank.sh
tilebank dos tilebank scripts/verify-dos-tilebank.sh
tilebank dvx tilebank scripts/verify-dvx-tilebank.sh
input iigs input scripts/verify-iigs-input.sh
input x68000 input scripts/verify-x68000-input.sh
input x68000 joy scripts/verify-x68000-joy.sh
input atarist input scripts/verify-atarist-input.sh
input amiga input scripts/verify-amiga-input.sh
input dos input scripts/verify-dos-input.sh
input dvx input scripts/verify-dvx-input.sh
input dvx depths scripts/verify-dvx-input.sh 640x480x8:1 800x600x15:2 1024x768x32:3
input dvx joy scripts/verify-dvx-joy.sh
audio iigs audio make -s -f make/iigs.mk iigs-verify-audio || exit 1
audio x68000 audio make -s -f make/x68000.mk x68000-verify-audio || exit 1
audio atarist audio scripts/verify-atarist-audio.sh
audio amiga audio scripts/verify-amiga-audio.sh
audio dos audio scripts/verify-dos-audio.sh
audio dvx audio scripts/verify-dvx-audio.sh
serial host serial scripts/check-serial.sh
serial iigs serial scripts/verify-iigs-serial.sh
serial x68000 serial scripts/verify-x68000-serial.sh
serial atarist serial scripts/verify-atarist-serial.sh
serial amiga serial scripts/verify-amiga-serial.sh
serial dos serial scripts/verify-dos-serial.sh
serial dvx serial scripts/verify-dvx-serial.sh
mouse x68000 mouse scripts/verify-x68000-mouse.sh
mouse x68000 sermouse scripts/verify-x68000-serial-mouse.sh
save iigs save make -s -f make/iigs.mk iigs-verify-save || exit 1
loss iigs loss make -s -f make/iigs.mk iigs-verify-serial-loss || exit 1
loss x68000 scb scripts/verify-x68000-serial-scb.sh
disk iigs cffa2 make -s -f make/iigs.mk iigs-verify-game-disk GAME=DRAW GAME_DISK_SIZE=2048KB || exit 1
disk iigs floppy make -s -f make/iigs.mk iigs-verify-game-disk GAME=DRAW || exit 1
disk iigs rom01 GAME_VERIFY_MACHINE=apple2gsr1 scripts/verify-iigs-game-disk.sh build/iigs/bin/DRAW.2mg
EOF
)
case " all $KINDS " in
*" $kind "*) ;;
*) echo "usage: scripts/verify-all.sh all|$(echo "$KINDS" | tr ' ' '|') [port ...]" >&2; exit 2 ;;
esac
if [ "$kind" = all ]; then
kinds=$KINDS
kindPorts=$ALL_PORTS
else
kinds=$kind
kindPorts=$(echo "$GATES" | awk -v k="$kind" '$1 == k { print $2 }' | awk '!seen[$0]++' | tr '\n' ' ')
fi
ports=${*:-$kindPorts}
for p in $ports; do
case " $kindPorts " in
*" $p "*) ;;
*) echo "$label: unknown port '$p' (choose from: $kindPorts)" >&2; exit 2 ;;
esac
done
# Echo a command's output as it happens, and into VERIFY_ALL_LOG if set;
# returns the command's exit code. stdin is /dev/null so no gate can read
# the rest of the gate list.
runLogged() {
if [ -n "${VERIFY_ALL_LOG:-}" ]; then
( cd "$repo" && bash -c "$1" ) < /dev/null 2>&1 | tee -a "$VERIFY_ALL_LOG"
return "${PIPESTATUS[0]}"
fi
( cd "$repo" && bash -c "$1" ) < /dev/null
}
# The build step of `all`: each selected port, then the IIgs extras its
# gates need (make iigs builds no examples; iigs-disk does).
buildPorts() {
local port
local cmd
for port in $ports; do
case $port in
host) continue ;;
iigs) cmd="make -f make/iigs.mk iigs-disk $repo/build/iigs/bin/SCCPROBE $repo/build/iigs/bin/SERLOSS $repo/build/iigs/bin/SERLOSSS" ;;
*) cmd="make $port" ;;
esac
echo
echo "=== $label: build $port ($cmd) ==="
if ! runLogged "$cmd"; then
echo "$label: FAIL - building $port failed" >&2
exit 1
fi
done
}
if [ "$kind" = all ]; then
buildPorts
fi
gateNames=()
gateVerdicts=()
gateSeconds=()
passed=0
failed=0
skipped=0
for k in $kinds; do
while read -r gKind gPort gName gCmd; do
[ "$gKind" = "$k" ] || continue
case " $ports " in *" $gPort "*) ;; *) continue ;; esac
echo
echo "=== $label: $gKind $gPort $gName ($gCmd) ==="
start=$SECONDS
runLogged "$gCmd"
rc=$?
case $rc in
0) verdict=PASS; passed=$((passed + 1)) ;;
2) verdict="SKIP (prerequisite missing)"; skipped=$((skipped + 1)) ;;
*) verdict=FAIL; failed=$((failed + 1)) ;;
esac
gateNames+=("$gKind $gPort $gName")
gateVerdicts+=("$verdict")
gateSeconds+=("$((SECONDS - start))")
done <<< "$GATES"
done
echo
echo "================ $label summary ================"
for i in "${!gateNames[@]}"; do
printf " %-26s %-28s %4ds\n" "${gateNames[$i]}" "${gateVerdicts[$i]}" "${gateSeconds[$i]}"
done
echo " ----"
printf " %d passed, %d failed, %d skipped\n" "$passed" "$failed" "$skipped"
if [ "$failed" -gt 0 ]; then
echo "$label: FAIL" >&2
exit 1
fi
if [ "$skipped" -gt 0 ]; then
echo "$label: INCOMPLETE - some gates skipped (build those ports, then re-run)" >&2
exit 3
fi
if [ "$passed" -eq 0 ]; then
echo "$label: nothing selected" >&2
exit 2
fi
echo "$label: PASS (all $passed gates)"
exit 0