#!/usr/bin/env bash # End-to-end smoke test for a running iLSP instance. # Usage: # ./scripts/smoke_test.sh [host] # default: localhost # ./scripts/smoke_test.sh autobox.i80.dk set -euo pipefail HOST="${1:-localhost}" PYTHON_PORT="${PYTHON_LSP_PORT:-2087}" BICEP_PORT="${BICEP_LSP_PORT:-2088}" HEALTH_PORT="${HEALTH_PORT:-2089}" PASS=0 FAIL=0 ok() { echo " ✓ $*"; PASS=$((PASS+1)); } fail() { echo " ✗ $*"; FAIL=$((FAIL+1)); } # ── Helper: send LSP initialize and read response ───────────────────────────── send_lsp_init() { local port="$1" local body='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":null,"rootUri":null,"capabilities":{}}}' local len=${#body} printf "Content-Length: %d\r\n\r\n%s" "$len" "$body" } lsp_check() { local name="$1" local port="$2" local timeout="${3:-3}" local response # Keep stdin open during LSP server startup: the server must NOT see EOF # on stdin before it has finished responding (especially slow .NET JIT). # We send the init message and then sleep for the full timeout so that nc # keeps the TCP write-side open while reading the server's response. response=$({ send_lsp_init "$port"; sleep "$timeout"; } \ | nc -w "$timeout" "$HOST" "$port" 2>/dev/null || true) if echo "$response" | grep -q '"result"'; then ok "$name LSP responded to initialize (port $port)" else fail "$name LSP did not respond (port $port) — is it running?" fi } # ── Tests ───────────────────────────────────────────────────────────────────── echo "" echo "iLSP smoke test — $HOST" echo "════════════════════════════════" # 1. Health endpoint echo "" echo "Health check (HTTP :$HEALTH_PORT)" health=$(curl -sf "http://$HOST:$HEALTH_PORT/health" 2>/dev/null || true) if echo "$health" | grep -q '"status": *"ok"'; then ok "Health endpoint returned ok" pypi=$(echo "$health" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('pypi_packages',0))" 2>/dev/null || echo "?") bicep=$(echo "$health" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('bicep_modules',0))" 2>/dev/null || echo "?") ok "Catalogs loaded: $pypi pypi packages, $bicep bicep modules" else fail "Health endpoint not reachable at http://$HOST:$HEALTH_PORT/health" fi # 2. Python LSP echo "" echo "Python LSP (TCP :$PYTHON_PORT)" if command -v nc &>/dev/null; then lsp_check "Python" "$PYTHON_PORT" else echo " ⚠ nc not found — skipping TCP tests" fi # 3. Bicep LSP (longer timeout — .NET startup takes a few seconds) echo "" echo "Bicep LSP (TCP :$BICEP_PORT)" if command -v nc &>/dev/null; then lsp_check "Bicep" "$BICEP_PORT" 12 fi # ── Summary ─────────────────────────────────────────────────────────────────── echo "" echo "════════════════════════════════" echo "Results: $PASS passed, $FAIL failed" [ "$FAIL" -eq 0 ] && exit 0 || exit 1