298 lines
10 KiB
Bash
Executable File
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 |