QDAirPortBackend0122/deploy/test_collision_prepare_flow.sh

267 lines
8.2 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
HEALTH_PATH="${HEALTH_PATH:-/actuator/health}"
AIRCRAFT_ID="${AIRCRAFT_ID:-SIM-AC-001}"
UNMANNED_ID="${UNMANNED_ID:-SIM-UV-001}"
SPECIAL_ID="${SPECIAL_ID:-SIM-SP-001}"
AIRCRAFT_ROUTE_TYPE="${AIRCRAFT_ROUTE_TYPE:-OUT}"
AIRCRAFT_IN_RUNWAY="${AIRCRAFT_IN_RUNWAY:-35}"
AIRCRAFT_OUT_RUNWAY="${AIRCRAFT_OUT_RUNWAY:-34}"
AIRCRAFT_CONTACT_CROSS="${AIRCRAFT_CONTACT_CROSS:-}"
AIRCRAFT_SEAT="${AIRCRAFT_SEAT:-165}"
AIRCRAFT_START_SEAT="${AIRCRAFT_START_SEAT:-165}"
UV_ROUTE_NAME="${UV_ROUTE_NAME:-SIM_UV_ROUTE_001}"
SP_ROUTE_NAME="${SP_ROUTE_NAME:-SIM_SP_ROUTE_001}"
AUTH_HEADER="${AUTH_HEADER:-}"
CONNECT_TIMEOUT="${CONNECT_TIMEOUT:-5}"
MAX_TIME="${MAX_TIME:-20}"
WORK_DIR="${WORK_DIR:-/tmp/qaup_collision_prepare_test}"
mkdir -p "$WORK_DIR"
log() {
printf '[%s] %s\n' "$(date '+%F %T')" "$*"
}
fail() {
log "FAIL: $*"
exit 1
}
have_jq() {
command -v jq >/dev/null 2>&1
}
json_get() {
local file="$1"
local expr="$2"
if have_jq; then
jq -r "$expr" "$file"
else
python3 - "$file" "$expr" <<'PY'
import json
import sys
path = sys.argv[2].strip().lstrip(".")
parts = [p for p in path.split(".") if p]
with open(sys.argv[1], "r", encoding="utf-8") as f:
data = json.load(f)
for part in parts:
if isinstance(data, list):
data = data[int(part)]
else:
data = data.get(part)
print("" if data is None else data)
PY
fi
}
json_contains_text() {
local file="$1"
local expected="$2"
grep -Fq "$expected" "$file"
}
curl_json() {
local method="$1"
local path="$2"
local body_file="${3:-}"
local response_file="$4"
local curl_args=(
--silent
--show-error
--connect-timeout "$CONNECT_TIMEOUT"
--max-time "$MAX_TIME"
--request "$method"
--header 'Content-Type: application/json'
--write-out '%{http_code}'
--output "$response_file"
)
if [[ -n "$AUTH_HEADER" ]]; then
curl_args+=(--header "Authorization: $AUTH_HEADER")
fi
if [[ -n "$body_file" ]]; then
curl_args+=(--data @"$body_file")
fi
curl "${curl_args[@]}" "${BASE_URL}${path}"
}
assert_http_ok() {
local code="$1"
local context="$2"
[[ "$code" == "200" ]] || fail "$context returned HTTP $code"
}
write_json() {
local file="$1"
shift
cat > "$file" <<EOF
$*
EOF
}
print_json() {
local file="$1"
if have_jq; then
jq . "$file"
else
cat "$file"
fi
}
run_health_check() {
log "Checking application health: ${BASE_URL}${HEALTH_PATH}"
local response_file="$WORK_DIR/health.json"
local code
code="$(curl --silent --show-error --connect-timeout "$CONNECT_TIMEOUT" --max-time "$MAX_TIME" --output "$response_file" --write-out '%{http_code}' "${BASE_URL}${HEALTH_PATH}")"
assert_http_ok "$code" "Health check"
log "Health check passed"
}
sync_registry() {
local body_file="$WORK_DIR/vehicle_registry.json"
local response_file="$WORK_DIR/vehicle_registry_response.json"
write_json "$body_file" "[
{\"vehicleID\":\"${UNMANNED_ID}\",\"vehicleType\":\"WUREN\"},
{\"vehicleID\":\"${SPECIAL_ID}\",\"vehicleType\":\"TEQIN\"},
{\"vehicleID\":\"${AIRCRAFT_ID}\",\"vehicleType\":\"HANGKONG\"}
]"
log "Registering simulated collision objects"
local code
code="$(curl_json POST /api/VehicleRegistry "$body_file" "$response_file")"
assert_http_ok "$code" "Vehicle registry"
[[ "$(json_get "$response_file" '.status')" == "success" ]] || fail "Vehicle registry response status is not success"
log "Registry synchronized"
}
query_preparation_status() {
local tag="$1"
local response_file="$WORK_DIR/preparation_status_${tag}.json"
local code
code="$(curl_json POST /api/collision/preparation/status "" "$response_file")"
assert_http_ok "$code" "Collision preparation status"
[[ "$(json_get "$response_file" '.status')" == "success" ]] || fail "Preparation status response status is not success"
print_json "$response_file"
}
assert_not_ready_before_binding() {
local response_file="$WORK_DIR/preparation_status_before.json"
local ready
ready="$(json_get "$response_file" '.ready')"
[[ "$ready" == "false" ]] || fail "Preparation status should be false before routes are bound"
json_contains_text "$response_file" "$AIRCRAFT_ID" || fail "Preparation status missing aircraft id before binding"
json_contains_text "$response_file" "$UNMANNED_ID" || fail "Preparation status missing unmanned id before binding"
json_contains_text "$response_file" "$SPECIAL_ID" || fail "Preparation status missing special vehicle id before binding"
log "Preparation status correctly reports missing route bindings"
}
bind_aircraft_route() {
local body_file="$WORK_DIR/aircraft_route_query.json"
local response_file="$WORK_DIR/aircraft_route_query_response.json"
if [[ "$AIRCRAFT_ROUTE_TYPE" == "OUT" ]]; then
write_json "$body_file" "{
\"objectId\": \"${AIRCRAFT_ID}\",
\"routeType\": \"OUT\",
\"outRunway\": \"${AIRCRAFT_OUT_RUNWAY}\",
\"inRunway\": \"${AIRCRAFT_IN_RUNWAY}\",
\"seat\": \"${AIRCRAFT_SEAT}\",
\"startSeat\": \"${AIRCRAFT_START_SEAT:-$AIRCRAFT_SEAT}\"
}"
else
write_json "$body_file" "{
\"objectId\": \"${AIRCRAFT_ID}\",
\"routeType\": \"IN\",
\"inRunway\": \"${AIRCRAFT_IN_RUNWAY}\",
\"outRunway\": \"${AIRCRAFT_OUT_RUNWAY}\",
\"contactCross\": \"${AIRCRAFT_CONTACT_CROSS}\",
\"seat\": \"${AIRCRAFT_SEAT}\"
}"
fi
log "Querying and binding aircraft route"
local code
code="$(curl_json POST /api/aircraft-routes/query "$body_file" "$response_file")"
assert_http_ok "$code" "Aircraft route query"
[[ "$(json_get "$response_file" '.code')" == "200" ]] || fail "Aircraft route query code is not 200"
[[ "$(json_get "$response_file" '.data.bindingObjectId')" == "$AIRCRAFT_ID" ]] || fail "Aircraft route bindingObjectId mismatch"
[[ "$(json_get "$response_file" '.data.routeBound')" == "true" ]] || fail "Aircraft route was not bound"
log "Aircraft route bound successfully"
}
bind_vehicle_route() {
local vehicle_id="$1"
local vehicle_type="$2"
local route_name="$3"
local point_a_lon="$4"
local point_a_lat="$5"
local point_b_lon="$6"
local point_b_lat="$7"
local response_tag="$8"
local body_file="$WORK_DIR/${response_tag}_route_assignment.json"
local response_file="$WORK_DIR/${response_tag}_route_assignment_response.json"
write_json "$body_file" "{
\"vehicleID\": \"${vehicle_id}\",
\"vehicleType\": \"${vehicle_type}\",
\"routeName\": \"${route_name}\",
\"route\": {
\"points\": [
{\"lon\": ${point_a_lon}, \"lat\": ${point_a_lat}},
{\"lon\": ${point_b_lon}, \"lat\": ${point_b_lat}}
]
}
}"
log "Binding route for ${vehicle_type} ${vehicle_id}"
local code
code="$(curl_json POST /api/vehicle-route/assignment "$body_file" "$response_file")"
assert_http_ok "$code" "Vehicle route assignment for ${vehicle_id}"
[[ "$(json_get "$response_file" '.status')" == "success" ]] || fail "Route assignment failed for ${vehicle_id}"
[[ "$(json_get "$response_file" '.objectId')" == "$vehicle_id" ]] || fail "Route assignment objectId mismatch for ${vehicle_id}"
log "Route bound for ${vehicle_id}"
}
assert_ready_after_binding() {
local response_file="$WORK_DIR/preparation_status_after.json"
[[ "$(json_get "$response_file" '.ready')" == "true" ]] || fail "Preparation status should be true after routes are bound"
[[ "$(json_get "$response_file" '.summary.registeredCount')" == "3" ]] || fail "Expected 3 registered collision objects"
[[ "$(json_get "$response_file" '.summary.missingRouteCount')" == "0" ]] || fail "Expected 0 missing routes after binding"
log "Preparation status confirms all registered objects are ready"
}
main() {
log "Starting collision preparation interface test"
log "BASE_URL=${BASE_URL}"
log "AIRCRAFT_ID=${AIRCRAFT_ID}, UNMANNED_ID=${UNMANNED_ID}, SPECIAL_ID=${SPECIAL_ID}"
run_health_check
sync_registry
query_preparation_status before
assert_not_ready_before_binding
bind_aircraft_route
bind_vehicle_route "$UNMANNED_ID" "WUREN" "$UV_ROUTE_NAME" 120.1000 36.1000 120.2000 36.2000 "uv"
bind_vehicle_route "$SPECIAL_ID" "TEQIN" "$SP_ROUTE_NAME" 120.1000 36.2000 120.2000 36.1000 "sp"
query_preparation_status after
assert_ready_after_binding
log "PASS: collision preparation interface flow is ready for deployment testing"
}
main "$@"