#!/usr/bin/env bash # Erlang-on-SX conformance runner. # # Loads every erlang test suite via the epoch protocol, collects # pass/fail counts, and writes lib/erlang/scoreboard.json + .md. # # Usage: # bash lib/erlang/conformance.sh # run all suites # bash lib/erlang/conformance.sh -v # verbose per-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:-}" TMPFILE=$(mktemp) OUTFILE=$(mktemp) trap "rm -f $TMPFILE $OUTFILE" EXIT # Each suite: name | counter pass | counter total SUITES=( "tokenize|er-test-pass|er-test-count" "parse|er-parse-test-pass|er-parse-test-count" "eval|er-eval-test-pass|er-eval-test-count" "runtime|er-rt-test-pass|er-rt-test-count" "ring|er-ring-test-pass|er-ring-test-count" "ping-pong|er-pp-test-pass|er-pp-test-count" "bank|er-bank-test-pass|er-bank-test-count" "echo|er-echo-test-pass|er-echo-test-count" "fib|er-fib-test-pass|er-fib-test-count" ) cat > "$TMPFILE" << 'EPOCHS' (epoch 1) (load "lib/erlang/tokenizer.sx") (load "lib/erlang/parser.sx") (load "lib/erlang/parser-core.sx") (load "lib/erlang/parser-expr.sx") (load "lib/erlang/parser-module.sx") (load "lib/erlang/transpile.sx") (load "lib/erlang/runtime.sx") (load "lib/erlang/tests/tokenize.sx") (load "lib/erlang/tests/parse.sx") (load "lib/erlang/tests/eval.sx") (load "lib/erlang/tests/runtime.sx") (load "lib/erlang/tests/programs/ring.sx") (load "lib/erlang/tests/programs/ping_pong.sx") (load "lib/erlang/tests/programs/bank.sx") (load "lib/erlang/tests/programs/echo.sx") (load "lib/erlang/tests/programs/fib_server.sx") (epoch 100) (eval "(list er-test-pass er-test-count)") (epoch 101) (eval "(list er-parse-test-pass er-parse-test-count)") (epoch 102) (eval "(list er-eval-test-pass er-eval-test-count)") (epoch 103) (eval "(list er-rt-test-pass er-rt-test-count)") (epoch 104) (eval "(list er-ring-test-pass er-ring-test-count)") (epoch 105) (eval "(list er-pp-test-pass er-pp-test-count)") (epoch 106) (eval "(list er-bank-test-pass er-bank-test-count)") (epoch 107) (eval "(list er-echo-test-pass er-echo-test-count)") (epoch 108) (eval "(list er-fib-test-pass er-fib-test-count)") EPOCHS timeout 120 "$SX_SERVER" < "$TMPFILE" > "$OUTFILE" 2>&1 # Parse "(N M)" from the line after each "(ok-len ...)" marker. parse_pair() { local epoch="$1" local line line=$(grep -A1 "^(ok-len $epoch " "$OUTFILE" | tail -1) echo "$line" | sed -E 's/[()]//g' } TOTAL_PASS=0 TOTAL_COUNT=0 JSON_SUITES="" MD_ROWS="" idx=0 for entry in "${SUITES[@]}"; do name="${entry%%|*}" epoch=$((100 + idx)) pair=$(parse_pair "$epoch") pass=$(echo "$pair" | awk '{print $1}') count=$(echo "$pair" | awk '{print $2}') if [ -z "$pass" ] || [ -z "$count" ]; then pass=0 count=0 fi TOTAL_PASS=$((TOTAL_PASS + pass)) TOTAL_COUNT=$((TOTAL_COUNT + count)) status="ok" marker="✅" if [ "$pass" != "$count" ]; then status="fail" marker="❌" fi if [ "$VERBOSE" = "-v" ]; then printf " %-12s %s/%s\n" "$name" "$pass" "$count" fi if [ -n "$JSON_SUITES" ]; then JSON_SUITES+=","; fi JSON_SUITES+=$'\n ' JSON_SUITES+="{\"name\":\"$name\",\"pass\":$pass,\"total\":$count,\"status\":\"$status\"}" MD_ROWS+="| $marker | $name | $pass | $count |"$'\n' idx=$((idx + 1)) done printf '\nErlang-on-SX conformance: %d / %d\n' "$TOTAL_PASS" "$TOTAL_COUNT" # scoreboard.json cat > lib/erlang/scoreboard.json < lib/erlang/scoreboard.md <