Files
quicproquo/scripts/chat-test.sh
Chris Nennemann 853ca4fec0 chore: rename project quicnprotochat -> quicproquo (binaries: qpq)
Rename the entire workspace:
- Crate packages: quicnprotochat-{core,proto,server,client,gui,p2p,mobile} -> quicproquo-*
- Binary names: quicnprotochat -> qpq, quicnprotochat-server -> qpq-server,
  quicnprotochat-gui -> qpq-gui
- Default files: *-state.bin -> qpq-state.bin, *-server.toml -> qpq-server.toml,
  *.db -> qpq.db
- Environment variable prefix: QUICNPROTOCHAT_* -> QPQ_*
- App identifier: chat.quicnproto.gui -> chat.quicproquo.gui
- Proto package: quicnprotochat.bench -> quicproquo.bench
- All documentation, Docker, CI, and script references updated

HKDF domain-separation strings and P2P ALPN remain unchanged for
backward compatibility with existing encrypted state and wire protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:11:51 +01:00

153 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# ── Interactive Chat Test ─────────────────────────────────────────────────────
#
# Spins up a server + two client containers (Alice & Bob), sets up an MLS
# group, and opens a tmux session with side-by-side interactive chat panes.
#
# Usage:
# ./scripts/chat-test.sh
#
# Requirements: docker, docker compose, tmux
# Exit: Ctrl+D in both panes, or: tmux kill-session -t qpc-chat
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
COMPOSE_FILE="$PROJECT_ROOT/docker/docker-compose.chat-test.yml"
COMPOSE="docker compose -f $COMPOSE_FILE -p qpc-chat-test"
# ── Colors ────────────────────────────────────────────────────────────────────
GREEN='\033[0;32m'
CYAN='\033[0;36m'
RED='\033[0;31m'
NC='\033[0m'
step() { echo -e "${GREEN}==> $1${NC}"; }
info() { echo -e " ${CYAN}$1${NC}"; }
error() { echo -e "${RED}ERROR: $1${NC}" >&2; }
# ── Cleanup on exit ──────────────────────────────────────────────────────────
cleanup() {
echo ""
step "Tearing down containers..."
$COMPOSE down -v --remove-orphans 2>/dev/null || true
}
trap cleanup EXIT INT TERM
# ── Preflight checks ─────────────────────────────────────────────────────────
if ! command -v docker &>/dev/null; then
error "docker is required but not installed."
exit 1
fi
if ! docker compose version &>/dev/null; then
error "docker compose (v2 plugin) is required."
echo " See: https://docs.docker.com/compose/install/"
exit 1
fi
if ! command -v tmux &>/dev/null; then
error "tmux is required but not installed."
echo " macOS: brew install tmux"
echo " Linux: sudo apt-get install tmux"
exit 1
fi
# ── Step 1: Build ─────────────────────────────────────────────────────────────
step "Building Docker image (server + client)..."
$COMPOSE build
# ── Step 2: Start services ────────────────────────────────────────────────────
step "Starting server, alice, bob..."
$COMPOSE up -d --wait
# ── Step 3: Verify server reachable via QUIC ──────────────────────────────────
step "Verifying QUIC connectivity from alice..."
$COMPOSE exec -T alice qpq health
# ── Step 4: Alice — register identity + upload KeyPackage ─────────────────────
step "Alice: register-state..."
$COMPOSE exec -T alice qpq register-state --state /chat/alice.bin
ALICE_KEY=$($COMPOSE exec -T alice qpq whoami --state /chat/alice.bin \
| grep 'identity_key' | awk '{print $3}' | tr -d '[:space:]')
info "Alice identity: ${ALICE_KEY}"
if [ -z "$ALICE_KEY" ]; then
error "Failed to extract Alice's identity key."
exit 1
fi
# ── Step 5: Bob — register identity + upload KeyPackage ───────────────────────
step "Bob: register-state..."
$COMPOSE exec -T bob qpq register-state --state /chat/bob.bin
BOB_KEY=$($COMPOSE exec -T bob qpq whoami --state /chat/bob.bin \
| grep 'identity_key' | awk '{print $3}' | tr -d '[:space:]')
info "Bob identity: ${BOB_KEY}"
if [ -z "$BOB_KEY" ]; then
error "Failed to extract Bob's identity key."
exit 1
fi
# ── Step 6: Alice creates group ───────────────────────────────────────────────
step "Alice: create-group 'docker-chat'..."
$COMPOSE exec -T alice qpq create-group \
--state /chat/alice.bin \
--group-id docker-chat
# ── Step 7: Alice invites Bob ─────────────────────────────────────────────────
step "Alice: invite Bob..."
$COMPOSE exec -T alice qpq invite \
--state /chat/alice.bin \
--peer-key "$BOB_KEY"
# ── Step 8: Bob joins ─────────────────────────────────────────────────────────
step "Bob: join group..."
$COMPOSE exec -T bob qpq join --state /chat/bob.bin
# ── Step 9: Launch tmux ──────────────────────────────────────────────────────
step "Launching interactive chat (tmux side-by-side)..."
echo ""
echo " Left pane: Alice"
echo " Right pane: Bob"
echo ""
echo " Type a message + Enter to send."
echo " Ctrl+D exits a pane."
echo " tmux kill-session -t qpc-chat to stop."
echo ""
ALICE_CMD="$COMPOSE exec alice qpq chat --state /chat/alice.bin"
BOB_CMD="$COMPOSE exec bob qpq chat --state /chat/bob.bin"
# Kill any stale tmux session with the same name.
tmux kill-session -t qpc-chat 2>/dev/null || true
# Create tmux session with Alice in the first pane, Bob in a horizontal split.
tmux new-session -d -s qpc-chat -x 200 -y 50 "$ALICE_CMD"
tmux split-window -h -t qpc-chat "$BOB_CMD"
# Label panes (tmux >= 2.6).
tmux select-pane -t qpc-chat:0.0 -T "Alice"
tmux select-pane -t qpc-chat:0.1 -T "Bob"
tmux set-option -t qpc-chat pane-border-status top 2>/dev/null || true
tmux set-option -t qpc-chat pane-border-format " #{pane_title} " 2>/dev/null || true
# Attach — blocks until the user exits tmux.
tmux attach-session -t qpc-chat
step "Chat session ended."