2026-03-23 19:21:09 -06:00

178 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# E2E test: starts the 5-node mix simulation, launches two chat clients,
# sends messages in both directions, and verifies delivery.
# Exit code 0 = all tests passed, 1 = failure.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Configurable timeouts (seconds)
SIM_TIMEOUT=${E2E_SIM_TIMEOUT:-900}
DISCOVERY_WAIT=${E2E_DISCOVERY_WAIT:-60}
MSG_TIMEOUT=${E2E_MSG_TIMEOUT:-120}
PASSED=0
FAILED=0
SIM_PID=""
CHAT1_PID=""
CHAT2_PID=""
SIM_LOG=$(mktemp)
CHAT1_LOG=$(mktemp)
CHAT2_LOG=$(mktemp)
PIPE1="/tmp/e2e_chat1_in_$$"
PIPE2="/tmp/e2e_chat2_in_$$"
cleanup() {
echo ""
echo "=== Cleanup ==="
exec 3>&- 2>/dev/null || true
exec 4>&- 2>/dev/null || true
[ -n "$CHAT1_PID" ] && kill "$CHAT1_PID" 2>/dev/null || true
[ -n "$CHAT2_PID" ] && kill "$CHAT2_PID" 2>/dev/null || true
if [ -n "$SIM_PID" ]; then
kill "$SIM_PID" 2>/dev/null || true
wait "$SIM_PID" 2>/dev/null || true
fi
pkill -f logos_host 2>/dev/null || true
rm -f "$PIPE1" "$PIPE2" 2>/dev/null || true
echo "Done."
}
trap cleanup EXIT
echo "=== RLN Mix Network E2E Test ==="
echo ""
# ── Phase 1: Start simulation ──────────────────────────────────────
echo "[1/5] Starting simulation (this takes a few minutes)..."
bash "$SCRIPT_DIR/run_simulation.sh" > "$SIM_LOG" 2>&1 &
SIM_PID=$!
# Disable errexit — polling loops use grep/kill that may return non-zero
set +e
LAST_STEP=""
ELAPSED=0
while [ $ELAPSED -lt $SIM_TIMEOUT ]; do
if grep -q '\[7/7\] Simulation running!' "$SIM_LOG" 2>/dev/null; then
echo " Simulation ready."
break
fi
# Show simulation progress as new [N/7] lines appear
STEP_LINE=$(grep -F '/7]' "$SIM_LOG" 2>/dev/null | tail -1)
if [ -n "$STEP_LINE" ] && [ "$STEP_LINE" != "$LAST_STEP" ]; then
echo " $STEP_LINE"
LAST_STEP="$STEP_LINE"
fi
if ! kill -0 "$SIM_PID" 2>/dev/null; then
echo "FATAL: Simulation exited prematurely."
tail -30 "$SIM_LOG"
exit 1
fi
sleep 2
ELAPSED=$((ELAPSED + 2))
done
if ! grep -q '\[7/7\] Simulation running!' "$SIM_LOG" 2>/dev/null; then
echo "FATAL: Simulation not ready after ${SIM_TIMEOUT}s."
tail -30 "$SIM_LOG"
exit 1
fi
# ── Phase 2: Start chat clients ────────────────────────────────────
echo "[2/5] Starting chat clients..."
rm -f "$PIPE1" "$PIPE2"
mkfifo "$PIPE1" "$PIPE2"
# Open FIFOs read-write (<>) so open(2) never blocks and the write end
# stays alive as long as the FD is open — even if readers come and go.
exec 3<>"$PIPE1"
exec 4<>"$PIPE2"
# Start chat clients reading from the FIFOs.
bash "$SCRIPT_DIR/run_chat_mix.sh" < "$PIPE1" > "$CHAT1_LOG" 2>&1 &
CHAT1_PID=$!
bash "$SCRIPT_DIR/run_chat_mix1.sh" < "$PIPE2" > "$CHAT2_LOG" 2>&1 &
CHAT2_PID=$!
echo "TestAlice" >&3
echo "TestBob" >&4
echo " Clients started, nicknames sent."
# ── Phase 3: Wait for mix node discovery ───────────────────────────
echo "[3/5] Waiting for mix node discovery (up to ${DISCOVERY_WAIT}s)..."
DISC_ELAPSED=0
C1_READY=0
C2_READY=0
while [ $DISC_ELAPSED -lt $DISCOVERY_WAIT ]; do
[ $C1_READY -eq 0 ] && grep -q "ready to publish messages now" "$CHAT1_LOG" 2>/dev/null && { echo " Alice: ready"; C1_READY=1; }
[ $C2_READY -eq 0 ] && grep -q "ready to publish messages now" "$CHAT2_LOG" 2>/dev/null && { echo " Bob: ready"; C2_READY=1; }
[ $C1_READY -eq 1 ] && [ $C2_READY -eq 1 ] && break
sleep 2
DISC_ELAPSED=$((DISC_ELAPSED + 2))
done
if [ $C1_READY -eq 0 ] || [ $C2_READY -eq 0 ]; then
echo "FATAL: Chat clients not ready within ${DISCOVERY_WAIT}s."
[ $C1_READY -eq 0 ] && { echo " Alice log tail:"; tail -10 "$CHAT1_LOG"; }
[ $C2_READY -eq 0 ] && { echo " Bob log tail:"; tail -10 "$CHAT2_LOG"; }
exit 1
fi
echo " Settling filter subscriptions (20s)..."
sleep 20
# ── Phase 4: Send messages and verify delivery ─────────────────────
echo "[4/5] Sending messages and verifying delivery..."
MSG_A="e2e_alice_$(date +%s)"
MSG_B="e2e_bob_$(date +%s)"
check_delivery() {
local log_file=$1
local pattern=$2
local label=$3
local elapsed=0
while [ $elapsed -lt $MSG_TIMEOUT ]; do
if grep -q "$pattern" "$log_file" 2>/dev/null; then
echo " PASS: $label"
PASSED=$((PASSED + 1))
return 0
fi
sleep 3
elapsed=$((elapsed + 3))
done
echo " FAIL: $label (not received after ${MSG_TIMEOUT}s)"
FAILED=$((FAILED + 1))
return 0
}
echo " Sending: Alice -> '$MSG_A'"
echo "$MSG_A" >&3
echo " Sending: Bob -> '$MSG_B'"
echo "$MSG_B" >&4
echo " Waiting for delivery (up to ${MSG_TIMEOUT}s per message)..."
check_delivery "$CHAT2_LOG" "$MSG_A" "Alice -> Bob"
check_delivery "$CHAT1_LOG" "$MSG_B" "Bob -> Alice"
# ── Phase 5: Report ────────────────────────────────────────────────
echo ""
echo "[5/5] Results: $PASSED passed, $FAILED failed"
echo ""
if [ $FAILED -eq 0 ] && [ $PASSED -ge 2 ]; then
echo "E2E TEST PASSED"
exit 0
else
echo "E2E TEST FAILED"
echo " Simulation log: $SIM_LOG"
echo " Alice log: $CHAT1_LOG"
echo " Bob log: $CHAT2_LOG"
exit 1
fi