342 lines
11 KiB
Bash
Executable File
342 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# SciCam Logger API Client Test Suite
|
|
# Usage: ./scicam_api_test.sh <device-ip>
|
|
# Note: server filenames are now <device_name>_<date>_<time>.ext (e.g. Pixel_7_20260101_120000.jpg)
|
|
|
|
IP=${1:-}
|
|
if [ -z "$IP" ]; then
|
|
echo "Usage: $0 <device-ip>"
|
|
echo "Example: $0 192.168.1.42"
|
|
exit 1
|
|
fi
|
|
|
|
BASE="http://${IP}:8080"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
# Helper functions
|
|
ok() { echo " [PASS] $1"; ((PASS+=1)) || true; }
|
|
err() { echo " [FAIL] $1"; ((FAIL+=1)) || true; }
|
|
|
|
req() {
|
|
local method=$1 endpoint=$2 extra_args="${3:-}"
|
|
local url="${BASE}${endpoint}"
|
|
if [ -n "$extra_args" ]; then
|
|
curl -s -w "\n%{http_code}" -X "$method" $extra_args "$url"
|
|
else
|
|
curl -s -w "\n%{http_code}" -X "$method" "$url"
|
|
fi
|
|
}
|
|
|
|
echo "========================================"
|
|
echo "SciCam API Client Tests"
|
|
echo "Target: $BASE"
|
|
echo "========================================"
|
|
echo
|
|
|
|
# Test 1: GET /api
|
|
echo "Test 1: GET /api (metadata)"
|
|
RESPONSE=$(req GET "/api")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"name":"SciCam API"'; then
|
|
ok "Returns 200 with API metadata"
|
|
else
|
|
err "Expected 200 + API metadata, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 2: GET /status
|
|
echo "Test 2: GET /status (current state)"
|
|
RESPONSE=$(req GET "/status")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"item_id"'; then
|
|
ok "Returns 200 with status fields"
|
|
else
|
|
err "Expected 200 + status JSON, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 3: POST /settings - set item_id and tags
|
|
echo "Test 3: POST /settings (update metadata)"
|
|
RESPONSE=$(req POST "/settings" "-H Content-Type:application/json -d {\"item_id\":\"API-TEST-001\",\"tags\":\"api-test,client\"}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"item_id":"API-TEST-001"'; then
|
|
ok "Returns 200 and reflects updated item_id"
|
|
else
|
|
err "Expected 200 + updated state, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 4: POST /settings - toggle lock
|
|
echo "Test 4: POST /settings (toggle AE/AWB lock)"
|
|
RESPONSE=$(req POST "/settings" "-H Content-Type:application/json -d {\"lock\":true}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"locked":true'; then
|
|
ok "Returns 200 and lock is true"
|
|
else
|
|
err "Expected 200 + locked=true, got HTTP $CODE / $BODY"
|
|
fi
|
|
# Unlock for subsequent tests
|
|
req POST "/settings" "-H Content-Type:application/json -d {\"lock\":false}" >/dev/null
|
|
ok "Unlocked AE/AWB after test"
|
|
echo
|
|
|
|
# Test 5: POST /capture
|
|
echo "Test 5: POST /capture (trigger photo)"
|
|
RESPONSE=$(req POST "/capture" "--max-time 15")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"success":true'; then
|
|
ok "Returns 200 and capture succeeded"
|
|
elif echo "$BODY" | grep -q '"error":"Camera not ready"'; then
|
|
err "Camera not ready (may need a few seconds after app launch)"
|
|
else
|
|
err "Expected 200 + success, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 6: GET /capture should return 404
|
|
echo "Test 6: GET /capture (wrong method)"
|
|
RESPONSE=$(req GET "/capture")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "404" ] || [ "$CODE" = "405" ]; then
|
|
ok "Returns 404/405 for GET as expected"
|
|
else
|
|
err "Expected 404/405 for GET /capture, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 7: POST /api should return 404
|
|
echo "Test 7: POST /api (wrong method)"
|
|
RESPONSE=$(req POST "/api")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "404" ] || [ "$CODE" = "405" ]; then
|
|
ok "Returns 404/405 for POST as expected"
|
|
else
|
|
err "Expected 404/405 for POST /api, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 8: Verify status after capture
|
|
echo "Test 8: GET /status (verify last_capture populated)"
|
|
RESPONSE=$(req GET "/status")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"last_capture"'; then
|
|
ok "Returns 200 with last_capture field"
|
|
else
|
|
err "Expected 200 + last_capture, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 9: POST /auto-capture enable
|
|
echo "Test 9: POST /auto-capture (enable)"
|
|
RESPONSE=$(req POST "/auto-capture" "-H Content-Type:application/json -d {\"enabled\":true}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"auto_capture":true'; then
|
|
ok "Returns 200 and auto_capture is true"
|
|
else
|
|
err "Expected 200 + auto_capture=true, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 10: POST /auto-capture disable
|
|
echo "Test 10: POST /auto-capture (disable)"
|
|
RESPONSE=$(req POST "/auto-capture" "-H Content-Type:application/json -d {\"enabled\":false}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"auto_capture":false'; then
|
|
ok "Returns 200 and auto_capture is false"
|
|
else
|
|
err "Expected 200 + auto_capture=false, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 11: GET /auto-capture should return 404
|
|
echo "Test 11: GET /auto-capture (wrong method)"
|
|
RESPONSE=$(req GET "/auto-capture")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "404" ] || [ "$CODE" = "405" ]; then
|
|
ok "Returns 404/405 for GET as expected"
|
|
else
|
|
err "Expected 404/405 for GET /auto-capture, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 12: GET /photo/last should return 404 when no capture exists yet or a photo if capture succeeded
|
|
# Note: If Test 5 passed, a photo exists and /photo/last should return 200. If Test 5 failed, 404 is expected.
|
|
echo "Test 12: GET /photo/last (download most recent photo)"
|
|
RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "${BASE}/photo/last")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ]; then
|
|
# Content-Type should be image/jpeg; we only have headers here because -o wasn't used,
|
|
# but we can verify it's not HTML/error text by checking length.
|
|
if [ "${#BODY}" -gt 100 ]; then
|
|
ok "Returns 200 and non-empty body for /photo/last"
|
|
else
|
|
err "Body too short for a JPEG"
|
|
fi
|
|
elif [ "$CODE" = "404" ]; then
|
|
ok "Returns 404 when no last capture exists"
|
|
else
|
|
err "Expected 200 or 404 for GET /photo/last, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 13: GET /photo/<filename> for specific filename
|
|
# We attempt with the filename returned by the last capture if any.
|
|
echo "Test 13: GET /photo/<filename> (download specific photo)"
|
|
FILENAME=$(echo "$RESPONSE" | jq -r '.filename' 2>/dev/null || echo "")
|
|
if [ -z "$FILENAME" ] || [ "$CODE" = "404" ]; then
|
|
# No filename available from capture result; try a dummy file -> expect 404
|
|
RESPONSE_B=$(curl -s -w "\n%{http_code}" -X GET "${BASE}/photo/nonexistent.jpg")
|
|
CODE_B=$(echo "$RESPONSE_B" | tail -n1)
|
|
if [ "$CODE_B" = "404" ]; then
|
|
ok "Returns 404 for nonexistent filename"
|
|
else
|
|
err "Expected 404 for nonexistent photo, got HTTP $CODE_B"
|
|
fi
|
|
else
|
|
RESPONSE_B=$(curl -s -w "\n%{http_code}" -X GET "${BASE}/photo/${FILENAME}")
|
|
CODE_B=$(echo "$RESPONSE_B" | tail -n1)
|
|
if [ "$CODE_B" = "200" ]; then
|
|
ok "Returns 200 for known filename"
|
|
else
|
|
err "Expected 200 for known filename, got HTTP $CODE_B"
|
|
fi
|
|
fi
|
|
echo
|
|
|
|
# Test 14: GET /events (SSE endpoint)
|
|
echo "Test 14: GET /events (SSE endpoint)"
|
|
# Start background SSE listener and redirect to file
|
|
curl -s -N -o /tmp/sse_test.txt "${BASE}/events" &
|
|
EVENT_PID=$!
|
|
sleep 1
|
|
# Trigger capture to produce an event
|
|
curl -s -X POST --max-time 15 "${BASE}/capture" > /dev/null
|
|
sleep 2
|
|
kill $EVENT_PID 2>/dev/null || true
|
|
if grep -q "data:" /tmp/sse_test.txt; then
|
|
ok "SSE received event data"
|
|
else
|
|
err "SSE did not receive event data"
|
|
fi
|
|
echo
|
|
|
|
# Test 15: POST /photo should return 404 (wrong method)
|
|
echo "Test 15: POST /photo/last (wrong method)"
|
|
RESPONSE=$(req POST "/photo/last")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "404" ] || [ "$CODE" = "405" ]; then
|
|
ok "Returns 404/405 for POST as expected"
|
|
else
|
|
err "Expected 404/405 for POST /photo/last, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 16: GET /captures
|
|
|
|
echo "Test 16: GET /captures (list all media)"
|
|
RESPONSE=$(req GET "/captures")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"captures"'; then
|
|
ok "Returns 200 with captures array"
|
|
else
|
|
err "Expected 200 + captures array, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 17: POST /record start
|
|
echo "Test 17: POST /record (start video recording)"
|
|
RESPONSE=$(req POST "/record" "--max-time 15")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"recording":true'; then
|
|
ok "Returns 200 and recording started"
|
|
# Stop the recording immediately to avoid long-running video test
|
|
sleep 1
|
|
req POST "/record" "--max-time 15" >/dev/null
|
|
ok "Stopped recording after 1s"
|
|
elif [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"error"'; then
|
|
err "Recording failed: $BODY"
|
|
else
|
|
err "Expected 200 + recording=true, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
# Test 18: GET /record should return 404
|
|
echo "Test 18: GET /record (wrong method)"
|
|
RESPONSE=$(req GET "/record")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "404" ] || [ "$CODE" = "405" ]; then
|
|
ok "Returns 404/405 for GET as expected"
|
|
else
|
|
err "Expected 404/405 for GET /record, got HTTP $CODE"
|
|
fi
|
|
echo
|
|
|
|
# Test 19: POST /settings toggle debug overlay
|
|
echo "Test 19: POST /settings (toggle debug overlay)"
|
|
RESPONSE=$(req POST "/settings" "-H Content-Type:application/json -d {\"debug\":true}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"debug":true'; then
|
|
ok "Returns 200 and debug is true"
|
|
else
|
|
err "Expected 200 + debug=true, got HTTP $CODE / $BODY"
|
|
fi
|
|
# Reset debug to false for clean state
|
|
req POST "/settings" "-H Content-Type:application/json -d {\"debug\":false}" >/dev/null
|
|
ok "Reset debug to false after test"
|
|
echo
|
|
|
|
# Test 20: POST /settings toggle capture_alert
|
|
echo "Test 20: POST /settings (toggle capture_alert)"
|
|
RESPONSE=$(req POST "/settings" "-H Content-Type:application/json -d {\"capture_alert\":false}")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"capture_alert":false'; then
|
|
ok "Returns 200 and capture_alert is false"
|
|
else
|
|
err "Expected 200 + capture_alert=false, got HTTP $CODE / $BODY"
|
|
fi
|
|
# Reset capture_alert to true (default) for clean state
|
|
req POST "/settings" "-H Content-Type:application/json -d {\"capture_alert\":true}" >/dev/null
|
|
ok "Reset capture_alert to true after test"
|
|
echo
|
|
|
|
# Test 21: Verify capture_alert default is true in /status
|
|
echo "Test 21: GET /status (capture_alert default)"
|
|
RESPONSE=$(req GET "/status")
|
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
CODE=$(echo "$RESPONSE" | tail -n1)
|
|
if [ "$CODE" = "200" ] && echo "$BODY" | grep -q '"capture_alert":true'; then
|
|
ok "Returns 200 and capture_alert defaults to true"
|
|
else
|
|
err "Expected 200 + capture_alert=true, got HTTP $CODE / $BODY"
|
|
fi
|
|
echo
|
|
|
|
echo "========================================"
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
echo "========================================"
|
|
|
|
if [ "$FAIL" -gt 0 ]; then
|
|
exit 1
|
|
fi
|