#!/usr/bin/env bash # Scheme-on-SX test runner — runs all tests in one sx_server process. # # Usage: # bash lib/scheme/test.sh # run all suites # bash lib/scheme/test.sh -v # verbose (list each suite) set -uo pipefail cd "$(git rev-parse --show-toplevel)" SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}" if [ ! -x "$SX_SERVER" ]; then SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe" fi if [ ! -x "$SX_SERVER" ]; then echo "ERROR: sx_server.exe not found." >&2 exit 1 fi VERBOSE="${1:-}" # Suites: NAME RUNNER-FN PATH SUITES=( "parse scm-tests-run! lib/scheme/tests/parse.sx" "eval scm-eval-tests-run! lib/scheme/tests/eval.sx" "syntax scm-syn-tests-run! lib/scheme/tests/syntax.sx" "runtime scm-rt-tests-run! lib/scheme/tests/runtime.sx" "control scm-ctl-tests-run! lib/scheme/tests/control.sx" "macros scm-mac-tests-run! lib/scheme/tests/macros.sx" "reflection scm-ref-tests-run! lib/scheme/tests/reflection.sx" "records scm-rec-tests-run! lib/scheme/tests/records.sx" "modules scm-mod-tests-run! lib/scheme/tests/modules.sx" ) TMPFILE=$(mktemp); trap "rm -f $TMPFILE" EXIT EPOCH=1 emit_load () { echo "(epoch $EPOCH)"; echo "(load \"$1\")"; EPOCH=$((EPOCH+1)); } emit_eval () { echo "(epoch $EPOCH)"; echo "(eval \"$1\")"; EPOCH=$((EPOCH+1)); } { emit_load "lib/guest/lex.sx" emit_load "lib/guest/reflective/env.sx" emit_load "lib/guest/reflective/quoting.sx" emit_load "lib/scheme/parser.sx" emit_load "lib/scheme/eval.sx" emit_load "lib/scheme/runtime.sx" for SUITE in "${SUITES[@]}"; do read -r _NAME _RUNNER FILE <<< "$SUITE" emit_load "$FILE" emit_eval "($_RUNNER)" done } > "$TMPFILE" OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>&1 || true) # Final 9 outputs are the suite results. Parse each "{:passed N :failed N ..}". TOTAL_PASS=0 TOTAL_FAIL=0 FAILED_SUITES=() # Walk the output; for each suite, extract the {:passed ...} line. # The dict format from sx_server is {:passed N :failed N :total N :fails (...)}. LAST_DICT_LINES=$(echo "$OUTPUT" | grep -E '^\{:' || true) I=0 while read -r LINE; do [ -z "$LINE" ] && continue P=$(echo "$LINE" | grep -oE ':passed [0-9]+' | awk '{print $2}') F=$(echo "$LINE" | grep -oE ':failed [0-9]+' | awk '{print $2}') [ -z "$P" ] && P=0 [ -z "$F" ] && F=0 SUITE_INFO="${SUITES[$I]}" SUITE_NAME=$(echo "$SUITE_INFO" | awk '{print $1}') TOTAL_PASS=$((TOTAL_PASS + P)) TOTAL_FAIL=$((TOTAL_FAIL + F)) if [ "$F" -gt 0 ]; then FAILED_SUITES+=("$SUITE_NAME: $P/$((P+F))") printf 'X %-12s %d/%d\n' "$SUITE_NAME" "$P" "$((P+F))" elif [ "$VERBOSE" = "-v" ]; then printf 'ok %-12s %d passed\n' "$SUITE_NAME" "$P" fi I=$((I+1)) done <<< "$LAST_DICT_LINES" TOTAL=$((TOTAL_PASS + TOTAL_FAIL)) if [ $TOTAL_FAIL -eq 0 ]; then echo "ok $TOTAL_PASS/$TOTAL scheme-on-sx tests passed (${#SUITES[@]} suites)" else echo "FAIL $TOTAL_PASS/$TOTAL passed, $TOTAL_FAIL failed:" for S in "${FAILED_SUITES[@]}"; do echo " $S"; done exit 1 fi