Files
c-relay/tests/run_all_tests.sh

298 lines
10 KiB
Bash
Executable File

#!/bin/bash
# C-Relay Comprehensive Test Suite Runner
# This script runs all security and stability tests for the Nostr relay
set -e
# Configuration
RELAY_HOST="127.0.0.1"
RELAY_PORT="8888"
RELAY_URL="ws://$RELAY_HOST:$RELAY_PORT"
TEST_TIMEOUT=30
LOG_FILE="test_results_$(date +%Y%m%d_%H%M%S).log"
REPORT_FILE="test_report_$(date +%Y%m%d_%H%M%S).html"
# Test keys for authentication (from AGENTS.md)
ADMIN_PRIVATE_KEY="6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"
RELAY_PUBKEY="4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test results tracking
TOTAL_SUITES=0
PASSED_SUITES=0
FAILED_SUITES=0
SKIPPED_SUITES=0
SUITE_RESULTS=()
# Function to create authenticated WebSocket connection
# Usage: authenticated_websocat <subscription_id> <filter_json>
authenticated_websocat() {
local sub_id="$1"
local filter="$2"
# Create a temporary script for authenticated connection
cat > /tmp/auth_ws_$$.sh << EOF
#!/bin/bash
# Authenticated WebSocket connection helper
# Connect and handle AUTH challenge
exec websocat -B 1048576 --no-close ws://$RELAY_HOST:$RELAY_PORT 2>/dev/null << 'INNER_EOF'
["REQ","$sub_id",$filter]
INNER_EOF
EOF
chmod +x /tmp/auth_ws_$$.sh
timeout $TEST_TIMEOUT bash /tmp/auth_ws_$$.sh
rm -f /tmp/auth_ws_$$.sh
}
# Function to log messages
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
# Function to run a test suite
run_test_suite() {
local suite_name="$1"
local suite_script="$2"
local description="$3"
TOTAL_SUITES=$((TOTAL_SUITES + 1))
log "=========================================="
log "Running Test Suite: $suite_name"
log "Description: $description"
log "=========================================="
if [[ ! -f "$suite_script" ]]; then
log "${RED}ERROR: Test script $suite_script not found${NC}"
FAILED_SUITES=$((FAILED_SUITES + 1))
SUITE_RESULTS+=("$suite_name: FAILED (script not found)")
return 1
fi
# Make script executable if not already
chmod +x "$suite_script"
# Run the test suite and capture output
local start_time=$(date +%s)
if bash "$suite_script" >> "$LOG_FILE" 2>&1; then
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log "${GREEN}✓ $suite_name PASSED${NC} (Duration: ${duration}s)"
PASSED_SUITES=$((PASSED_SUITES + 1))
SUITE_RESULTS+=("$suite_name: PASSED (${duration}s)")
return 0
else
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log "${RED}✗ $suite_name FAILED${NC} (Duration: ${duration}s)"
FAILED_SUITES=$((FAILED_SUITES + 1))
SUITE_RESULTS+=("$suite_name: FAILED (${duration}s)")
return 1
fi
}
# Function to check if relay is running
check_relay_status() {
log "Checking relay status at $RELAY_URL..."
# First check if HTTP endpoint is accessible
if curl -s -H "Accept: application/nostr+json" "http://$RELAY_HOST:$RELAY_PORT" >/dev/null 2>&1; then
log "${GREEN}✓ Relay HTTP endpoint is accessible${NC}"
return 0
fi
# Fallback: Try WebSocket connection
if timeout 5 bash -c "
echo '[\"REQ\",\"status_check\",{}]' | websocat -B 1048576 --no-close '$RELAY_URL' >/dev/null 2>&1
" 2>/dev/null; then
log "${GREEN}✓ Relay WebSocket endpoint is accessible${NC}"
return 0
else
log "${RED}✗ Relay is not accessible at $RELAY_URL${NC}"
log "Please start the relay first using: ./make_and_restart_relay.sh"
return 1
fi
}
# Function to generate HTML report
generate_html_report() {
local total_duration=$1
cat > "$REPORT_FILE" << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>C-Relay Test Report - $(date)</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; margin-bottom: 30px; }
.summary { background: white; padding: 20px; border-radius: 8px; margin-bottom: 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.suite { background: white; margin-bottom: 10px; padding: 15px; border-radius: 5px; box-shadow: 0 1px 5px rgba(0,0,0,0.1); }
.passed { border-left: 5px solid #28a745; }
.failed { border-left: 5px solid #dc3545; }
.skipped { border-left: 5px solid #ffc107; }
.metric { display: inline-block; margin: 10px; padding: 10px; background: #e9ecef; border-radius: 5px; }
.status-passed { color: #28a745; font-weight: bold; }
.status-failed { color: #dc3545; font-weight: bold; }
.status-skipped { color: #ffc107; font-weight: bold; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #f8f9fa; }
</style>
</head>
<body>
<div class="header">
<h1>C-Relay Comprehensive Test Report</h1>
<p>Generated on: $(date)</p>
<p>Test Environment: $RELAY_URL</p>
</div>
<div class="summary">
<h2>Test Summary</h2>
<div class="metric">
<strong>Total Suites:</strong> $TOTAL_SUITES
</div>
<div class="metric">
<strong>Passed:</strong> <span class="status-passed">$PASSED_SUITES</span>
</div>
<div class="metric">
<strong>Failed:</strong> <span class="status-failed">$FAILED_SUITES</span>
</div>
<div class="metric">
<strong>Skipped:</strong> <span class="status-skipped">$SKIPPED_SUITES</span>
</div>
<div class="metric">
<strong>Total Duration:</strong> ${total_duration}s
</div>
<div class="metric">
<strong>Success Rate:</strong> $(( (PASSED_SUITES * 100) / TOTAL_SUITES ))%
</div>
</div>
<h2>Test Suite Results</h2>
EOF
for result in "${SUITE_RESULTS[@]}"; do
local suite_name=$(echo "$result" | cut -d: -f1)
local status=$(echo "$result" | cut -d: -f2 | cut -d' ' -f1)
local duration=$(echo "$result" | cut -d: -f2 | cut -d'(' -f2 | cut -d')' -f1)
local css_class="passed"
if [[ "$status" == "FAILED" ]]; then
css_class="failed"
elif [[ "$status" == "SKIPPED" ]]; then
css_class="skipped"
fi
cat >> "$REPORT_FILE" << EOF
<div class="suite $css_class">
<strong>$suite_name</strong> - <span class="status-$css_class">$status</span> ($duration)
</div>
EOF
done
cat >> "$REPORT_FILE" << EOF
</body>
</html>
EOF
log "HTML report generated: $REPORT_FILE"
}
# Main execution
log "=========================================="
log "C-Relay Comprehensive Test Suite Runner"
log "=========================================="
log "Relay URL: $RELAY_URL"
log "Log file: $LOG_FILE"
log "Report file: $REPORT_FILE"
log ""
# Check if relay is running
if ! check_relay_status; then
log "${RED}Cannot proceed without a running relay. Exiting.${NC}"
exit 1
fi
log ""
log "Starting comprehensive test execution..."
log ""
# Record start time
OVERALL_START_TIME=$(date +%s)
# Run Security Test Suites
log "${BLUE}=== SECURITY TEST SUITES ===${NC}"
run_test_suite "SQL Injection Tests" "tests/sql_injection_tests.sh" "Comprehensive SQL injection vulnerability testing"
run_test_suite "Filter Validation Tests" "tests/filter_validation_test.sh" "Input validation for REQ and COUNT messages"
run_test_suite "Subscription Validation Tests" "tests/subscription_validation.sh" "Subscription ID and message validation"
run_test_suite "Memory Corruption Tests" "tests/memory_corruption_tests.sh" "Buffer overflow and memory safety testing"
run_test_suite "Input Validation Tests" "tests/input_validation_tests.sh" "Comprehensive input boundary testing"
# Run Performance Test Suites
log ""
log "${BLUE}=== PERFORMANCE TEST SUITES ===${NC}"
run_test_suite "Subscription Limit Tests" "tests/subscription_limits.sh" "Subscription limit enforcement testing"
run_test_suite "Load Testing" "tests/load_tests.sh" "High concurrent connection testing"
run_test_suite "Stress Testing" "tests/stress_tests.sh" "Resource usage and stability testing"
run_test_suite "Rate Limiting Tests" "tests/rate_limiting_tests.sh" "Rate limiting and abuse prevention"
# Run Integration Test Suites
log ""
log "${BLUE}=== INTEGRATION TEST SUITES ===${NC}"
run_test_suite "NIP Protocol Tests" "tests/run_nip_tests.sh" "All NIP protocol compliance tests"
run_test_suite "Configuration Tests" "tests/config_tests.sh" "Configuration management and persistence"
run_test_suite "Authentication Tests" "tests/auth_tests.sh" "NIP-42 authentication testing"
# Run Benchmarking Suites
log ""
log "${BLUE}=== BENCHMARKING SUITES ===${NC}"
run_test_suite "Performance Benchmarks" "tests/performance_benchmarks.sh" "Performance metrics and benchmarking"
run_test_suite "Resource Monitoring" "tests/resource_monitoring.sh" "Memory and CPU usage monitoring"
# Calculate total duration
OVERALL_END_TIME=$(date +%s)
TOTAL_DURATION=$((OVERALL_END_TIME - OVERALL_START_TIME))
# Generate final report
log ""
log "=========================================="
log "TEST EXECUTION COMPLETE"
log "=========================================="
log "Total test suites: $TOTAL_SUITES"
log "Passed: $PASSED_SUITES"
log "Failed: $FAILED_SUITES"
log "Skipped: $SKIPPED_SUITES"
log "Total duration: ${TOTAL_DURATION}s"
log "Success rate: $(( (PASSED_SUITES * 100) / TOTAL_SUITES ))%"
log ""
log "Detailed log: $LOG_FILE"
# Generate HTML report
generate_html_report "$TOTAL_DURATION"
# Exit with appropriate code
if [[ $FAILED_SUITES -eq 0 ]]; then
log "${GREEN}✓ ALL TESTS PASSED${NC}"
exit 0
else
log "${RED}✗ SOME TESTS FAILED${NC}"
log "Check $LOG_FILE for detailed error information"
exit 1
fi