Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
clients.sx (RFC 6749 §2) — confidential clients must present the correct secret at the token endpoint (wrong → invalid_client); public clients are identified but not authenticated; redirect_uris are pre-registered and checked by exact-match valid_redirect (§3.1.2.2 + Security BCP). Standalone module for now; wiring confidential-client auth into oauth exchange is a follow-up. New tests/clients.sx. 149/149. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
174 lines
4.8 KiB
Bash
Executable File
174 lines
4.8 KiB
Bash
Executable File
#!/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"
|
|
)
|
|
|
|
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/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")
|
|
(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)")
|
|
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 <<JSON
|
|
{
|
|
"language": "identity",
|
|
"total_pass": $TOTAL_PASS,
|
|
"total": $TOTAL_COUNT,
|
|
"suites": [$JSON_SUITES
|
|
]
|
|
}
|
|
JSON
|
|
|
|
cat > lib/identity/scoreboard.md <<MD
|
|
# identity-on-sx Scoreboard
|
|
|
|
**Total: ${TOTAL_PASS} / ${TOTAL_COUNT} tests passing**
|
|
|
|
| | Suite | Pass | Total |
|
|
|---|---|---|---|
|
|
$MD_ROWS
|
|
|
|
Generated by \`lib/identity/conformance.sh\`.
|
|
MD
|
|
|
|
if [ "$TOTAL_PASS" -eq "$TOTAL_COUNT" ]; then
|
|
exit 0
|
|
else
|
|
exit 1
|
|
fi
|