conformance: migrate feed onto shared driver (counters, 189/189 parity)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
Feed is the canonical MODE=counters shape: each suite runs in a fresh session with shared preloads and a single feed-test-pass/feed-test-fail pair. Lifted the old script's inline epoch-2 counter + feed-test helper defs into lib/feed/test-harness.sx (preloaded last) so the driver can load them before each suite. conformance.conf + 3-line shim; historical scoreboard schema preserved. No driver change needed. Parity verified 189/189 (0 fail), every suite matching baseline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
82
lib/feed/conformance.conf
Normal file
82
lib/feed/conformance.conf
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Feed-on-SX conformance config — sourced by lib/guest/conformance.sh.
|
||||||
|
#
|
||||||
|
# Every feed suite runs in a fresh session with the same preloads and a single
|
||||||
|
# pass/fail counter pair — the canonical MODE=counters shape. The counters and
|
||||||
|
# the feed-test helper (previously defined inline in the old conformance.sh) are
|
||||||
|
# preloaded via lib/feed/test-harness.sx.
|
||||||
|
|
||||||
|
LANG_NAME=feed
|
||||||
|
MODE=counters
|
||||||
|
COUNTERS_PASS=feed-test-pass
|
||||||
|
COUNTERS_FAIL=feed-test-fail
|
||||||
|
TIMEOUT_PER_SUITE=300
|
||||||
|
|
||||||
|
PRELOADS=(
|
||||||
|
spec/stdlib.sx
|
||||||
|
lib/r7rs.sx
|
||||||
|
lib/apl/runtime.sx
|
||||||
|
lib/feed/normalize.sx
|
||||||
|
lib/feed/stream.sx
|
||||||
|
lib/feed/api.sx
|
||||||
|
lib/feed/fanout.sx
|
||||||
|
lib/feed/dedupe.sx
|
||||||
|
lib/feed/aggregate.sx
|
||||||
|
lib/feed/rank.sx
|
||||||
|
lib/feed/acl.sx
|
||||||
|
lib/feed/fed.sx
|
||||||
|
lib/feed/content.sx
|
||||||
|
lib/feed/notify.sx
|
||||||
|
lib/feed/home.sx
|
||||||
|
lib/feed/trending.sx
|
||||||
|
lib/feed/mute.sx
|
||||||
|
lib/feed/page.sx
|
||||||
|
lib/feed/thread.sx
|
||||||
|
lib/feed/test-harness.sx
|
||||||
|
)
|
||||||
|
|
||||||
|
SUITES=(
|
||||||
|
"basic:lib/feed/tests/basic.sx"
|
||||||
|
"fanout:lib/feed/tests/fanout.sx"
|
||||||
|
"rank:lib/feed/tests/rank.sx"
|
||||||
|
"integration:lib/feed/tests/integration.sx"
|
||||||
|
"content:lib/feed/tests/content.sx"
|
||||||
|
"notify:lib/feed/tests/notify.sx"
|
||||||
|
"home:lib/feed/tests/home.sx"
|
||||||
|
"dedupe:lib/feed/tests/dedupe.sx"
|
||||||
|
"trending:lib/feed/tests/trending.sx"
|
||||||
|
"mute:lib/feed/tests/mute.sx"
|
||||||
|
"page:lib/feed/tests/page.sx"
|
||||||
|
"thread:lib/feed/tests/thread.sx"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Preserve the historical scoreboard schema so consumers of
|
||||||
|
# lib/feed/scoreboard.json keep working.
|
||||||
|
emit_scoreboard_json() {
|
||||||
|
local n=${#GC_NAMES[@]} i
|
||||||
|
printf '{\n'
|
||||||
|
printf ' "suites": {\n'
|
||||||
|
for ((i=0; i<n; i++)); do
|
||||||
|
[ "$i" -gt 0 ] && printf ',\n'
|
||||||
|
printf ' "%s": {"pass": %d, "fail": %d}' \
|
||||||
|
"${GC_NAMES[$i]}" "${GC_PASS[$i]}" "${GC_FAIL[$i]}"
|
||||||
|
done
|
||||||
|
printf '\n },\n'
|
||||||
|
printf ' "total_pass": %d,\n' "$GC_TOTAL_PASS"
|
||||||
|
printf ' "total_fail": %d,\n' "$GC_TOTAL_FAIL"
|
||||||
|
printf ' "total": %d\n' "$GC_TOTAL"
|
||||||
|
printf '}\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_scoreboard_md() {
|
||||||
|
local n=${#GC_NAMES[@]} i p f
|
||||||
|
printf '# feed Conformance Scoreboard\n\n'
|
||||||
|
printf '_Generated by `lib/feed/conformance.sh`_\n\n'
|
||||||
|
printf '| Suite | Pass | Fail | Total |\n'
|
||||||
|
printf '|-------|-----:|-----:|------:|\n'
|
||||||
|
for ((i=0; i<n; i++)); do
|
||||||
|
p=${GC_PASS[$i]}; f=${GC_FAIL[$i]}
|
||||||
|
printf '| %s | %d | %d | %d |\n' "${GC_NAMES[$i]}" "$p" "$f" "$((p+f))"
|
||||||
|
done
|
||||||
|
printf '| **Total** | **%d** | **%d** | **%d** |\n' \
|
||||||
|
"$GC_TOTAL_PASS" "$GC_TOTAL_FAIL" "$GC_TOTAL"
|
||||||
|
}
|
||||||
@@ -1,125 +1,3 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# lib/feed/conformance.sh — run feed test suites, emit scoreboard.json + scoreboard.md.
|
# Thin wrapper — see lib/guest/conformance.sh and lib/feed/conformance.conf.
|
||||||
|
exec bash "$(dirname "$0")/../guest/conformance.sh" "$(dirname "$0")/conformance.conf" "$@"
|
||||||
set -uo pipefail
|
|
||||||
cd "$(git rev-parse --show-toplevel)"
|
|
||||||
|
|
||||||
SX_SERVER="${SX_SERVER:-/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe}"
|
|
||||||
if [ ! -x "$SX_SERVER" ]; then
|
|
||||||
SX_SERVER="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
|
|
||||||
|
|
||||||
SUITES=(basic fanout rank integration content notify home dedupe trending mute page thread)
|
|
||||||
|
|
||||||
OUT_JSON="lib/feed/scoreboard.json"
|
|
||||||
OUT_MD="lib/feed/scoreboard.md"
|
|
||||||
|
|
||||||
run_suite() {
|
|
||||||
local suite=$1
|
|
||||||
local file="lib/feed/tests/${suite}.sx"
|
|
||||||
local TMP
|
|
||||||
TMP=$(mktemp)
|
|
||||||
cat > "$TMP" << EPOCHS
|
|
||||||
(epoch 1)
|
|
||||||
(load "spec/stdlib.sx")
|
|
||||||
(load "lib/r7rs.sx")
|
|
||||||
(load "lib/apl/runtime.sx")
|
|
||||||
(load "lib/feed/normalize.sx")
|
|
||||||
(load "lib/feed/stream.sx")
|
|
||||||
(load "lib/feed/api.sx")
|
|
||||||
(load "lib/feed/fanout.sx")
|
|
||||||
(load "lib/feed/dedupe.sx")
|
|
||||||
(load "lib/feed/aggregate.sx")
|
|
||||||
(load "lib/feed/rank.sx")
|
|
||||||
(load "lib/feed/acl.sx")
|
|
||||||
(load "lib/feed/fed.sx")
|
|
||||||
(load "lib/feed/content.sx")
|
|
||||||
(load "lib/feed/notify.sx")
|
|
||||||
(load "lib/feed/home.sx")
|
|
||||||
(load "lib/feed/trending.sx")
|
|
||||||
(load "lib/feed/mute.sx")
|
|
||||||
(load "lib/feed/page.sx")
|
|
||||||
(load "lib/feed/thread.sx")
|
|
||||||
(epoch 2)
|
|
||||||
(eval "(define feed-test-pass 0)")
|
|
||||||
(eval "(define feed-test-fail 0)")
|
|
||||||
(eval "(define feed-test (fn (name got expected) (if (= got expected) (set! feed-test-pass (+ feed-test-pass 1)) (set! feed-test-fail (+ feed-test-fail 1)))))")
|
|
||||||
(epoch 3)
|
|
||||||
(load "${file}")
|
|
||||||
(epoch 4)
|
|
||||||
(eval "(list feed-test-pass feed-test-fail)")
|
|
||||||
EPOCHS
|
|
||||||
|
|
||||||
local OUTPUT
|
|
||||||
OUTPUT=$(timeout 300 "$SX_SERVER" < "$TMP" 2>/dev/null)
|
|
||||||
rm -f "$TMP"
|
|
||||||
|
|
||||||
local LINE
|
|
||||||
LINE=$(echo "$OUTPUT" | awk '/^\(ok-len 4 / {getline; print; exit}')
|
|
||||||
if [ -z "$LINE" ]; then
|
|
||||||
LINE=$(echo "$OUTPUT" | grep -E '^\(ok 4 \([0-9]+ [0-9]+\)\)' | tail -1 \
|
|
||||||
| sed -E 's/^\(ok 4 //; s/\)$//')
|
|
||||||
fi
|
|
||||||
|
|
||||||
local P F
|
|
||||||
P=$(echo "$LINE" | sed -E 's/^\(([0-9]+) ([0-9]+)\).*/\1/')
|
|
||||||
F=$(echo "$LINE" | sed -E 's/^\(([0-9]+) ([0-9]+)\).*/\2/')
|
|
||||||
P=${P:-0}
|
|
||||||
F=${F:-0}
|
|
||||||
echo "${P} ${F}"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare -A SUITE_PASS
|
|
||||||
declare -A SUITE_FAIL
|
|
||||||
TOTAL_PASS=0
|
|
||||||
TOTAL_FAIL=0
|
|
||||||
|
|
||||||
echo "Running feed conformance suite..." >&2
|
|
||||||
for s in "${SUITES[@]}"; do
|
|
||||||
read -r p f < <(run_suite "$s")
|
|
||||||
SUITE_PASS[$s]=$p
|
|
||||||
SUITE_FAIL[$s]=$f
|
|
||||||
TOTAL_PASS=$((TOTAL_PASS + p))
|
|
||||||
TOTAL_FAIL=$((TOTAL_FAIL + f))
|
|
||||||
printf " %-12s %d/%d\n" "$s" "$p" "$((p+f))" >&2
|
|
||||||
done
|
|
||||||
|
|
||||||
# scoreboard.json
|
|
||||||
{
|
|
||||||
printf '{\n'
|
|
||||||
printf ' "suites": {\n'
|
|
||||||
first=1
|
|
||||||
for s in "${SUITES[@]}"; do
|
|
||||||
if [ $first -eq 0 ]; then printf ',\n'; fi
|
|
||||||
printf ' "%s": {"pass": %d, "fail": %d}' "$s" "${SUITE_PASS[$s]}" "${SUITE_FAIL[$s]}"
|
|
||||||
first=0
|
|
||||||
done
|
|
||||||
printf '\n },\n'
|
|
||||||
printf ' "total_pass": %d,\n' "$TOTAL_PASS"
|
|
||||||
printf ' "total_fail": %d,\n' "$TOTAL_FAIL"
|
|
||||||
printf ' "total": %d\n' "$((TOTAL_PASS + TOTAL_FAIL))"
|
|
||||||
printf '}\n'
|
|
||||||
} > "$OUT_JSON"
|
|
||||||
|
|
||||||
# scoreboard.md
|
|
||||||
{
|
|
||||||
printf '# feed Conformance Scoreboard\n\n'
|
|
||||||
printf '_Generated by `lib/feed/conformance.sh`_\n\n'
|
|
||||||
printf '| Suite | Pass | Fail | Total |\n'
|
|
||||||
printf '|-------|-----:|-----:|------:|\n'
|
|
||||||
for s in "${SUITES[@]}"; do
|
|
||||||
p=${SUITE_PASS[$s]}
|
|
||||||
f=${SUITE_FAIL[$s]}
|
|
||||||
printf '| %s | %d | %d | %d |\n' "$s" "$p" "$f" "$((p+f))"
|
|
||||||
done
|
|
||||||
printf '| **Total** | **%d** | **%d** | **%d** |\n' "$TOTAL_PASS" "$TOTAL_FAIL" "$((TOTAL_PASS + TOTAL_FAIL))"
|
|
||||||
} > "$OUT_MD"
|
|
||||||
|
|
||||||
echo "Wrote $OUT_JSON and $OUT_MD" >&2
|
|
||||||
echo "Total: $TOTAL_PASS pass, $TOTAL_FAIL fail" >&2
|
|
||||||
|
|
||||||
[ "$TOTAL_FAIL" -eq 0 ]
|
|
||||||
|
|||||||
14
lib/feed/test-harness.sx
Normal file
14
lib/feed/test-harness.sx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
;; lib/feed/test-harness.sx — counter definitions for the feed conformance
|
||||||
|
;; suites, lifted from the inline epoch-2 defs in the old conformance.sh so the
|
||||||
|
;; shared driver (MODE=counters) can preload them before each suite.
|
||||||
|
|
||||||
|
(define feed-test-pass 0)
|
||||||
|
(define feed-test-fail 0)
|
||||||
|
(define
|
||||||
|
feed-test
|
||||||
|
(fn
|
||||||
|
(name got expected)
|
||||||
|
(if
|
||||||
|
(= got expected)
|
||||||
|
(set! feed-test-pass (+ feed-test-pass 1))
|
||||||
|
(set! feed-test-fail (+ feed-test-fail 1)))))
|
||||||
@@ -87,7 +87,7 @@ Blocked with specifics and move to the next candidate next iteration.
|
|||||||
|
|
||||||
- [x] common-lisp — migrated 487/487 (counters; driver extended for per-suite counters+preloads)
|
- [x] common-lisp — migrated 487/487 (counters; driver extended for per-suite counters+preloads)
|
||||||
- [x] erlang — migrated 761/761 (dict; pass/count → :failed = count-pass)
|
- [x] erlang — migrated 761/761 (dict; pass/count → :failed = count-pass)
|
||||||
- [ ] feed
|
- [x] feed — migrated 189/189 (counters; test-harness.sx preload for counters+helper)
|
||||||
- [ ] forth
|
- [ ] forth
|
||||||
- [ ] go
|
- [ ] go
|
||||||
- [ ] js
|
- [ ] js
|
||||||
@@ -100,6 +100,13 @@ Blocked with specifics and move to the next candidate next iteration.
|
|||||||
|
|
||||||
## Progress log (newest first)
|
## Progress log (newest first)
|
||||||
|
|
||||||
|
- 2026-06-07 — feed: migrated to `MODE=counters`, 189/189 exact parity (basic 30,
|
||||||
|
fanout 29, rank 24, integration 22, content 15, notify 8, home 6, dedupe 9, trending 11,
|
||||||
|
mute 9, page 14, thread 12). Canonical counters shape: fresh session per suite, shared
|
||||||
|
preloads, single feed-test-pass/feed-test-fail pair. Lifted the old script's inline
|
||||||
|
epoch-2 counter+helper defs into lib/feed/test-harness.sx (preloaded last). No driver
|
||||||
|
change — only conformance.conf + test-harness.sx + shim. Kept historical scoreboard
|
||||||
|
schema (suites{name:{pass,fail}}, total_pass/total_fail/total).
|
||||||
- 2026-06-07 — erlang: migrated to `MODE=dict`, 761/761 exact parity (tokenize 62,
|
- 2026-06-07 — erlang: migrated to `MODE=dict`, 761/761 exact parity (tokenize 62,
|
||||||
parse 52, eval 408, runtime 93, ring 4, ping-pong 4, bank 8, echo 7, fib 8, ffi 37,
|
parse 52, eval 408, runtime 93, ring 4, ping-pong 4, bank 8, echo 7, fib 8, ffi 37,
|
||||||
vm 78). Erlang exposes pass + *count* (total) counters, not pass/fail, so each suite's
|
vm 78). Erlang exposes pass + *count* (total) counters, not pass/fail, so each suite's
|
||||||
|
|||||||
Reference in New Issue
Block a user