Files
LithosAnanake/tools/hermes_channel_smoke.sh

121 lines
4.0 KiB
Bash
Executable File

#!/bin/sh
# Hermes channel negotiation smoke test.
# Exercises the full CH-REQUEST → CH-ACCEPT → CH-CLOSE → reap lifecycle.
#
# Protocol under test (from HERMES.md):
# 1. X (Hera=0) publishes request on COMMON via CH-REQUEST
# 2. Y (Hermes=1) accepts via CH-ACCEPT → creates ephemeral channel
# 3. Y sends channel_id back to X via MSG-SEND on COMMON
# 4. Business on ephemeral channel (simulated MSG-SEND)
# 5. Y closes channel via CH-CLOSE
# 6. Channel cools → HERMES-TICK reaps it → CH-ACTIVE = COMMON-CH only
#
# Run: bash tools/hermes_channel_smoke.sh
SF=./build/amd64/standard/starforth
CORE_INIT=./capsules/core/init.4th
HERMES=./capsules/hermes/init.4th
BACKUP=${CORE_INIT}.chan_bak
cleanup() {
if [ -f "$BACKUP" ]; then
mv "$BACKUP" "$CORE_INIT"
fi
}
trap cleanup EXIT INT TERM
cp "$CORE_INIT" "$BACKUP"
# NOTE: read from BACKUP — redirect to CORE_INIT truncates it first.
{
cat "$BACKUP"
cat "$HERMES"
cat <<'TESTBLOCK'
Block 9998
( Channel negotiation smoke — helpers )
VARIABLE MYCHAN
: ASSERT-CH ( ch -- )
DUP 0= IF ." FAIL: CH-ACCEPT returned 0" CR BYE THEN DROP ;
: TRIP-ZERO-CH ( -- )
0 MYCHAN @ CH-HEAT! HERMES-TICK ;
Block 9999
( Channel negotiation smoke — part 1 )
CD-INIT
." >>> [1] CH-REQUEST Hera->Hermes negotiate" CR
SPAWN-EVENT 0 1 S" negotiate" CH-REQUEST
." >>> [2] CH-ACCEPT (Hermes creates ephemeral ch)" CR
CH-ACCEPT DUP MYCHAN ! ASSERT-CH
." >>> [3] CH-STATE (expect 1=OPEN): " MYCHAN @ CH-STATE@ . CR
." >>> [4] CH-ID (expect non-0): " MYCHAN @ CH-ID@ . CR
." >>> [5] CH-OWNER (expect 1=Hermes): " MYCHAN @ CH-OWNER@ . CR
." >>> [6] Y sends chanid to X on COMMON" CR
MYCHAN @ CH-ID@ 0 1 S" chanid" MSG-SEND
." >>> [7] COMMON-CH OPEN (expect 1): " COMMON-CH @ CH-STATE@ . CR
." >>> [8] business msg on ephemeral ch" CR
42 1 0 S" work" MSG-SEND
." >>> [9] CH-CLOSE" CR
MYCHAN @ CH-CLOSE
." >>> [10] CH-STATE (expect 2=CLOSING): " MYCHAN @ CH-STATE@ . CR
." >>> [11] HERMES-TICK (hot channel, no reap yet)" CR
HERMES-TICK
." >>> [12] CH-STATE after tick (expect 2=CLOSING): " MYCHAN @ CH-STATE@ . CR
Block 9000
( Channel negotiation smoke — part 2 )
." >>> [13] Zero heat + HERMES-TICK (reap)" CR
TRIP-ZERO-CH
." >>> [14] COMMON-CH OPEN (expect 1): " COMMON-CH @ CH-STATE@ . CR
." >>> [15] CH-ACTIVE is COMMON-CH (expect 1): "
CH-ACTIVE @ COMMON-CH @ = . CR
." >>> === Channel negotiation smoke complete ===" CR
BYE
TESTBLOCK
} > "$CORE_INIT"
OUTPUT=$($SF --log-none 2>&1)
echo "$OUTPUT" | grep '^>>>'
PASS=0
FAIL=0
check() {
label="$1"
pattern="$2"
if echo "$OUTPUT" | grep -qF "$pattern"; then
echo " PASS: $label"
PASS=$((PASS + 1))
else
echo " FAIL: $label (expected: $pattern)"
FAIL=$((FAIL + 1))
fi
}
echo ""
echo "=== Validation ==="
check "test started" ">>> [1] CH-REQUEST"
check "CH-ACCEPT ok" ">>> [2] CH-ACCEPT"
check "ch state OPEN" ">>> [3] CH-STATE (expect 1=OPEN): 1"
check "ch id non-zero" ">>> [4] CH-ID (expect non-0):"
check "ch owner Hermes" ">>> [5] CH-OWNER (expect 1=Hermes): 1"
check "chanid sent" ">>> [6] Y sends chanid to X on COMMON"
check "COMMON still OPEN" ">>> [7] COMMON-CH OPEN (expect 1): 1"
check "business msg" ">>> [8] business msg on ephemeral ch"
check "CH-CLOSE called" ">>> [9] CH-CLOSE"
check "state CLOSING" ">>> [10] CH-STATE (expect 2=CLOSING): 2"
check "tick no reap" ">>> [11] HERMES-TICK"
check "still CLOSING after tick" ">>> [12] CH-STATE after tick (expect 2=CLOSING): 2"
check "zero+tick reap" ">>> [13] Zero heat + HERMES-TICK (reap)"
check "COMMON still OPEN after" ">>> [14] COMMON-CH OPEN (expect 1): 1"
check "CH-ACTIVE is COMMON-CH" ">>> [15] CH-ACTIVE is COMMON-CH (expect 1): -1"
check "smoke complete" ">>> === Channel negotiation smoke complete ==="
echo ""
echo "Result: $PASS passed, $FAIL failed"
if [ "$FAIL" -eq 0 ]; then
echo "CHANNEL SMOKE: PASS"
exit 0
else
echo "CHANNEL SMOKE: FAIL"
exit 1
fi