#!/usr/bin/env bash # e2e-backup-test.sh — Backup/restore E2E test (v0.6.1) # # Requires: docker compose running with a single instance. # Usage: # docker compose up --build -d # ./ci/e2e-backup-test.sh # docker compose down -v set -euo pipefail BASE="http://localhost:8080" PASS=0 FAIL=0 pass() { PASS=$((PASS + 1)); echo " PASS: $1"; } fail() { FAIL=$((FAIL + 1)); echo " FAIL: $1"; } # ── Wait for service ───────────────────────── echo "=== Waiting for service ===" for i in $(seq 1 30); do if curl -sf "$BASE/health" > /dev/null 2>&1; then echo " service ready" break fi sleep 1 if [ "$i" -eq 30 ]; then echo "FATAL: service did not become healthy" exit 1 fi done # ── Login as admin ─────────────────────────── echo "=== Authenticating ===" TOKEN=$(curl -sf "$BASE/api/v1/auth/login" \ -H "Content-Type: application/json" \ -d '{"login":"admin","password":"admin"}' | jq -r '.access_token') if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then echo "FATAL: login failed" exit 1 fi echo " admin token acquired" auth() { echo "Authorization: Bearer $TOKEN"; } # ── Seed test data ─────────────────────────── echo "=== Seeding test data ===" # Create a test user curl -sf "$BASE/api/v1/auth/register" \ -H "Content-Type: application/json" \ -d '{"username":"backup-test-user","email":"bktest@test.com","password":"testpass123"}' > /dev/null USER_COUNT=$(curl -sf "$BASE/api/v1/admin/users" -H "$(auth)" | jq '.data | length') echo " users: $USER_COUNT" # ── Test 1: List backups (empty) ───────────── echo "=== Test 1: List backups (empty) ===" LIST=$(curl -sf "$BASE/api/v1/admin/backups" -H "$(auth)") COUNT=$(echo "$LIST" | jq '.data | length') if [ "$COUNT" -eq 0 ]; then pass "empty backup list" else fail "expected 0 backups, got $COUNT" fi # ── Test 2: Create server-side backup ──────── echo "=== Test 2: Create server-side backup ===" RESULT=$(curl -sf "$BASE/api/v1/admin/backup?store=true" \ -X POST \ -H "$(auth)") FILENAME=$(echo "$RESULT" | jq -r '.data.filename') if [ -n "$FILENAME" ] && [ "$FILENAME" != "null" ]; then pass "created backup: $FILENAME" else fail "backup creation failed: $RESULT" fi # ── Test 3: List backups (has one) ─────────── echo "=== Test 3: List backups (has one) ===" LIST=$(curl -sf "$BASE/api/v1/admin/backups" -H "$(auth)") COUNT=$(echo "$LIST" | jq '.data | length') if [ "$COUNT" -eq 1 ]; then pass "one backup listed" else fail "expected 1 backup, got $COUNT" fi # ── Test 4: Download backup ────────────────── echo "=== Test 4: Download backup ===" TMPFILE=$(mktemp /tmp/backup-test-XXXXXX.swb) HTTP_CODE=$(curl -sf -o "$TMPFILE" -w "%{http_code}" \ "$BASE/api/v1/admin/backups/$FILENAME" -H "$(auth)") if [ "$HTTP_CODE" = "200" ] && [ -s "$TMPFILE" ]; then pass "download OK ($(wc -c < "$TMPFILE") bytes)" else fail "download failed (HTTP $HTTP_CODE)" fi # ── Test 5: Streaming backup (direct download) ── echo "=== Test 5: Streaming backup ===" STREAM_FILE=$(mktemp /tmp/backup-stream-XXXXXX.swb) HTTP_CODE=$(curl -sf -o "$STREAM_FILE" -w "%{http_code}" \ -X POST "$BASE/api/v1/admin/backup" -H "$(auth)") if [ "$HTTP_CODE" = "200" ] && [ -s "$STREAM_FILE" ]; then pass "streaming download OK ($(wc -c < "$STREAM_FILE") bytes)" else fail "streaming download failed (HTTP $HTTP_CODE)" fi # ── Test 6: Delete backup ──────────────────── echo "=== Test 6: Delete backup ===" DEL=$(curl -sf -X DELETE "$BASE/api/v1/admin/backups/$FILENAME" -H "$(auth)") DELETED=$(echo "$DEL" | jq -r '.data.deleted') if [ "$DELETED" = "$FILENAME" ]; then pass "deleted backup" else fail "delete failed: $DEL" fi # Verify deletion LIST=$(curl -sf "$BASE/api/v1/admin/backups" -H "$(auth)") COUNT=$(echo "$LIST" | jq '.data | length') if [ "$COUNT" -eq 0 ]; then pass "backup list empty after delete" else fail "expected 0 backups after delete, got $COUNT" fi # ── Cleanup ────────────────────────────────── rm -f "$TMPFILE" "$STREAM_FILE" # ── Summary ────────────────────────────────── echo "" echo "=== Results: $PASS passed, $FAIL failed ===" if [ "$FAIL" -gt 0 ]; then exit 1 fi