test(net): add integration test harness against Headscale

Spins up Headscale 0.23 (with embedded DERP) plus two Tailscale peers
in docker compose, generates pre-auth keys, and runs three integration
tests behind the `integration` feature:

- test_register_and_receive_netmap: full TS2021 → register → first
  netmap fetch
- test_proxy_listener_accepts: starts the daemon and waits for it to
  reach the Running state
- test_daemon_lifecycle: full lifecycle including DERP connect, then
  clean shutdown via the DaemonHandle

Run with `sunbeam-net/tests/run.sh` (handles compose up/down + auth
key provisioning) or manually via cargo nextest with the env vars
SUNBEAM_NET_TEST_AUTH_KEY and SUNBEAM_NET_TEST_COORD_URL set.
This commit is contained in:
2026-04-07 13:42:46 +01:00
parent 9750d4e0b3
commit bea8a308da
4 changed files with 371 additions and 0 deletions

52
sunbeam-net/tests/run.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Integration test runner for sunbeam-net.
#
# Spins up Headscale + two Tailscale peers, creates pre-auth keys,
# runs the Rust integration tests, then tears everything down.
set -euo pipefail
cd "$(dirname "$0")"
COMPOSE="docker compose -f docker-compose.yml"
cleanup() { $COMPOSE down -v 2>/dev/null; }
trap cleanup EXIT
echo "==> Starting Headscale..."
$COMPOSE up -d headscale
$COMPOSE exec -T headscale sh -c 'until headscale health 2>/dev/null; do sleep 1; done'
echo "==> Creating pre-auth keys..."
PEER_A_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | grep -o '"key":"[^"]*"' | cut -d'"' -f4)
PEER_B_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | grep -o '"key":"[^"]*"' | cut -d'"' -f4)
CLIENT_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | grep -o '"key":"[^"]*"' | cut -d'"' -f4)
echo "==> Starting peers..."
PEER_A_AUTH_KEY="$PEER_A_KEY" PEER_B_AUTH_KEY="$PEER_B_KEY" $COMPOSE up -d peer-a peer-b echo
echo "==> Waiting for peers to register..."
for i in $(seq 1 30); do
NODES=$($COMPOSE exec -T headscale headscale nodes list -o json 2>/dev/null | grep -c '"id"' || true)
if [ "$NODES" -ge 2 ]; then
echo " $NODES peers registered."
break
fi
sleep 2
done
# Get the server's Noise public key
SERVER_KEY=$($COMPOSE exec -T headscale cat /var/lib/headscale/noise_private.key 2>/dev/null | head -1 || echo "")
echo "==> Peer A tailnet IP:"
$COMPOSE exec -T peer-a tailscale ip -4 || true
echo "==> Peer B tailnet IP:"
$COMPOSE exec -T peer-b tailscale ip -4 || true
echo "==> Running integration tests..."
cd ../..
SUNBEAM_NET_TEST_AUTH_KEY="$CLIENT_KEY" \
SUNBEAM_NET_TEST_COORD_URL="http://localhost:8080" \
SUNBEAM_NET_TEST_PEER_A_IP=$($COMPOSE -f sunbeam-net/tests/docker-compose.yml exec -T peer-a tailscale ip -4 2>/dev/null | tr -d '[:space:]') \
cargo test -p sunbeam-net --features integration --test integration -- --nocapture
echo "==> Done."