#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" API_URL="${API_URL:-http://localhost:18980}" cleanup() { echo "Cleaning up..." } trap cleanup EXIT echo "=== Satellite Provider Performance Tests ===" echo "API URL: $API_URL" echo "" PASS=0 FAIL=0 check_threshold() { local test_name="$1" local actual_ms="$2" local threshold_ms="$3" if (( actual_ms <= threshold_ms )); then echo " ✓ $test_name: ${actual_ms}ms (threshold: ${threshold_ms}ms)" PASS=$((PASS + 1)) else echo " ✗ $test_name: ${actual_ms}ms EXCEEDS threshold ${threshold_ms}ms" FAIL=$((FAIL + 1)) fi } wait_region_completed() { local region_id="$1" local timeout_s="${2:-180}" local elapsed=0 while (( elapsed < timeout_s )); do local status status=$(curl -s "$API_URL/api/satellite/region/$region_id" | grep -o '"status":"[^"]*"' | head -1 || true) case "$status" in *completed*) return 0 ;; *failed*) echo " region $region_id failed during wait" >&2; return 2 ;; esac sleep 2 elapsed=$((elapsed + 2)) done return 1 } # PT-01: Tile download latency for a fresh tile (cold path). # Uses lat/lon offset so the cache miss is likely; threshold 30s. echo "PT-01: Tile Download Latency (cold) (threshold: 30000ms)" PT01_LAT="47.461347" PT01_LON="37.646663" START=$(date +%s%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL/api/satellite/tiles/latlon?Latitude=$PT01_LAT&Longitude=$PT01_LON&ZoomLevel=18") END=$(date +%s%N) ELAPSED_MS=$(( (END - START) / 1000000 )) if [[ "$HTTP_CODE" == "200" ]]; then check_threshold "Tile download (cold)" "$ELAPSED_MS" 30000 else echo " ✗ PT-01: HTTP $HTTP_CODE (expected 200)" FAIL=$((FAIL + 1)) fi echo "" echo "PT-02: Cached Tile Retrieval Latency (threshold: 500ms)" START=$(date +%s%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL/api/satellite/tiles/latlon?Latitude=47.461747&Longitude=37.647063&ZoomLevel=18") END=$(date +%s%N) ELAPSED_MS=$(( (END - START) / 1000000 )) if [[ "$HTTP_CODE" == "200" ]]; then check_threshold "Cached tile retrieval" "$ELAPSED_MS" 500 else echo " ✗ PT-02: HTTP $HTTP_CODE (expected 200) - tile may not be cached yet" FAIL=$((FAIL + 1)) fi # PT-03: Region 200m at zoom 18, no stitching, threshold 60s end-to-end. echo "" echo "PT-03: Region Processing 200m / zoom 18 (threshold: 60000ms)" PT03_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') PT03_BODY="{\"id\":\"$PT03_ID\",\"latitude\":47.461747,\"longitude\":37.647063,\"sizeMeters\":200,\"zoomLevel\":18,\"stitchTiles\":false}" START=$(date +%s%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "$PT03_BODY" "$API_URL/api/satellite/request") if [[ "$HTTP_CODE" == "200" || "$HTTP_CODE" == "202" ]]; then if wait_region_completed "$PT03_ID" 60; then END=$(date +%s%N) ELAPSED_MS=$(( (END - START) / 1000000 )) check_threshold "Region 200m/z18" "$ELAPSED_MS" 60000 else echo " ✗ PT-03: region did not complete within 60s" FAIL=$((FAIL + 1)) fi else echo " ✗ PT-03: enqueue HTTP $HTTP_CODE (expected 200/202)" FAIL=$((FAIL + 1)) fi # PT-04: Region 500m at zoom 18 with stitching, threshold 120s end-to-end. echo "" echo "PT-04: Region Processing 500m / zoom 18 + stitch (threshold: 120000ms)" PT04_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') PT04_BODY="{\"id\":\"$PT04_ID\",\"latitude\":47.461747,\"longitude\":37.647063,\"sizeMeters\":500,\"zoomLevel\":18,\"stitchTiles\":true}" START=$(date +%s%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "$PT04_BODY" "$API_URL/api/satellite/request") if [[ "$HTTP_CODE" == "200" || "$HTTP_CODE" == "202" ]]; then if wait_region_completed "$PT04_ID" 120; then END=$(date +%s%N) ELAPSED_MS=$(( (END - START) / 1000000 )) check_threshold "Region 500m/z18 stitched" "$ELAPSED_MS" 120000 else echo " ✗ PT-04: region did not complete within 120s" FAIL=$((FAIL + 1)) fi else echo " ✗ PT-04: enqueue HTTP $HTTP_CODE (expected 200/202)" FAIL=$((FAIL + 1)) fi # PT-05: 5 concurrent regions all complete within 5min (300s) end-to-end. echo "" echo "PT-05: Concurrent Region Processing (5 in 300000ms)" PT05_IDS=() PT05_START=$(date +%s%N) for i in 1 2 3 4 5; do rid=$(uuidgen | tr '[:upper:]' '[:lower:]') PT05_IDS+=("$rid") LAT=$(awk "BEGIN { printf \"%.6f\", 47.461747 + 0.001 * $i }") LON=$(awk "BEGIN { printf \"%.6f\", 37.647063 + 0.001 * $i }") BODY="{\"id\":\"$rid\",\"latitude\":$LAT,\"longitude\":$LON,\"sizeMeters\":200,\"zoomLevel\":18,\"stitchTiles\":false}" HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "$BODY" "$API_URL/api/satellite/request") if [[ "$HTTP_CODE" != "200" && "$HTTP_CODE" != "202" ]]; then echo " ✗ PT-05: enqueue $i HTTP $HTTP_CODE (expected 200/202)" FAIL=$((FAIL + 1)) fi done PT05_OK=1 for rid in "${PT05_IDS[@]}"; do if ! wait_region_completed "$rid" 300; then PT05_OK=0 echo " ✗ PT-05: region $rid did not complete within 300s" break fi done if (( PT05_OK == 1 )); then PT05_END=$(date +%s%N) ELAPSED_MS=$(( (PT05_END - PT05_START) / 1000000 )) check_threshold "5 concurrent regions" "$ELAPSED_MS" 300000 else FAIL=$((FAIL + 1)) fi echo "" echo "PT-06: Route Point Interpolation Speed (threshold: 5000ms)" ROUTE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') BODY="{\"id\":\"$ROUTE_ID\",\"name\":\"Perf Test\",\"regionSizeMeters\":300,\"zoomLevel\":18,\"points\":[{\"lat\":48.276067,\"lon\":37.384458},{\"lat\":48.270740,\"lon\":37.374029}]}" START=$(date +%s%N) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "Content-Type: application/json" -d "$BODY" "$API_URL/api/satellite/route") END=$(date +%s%N) ELAPSED_MS=$(( (END - START) / 1000000 )) if [[ "$HTTP_CODE" == "200" ]]; then check_threshold "Route creation (2 points)" "$ELAPSED_MS" 5000 else echo " ✗ PT-06: HTTP $HTTP_CODE (expected 200)" FAIL=$((FAIL + 1)) fi echo "" echo "=== Performance Test Summary ===" echo " Passed: $PASS" echo " Failed: $FAIL" echo "" if [[ $FAIL -gt 0 ]]; then echo "FAILED: $FAIL performance threshold(s) exceeded" exit 1 fi echo "ALL PERFORMANCE TESTS PASSED" exit 0