2026-06-21 18:30:56 +02:00
|
|
|
#!/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"
|
2026-06-21 18:46:40 +02:00
|
|
|
mkdir -p "$DATA_ROOT/bin"
|
2026-06-21 18:30:56 +02:00
|
|
|
|
2026-06-22 15:13:26 +02:00
|
|
|
# Seed per-network share directories with dummy files.
|
2026-06-22 13:42:28 +02:00
|
|
|
mkdir -p "$DATA_ROOT/alice/share" "$DATA_ROOT/bob/share" "$DATA_ROOT/charlie/share"
|
2026-06-22 15:13:26 +02:00
|
|
|
echo "alice's notes" > "$DATA_ROOT/alice/share/notes.txt"
|
2026-06-22 13:42:28 +02:00
|
|
|
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"
|
2026-06-22 15:13:26 +02:00
|
|
|
echo "charlie's doc" > "$DATA_ROOT/charlie/share/document.txt"
|
|
|
|
|
echo "#!/bin/sh" > "$DATA_ROOT/charlie/share/script.sh"
|
2026-06-22 13:42:28 +02:00
|
|
|
|
2026-06-22 11:38:01 +02:00
|
|
|
# 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
|
|
|
|
|
|
2026-06-21 18:30:56 +02:00
|
|
|
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
|
2026-06-21 18:46:40 +02:00
|
|
|
return 0
|
2026-06-21 18:30:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
|
2026-06-22 15:13:26 +02:00
|
|
|
# Daemons — no global -share-dir; share dirs are set per network at join_network time.
|
2026-06-21 18:30:56 +02:00
|
|
|
"$DATA_ROOT/bin/waste-daemon" -alias alice -data-dir "$DATA_ROOT/alice" \
|
2026-06-21 19:07:11 +02:00
|
|
|
-ipc-port "$ALICE_IPC" -anchor "$ANCHOR_URL" \
|
2026-06-22 14:45:15 +02:00
|
|
|
2>"$DATA_ROOT/alice/daemon.log" &
|
2026-06-21 18:30:56 +02:00
|
|
|
PIDS+=($!)
|
|
|
|
|
|
|
|
|
|
"$DATA_ROOT/bin/waste-daemon" -alias bob -data-dir "$DATA_ROOT/bob" \
|
2026-06-21 19:07:11 +02:00
|
|
|
-ipc-port "$BOB_IPC" -anchor "$ANCHOR_URL" \
|
2026-06-22 14:45:15 +02:00
|
|
|
2>"$DATA_ROOT/bob/daemon.log" &
|
2026-06-21 18:30:56 +02:00
|
|
|
PIDS+=($!)
|
|
|
|
|
|
|
|
|
|
"$DATA_ROOT/bin/waste-daemon" -alias charlie -data-dir "$DATA_ROOT/charlie" \
|
2026-06-21 19:07:11 +02:00
|
|
|
-ipc-port "$CHARLIE_IPC" -anchor "$ANCHOR_URL" \
|
2026-06-22 14:45:15 +02:00
|
|
|
2>"$DATA_ROOT/charlie/daemon.log" &
|
2026-06-21 18:30:56 +02:00
|
|
|
PIDS+=($!)
|
|
|
|
|
|
|
|
|
|
wait_port "$ALICE_IPC"
|
|
|
|
|
wait_port "$BOB_IPC"
|
|
|
|
|
wait_port "$CHARLIE_IPC"
|
|
|
|
|
|
2026-06-22 15:13:26 +02:00
|
|
|
# Join all three with per-network share directories.
|
|
|
|
|
ipc "$ALICE_IPC" "$(jq -cn --arg net "$NETWORK_NAME" --arg dir "$DATA_ROOT/alice/share" \
|
|
|
|
|
'{"type":"join_network","network_name":$net,"share_dir":$dir}')"
|
|
|
|
|
sleep 0.2
|
|
|
|
|
ipc "$BOB_IPC" "$(jq -cn --arg net "$NETWORK_NAME" --arg dir "$DATA_ROOT/bob/share" \
|
|
|
|
|
'{"type":"join_network","network_name":$net,"share_dir":$dir}')"
|
|
|
|
|
sleep 0.2
|
|
|
|
|
ipc "$CHARLIE_IPC" "$(jq -cn --arg net "$NETWORK_NAME" --arg dir "$DATA_ROOT/charlie/share" \
|
|
|
|
|
'{"type":"join_network","network_name":$net,"share_dir":$dir}')"
|
|
|
|
|
sleep 0.5
|
|
|
|
|
|
|
|
|
|
# Resolve peer IDs (network-scoped identity, available after joining).
|
2026-06-21 18:30:56 +02:00
|
|
|
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')
|
|
|
|
|
|
|
|
|
|
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"
|