#!/usr/bin/env bash # test-tui.sh — spin up anchor + 3 peers, then launch the TUI as alice. # Bob and Charlie send periodic messages so the UI updates live. # Usage: ./test-tui.sh # Requires: go, nc, jq set -euo pipefail ANCHOR_PORT=19339 ALICE_IPC=19337 BOB_IPC=19340 CHARLIE_IPC=19343 NETWORK_NAME="friends" DATA_ROOT="/tmp/waste-tui-test" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' CYAN='\033[0;36m'; DIM='\033[2m'; BOLD='\033[1m'; RESET='\033[0m' rm -rf "$DATA_ROOT" mkdir -p "$DATA_ROOT/bin" # Seed per-peer share directories with dummy files. mkdir -p "$DATA_ROOT/alice/share" "$DATA_ROOT/bob/share" "$DATA_ROOT/charlie/share" echo "alice's notes" > "$DATA_ROOT/alice/share/notes.txt" dd if=/dev/urandom bs=1K count=64 2>/dev/null | base64 > "$DATA_ROOT/alice/share/photo.jpg.b64" dd if=/dev/urandom bs=1K count=128 2>/dev/null | base64 > "$DATA_ROOT/bob/share/archive.tar.b64" echo -e "file1.mp3\nfile2.mp3" > "$DATA_ROOT/bob/share/playlist.m3u" echo "charlie's doc" > "$DATA_ROOT/charlie/share/document.txt" echo "#!/bin/sh" > "$DATA_ROOT/charlie/share/script.sh" # Kill any leftover processes holding our fixed ports. for port in "$ANCHOR_PORT" "$ALICE_IPC" "$BOB_IPC" "$CHARLIE_IPC"; do pid=$(lsof -ti tcp:"$port" 2>/dev/null || true) [ -n "$pid" ] && kill -9 $pid 2>/dev/null || true done for port in "$ANCHOR_PORT" "$ALICE_IPC" "$BOB_IPC" "$CHARLIE_IPC"; do n=0 while lsof -ti tcp:"$port" >/dev/null 2>&1; do sleep 0.1; n=$(( n + 1 )) [ "$n" -gt 30 ] && break done done PIDS=() cleanup() { for pid in "${PIDS[@]:-}"; do kill "$pid" 2>/dev/null || true done wait 2>/dev/null || true } trap cleanup EXIT INT TERM wait_port() { local port="$1" n=0 while ! nc -z 127.0.0.1 "$port" 2>/dev/null; do sleep 0.1 n=$(( n + 1 )) [ "$n" -gt 80 ] && { echo "timeout waiting for :$port" >&2; exit 1; } done return 0 } ipc() { echo "$2" | nc -q 0 127.0.0.1 "$1" >/dev/null 2>&1 || true; } peer_field() { local port="$1" expr="$2" result="" n=0 while [ -z "$result" ] || [ "$result" = "null" ]; do result=$(echo '{"type":"get_state"}' \ | timeout 2 nc 127.0.0.1 "$port" 2>/dev/null \ | grep '"type":"state_snapshot"' | head -1 \ | jq -r "$expr" 2>/dev/null || true) n=$(( n + 1 )) [ "$n" -ge 15 ] && break [ -z "$result" ] || [ "$result" = "null" ] && sleep 0.3 done echo "$result" } echo "" echo -e "${BOLD}waste-go TUI test${RESET}" echo -e "${DIM}network: ${BOLD}${NETWORK_NAME}${RESET}" echo -e "${DIM}data: ${DATA_ROOT}${RESET}" echo "" echo -e "${DIM}building binaries…${RESET}" go build -o "$DATA_ROOT/bin/waste-anchor" ./cmd/anchor go build -o "$DATA_ROOT/bin/waste-daemon" ./cmd/daemon go build -o "$DATA_ROOT/bin/waste-tui" ./cmd/tui echo -e "${GREEN}✓ built${RESET}" echo "" # Anchor "$DATA_ROOT/bin/waste-anchor" -bind "127.0.0.1:${ANCHOR_PORT}" \ 2>/dev/null & PIDS+=($!) wait_port "$ANCHOR_PORT" ANCHOR_URL="ws://127.0.0.1:${ANCHOR_PORT}/ws" # Daemons "$DATA_ROOT/bin/waste-daemon" -alias alice -data-dir "$DATA_ROOT/alice" \ -ipc-port "$ALICE_IPC" -anchor "$ANCHOR_URL" \ -share-dir "$DATA_ROOT/alice/share" 2>/dev/null & PIDS+=($!) "$DATA_ROOT/bin/waste-daemon" -alias bob -data-dir "$DATA_ROOT/bob" \ -ipc-port "$BOB_IPC" -anchor "$ANCHOR_URL" \ -share-dir "$DATA_ROOT/bob/share" 2>/dev/null & PIDS+=($!) "$DATA_ROOT/bin/waste-daemon" -alias charlie -data-dir "$DATA_ROOT/charlie" \ -ipc-port "$CHARLIE_IPC" -anchor "$ANCHOR_URL" \ -share-dir "$DATA_ROOT/charlie/share" 2>/dev/null & PIDS+=($!) wait_port "$ALICE_IPC" wait_port "$BOB_IPC" wait_port "$CHARLIE_IPC" # Resolve peer IDs ALICE_ID=$(peer_field "$ALICE_IPC" '.local_peer.id') BOB_ID=$(peer_field "$BOB_IPC" '.local_peer.id') CHARLIE_ID=$(peer_field "$CHARLIE_IPC" '.local_peer.id') # Join all three JOIN=$(printf '{"type":"join_network","network_name":"%s"}' "$NETWORK_NAME") ipc "$ALICE_IPC" "$JOIN" sleep 0.2 ipc "$BOB_IPC" "$JOIN" sleep 0.2 ipc "$CHARLIE_IPC" "$JOIN" echo -e "${DIM}waiting for WebRTC DataChannels (6s)…${RESET}" sleep 6 # Bob and Charlie send a few messages as background noise, then loop ( set +e while true; do ipc "$BOB_IPC" '{"type":"send_message","room":"general","body":"bob: still here!"}' sleep 5 ipc "$CHARLIE_IPC" '{"type":"send_message","room":"general","body":"charlie: mesh is alive"}' sleep 5 # Charlie DMs alice ipc "$CHARLIE_IPC" "$(jq -cn \ --arg to "$ALICE_ID" \ --arg room "dm:$ALICE_ID" \ --arg body "charlie whispering to alice…" \ '{"type":"send_message","room":$room,"body":$body,"to":$to}')" sleep 10 done ) & PIDS+=($!) echo "" echo -e "${BOLD}Launching TUI as alice${RESET} — ${DIM}ctrl+c to quit${RESET}" echo "" # Run the TUI in the foreground (it takes over the terminal with alt-screen) "$DATA_ROOT/bin/waste-tui" -ipc "$ALICE_IPC" -network "$NETWORK_NAME"