#!/usr/bin/env bash # identity-on-sx conformance runner. # # Loads the Erlang-on-SX substrate, the identity library, and every # identity test suite via the epoch protocol, collects pass/fail counts, # and writes lib/identity/scoreboard.json + .md. # # Usage: # bash lib/identity/conformance.sh # run all suites # bash lib/identity/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=( "session|id-session-test-pass|id-session-test-count" "token|id-token-test-pass|id-token-test-count" "registry|id-registry-test-pass|id-registry-test-count" "api|id-api-test-pass|id-api-test-count" "oauth|id-oauth-test-pass|id-oauth-test-count" "sso|id-sso-test-pass|id-sso-test-count" "membership|id-membership-test-pass|id-membership-test-count" "cache|id-cache-test-pass|id-cache-test-count" "audit|id-audit-test-pass|id-audit-test-count" "federation|id-fed-test-pass|id-fed-test-count" "expiry|id-expiry-test-pass|id-expiry-test-count" "clients|id-clients-test-pass|id-clients-test-count" "grants|id-grants-test-pass|id-grants-test-count" "device|id-device-test-pass|id-device-test-count" "facade|id-facade-test-pass|id-facade-test-count" "delegation|id-deleg-test-pass|id-deleg-test-count" "session-mgmt|id-smgmt-test-pass|id-smgmt-test-count" "exchange|id-xchg-test-pass|id-xchg-test-count" "introspect|id-intr-test-pass|id-intr-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/identity/session.sx") (load "lib/identity/token.sx") (load "lib/identity/registry.sx") (load "lib/identity/api.sx") (load "lib/identity/oauth.sx") (load "lib/identity/membership.sx") (load "lib/identity/cache.sx") (load "lib/identity/audit.sx") (load "lib/identity/federation.sx") (load "lib/identity/clients.sx") (load "lib/identity/device.sx") (load "lib/identity/delegation.sx") (load "lib/identity/tests/session.sx") (load "lib/identity/tests/token.sx") (load "lib/identity/tests/registry.sx") (load "lib/identity/tests/api.sx") (load "lib/identity/tests/oauth.sx") (load "lib/identity/tests/sso.sx") (load "lib/identity/tests/membership.sx") (load "lib/identity/tests/cache.sx") (load "lib/identity/tests/audit.sx") (load "lib/identity/tests/federation.sx") (load "lib/identity/tests/expiry.sx") (load "lib/identity/tests/clients.sx") (load "lib/identity/tests/grants.sx") (load "lib/identity/tests/device.sx") (load "lib/identity/tests/facade.sx") (load "lib/identity/tests/delegation.sx") (load "lib/identity/tests/session_mgmt.sx") (load "lib/identity/tests/exchange.sx") (load "lib/identity/tests/introspect.sx") (epoch 100) (eval "(list id-session-test-pass id-session-test-count)") (epoch 101) (eval "(list id-token-test-pass id-token-test-count)") (epoch 102) (eval "(list id-registry-test-pass id-registry-test-count)") (epoch 103) (eval "(list id-api-test-pass id-api-test-count)") (epoch 104) (eval "(list id-oauth-test-pass id-oauth-test-count)") (epoch 105) (eval "(list id-sso-test-pass id-sso-test-count)") (epoch 106) (eval "(list id-membership-test-pass id-membership-test-count)") (epoch 107) (eval "(list id-cache-test-pass id-cache-test-count)") (epoch 108) (eval "(list id-audit-test-pass id-audit-test-count)") (epoch 109) (eval "(list id-fed-test-pass id-fed-test-count)") (epoch 110) (eval "(list id-expiry-test-pass id-expiry-test-count)") (epoch 111) (eval "(list id-clients-test-pass id-clients-test-count)") (epoch 112) (eval "(list id-grants-test-pass id-grants-test-count)") (epoch 113) (eval "(list id-device-test-pass id-device-test-count)") (epoch 114) (eval "(list id-facade-test-pass id-facade-test-count)") (epoch 115) (eval "(list id-deleg-test-pass id-deleg-test-count)") (epoch 116) (eval "(list id-smgmt-test-pass id-smgmt-test-count)") (epoch 117) (eval "(list id-xchg-test-pass id-xchg-test-count)") (epoch 118) (eval "(list id-intr-test-pass id-intr-test-count)") EPOCHS timeout 600 "$SX_SERVER" < "$TMPFILE" > "$OUTFILE" 2>&1 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 '\nidentity-on-sx conformance: %d / %d\n' "$TOTAL_PASS" "$TOTAL_COUNT" cat > lib/identity/scoreboard.json < lib/identity/scoreboard.md <