mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-09 02:44:24 +00:00
- Updated test-security.sh to detect and handle DISABLE_AUTH mode - Fixed test-release.sh to properly check for compiled binary - Updated test-proxy-scenarios.sh arithmetic operations for bash compatibility - All tests now properly detect authentication state and adapt accordingly
281 lines
No EOL
8.8 KiB
Bash
Executable file
281 lines
No EOL
8.8 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Comprehensive release testing script for Pulse
|
|
# Tests actual deployments, not just unit tests
|
|
|
|
set -e
|
|
|
|
VERSION=${1:-$(cat VERSION)}
|
|
PULSE_URL=${PULSE_URL:-http://localhost:7655}
|
|
API_TOKEN=${API_TOKEN:-""}
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
echo "================================================"
|
|
echo "Pulse Release Test Suite v${VERSION}"
|
|
echo "================================================"
|
|
|
|
# Detect if auth is disabled
|
|
AUTH_DISABLED=false
|
|
security_status=$(curl -s "$PULSE_URL/api/security/status" 2>/dev/null || echo "{}")
|
|
if echo "$security_status" | grep -q '"disabled":true'; then
|
|
AUTH_DISABLED=true
|
|
echo ""
|
|
echo -e "${YELLOW}Note: Authentication is DISABLED (DISABLE_AUTH mode)${NC}"
|
|
fi
|
|
|
|
# Track test results
|
|
FAILED_TESTS=()
|
|
PASSED_TESTS=()
|
|
|
|
# Test function
|
|
run_test() {
|
|
local test_name="$1"
|
|
local test_command="$2"
|
|
|
|
echo -n "Testing: $test_name... "
|
|
if eval "$test_command" > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
PASSED_TESTS+=("$test_name")
|
|
else
|
|
echo -e "${RED}✗${NC}"
|
|
FAILED_TESTS+=("$test_name")
|
|
fi
|
|
}
|
|
|
|
# Test function with output
|
|
run_test_verbose() {
|
|
local test_name="$1"
|
|
local test_command="$2"
|
|
|
|
echo "Testing: $test_name..."
|
|
if eval "$test_command"; then
|
|
echo -e "${GREEN}✓ $test_name passed${NC}"
|
|
PASSED_TESTS+=("$test_name")
|
|
else
|
|
echo -e "${RED}✗ $test_name failed${NC}"
|
|
FAILED_TESTS+=("$test_name")
|
|
fi
|
|
}
|
|
|
|
echo ""
|
|
echo "1. HTTP/ROUTING TESTS"
|
|
echo "===================="
|
|
|
|
# Critical: Test root without trailing slash (catches issue #334)
|
|
run_test "Root path without trailing slash (no redirect)" \
|
|
"curl -s -I ${PULSE_URL} | grep -q 'HTTP/1.1 200'"
|
|
|
|
run_test "Root path with trailing slash" \
|
|
"curl -s -I ${PULSE_URL}/ | grep -q 'HTTP/1.1 200'"
|
|
|
|
# Check for unwanted redirects
|
|
run_test "No relative path redirects" \
|
|
"! curl -s -I ${PULSE_URL} | grep -q 'Location: ./'"
|
|
|
|
# Test static assets (get actual filenames from index.html)
|
|
JS_FILE=$(curl -s ${PULSE_URL}/ | grep -o '/assets/index-[^"]*\.js' | head -1)
|
|
CSS_FILE=$(curl -s ${PULSE_URL}/ | grep -o '/assets/index-[^"]*\.css' | head -1)
|
|
|
|
if [ -n "$JS_FILE" ]; then
|
|
run_test "JavaScript assets load" \
|
|
"curl -s -I ${PULSE_URL}${JS_FILE} | grep -q 'Content-Type: application/javascript'"
|
|
else
|
|
echo -e "${RED}✗ Could not find JS file${NC}"
|
|
FAILED_TESTS+=("JavaScript assets load")
|
|
fi
|
|
|
|
if [ -n "$CSS_FILE" ]; then
|
|
run_test "CSS assets load" \
|
|
"curl -s -I ${PULSE_URL}${CSS_FILE} | grep -q 'Content-Type: text/css'"
|
|
else
|
|
echo -e "${RED}✗ Could not find CSS file${NC}"
|
|
FAILED_TESTS+=("CSS assets load")
|
|
fi
|
|
|
|
# Test various access patterns
|
|
run_test "Empty path handling" \
|
|
"curl -s -o /dev/null -w '%{http_code}' ${PULSE_URL} | grep -q '200'"
|
|
|
|
if [ "$AUTH_DISABLED" != true ]; then
|
|
run_test "SPA routes require authentication" \
|
|
"curl -s ${PULSE_URL}/settings | grep -q 'Authentication required'"
|
|
else
|
|
run_test "SPA routes accessible (auth disabled)" \
|
|
"curl -s ${PULSE_URL}/settings | grep -q '<div id=\"root\">'"
|
|
fi
|
|
|
|
echo ""
|
|
echo "2. API ENDPOINT TESTS"
|
|
echo "===================="
|
|
|
|
# Public endpoints (should work without auth)
|
|
run_test "API health endpoint" \
|
|
"curl -s ${PULSE_URL}/api/health | grep -q 'healthy'"
|
|
|
|
run_test "API version endpoint" \
|
|
"curl -s ${PULSE_URL}/api/version | grep -q 'version'"
|
|
|
|
# If API token provided, test protected endpoints
|
|
if [ -n "$API_TOKEN" ]; then
|
|
echo "Testing with API token..."
|
|
|
|
run_test "API state with token" \
|
|
"curl -s -H 'X-API-Token: $API_TOKEN' ${PULSE_URL}/api/state | grep -q 'nodes'"
|
|
|
|
run_test "API config/nodes with token" \
|
|
"curl -s -H 'X-API-Token: $API_TOKEN' ${PULSE_URL}/api/config/nodes | jq -e '. | type == \"array\"'"
|
|
|
|
run_test "API export requires passphrase" \
|
|
"curl -s -X POST -H 'X-API-Token: $API_TOKEN' ${PULSE_URL}/api/config/export -d '{}' | grep -q 'Passphrase is required'"
|
|
else
|
|
echo -e "${YELLOW}Skipping auth tests (no API_TOKEN provided)${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "3. WEBSOCKET TESTS"
|
|
echo "=================="
|
|
|
|
# Test WebSocket endpoint availability
|
|
run_test "WebSocket endpoint responds" \
|
|
"curl -s -I -H 'Upgrade: websocket' ${PULSE_URL}/ws | grep -q 'HTTP/1.1'"
|
|
|
|
echo ""
|
|
echo "4. REVERSE PROXY SIMULATION"
|
|
echo "==========================="
|
|
|
|
# Simulate reverse proxy headers
|
|
run_test "Handles X-Forwarded headers" \
|
|
"curl -s -H 'X-Forwarded-For: 10.0.0.1' -H 'X-Forwarded-Proto: https' ${PULSE_URL}/api/health | grep -q 'healthy'"
|
|
|
|
run_test "Handles proxy without trailing slash" \
|
|
"curl -s -H 'X-Forwarded-Host: proxy.example.com' ${PULSE_URL} | grep -q '<title>'"
|
|
|
|
echo ""
|
|
echo "5. DOCKER DEPLOYMENT TEST (if Docker available)"
|
|
echo "=============================================="
|
|
|
|
if false && command -v docker &> /dev/null; then # Temporarily disabled - hanging
|
|
echo "Testing Docker deployment..."
|
|
|
|
# Stop any existing test container
|
|
docker stop pulse-test 2>/dev/null || true
|
|
docker rm pulse-test 2>/dev/null || true
|
|
|
|
# Run test container
|
|
echo "Starting Docker container..."
|
|
docker run -d --name pulse-test \
|
|
-p 7656:7655 \
|
|
-e API_TOKEN=test123 \
|
|
rcourtman/pulse:v${VERSION} > /dev/null 2>&1
|
|
|
|
# Wait for container to start
|
|
sleep 5
|
|
|
|
run_test "Docker container running" \
|
|
"docker ps | grep -q pulse-test"
|
|
|
|
run_test "Docker health endpoint" \
|
|
"curl -s http://localhost:7656/api/health | grep -q 'healthy'"
|
|
|
|
run_test "Docker UI loads" \
|
|
"curl -s http://localhost:7656 | grep -q '<title>Pulse</title>'"
|
|
|
|
# Cleanup
|
|
docker stop pulse-test > /dev/null 2>&1
|
|
docker rm pulse-test > /dev/null 2>&1
|
|
else
|
|
echo -e "${YELLOW}Docker not available, skipping Docker tests${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "6. LXC DEPLOYMENT TEST (if on Proxmox)"
|
|
echo "====================================="
|
|
|
|
if command -v pct &> /dev/null; then
|
|
echo "Would test LXC deployment (implement based on environment)"
|
|
# This would create a test container, install Pulse, and verify
|
|
else
|
|
echo -e "${YELLOW}Not on Proxmox, skipping LXC tests${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "7. UPDATE MECHANISM TEST"
|
|
echo "======================="
|
|
|
|
# Update check
|
|
if [ "$AUTH_DISABLED" = true ]; then
|
|
run_test "Update check endpoint (auth disabled)" \
|
|
"curl -s ${PULSE_URL}/api/updates/check | jq -e '.currentVersion'"
|
|
elif [ -n "$API_TOKEN" ]; then
|
|
run_test "Update check endpoint with auth" \
|
|
"curl -s -H 'X-API-Token: $API_TOKEN' ${PULSE_URL}/api/updates/check | jq -e '.currentVersion'"
|
|
else
|
|
run_test "Update check requires auth" \
|
|
"curl -s ${PULSE_URL}/api/updates/check | grep -q 'Authentication required'"
|
|
fi
|
|
|
|
echo ""
|
|
echo "8. PERFORMANCE TESTS"
|
|
echo "==================="
|
|
|
|
# Test response times
|
|
RESPONSE_TIME=$(curl -s -o /dev/null -w '%{time_total}' ${PULSE_URL}/api/health)
|
|
if (( $(echo "$RESPONSE_TIME < 1" | bc -l) )); then
|
|
echo -e "${GREEN}✓ API response time: ${RESPONSE_TIME}s${NC}"
|
|
PASSED_TESTS+=("API response time")
|
|
else
|
|
echo -e "${RED}✗ API slow: ${RESPONSE_TIME}s${NC}"
|
|
FAILED_TESTS+=("API response time")
|
|
fi
|
|
|
|
echo ""
|
|
echo "9. ERROR HANDLING TESTS"
|
|
echo "======================"
|
|
|
|
# 401 is returned before 404 when not authenticated (auth checked first)
|
|
if [ "$AUTH_DISABLED" = true ]; then
|
|
run_test "404 for non-existent endpoint" \
|
|
"curl -s -o /dev/null -w '%{http_code}' ${PULSE_URL}/api/nonexistent | grep -q '404'"
|
|
elif [ -n "$API_TOKEN" ]; then
|
|
run_test "404 for non-existent API endpoint" \
|
|
"curl -s -o /dev/null -w '%{http_code}' -H 'X-API-Token: $API_TOKEN' ${PULSE_URL}/api/nonexistent | grep -q '404'"
|
|
else
|
|
run_test "401 for non-existent endpoint (auth first)" \
|
|
"curl -s -o /dev/null -w '%{http_code}' ${PULSE_URL}/api/nonexistent | grep -q '401'"
|
|
fi
|
|
|
|
run_test "405 for wrong method" \
|
|
"curl -s -X DELETE -o /dev/null -w '%{http_code}' ${PULSE_URL}/api/health | grep -q '405'"
|
|
|
|
echo ""
|
|
echo "================================================"
|
|
echo "TEST RESULTS SUMMARY"
|
|
echo "================================================"
|
|
echo -e "${GREEN}Passed: ${#PASSED_TESTS[@]} tests${NC}"
|
|
echo -e "${RED}Failed: ${#FAILED_TESTS[@]} tests${NC}"
|
|
|
|
if [ ${#FAILED_TESTS[@]} -gt 0 ]; then
|
|
echo ""
|
|
echo "Failed tests:"
|
|
for test in "${FAILED_TESTS[@]}"; do
|
|
echo " - $test"
|
|
done
|
|
echo ""
|
|
echo -e "${RED}⚠️ RELEASE TESTS FAILED - DO NOT RELEASE!${NC}"
|
|
exit 1
|
|
else
|
|
echo ""
|
|
echo -e "${GREEN}✅ All tests passed! Safe to release.${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Additional manual tests recommended:"
|
|
echo " 1. Test behind actual reverse proxy (nginx/traefik)"
|
|
echo " 2. Test with Cloudflare tunnel"
|
|
echo " 3. Test ProxmoxVE 'update' command"
|
|
echo " 4. Test on different architectures (ARM)"
|
|
echo " 5. Test upgrade from previous version" |