zai-proxy/proxy/tests/run-canary-tests.sh
jedarden e7c24a0c08 feat: initial zai-proxy ecosystem repo
Extracted from ardenone-cluster/containers/zai-proxy and
ardenone-cluster/containers/zai-proxy-dashboard.

- proxy/: OpenAI-compatible ZAI reverse proxy (Go, v1.10.0)
  - Token counting, rate limiting, Prometheus metrics, canary support
- dashboard/: Metrics dashboard backend + React frontend (Go, v1.0.0)
  - Prometheus collector, SQLite storage, SSE live updates
- docs/: Operational notes, research, and plan subdirs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:53:52 -04:00

280 lines
9.2 KiB
Bash
Executable file

#!/bin/bash
# Canary Integration Test Script for ZAI Proxy Token Counting
# This script runs the full integration test suite against the canary deployment
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration
CANARY_URL="${CANARY_URL:-http://zai-proxy-canary.devpod.svc.cluster.local:8080}"
PROD_URL="${PROD_URL:-http://zai-proxy.devpod.svc.cluster.local:8080}"
NAMESPACE="${NAMESPACE:-devpod}"
# Get API key from secret
echo "Getting API key from secret..."
API_KEY=$(kubectl get secret -n "$NAMESPACE" zai-api-key -o jsonpath='{.data.key}' 2>/dev/null | base64 -d || echo "")
if [ -z "$API_KEY" ]; then
echo -e "${RED}ERROR: Could not get API key from secret${NC}"
echo "Please set API_KEY environment variable or ensure secret exists"
exit 1
fi
# Test counter
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
# Helper functions
print_header() {
echo ""
echo "========================================"
echo "$1"
echo "========================================"
}
print_test() {
TOTAL_TESTS=$((TOTAL_TESTS + 1))
echo -e "\n${YELLOW}[Test $TOTAL_TESTS]${NC} $1"
}
print_pass() {
echo -e "${GREEN}✓ PASS${NC}: $1"
PASSED_TESTS=$((PASSED_TESTS + 1))
}
print_fail() {
echo -e "${RED}✗ FAIL${NC}: $1"
FAILED_TESTS=$((FAILED_TESTS + 1))
}
# Pre-flight checks
print_header "Pre-flight Checks"
echo -n "Checking canary deployment... "
if kubectl get deployment -n "$NAMESPACE" zai-proxy-canary >/dev/null 2>&1; then
print_pass "Canary deployment exists"
else
print_fail "Canary deployment NOT found. Deploy canary first."
exit 1
fi
echo -n "Checking canary service... "
if kubectl get service -n "$NAMESPACE" zai-proxy-canary >/dev/null 2>&1; then
print_pass "Canary service exists"
else
print_fail "Canary service NOT found"
exit 1
fi
echo -n "Checking production pods... "
PROD_PODS=$(kubectl get pods -n "$NAMESPACE" -l app=zai-proxy --no-headers 2>/dev/null | wc -l)
if [ "$PROD_PODS" -ge 5 ]; then
print_pass "Production has $PROD_PODS pods running"
else
print_fail "Production has only $PROD_PODS pods (expected >=5)"
fi
# Test 1: Token Counting Validation
print_header "Test 1: Token Counting Validation"
print_test "Sending basic request to canary..."
RESPONSE=$(curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "glm-4",
"max_tokens": 100,
"messages": [{"role": "user", "content": "Hello, how are you?"}]
}' 2>&1)
if echo "$RESPONSE" | jq -e '.content' >/dev/null 2>&1; then
print_pass "Canary responds with valid JSON"
else
print_fail "Canary response invalid: $RESPONSE"
fi
print_test "Checking Prometheus metrics for token counts..."
METRICS=$(curl -s "$CANARY_URL/metrics" 2>/dev/null || echo "")
if echo "$METRICS" | grep -q "zai_proxy_tokens_total"; then
TOKEN_COUNT=$(echo "$METRICS" | grep "zai_proxy_tokens_total.*direction=\"input\"" | awk '{print $2}')
if [ "$TOKEN_COUNT" -gt 0 ]; then
print_pass "Token counting active: $TOKEN_COUNT input tokens counted"
else
print_fail "Token count is 0"
fi
else
print_fail "Token metrics not found"
fi
print_test "Verifying production has NO token counting..."
PROD_METRICS=$(curl -s "$PROD_URL/metrics" 2>/dev/null || echo "")
if echo "$PROD_METRICS" | grep -q "zai_proxy_tokens_total"; then
PROD_TOKEN_COUNT=$(echo "$PROD_METRICS" | grep "zai_proxy_tokens_total.*direction=\"input\"" | awk '{print $2}')
if [ "$PROD_TOKEN_COUNT" = "0" ] || [ -z "$PROD_TOKEN_COUNT" ]; then
print_pass "Production has no token counting (as expected)"
else
print_fail "Production unexpectedly has token counting: $PROD_TOKEN_COUNT"
fi
else
print_pass "Production has no token metrics (as expected)"
fi
# Test 2: Format Comparison
print_header "Test 2: Format Comparison Tests"
print_test "Comparing response formats..."
PROD_RESPONSE=$(curl -s -X POST "$PROD_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":50,"messages":[{"role":"user","content":"Say hello"}]}' 2>/dev/null)
CANARY_RESPONSE=$(curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":50,"messages":[{"role":"user","content":"Say hello"}]}' 2>/dev/null)
# Check both have required fields
PROD_HAS_ID=$(echo "$PROD_RESPONSE" | jq -e '.id' >/dev/null 2>&1 && echo "yes" || echo "no")
CANARY_HAS_ID=$(echo "$CANARY_RESPONSE" | jq -e '.id' >/dev/null 2>&1 && echo "yes" || echo "no")
PROD_HAS_CONTENT=$(echo "$PROD_RESPONSE" | jq -e '.content' >/dev/null 2>&1 && echo "yes" || echo "no")
CANARY_HAS_CONTENT=$(echo "$CANARY_RESPONSE" | jq -e '.content' >/dev/null 2>&1 && echo "yes" || echo "no")
if [ "$PROD_HAS_ID" = "yes" ] && [ "$CANARY_HAS_ID" = "yes" ] && \
[ "$PROD_HAS_CONTENT" = "yes" ] && [ "$CANARY_HAS_CONTENT" = "yes" ]; then
print_pass "Both responses have identical structure"
else
print_fail "Response structure mismatch"
fi
# Test 3: Performance Benchmarks
print_header "Test 3: Performance Benchmarks"
print_test "Measuring production latency (10 samples)..."
PROD_TOTAL=0
for i in {1..10}; do
START=$(date +%s%3N)
curl -s -X POST "$PROD_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":20,"messages":[{"role":"user","content":"Hi"}]}' >/dev/null 2>&1
END=$(date +%s%3N)
PROD_TOTAL=$((PROD_TOTAL + END - START))
done
PROD_AVG=$((PROD_TOTAL / 10))
echo "Production average: ${PROD_AVG}ms"
print_test "Measuring canary latency (10 samples)..."
CANARY_TOTAL=0
for i in {1..10}; do
START=$(date +%s%3N)
curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":20,"messages":[{"role":"user","content":"Hi"}]}' >/dev/null 2>&1
END=$(date +%s%3N)
CANARY_TOTAL=$((CANARY_TOTAL + END - START))
done
CANARY_AVG=$((CANARY_TOTAL / 10))
echo "Canary average: ${CANARY_AVG}ms"
OVERHEAD=$((CANARY_AVG - PROD_AVG))
if [ $OVERHEAD -lt 50 ]; then
print_pass "Canary overhead: ${OVERHEAD}ms (within 50ms threshold)"
else
print_fail "Canary overhead: ${OVERHEAD}ms (exceeds 50ms threshold)"
fi
# Test 4: Streaming Response Tests
print_header "Test 4: Streaming Response Tests"
print_test "Testing streaming responses..."
STREAM_RESPONSE=$(curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":50,"stream":true,"messages":[{"role":"user","content":"Count to 3"}]}' 2>/dev/null)
if echo "$STREAM_RESPONSE" | grep -q "data:"; then
print_pass "Streaming response format correct"
else
print_fail "Streaming response missing SSE format"
fi
# Test 5: Load Testing
print_header "Test 5: Load Testing (Concurrent Requests)"
print_test "Running 20 concurrent requests..."
FAILURES=0
for i in {1..20}; do
(
curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":20,"messages":[{"role":"user","content":"Test"}]}' >/dev/null 2>&1
) &
done
wait
if [ $FAILURES -eq 0 ]; then
print_pass "All concurrent requests completed"
else
print_fail "$FAILURES requests failed"
fi
# Test 6: Edge Cases
print_header "Test 6: Edge Cases"
print_test "Testing empty message..."
EMPTY_RESPONSE=$(curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":20,"messages":[{"role":"user","content":""}]}' 2>/dev/null)
if echo "$EMPTY_RESPONSE" | jq -e '.content' >/dev/null 2>&1; then
print_pass "Empty message handled"
else
print_fail "Empty message caused error"
fi
print_test "Testing multi-turn conversation..."
MULTI_RESPONSE=$(curl -s -X POST "$CANARY_URL/v1/messages" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-d '{"model":"glm-4","max_tokens":50,"messages":[{"role":"user","content":"What is 2+2?"},{"role":"assistant","content":"4"},{"role":"user","content":"And 3+3?"}]}' 2>/dev/null)
if echo "$MULTI_RESPONSE" | jq -e '.content' >/dev/null 2>&1; then
print_pass "Multi-turn conversation handled"
else
print_fail "Multi-turn conversation failed"
fi
# Test 7: Production Isolation
print_header "Test 7: Production Isolation Verification"
print_test "Verifying production unaffected..."
FINAL_PROD_PODS=$(kubectl get pods -n "$NAMESPACE" -l app=zai-proxy --no-headers 2>/dev/null | wc -l)
if [ "$FINAL_PROD_PODS" = "$PROD_PODS" ]; then
print_pass "Production pods stable ($FINAL_PROD_PODS running)"
else
print_fail "Production pods changed ($PROD_PODS -> $FINAL_PROD_PODS)"
fi
# Final Summary
print_header "Test Summary"
echo ""
echo "Total Tests: $TOTAL_TESTS"
echo -e "${GREEN}Passed: $PASSED_TESTS${NC}"
echo -e "${RED}Failed: $FAILED_TESTS${NC}"
echo ""
if [ $FAILED_TESTS -eq 0 ]; then
echo -e "${GREEN}ALL TESTS PASSED${NC}"
exit 0
else
echo -e "${RED}SOME TESTS FAILED${NC}"
exit 1
fi