prefect server in zig
at main 292 lines 8.1 kB view raw
1#!/usr/bin/env bash 2# test-matrix - run integration tests across all backend combinations 3# 4# combinations tested: 5# 1. sqlite + memory broker 6# 2. sqlite + redis broker 7# 3. postgres + memory broker 8# 4. postgres + redis broker 9# 10# usage: 11# ./scripts/test-matrix # run full matrix (default) 12# ./scripts/test-matrix --quick # sqlite + memory only (fast local dev) 13# ./scripts/test-matrix --no-cleanup # keep containers running after 14 15set -euo pipefail 16 17SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 18PROJECT_DIR="$(dirname "$SCRIPT_DIR")" 19 20RED='\033[0;31m' 21GREEN='\033[0;32m' 22YELLOW='\033[1;33m' 23BLUE='\033[0;34m' 24CYAN='\033[0;36m' 25NC='\033[0m' 26 27info() { echo -e "${GREEN}[INFO]${NC} $*"; } 28step() { echo -e "${BLUE}[STEP]${NC} $*"; } 29warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } 30error() { echo -e "${RED}[ERROR]${NC} $*"; } 31matrix() { echo -e "${CYAN}[MATRIX]${NC} $*"; } 32 33SERVER_PID="" 34TEST_PORT=4202 35POSTGRES_PORT=5434 36REDIS_PORT=6380 37CLEANUP=true 38QUICK_MODE=false 39 40# parse args 41for arg in "$@"; do 42 case $arg in 43 --quick) QUICK_MODE=true ;; 44 --no-cleanup) CLEANUP=false ;; 45 esac 46done 47 48cleanup() { 49 if [[ -n "$SERVER_PID" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then 50 kill "$SERVER_PID" 2>/dev/null || true 51 wait "$SERVER_PID" 2>/dev/null || true 52 fi 53 lsof -ti:$TEST_PORT 2>/dev/null | xargs -r kill 2>/dev/null || true 54 rm -f /tmp/prefect-matrix-*.db 2>/dev/null || true 55} 56trap cleanup EXIT 57 58wait_for_server() { 59 local timeout=${1:-30} 60 local count=0 61 while [[ $count -lt $timeout ]]; do 62 if curl -s "http://localhost:$TEST_PORT/api/health" >/dev/null 2>&1; then 63 return 0 64 fi 65 sleep 0.5 66 ((count++)) 67 done 68 return 1 69} 70 71wait_for_postgres() { 72 local timeout=${1:-30} 73 local count=0 74 while [[ $count -lt $timeout ]]; do 75 if docker exec prefect-test-matrix-postgres pg_isready -U prefect >/dev/null 2>&1; then 76 return 0 77 fi 78 sleep 1 79 ((count++)) 80 done 81 return 1 82} 83 84start_services() { 85 step "Starting docker services (postgres + redis)..." 86 87 # stop any existing test containers 88 docker rm -f prefect-test-matrix-postgres prefect-test-matrix-redis 2>/dev/null || true 89 90 # start postgres 91 docker run -d \ 92 --name prefect-test-matrix-postgres \ 93 -e POSTGRES_USER=prefect \ 94 -e POSTGRES_PASSWORD=prefect \ 95 -e POSTGRES_DB=prefect_test \ 96 -p "${POSTGRES_PORT}:5432" \ 97 postgres:16-alpine >/dev/null 2>&1 98 99 # start redis 100 docker run -d \ 101 --name prefect-test-matrix-redis \ 102 -p "${REDIS_PORT}:6379" \ 103 redis:7-alpine >/dev/null 2>&1 104 105 # wait for postgres 106 if ! wait_for_postgres 30; then 107 error "PostgreSQL failed to start" 108 return 1 109 fi 110 111 # wait for redis 112 local count=0 113 while [[ $count -lt 30 ]]; do 114 if redis-cli -p "$REDIS_PORT" ping >/dev/null 2>&1; then 115 break 116 fi 117 sleep 0.5 118 ((count++)) 119 done 120 121 info "Services ready" 122} 123 124stop_services() { 125 if [[ "$CLEANUP" == "true" ]]; then 126 step "Stopping docker services..." 127 docker rm -f prefect-test-matrix-postgres prefect-test-matrix-redis 2>/dev/null || true 128 else 129 info "Leaving containers running (--no-cleanup)" 130 fi 131} 132 133# run a single test configuration 134run_test() { 135 local db_backend="$1" 136 local broker_backend="$2" 137 local label="${db_backend}+${broker_backend}" 138 139 matrix "Testing: $label" 140 141 # prepare environment 142 local db_path="/tmp/prefect-matrix-${db_backend}-${broker_backend}-$$.db" 143 rm -f "$db_path" 144 145 export PREFECT_SERVER_PORT=$TEST_PORT 146 export PREFECT_SERVER_LOGGING_LEVEL=WARNING 147 export PREFECT_BROKER_BACKEND="$broker_backend" 148 149 if [[ "$db_backend" == "sqlite" ]]; then 150 export PREFECT_DATABASE_BACKEND=sqlite 151 export PREFECT_DATABASE_PATH="$db_path" 152 unset PREFECT_DATABASE_URL 2>/dev/null || true 153 else 154 export PREFECT_DATABASE_BACKEND=postgres 155 export PREFECT_DATABASE_URL="postgresql://prefect:prefect@localhost:${POSTGRES_PORT}/prefect_test" 156 # truncate all tables between tests (safer than DROP SCHEMA which breaks connections) 157 docker exec prefect-test-matrix-postgres psql -U prefect -d prefect_test -c " 158 DO \$\$ DECLARE r RECORD; 159 BEGIN 160 FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP 161 EXECUTE 'TRUNCATE TABLE ' || quote_ident(r.tablename) || ' CASCADE'; 162 END LOOP; 163 END \$\$; 164 " >/dev/null 2>&1 || true 165 fi 166 167 if [[ "$broker_backend" == "redis" ]]; then 168 export PREFECT_REDIS_MESSAGING_HOST=localhost 169 export PREFECT_REDIS_MESSAGING_PORT=$REDIS_PORT 170 # clear redis between tests 171 redis-cli -p "$REDIS_PORT" FLUSHALL >/dev/null 2>&1 || true 172 fi 173 174 # start server 175 "$PROJECT_DIR/zig-out/bin/prefect-server" & 176 SERVER_PID=$! 177 178 if ! wait_for_server 30; then 179 error "[$label] Server failed to start" 180 return 1 181 fi 182 183 # run test suite 184 step "[$label] Running API tests..." 185 if PREFECT_API_URL="http://localhost:$TEST_PORT/api" "$PROJECT_DIR/scripts/test-api-sequence" >/dev/null 2>&1; then 186 info "[$label] PASSED" 187 local result=0 188 else 189 error "[$label] FAILED" 190 local result=1 191 fi 192 193 # stop server 194 kill "$SERVER_PID" 2>/dev/null || true 195 wait "$SERVER_PID" 2>/dev/null || true 196 SERVER_PID="" 197 198 # ensure port is released before next test 199 local port_wait=0 200 while [[ $port_wait -lt 20 ]] && lsof -ti:$TEST_PORT >/dev/null 2>&1; do 201 lsof -ti:$TEST_PORT 2>/dev/null | xargs -r kill 2>/dev/null || true 202 sleep 0.25 203 ((port_wait++)) 204 done 205 206 rm -f "$db_path" 207 return $result 208} 209 210main() { 211 echo "" 212 matrix "============================================" 213 matrix " prefect-server test matrix" 214 matrix "============================================" 215 echo "" 216 217 # build first 218 step "Building..." 219 (cd "$PROJECT_DIR" && zig build) || { error "Build failed"; exit 1; } 220 221 # run unit tests 222 step "Running unit tests..." 223 (cd "$PROJECT_DIR" && zig build test --summary all 2>&1) || { error "Unit tests failed"; exit 1; } 224 echo "" 225 226 if [[ "$QUICK_MODE" == "true" ]]; then 227 matrix "Quick mode: sqlite + memory only" 228 echo "" 229 230 run_test sqlite memory || exit 1 231 232 echo "" 233 matrix "============================================" 234 matrix " QUICK TEST PASSED (1/4 combinations)" 235 matrix "============================================" 236 echo "" 237 warn "Run without --quick to test full matrix" 238 exit 0 239 fi 240 241 # start services for full matrix 242 start_services || exit 1 243 echo "" 244 245 # track results 246 local passed=0 247 local failed=0 248 declare -a results=() 249 250 # test all 4 combinations 251 for db in sqlite postgres; do 252 for broker in memory redis; do 253 step "Starting test: ${db}+${broker}" 254 if run_test "$db" "$broker"; then 255 results+=("${GREEN}PASS${NC} ${db}+${broker}") 256 ((passed++)) || true 257 else 258 results+=("${RED}FAIL${NC} ${db}+${broker}") 259 ((failed++)) || true 260 fi 261 step "Completed test: ${db}+${broker}" 262 echo "" 263 done 264 done 265 266 # cleanup 267 stop_services 268 269 # summary 270 echo "" 271 matrix "============================================" 272 matrix " TEST MATRIX RESULTS" 273 matrix "============================================" 274 for r in "${results[@]}"; do 275 echo -e " $r" 276 done 277 echo "" 278 matrix "Passed: $passed / 4" 279 280 if [[ $failed -gt 0 ]]; then 281 error "Matrix test FAILED" 282 exit 1 283 fi 284 285 echo "" 286 matrix "============================================" 287 matrix " ALL 4 COMBINATIONS PASSED" 288 matrix "============================================" 289 echo "" 290} 291 292main