#!/bin/bash # RFCP Propagation Models Test # Tests all propagation presets and validates results # Usage: ./rfcp-propagation-test.sh [base_url] BASE_URL="${1:-https://api.rfcp.eliah.one}" PASSED=0 FAILED=0 # Colors GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # Test site (центр Дніпра) TEST_LAT=48.46 TEST_LON=35.05 TEST_HEIGHT=30 TEST_POWER=43 TEST_GAIN=15 TEST_FREQ=1800 echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo " RFCP Propagation Models Test" echo " Target: $BASE_URL" echo " Site: $TEST_LAT, $TEST_LON (Dnipro)" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Helper function test_preset() { local preset="$1" local radius="$2" local resolution="$3" local expected_models="$4" local max_time="$5" echo -e "${CYAN}Testing preset: $preset${NC}" echo " Radius: ${radius}m, Resolution: ${resolution}m" start_time=$(date +%s.%N) response=$(curl -s -X POST "$BASE_URL/api/coverage/calculate" \ -H "Content-Type: application/json" \ -d "{ \"sites\": [{ \"lat\": $TEST_LAT, \"lon\": $TEST_LON, \"height\": $TEST_HEIGHT, \"power\": $TEST_POWER, \"gain\": $TEST_GAIN, \"frequency\": $TEST_FREQ }], \"settings\": { \"radius\": $radius, \"resolution\": $resolution, \"preset\": \"$preset\" } }") end_time=$(date +%s.%N) curl_time=$(echo "$end_time - $start_time" | bc) # Parse response count=$(echo "$response" | jq -r '.count // 0') comp_time=$(echo "$response" | jq -r '.computation_time // 0') models=$(echo "$response" | jq -r '.models_used | join(", ") // "none"') min_rsrp=$(echo "$response" | jq -r '.stats.min_rsrp // 0' | xargs printf "%.1f") max_rsrp=$(echo "$response" | jq -r '.stats.max_rsrp // 0' | xargs printf "%.1f") avg_rsrp=$(echo "$response" | jq -r '.stats.avg_rsrp // 0' | xargs printf "%.1f") los_pct=$(echo "$response" | jq -r '.stats.los_percentage // 0' | xargs printf "%.1f") terrain_pts=$(echo "$response" | jq -r '.stats.points_with_terrain_loss // 0') building_pts=$(echo "$response" | jq -r '.stats.points_with_buildings // 0') reflection_pts=$(echo "$response" | jq -r '.stats.points_with_reflection_gain // 0') # Validate local errors=0 # Check count > 0 if [ "$count" -eq 0 ]; then echo -e " ${RED}✗ No points returned${NC}" ((errors++)) else echo -e " ${GREEN}✓${NC} Points: $count" fi # Check models if [[ "$models" == *"$expected_models"* ]] || [ -z "$expected_models" ]; then echo -e " ${GREEN}✓${NC} Models: $models" else echo -e " ${YELLOW}⚠${NC} Models: $models (expected: $expected_models)" fi # Check computation time if (( $(echo "$comp_time > $max_time" | bc -l) )); then echo -e " ${YELLOW}⚠${NC} Time: ${comp_time}s (expected < ${max_time}s)" else echo -e " ${GREEN}✓${NC} Time: ${comp_time}s" fi # Check RSRP range (sanity check) if (( $(echo "$max_rsrp > 0" | bc -l) )); then echo -e " ${RED}✗ Max RSRP > 0 dBm (impossible): $max_rsrp${NC}" ((errors++)) elif (( $(echo "$min_rsrp < -150" | bc -l) )); then echo -e " ${RED}✗ Min RSRP < -150 dBm (too low): $min_rsrp${NC}" ((errors++)) else echo -e " ${GREEN}✓${NC} RSRP range: $min_rsrp to $max_rsrp dBm (avg: $avg_rsrp)" fi # Stats echo " LoS: ${los_pct}% | Terrain: $terrain_pts | Buildings: $building_pts | Reflections: $reflection_pts" if [ $errors -eq 0 ]; then echo -e " ${GREEN}PASSED${NC}" ((PASSED++)) else echo -e " ${RED}FAILED${NC}" ((FAILED++)) fi echo "" } # Test presets endpoint echo -e "${CYAN}Testing presets endpoint...${NC}" presets_response=$(curl -s "$BASE_URL/api/coverage/presets") presets_count=$(echo "$presets_response" | jq '.presets | keys | length') if [ "$presets_count" -eq 4 ]; then echo -e "${GREEN}✓${NC} Presets endpoint: $presets_count presets found" ((PASSED++)) else echo -e "${RED}✗${NC} Presets endpoint: expected 4, got $presets_count" ((FAILED++)) fi echo "" # Test terrain endpoint echo -e "${CYAN}Testing terrain elevation...${NC}" elevation=$(curl -s "$BASE_URL/api/terrain/elevation?lat=$TEST_LAT&lon=$TEST_LON" | jq '.elevation') if (( $(echo "$elevation > 0 && $elevation < 500" | bc -l) )); then echo -e "${GREEN}✓${NC} Elevation at test site: ${elevation}m" ((PASSED++)) else echo -e "${RED}✗${NC} Invalid elevation: $elevation" ((FAILED++)) fi echo "" # Test each preset echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo " Preset Tests" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Fast - 2km radius, should be quick test_preset "fast" 2000 100 "terrain_los" 10 # Standard - 1km radius with buildings test_preset "standard" 1000 100 "materials" 60 # Detailed - smaller radius, dominant path test_preset "detailed" 500 100 "dominant_path" 120 # Full - smallest radius, all models test_preset "full" 300 50 "reflections" 300 # Test buildings endpoint echo -e "${CYAN}Testing buildings endpoint...${NC}" buildings_count=$(curl -s "$BASE_URL/api/coverage/buildings?min_lat=48.455&min_lon=35.045&max_lat=48.465&max_lon=35.055" | jq '.count') if [ "$buildings_count" -gt 0 ]; then echo -e "${GREEN}✓${NC} Buildings in test area: $buildings_count" ((PASSED++)) else echo -e "${YELLOW}⚠${NC} No buildings found (may be cached or OSM issue)" fi echo "" # Multi-site test echo -e "${CYAN}Testing multi-site coverage...${NC}" multi_response=$(curl -s -X POST "$BASE_URL/api/coverage/calculate" \ -H "Content-Type: application/json" \ -d '{ "sites": [ {"lat": 48.46, "lon": 35.05, "height": 30, "power": 43, "gain": 15, "frequency": 1800}, {"lat": 48.47, "lon": 35.06, "height": 25, "power": 40, "gain": 12, "frequency": 1800} ], "settings": {"radius": 1000, "resolution": 100, "preset": "fast"} }') multi_count=$(echo "$multi_response" | jq '.count') if [ "$multi_count" -gt 0 ]; then echo -e "${GREEN}✓${NC} Multi-site coverage: $multi_count points" ((PASSED++)) else echo -e "${RED}✗${NC} Multi-site coverage failed" ((FAILED++)) fi echo "" # Summary echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" TOTAL=$((PASSED + FAILED)) if [ $FAILED -eq 0 ]; then echo -e " ${GREEN}All tests passed!${NC} ($PASSED/$TOTAL)" else echo -e " ${YELLOW}Results:${NC} ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}" fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" exit $FAILED