Comprehensive test suite for Pi deployments: - Connectivity check - Auto-setup if first boot (admin/stegasoo) - Login and session handling - All page accessibility - LSB encode/decode round trip - DCT encode/decode round trip - Tools API (capacity, EXIF) Usage: ./rpi/smoke-test.sh [host] [port] [user] [pass] 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
329 lines
9.3 KiB
Bash
Executable File
329 lines
9.3 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Stegasoo Pi Smoke Test
|
|
# Tests all core functionality against a running Pi instance
|
|
#
|
|
# Usage: ./smoke-test.sh [host] [port] [user] [pass]
|
|
#
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
HOST="${1:-stegasoo.local}"
|
|
PORT="${2:-443}"
|
|
USER="${3:-admin}"
|
|
PASS="${4:-stegasoo}"
|
|
|
|
# Build URL (don't include :443 since it's default for https)
|
|
if [ "$PORT" = "443" ]; then
|
|
BASE_URL="https://$HOST"
|
|
else
|
|
BASE_URL="https://$HOST:$PORT"
|
|
fi
|
|
COOKIE_JAR="/tmp/stegasoo_smoke_cookies.txt"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
TEST_DATA="$SCRIPT_DIR/../test_data"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
PASSED=0
|
|
FAILED=0
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Helper functions
|
|
# -----------------------------------------------------------------------------
|
|
|
|
log_test() {
|
|
echo -e "${CYAN}[TEST]${NC} $1"
|
|
}
|
|
|
|
log_pass() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
PASSED=$((PASSED + 1))
|
|
}
|
|
|
|
log_fail() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
FAILED=$((FAILED + 1))
|
|
}
|
|
|
|
curl_get() {
|
|
curl -sk "$BASE_URL$1" -b "$COOKIE_JAR" -c "$COOKIE_JAR" "${@:2}"
|
|
}
|
|
|
|
curl_post() {
|
|
curl -sk -X POST "$BASE_URL$1" -b "$COOKIE_JAR" -c "$COOKIE_JAR" "${@:2}"
|
|
}
|
|
|
|
wait_for_job() {
|
|
local endpoint="$1"
|
|
local job_id="$2"
|
|
local max_polls="${3:-30}"
|
|
|
|
for i in $(seq 1 $max_polls); do
|
|
sleep 1
|
|
result=$(curl_get "$endpoint/$job_id")
|
|
if echo "$result" | grep -q '"status":\s*"complete"'; then
|
|
echo "$result"
|
|
return 0
|
|
fi
|
|
if echo "$result" | grep -q '"status":\s*"error"'; then
|
|
echo "$result"
|
|
return 1
|
|
fi
|
|
done
|
|
echo '{"status":"timeout"}'
|
|
return 1
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Tests
|
|
# -----------------------------------------------------------------------------
|
|
|
|
test_connectivity() {
|
|
log_test "Connectivity to $BASE_URL"
|
|
if curl -sk --connect-timeout 5 "$BASE_URL" -o /dev/null; then
|
|
log_pass "Server reachable"
|
|
else
|
|
log_fail "Cannot reach server"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
test_setup_or_login() {
|
|
log_test "Setup/Login"
|
|
|
|
# Check if setup needed
|
|
response=$(curl_get "/" -L -o /dev/null -w "%{url_effective}")
|
|
|
|
if echo "$response" | grep -q "/setup"; then
|
|
log_test "Completing first-time setup..."
|
|
curl_post "/setup" \
|
|
-d "username=$USER" \
|
|
-d "password=$PASS" \
|
|
-d "password_confirm=$PASS" \
|
|
-L -o /dev/null
|
|
fi
|
|
|
|
# Login
|
|
curl_get "/login" -o /dev/null # Get session
|
|
curl_post "/login" \
|
|
-d "username=$USER" \
|
|
-d "password=$PASS" \
|
|
-L -o /dev/null
|
|
|
|
# Verify logged in
|
|
code=$(curl_get "/encode" -o /dev/null -w "%{http_code}")
|
|
if [ "$code" = "200" ]; then
|
|
log_pass "Authenticated successfully"
|
|
else
|
|
log_fail "Authentication failed (got $code)"
|
|
fi
|
|
}
|
|
|
|
test_pages() {
|
|
log_test "Page accessibility"
|
|
|
|
local pages="encode decode generate tools about"
|
|
local all_pass=true
|
|
|
|
for page in $pages; do
|
|
code=$(curl_get "/$page" -o /dev/null -w "%{http_code}")
|
|
if [ "$code" = "200" ]; then
|
|
echo -e " ${GREEN}✓${NC} /$page"
|
|
else
|
|
echo -e " ${RED}✗${NC} /$page ($code)"
|
|
all_pass=false
|
|
fi
|
|
done
|
|
|
|
if $all_pass; then
|
|
log_pass "All pages accessible"
|
|
else
|
|
log_fail "Some pages inaccessible"
|
|
fi
|
|
}
|
|
|
|
test_encode_decode_dct() {
|
|
log_test "DCT Encode/Decode round trip"
|
|
|
|
local message="DCT smoke test $(date +%s)"
|
|
|
|
# Encode
|
|
response=$(curl_post "/encode" \
|
|
-F "reference_photo=@$TEST_DATA/ref.jpg" \
|
|
-F "carrier=@$TEST_DATA/carrier.jpg" \
|
|
-F "message=$message" \
|
|
-F "passphrase=tower booty sunny windy" \
|
|
-F "pin=727643678" \
|
|
-F "embed_mode=dct" \
|
|
-F "channel_key=auto" \
|
|
-F "async=true")
|
|
|
|
job_id=$(echo "$response" | grep -oP '"job_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
|
|
if [ -z "$job_id" ]; then
|
|
log_fail "DCT encode - no job ID returned"
|
|
return
|
|
fi
|
|
|
|
# Wait for encode
|
|
result=$(wait_for_job "/encode/status" "$job_id" 15)
|
|
if ! echo "$result" | grep -q '"status":\s*"complete"'; then
|
|
log_fail "DCT encode timeout or error"
|
|
return
|
|
fi
|
|
|
|
file_id=$(echo "$result" | grep -oP '"file_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
curl_get "/encode/download/$file_id" -o /tmp/stego_dct_test.jpg
|
|
|
|
echo -e " ${GREEN}✓${NC} Encoded $(ls -lh /tmp/stego_dct_test.jpg | awk '{print $5}')"
|
|
|
|
# Decode
|
|
response=$(curl_post "/decode" \
|
|
-F "reference_photo=@$TEST_DATA/ref.jpg" \
|
|
-F "stego_image=@/tmp/stego_dct_test.jpg" \
|
|
-F "passphrase=tower booty sunny windy" \
|
|
-F "pin=727643678" \
|
|
-F "embed_mode=auto" \
|
|
-F "channel_key=auto" \
|
|
-F "async=true")
|
|
|
|
job_id=$(echo "$response" | grep -oP '"job_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
|
|
# Wait for decode (DCT is slower on Pi)
|
|
result=$(wait_for_job "/decode/status" "$job_id" 60)
|
|
|
|
if echo "$result" | grep -q "$message"; then
|
|
log_pass "DCT round trip - message verified"
|
|
else
|
|
log_fail "DCT decode - message mismatch"
|
|
echo " Expected: $message"
|
|
echo " Got: $result"
|
|
fi
|
|
}
|
|
|
|
test_encode_decode_lsb() {
|
|
log_test "LSB Encode/Decode round trip"
|
|
|
|
local message="LSB smoke test $(date +%s)"
|
|
|
|
# Encode
|
|
response=$(curl_post "/encode" \
|
|
-F "reference_photo=@$TEST_DATA/ref.jpg" \
|
|
-F "carrier=@$TEST_DATA/carrier.jpg" \
|
|
-F "message=$message" \
|
|
-F "passphrase=tower booty sunny windy" \
|
|
-F "pin=727643678" \
|
|
-F "embed_mode=lsb" \
|
|
-F "channel_key=auto" \
|
|
-F "async=true")
|
|
|
|
job_id=$(echo "$response" | grep -oP '"job_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
|
|
if [ -z "$job_id" ]; then
|
|
log_fail "LSB encode - no job ID returned"
|
|
return
|
|
fi
|
|
|
|
result=$(wait_for_job "/encode/status" "$job_id" 10)
|
|
if ! echo "$result" | grep -q '"status":\s*"complete"'; then
|
|
log_fail "LSB encode timeout or error"
|
|
return
|
|
fi
|
|
|
|
file_id=$(echo "$result" | grep -oP '"file_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
curl_get "/encode/download/$file_id" -o /tmp/stego_lsb_test.png
|
|
|
|
echo -e " ${GREEN}✓${NC} Encoded $(ls -lh /tmp/stego_lsb_test.png | awk '{print $5}')"
|
|
|
|
# Decode
|
|
response=$(curl_post "/decode" \
|
|
-F "reference_photo=@$TEST_DATA/ref.jpg" \
|
|
-F "stego_image=@/tmp/stego_lsb_test.png" \
|
|
-F "passphrase=tower booty sunny windy" \
|
|
-F "pin=727643678" \
|
|
-F "embed_mode=lsb" \
|
|
-F "channel_key=auto" \
|
|
-F "async=true")
|
|
|
|
job_id=$(echo "$response" | grep -oP '"job_id":\s*"[^"]+"' | cut -d'"' -f4)
|
|
result=$(wait_for_job "/decode/status" "$job_id" 15)
|
|
|
|
if echo "$result" | grep -q "$message"; then
|
|
log_pass "LSB round trip - message verified"
|
|
else
|
|
log_fail "LSB decode - message mismatch"
|
|
fi
|
|
}
|
|
|
|
test_tools() {
|
|
log_test "Tools endpoints"
|
|
|
|
# Capacity check
|
|
response=$(curl_post "/api/tools/capacity" \
|
|
-F "image=@$TEST_DATA/carrier.jpg" \
|
|
-w "%{http_code}" -o /tmp/capacity_result.json)
|
|
|
|
if [ "$response" = "200" ]; then
|
|
echo -e " ${GREEN}✓${NC} Capacity check"
|
|
else
|
|
echo -e " ${RED}✗${NC} Capacity check ($response)"
|
|
fi
|
|
|
|
# EXIF read
|
|
response=$(curl_post "/api/tools/exif" \
|
|
-F "image=@$TEST_DATA/carrier.jpg" \
|
|
-w "%{http_code}" -o /tmp/exif_result.json)
|
|
|
|
if [ "$response" = "200" ]; then
|
|
echo -e " ${GREEN}✓${NC} EXIF read"
|
|
log_pass "Tools API works"
|
|
else
|
|
echo -e " ${RED}✗${NC} EXIF read ($response)"
|
|
log_fail "Tools API failed"
|
|
fi
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Main
|
|
# -----------------------------------------------------------------------------
|
|
|
|
echo ""
|
|
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║ Stegasoo Pi Smoke Test ║${NC}"
|
|
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
echo -e "Target: ${YELLOW}$BASE_URL${NC}"
|
|
echo -e "User: ${YELLOW}$USER${NC}"
|
|
echo ""
|
|
|
|
# Clean up
|
|
rm -f "$COOKIE_JAR" /tmp/stego_*_test.* /tmp/exif_stripped.jpg
|
|
|
|
# Run tests
|
|
test_connectivity
|
|
test_setup_or_login
|
|
test_pages
|
|
test_encode_decode_lsb
|
|
test_encode_decode_dct
|
|
test_tools
|
|
|
|
# Summary
|
|
echo ""
|
|
echo -e "${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
|
echo -e "Results: ${GREEN}$PASSED passed${NC}, ${RED}$FAILED failed${NC}"
|
|
echo -e "${CYAN}════════════════════════════════════════════════════════════════${NC}"
|
|
|
|
# Clean up
|
|
rm -f "$COOKIE_JAR"
|
|
|
|
if [ $FAILED -gt 0 ]; then
|
|
exit 1
|
|
fi
|