From a00a154a1a945b707d02844f807914cf3c529ec9 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Wed, 7 Jan 2026 23:25:45 -0500 Subject: [PATCH] Add Pi smoke test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- rpi/smoke-test.sh | 328 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100755 rpi/smoke-test.sh diff --git a/rpi/smoke-test.sh b/rpi/smoke-test.sh new file mode 100755 index 0000000..e9f68e1 --- /dev/null +++ b/rpi/smoke-test.sh @@ -0,0 +1,328 @@ +#!/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