576 lines
No EOL
20 KiB
Bash
576 lines
No EOL
20 KiB
Bash
#!/bin/bash
|
|
# HTTP Matrix Test Harness
|
|
# Comprehensive HTTP/API testing for Veza Web App
|
|
|
|
set -euo pipefail
|
|
|
|
# Get script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR/.."
|
|
|
|
# Load environment
|
|
if [ -f .env ]; then
|
|
source .env
|
|
else
|
|
echo "Error: .env file not found. Copy env.example to .env and configure."
|
|
exit 1
|
|
fi
|
|
|
|
# Load assertion library
|
|
source http/http_assert.sh
|
|
|
|
# Generate unique test data
|
|
RAND="${RAND:-$(date +%s)}"
|
|
TEST_EMAIL="$(generate_test_email "$RAND")"
|
|
TEST_PASSWORD="$(generate_test_password "$RAND")"
|
|
SESSION_FILE="${SESSION_FILE:-.session.json}"
|
|
|
|
# Global variables
|
|
ACCESS_TOKEN=""
|
|
REFRESH_TOKEN=""
|
|
USER_ID=""
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
if [ -f "$SESSION_FILE" ]; then
|
|
rm -f "$SESSION_FILE"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Helper functions
|
|
save_session() {
|
|
local access="$1"
|
|
local refresh="$2"
|
|
local user_id="${3:-}"
|
|
|
|
jo access_token="$access" \
|
|
refresh_token="$refresh" \
|
|
user_id="$user_id" \
|
|
issued_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$SESSION_FILE"
|
|
}
|
|
|
|
load_session() {
|
|
if [ -f "$SESSION_FILE" ]; then
|
|
ACCESS_TOKEN=$(jq -r '.access_token // empty' "$SESSION_FILE")
|
|
REFRESH_TOKEN=$(jq -r '.refresh_token // empty' "$SESSION_FILE")
|
|
USER_ID=$(jq -r '.user_id // empty' "$SESSION_FILE")
|
|
fi
|
|
}
|
|
|
|
# HTTP request wrapper with timing
|
|
http_request() {
|
|
local method="$1"
|
|
local url="$2"
|
|
local data="${3:-}"
|
|
local extra_args=("${@:4}")
|
|
|
|
local temp_file=$(mktemp)
|
|
local start_time=$(date +%s.%N)
|
|
|
|
# Build curl command
|
|
local curl_cmd=(curl -sk -X "$method" "$url")
|
|
curl_cmd+=(-w '\n%{http_code}\n%{time_total}\n')
|
|
curl_cmd+=(-D "$temp_file")
|
|
|
|
# Add authorization if available
|
|
if [ -n "$ACCESS_TOKEN" ]; then
|
|
curl_cmd+=(-H "Authorization: Bearer $ACCESS_TOKEN")
|
|
fi
|
|
|
|
# Add data if provided
|
|
if [ -n "$data" ]; then
|
|
curl_cmd+=(-H "Content-Type: application/json")
|
|
curl_cmd+=(-d "$data")
|
|
fi
|
|
|
|
# Add extra arguments
|
|
curl_cmd+=("${extra_args[@]}")
|
|
|
|
# Execute request
|
|
local response
|
|
response=$("${curl_cmd[@]}" 2>/dev/null || echo "CURL_ERROR")
|
|
|
|
local end_time=$(date +%s.%N)
|
|
local duration=$(echo "$end_time - $start_time" | bc || echo "0")
|
|
|
|
# Parse response
|
|
local body=$(echo "$response" | sed -n '1,/^$/p' | head -n -3)
|
|
local code=$(echo "$response" | tail -n 2 | head -n 1)
|
|
local time_total=$(echo "$response" | tail -n 1)
|
|
local headers=$(cat "$temp_file")
|
|
|
|
# Convert to milliseconds
|
|
local latency_ms=$(echo "$time_total * 1000" | bc || echo "0")
|
|
|
|
# Cleanup
|
|
rm -f "$temp_file"
|
|
|
|
# Return as structured data
|
|
echo "$body"
|
|
echo "HTTP_STATUS:$code"
|
|
echo "HTTP_HEADERS:$headers"
|
|
echo "HTTP_LATENCY:$latency_ms"
|
|
}
|
|
|
|
# Parse HTTP response
|
|
parse_response() {
|
|
local response="$1"
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local headers=$(echo "$response" | sed -n '/^HTTP_HEADERS:/,/^HTTP_LATENCY:/p' | sed '1d;$d')
|
|
local latency=$(echo "$response" | grep "^HTTP_LATENCY:" | cut -d: -f2)
|
|
|
|
echo "BODY:$body"
|
|
echo "STATUS:$status"
|
|
echo "HEADERS:$headers"
|
|
echo "LATENCY:$latency"
|
|
}
|
|
|
|
# Test functions
|
|
test_health_check() {
|
|
log_info "Testing health check..."
|
|
|
|
local response=$(http_request GET "$API_ORIGIN/health")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "GET /health"
|
|
assert_json_has "$body" '.status' "health response"
|
|
assert_json_equals "$body" '.status' "ok" "health status"
|
|
}
|
|
|
|
test_cors() {
|
|
log_info "Testing CORS..."
|
|
|
|
# Test preflight
|
|
local response=$(http_request OPTIONS "$API_ORIGIN/auth/login" "" \
|
|
-H "Origin: https://app.lab.veza" \
|
|
-H "Access-Control-Request-Method: POST" \
|
|
-H "Access-Control-Request-Headers: Content-Type")
|
|
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local headers=$(echo "$response" | sed -n '/^HTTP_HEADERS:/,/^HTTP_LATENCY:/p' | sed '1d;$d')
|
|
|
|
assert_status_range "$status" 200 204 "OPTIONS /auth/login"
|
|
assert_header_exists "$headers" "Access-Control-Allow-Origin" "CORS preflight"
|
|
assert_header_exists "$headers" "Access-Control-Allow-Methods" "CORS preflight"
|
|
}
|
|
|
|
test_auth_register() {
|
|
log_info "Testing user registration..."
|
|
|
|
# Test invalid email
|
|
local response=$(http_request POST "$API_ORIGIN/auth/register" \
|
|
'{"email":"invalid-email","password":"ValidPass123!"}')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 400 "register with invalid email"
|
|
|
|
# Test weak password
|
|
local response=$(http_request POST "$API_ORIGIN/auth/register" \
|
|
"{\"email\":\"$TEST_EMAIL\",\"password\":\"weak\"}")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 400 "register with weak password"
|
|
|
|
# Test successful registration
|
|
local response=$(http_request POST "$API_ORIGIN/auth/register" \
|
|
"{\"email\":\"$TEST_EMAIL\",\"password\":\"$TEST_PASSWORD\"}")
|
|
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local headers=$(echo "$response" | sed -n '/^HTTP_HEADERS:/,/^HTTP_LATENCY:/p' | sed '1d;$d')
|
|
local latency=$(echo "$response" | grep "^HTTP_LATENCY:" | cut -d: -f2)
|
|
|
|
# This is where we detect the registration bug
|
|
assert_status "$status" 201 "register new user"
|
|
assert_json_has "$body" '.user' "register response"
|
|
assert_json_has "$body" '.user.id' "register response"
|
|
assert_json_has "$body" '.user.email' "register response"
|
|
assert_json_equals "$body" '.user.email' "$TEST_EMAIL" "registered email"
|
|
assert_json_has "$body" '.access_token' "register response"
|
|
assert_json_has "$body" '.refresh_token' "register response"
|
|
assert_latency_lt "$latency" 800 "register"
|
|
|
|
# Save tokens
|
|
if [ "$status" -eq 201 ]; then
|
|
ACCESS_TOKEN=$(echo "$body" | jq -r '.access_token')
|
|
REFRESH_TOKEN=$(echo "$body" | jq -r '.refresh_token')
|
|
USER_ID=$(echo "$body" | jq -r '.user.id')
|
|
save_session "$ACCESS_TOKEN" "$REFRESH_TOKEN" "$USER_ID"
|
|
fi
|
|
|
|
# Test duplicate registration
|
|
local response=$(http_request POST "$API_ORIGIN/auth/register" \
|
|
"{\"email\":\"$TEST_EMAIL\",\"password\":\"$TEST_PASSWORD\"}")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 409 "register duplicate email"
|
|
}
|
|
|
|
test_auth_login() {
|
|
log_info "Testing user login..."
|
|
|
|
# Test login with wrong password
|
|
local response=$(http_request POST "$API_ORIGIN/auth/login" \
|
|
"{\"email\":\"$TEST_EMAIL\",\"password\":\"WrongPassword123!\"}")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 401 "login with wrong password"
|
|
|
|
# Test login with unknown email
|
|
local response=$(http_request POST "$API_ORIGIN/auth/login" \
|
|
'{"email":"unknown@lab.veza","password":"AnyPassword123!"}')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status_range "$status" 401 404 "login with unknown email"
|
|
|
|
# Test successful login
|
|
local response=$(http_request POST "$API_ORIGIN/auth/login" \
|
|
"{\"email\":\"$TEST_EMAIL\",\"password\":\"$TEST_PASSWORD\"}")
|
|
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local latency=$(echo "$response" | grep "^HTTP_LATENCY:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "login"
|
|
assert_json_has "$body" '.user' "login response"
|
|
assert_json_has "$body" '.access_token' "login response"
|
|
assert_json_has "$body" '.refresh_token' "login response"
|
|
assert_latency_lt "$latency" "${PERF_AUTH_LOGIN_P95:-300}" "login"
|
|
|
|
# Update tokens
|
|
if [ "$status" -eq 200 ]; then
|
|
ACCESS_TOKEN=$(echo "$body" | jq -r '.access_token')
|
|
REFRESH_TOKEN=$(echo "$body" | jq -r '.refresh_token')
|
|
USER_ID=$(echo "$body" | jq -r '.user.id')
|
|
save_session "$ACCESS_TOKEN" "$REFRESH_TOKEN" "$USER_ID"
|
|
fi
|
|
}
|
|
|
|
test_auth_refresh() {
|
|
log_info "Testing token refresh..."
|
|
|
|
# Test with invalid refresh token
|
|
local response=$(http_request POST "$API_ORIGIN/auth/refresh" \
|
|
'{"refresh_token":"invalid-token"}')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 401 "refresh with invalid token"
|
|
|
|
# Test with valid refresh token
|
|
local response=$(http_request POST "$API_ORIGIN/auth/refresh" \
|
|
"{\"refresh_token\":\"$REFRESH_TOKEN\"}")
|
|
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "refresh token"
|
|
assert_json_has "$body" '.access_token' "refresh response"
|
|
assert_json_has "$body" '.refresh_token' "refresh response"
|
|
|
|
# Update tokens
|
|
if [ "$status" -eq 200 ]; then
|
|
ACCESS_TOKEN=$(echo "$body" | jq -r '.access_token')
|
|
REFRESH_TOKEN=$(echo "$body" | jq -r '.refresh_token')
|
|
save_session "$ACCESS_TOKEN" "$REFRESH_TOKEN" "$USER_ID"
|
|
fi
|
|
}
|
|
|
|
test_profile() {
|
|
log_info "Testing user profile..."
|
|
|
|
# Test without auth
|
|
local old_token="$ACCESS_TOKEN"
|
|
ACCESS_TOKEN=""
|
|
local response=$(http_request GET "$API_ORIGIN/me")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status "$status" 401 "GET /me without auth"
|
|
ACCESS_TOKEN="$old_token"
|
|
|
|
# Test with auth
|
|
local response=$(http_request GET "$API_ORIGIN/me")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local latency=$(echo "$response" | grep "^HTTP_LATENCY:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "GET /me"
|
|
assert_json_has "$body" '.id' "profile response"
|
|
assert_json_has "$body" '.email' "profile response"
|
|
assert_json_equals "$body" '.email' "$TEST_EMAIL" "profile email"
|
|
assert_latency_lt "$latency" "${PERF_API_ME_P95:-200}" "GET /me"
|
|
|
|
# Test profile update
|
|
local new_nickname="TestUser$RAND"
|
|
local response=$(http_request PATCH "$API_ORIGIN/me" \
|
|
"{\"nickname\":\"$new_nickname\"}")
|
|
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "PATCH /me"
|
|
assert_json_equals "$body" '.nickname' "$new_nickname" "updated nickname"
|
|
}
|
|
|
|
test_avatar_upload() {
|
|
log_info "Testing avatar upload..."
|
|
|
|
# Create test image if not exists
|
|
if [ ! -f "$TEST_IMAGE_FILE" ]; then
|
|
mkdir -p data/images
|
|
# Create a simple 100x100 JPEG
|
|
convert -size 100x100 xc:blue "$TEST_IMAGE_FILE" 2>/dev/null || \
|
|
echo "Warning: ImageMagick not installed, skipping avatar test"
|
|
return
|
|
fi
|
|
|
|
# Upload avatar
|
|
local response=$(curl -sk -X POST "$API_ORIGIN/me/avatar" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-F "avatar=@$TEST_IMAGE_FILE" \
|
|
-w '\n%{http_code}\n%{time_total}\n')
|
|
|
|
local body=$(echo "$response" | sed -n '1,/^$/p' | head -n -3)
|
|
local code=$(echo "$response" | tail -n 2 | head -n 1)
|
|
|
|
assert_status "$code" 200 "avatar upload"
|
|
assert_json_has "$body" '.avatar_url' "avatar response" || true
|
|
}
|
|
|
|
test_file_operations() {
|
|
log_info "Testing file operations..."
|
|
|
|
# Create test file
|
|
local test_file="/tmp/test-upload-$RAND.txt"
|
|
echo "Test content for file upload" > "$test_file"
|
|
|
|
# Test upload
|
|
local response=$(curl -sk -X POST "$API_ORIGIN/files/upload" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-F "file=@$test_file" \
|
|
-w '\n%{http_code}\n%{time_total}\n')
|
|
|
|
local body=$(echo "$response" | sed -n '1,/^$/p' | head -n -3)
|
|
local code=$(echo "$response" | tail -n 2 | head -n 1)
|
|
|
|
assert_status "$code" 201 "file upload"
|
|
|
|
local file_id=""
|
|
if [ "$code" -eq 201 ]; then
|
|
file_id=$(echo "$body" | jq -r '.file.id // empty')
|
|
assert_json_has "$body" '.file.id' "upload response"
|
|
assert_json_has "$body" '.file.name' "upload response"
|
|
assert_json_has "$body" '.file.size' "upload response"
|
|
fi
|
|
|
|
# Test file listing
|
|
local response=$(http_request GET "$API_ORIGIN/files")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "list files"
|
|
assert_json_has "$body" '.files' "files list"
|
|
assert_json_type "$body" '.files' "array" "files list"
|
|
|
|
# Test file download
|
|
if [ -n "$file_id" ]; then
|
|
local response=$(curl -sk -X GET "$API_ORIGIN/files/$file_id/download" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-w '\n%{http_code}\n' \
|
|
-o /tmp/downloaded-$RAND.txt)
|
|
|
|
local code=$(echo "$response" | tail -n 1)
|
|
assert_status "$code" 200 "file download"
|
|
fi
|
|
|
|
# Cleanup
|
|
rm -f "$test_file" "/tmp/downloaded-$RAND.txt"
|
|
}
|
|
|
|
test_chat_http() {
|
|
log_info "Testing chat HTTP endpoints..."
|
|
|
|
# Get chat rooms
|
|
local response=$(http_request GET "$API_ORIGIN/chat/rooms")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "list chat rooms"
|
|
assert_json_has "$body" '.rooms' "rooms list"
|
|
assert_json_type "$body" '.rooms' "array" "rooms list"
|
|
|
|
# Get messages history
|
|
local response=$(http_request GET "$API_ORIGIN/chat/rooms/general/messages?limit=50")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "get chat messages"
|
|
assert_json_has "$body" '.messages' "messages list"
|
|
assert_json_type "$body" '.messages' "array" "messages list"
|
|
}
|
|
|
|
test_streaming() {
|
|
log_info "Testing streaming endpoints..."
|
|
|
|
# Test stream health
|
|
local response=$(http_request GET "$STREAM_ORIGIN/health")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "stream health"
|
|
|
|
# Create audio sample if not exists
|
|
if [ ! -f "$TEST_AUDIO_FILE" ]; then
|
|
mkdir -p data/audio
|
|
# Generate 10 second silence MP3
|
|
ffmpeg -f lavfi -i anullsrc=r=44100:cl=stereo -t 10 \
|
|
-acodec mp3 "$TEST_AUDIO_FILE" 2>/dev/null || \
|
|
echo "Warning: ffmpeg not installed, skipping audio test"
|
|
fi
|
|
|
|
# Test stream upload
|
|
if [ -f "$TEST_AUDIO_FILE" ]; then
|
|
local response=$(curl -sk -X POST "$STREAM_ORIGIN/upload" \
|
|
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
-F "audio=@$TEST_AUDIO_FILE" \
|
|
-w '\n%{http_code}\n')
|
|
|
|
local code=$(echo "$response" | tail -n 1)
|
|
assert_status "$code" 201 "stream upload" || true
|
|
fi
|
|
}
|
|
|
|
test_docs() {
|
|
log_info "Testing documentation..."
|
|
|
|
# Test docs home
|
|
local response=$(http_request GET "$DOCS_ORIGIN/")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 200 "docs home"
|
|
assert_body_contains "$body" "Veza" "docs content"
|
|
|
|
# Test docs assets
|
|
local response=$(http_request GET "$DOCS_ORIGIN/img/logo.svg")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
# Logo might be optional
|
|
if [ "$status" -ne 404 ]; then
|
|
assert_status "$status" 200 "docs logo"
|
|
fi
|
|
}
|
|
|
|
test_security_headers() {
|
|
log_info "Testing security headers..."
|
|
|
|
local response=$(http_request GET "$API_ORIGIN/health")
|
|
local headers=$(echo "$response" | sed -n '/^HTTP_HEADERS:/,/^HTTP_LATENCY:/p' | sed '1d;$d')
|
|
|
|
assert_security_headers "$headers" "API security headers"
|
|
|
|
# Test specific headers
|
|
assert_header_equals "$headers" "X-Content-Type-Options" "nosniff" "X-CTO header"
|
|
assert_header_exists "$headers" "X-Frame-Options" "X-Frame-Options"
|
|
assert_header_exists "$headers" "Referrer-Policy" "Referrer-Policy"
|
|
}
|
|
|
|
test_error_handling() {
|
|
log_info "Testing error handling..."
|
|
|
|
# Test 404
|
|
local response=$(http_request GET "$API_ORIGIN/nonexistent/endpoint")
|
|
local body=$(echo "$response" | sed '/^HTTP_STATUS:/,$d')
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 404 "404 error"
|
|
assert_json_has "$body" '.error' "404 error response" || \
|
|
assert_json_has "$body" '.message' "404 error response"
|
|
|
|
# Test malformed JSON
|
|
local response=$(http_request POST "$API_ORIGIN/auth/login" \
|
|
"{invalid-json}" \
|
|
-H "Content-Type: application/json")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
assert_status "$status" 400 "malformed JSON"
|
|
}
|
|
|
|
test_rate_limiting() {
|
|
log_info "Testing rate limiting..."
|
|
|
|
# Make multiple rapid requests
|
|
local rate_limited=false
|
|
for i in {1..15}; do
|
|
local response=$(http_request POST "$API_ORIGIN/auth/login" \
|
|
"{\"email\":\"test$i@lab.veza\",\"password\":\"wrong\"}")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
local headers=$(echo "$response" | sed -n '/^HTTP_HEADERS:/,/^HTTP_LATENCY:/p' | sed '1d;$d')
|
|
|
|
if [ "$status" -eq 429 ]; then
|
|
rate_limited=true
|
|
assert_header_exists "$headers" "Retry-After" "rate limit headers" || true
|
|
assert_header_exists "$headers" "X-RateLimit-Limit" "rate limit headers" || true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$rate_limited" = true ]; then
|
|
pass "Rate limiting is active"
|
|
else
|
|
log_warn "Rate limiting might not be configured"
|
|
fi
|
|
}
|
|
|
|
test_auth_logout() {
|
|
log_info "Testing logout..."
|
|
|
|
local response=$(http_request POST "$API_ORIGIN/auth/logout" \
|
|
"{\"refresh_token\":\"$REFRESH_TOKEN\"}")
|
|
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
assert_status_range "$status" 200 204 "logout"
|
|
|
|
# Test that old tokens are invalidated
|
|
local response=$(http_request GET "$API_ORIGIN/me")
|
|
local status=$(echo "$response" | grep "^HTTP_STATUS:" | cut -d: -f2)
|
|
|
|
# Might still work if no token blacklisting
|
|
if [ "$status" -eq 401 ]; then
|
|
pass "Tokens invalidated after logout"
|
|
else
|
|
log_warn "Tokens might still be valid after logout"
|
|
fi
|
|
}
|
|
|
|
# Main test execution
|
|
main() {
|
|
log_info "Starting HTTP Matrix Tests"
|
|
log_info "Environment: LAB"
|
|
log_info "Test user: $TEST_EMAIL"
|
|
echo
|
|
|
|
# Run all tests
|
|
test_health_check
|
|
test_cors
|
|
test_auth_register
|
|
|
|
# Only continue if registration worked
|
|
if [ -n "$ACCESS_TOKEN" ]; then
|
|
test_auth_login
|
|
test_auth_refresh
|
|
test_profile
|
|
test_avatar_upload
|
|
test_file_operations
|
|
test_chat_http
|
|
test_streaming
|
|
test_docs
|
|
test_security_headers
|
|
test_error_handling
|
|
test_rate_limiting
|
|
test_auth_logout
|
|
else
|
|
log_error "Registration failed - skipping authenticated tests"
|
|
log_error "This indicates a critical bug in the registration endpoint"
|
|
fi
|
|
|
|
# Print summary
|
|
print_test_summary
|
|
}
|
|
|
|
# Run tests
|
|
main "$@" |