357 lines
10 KiB
Bash
Executable File
357 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Comprehensive Error Handling and Recovery Testing for Event-Based Configuration System
|
|
# Tests various failure scenarios and recovery mechanisms
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
RELAY_BINARY="./build/c_relay_x86"
|
|
TEST_DB_PREFIX="test_relay"
|
|
LOG_FILE="test_results.log"
|
|
|
|
# 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
|
|
TESTS_PASSED=0
|
|
TESTS_FAILED=0
|
|
TESTS_TOTAL=0
|
|
|
|
# Function to print colored output
|
|
print_test_header() {
|
|
echo -e "${BLUE}[TEST]${NC} $1"
|
|
((TESTS_TOTAL++))
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
((TESTS_PASSED++))
|
|
}
|
|
|
|
print_failure() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
((TESTS_FAILED++))
|
|
}
|
|
|
|
print_info() {
|
|
echo -e "${YELLOW}[INFO]${NC} $1"
|
|
}
|
|
|
|
# Clean up function
|
|
cleanup_test_files() {
|
|
print_info "Cleaning up test files..."
|
|
pkill -f "c_relay_" 2>/dev/null || true
|
|
rm -f ${TEST_DB_PREFIX}*.nrdb* 2>/dev/null || true
|
|
rm -f test_*.log 2>/dev/null || true
|
|
sleep 1
|
|
}
|
|
|
|
# Function to start relay and capture output
|
|
start_relay_test() {
|
|
local test_name="$1"
|
|
local timeout="${2:-10}"
|
|
|
|
print_info "Starting relay for test: $test_name"
|
|
timeout $timeout $RELAY_BINARY > "test_${test_name}.log" 2>&1 &
|
|
local relay_pid=$!
|
|
sleep 2
|
|
|
|
if kill -0 $relay_pid 2>/dev/null; then
|
|
echo $relay_pid
|
|
else
|
|
echo "0"
|
|
fi
|
|
}
|
|
|
|
# Function to stop relay
|
|
stop_relay_test() {
|
|
local relay_pid="$1"
|
|
if [ "$relay_pid" != "0" ]; then
|
|
kill $relay_pid 2>/dev/null || true
|
|
wait $relay_pid 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
# Function to check if relay started successfully
|
|
check_relay_startup() {
|
|
local log_file="$1"
|
|
if grep -q "First-time startup sequence completed\|Existing relay startup" "$log_file" 2>/dev/null; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Function to check if relay has admin keys
|
|
check_admin_keys() {
|
|
local log_file="$1"
|
|
if grep -q "Admin Private Key:" "$log_file" 2>/dev/null; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Function to check database file creation
|
|
check_database_creation() {
|
|
if ls *.nrdb 2>/dev/null | head -1; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Function to check configuration event in database
|
|
check_config_event_stored() {
|
|
local db_file="$1"
|
|
if [ -f "$db_file" ]; then
|
|
local count=$(sqlite3 "$db_file" "SELECT COUNT(*) FROM events WHERE kind = 33334;" 2>/dev/null || echo "0")
|
|
if [ "$count" -gt 0 ]; then
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
echo "========================================"
|
|
echo "Event-Based Configuration System Tests"
|
|
echo "========================================"
|
|
echo
|
|
|
|
# Ensure binary exists
|
|
if [ ! -f "$RELAY_BINARY" ]; then
|
|
print_failure "Relay binary not found. Please build first: make"
|
|
exit 1
|
|
fi
|
|
|
|
print_info "Starting comprehensive error handling and recovery tests..."
|
|
echo
|
|
|
|
# TEST 1: Normal First-Time Startup
|
|
print_test_header "Test 1: Normal First-Time Startup"
|
|
cleanup_test_files
|
|
|
|
relay_pid=$(start_relay_test "first_startup" 15)
|
|
sleep 5
|
|
stop_relay_test $relay_pid
|
|
|
|
if check_relay_startup "test_first_startup.log"; then
|
|
if check_admin_keys "test_first_startup.log"; then
|
|
if db_file=$(check_database_creation); then
|
|
if check_config_event_stored "$db_file"; then
|
|
print_success "First-time startup completed successfully"
|
|
else
|
|
print_failure "Configuration event not stored in database"
|
|
fi
|
|
else
|
|
print_failure "Database file not created"
|
|
fi
|
|
else
|
|
print_failure "Admin keys not generated"
|
|
fi
|
|
else
|
|
print_failure "Relay failed to complete startup"
|
|
fi
|
|
|
|
# TEST 2: Existing Relay Startup
|
|
print_test_header "Test 2: Existing Relay Startup (using existing database)"
|
|
|
|
relay_pid=$(start_relay_test "existing_startup" 10)
|
|
sleep 3
|
|
stop_relay_test $relay_pid
|
|
|
|
if check_relay_startup "test_existing_startup.log"; then
|
|
if ! check_admin_keys "test_existing_startup.log"; then
|
|
print_success "Existing relay startup (no new keys generated)"
|
|
else
|
|
print_failure "New admin keys generated for existing relay"
|
|
fi
|
|
else
|
|
print_failure "Existing relay failed to start"
|
|
fi
|
|
|
|
# TEST 3: Corrupted Database Recovery
|
|
print_test_header "Test 3: Corrupted Database Recovery"
|
|
|
|
if db_file=$(check_database_creation); then
|
|
# Corrupt the database by truncating it
|
|
truncate -s 100 "$db_file"
|
|
print_info "Database corrupted for recovery test"
|
|
|
|
relay_pid=$(start_relay_test "corrupted_db" 10)
|
|
sleep 3
|
|
stop_relay_test $relay_pid
|
|
|
|
if grep -q "ERROR.*database\|Failed.*database\|disk I/O error" "test_corrupted_db.log"; then
|
|
print_success "Corrupted database properly detected and handled"
|
|
else
|
|
print_failure "Corrupted database not properly handled"
|
|
fi
|
|
fi
|
|
|
|
# TEST 4: Missing Database File Recovery
|
|
print_test_header "Test 4: Missing Database File Recovery"
|
|
cleanup_test_files
|
|
|
|
# Create a database then remove it to simulate loss
|
|
relay_pid=$(start_relay_test "create_db" 10)
|
|
sleep 3
|
|
stop_relay_test $relay_pid
|
|
|
|
if db_file=$(check_database_creation); then
|
|
rm -f "$db_file"*
|
|
print_info "Database files removed to test recovery"
|
|
|
|
relay_pid=$(start_relay_test "missing_db" 15)
|
|
sleep 5
|
|
stop_relay_test $relay_pid
|
|
|
|
if check_relay_startup "test_missing_db.log"; then
|
|
if check_admin_keys "test_missing_db.log"; then
|
|
print_success "Missing database recovery successful (new keys generated)"
|
|
else
|
|
print_failure "New admin keys not generated after database loss"
|
|
fi
|
|
else
|
|
print_failure "Failed to recover from missing database"
|
|
fi
|
|
fi
|
|
|
|
# TEST 5: Invalid Configuration Event Handling
|
|
print_test_header "Test 5: Configuration Event Structure Validation"
|
|
|
|
# This test would require injecting an invalid configuration event
|
|
# For now, we check that the validation functions are properly integrated
|
|
if grep -q "nostr_validate_event_structure\|nostr_verify_event_signature" src/config.c; then
|
|
print_success "Configuration event validation functions integrated"
|
|
else
|
|
print_failure "Configuration event validation functions not found"
|
|
fi
|
|
|
|
# TEST 6: Database Schema Version Check
|
|
print_test_header "Test 6: Database Schema Consistency"
|
|
|
|
if db_file=$(check_database_creation); then
|
|
# Check that the database has the correct schema version
|
|
schema_version=$(sqlite3 "$db_file" "SELECT value FROM schema_info WHERE key = 'version';" 2>/dev/null || echo "")
|
|
if [ "$schema_version" = "4" ]; then
|
|
print_success "Database schema version is correct (v4)"
|
|
else
|
|
print_failure "Database schema version incorrect: $schema_version (expected: 4)"
|
|
fi
|
|
|
|
# Check that legacy tables don't exist
|
|
if ! sqlite3 "$db_file" ".tables" 2>/dev/null | grep -q "config_file_cache\|active_config"; then
|
|
print_success "Legacy configuration tables properly removed"
|
|
else
|
|
print_failure "Legacy configuration tables still present"
|
|
fi
|
|
fi
|
|
|
|
# TEST 7: Memory and Resource Management
|
|
print_test_header "Test 7: Resource Cleanup and Memory Management"
|
|
|
|
relay_pid=$(start_relay_test "resource_test" 15)
|
|
sleep 5
|
|
|
|
# Check for memory leaks or resource issues (basic check)
|
|
if kill -0 $relay_pid 2>/dev/null; then
|
|
# Send termination signal and check cleanup
|
|
kill -TERM $relay_pid 2>/dev/null || true
|
|
sleep 2
|
|
|
|
if ! kill -0 $relay_pid 2>/dev/null; then
|
|
if grep -q "Configuration system cleaned up" "test_resource_test.log"; then
|
|
print_success "Resource cleanup completed successfully"
|
|
else
|
|
print_failure "Resource cleanup not logged properly"
|
|
fi
|
|
else
|
|
kill -KILL $relay_pid 2>/dev/null || true
|
|
print_failure "Relay did not shut down cleanly"
|
|
fi
|
|
else
|
|
print_failure "Relay process not running for resource test"
|
|
fi
|
|
|
|
# TEST 8: Configuration Cache Consistency
|
|
print_test_header "Test 8: Configuration Cache Consistency"
|
|
|
|
if db_file=$(check_database_creation); then
|
|
# Check that configuration is properly cached and accessible
|
|
config_count=$(sqlite3 "$db_file" "SELECT COUNT(*) FROM events WHERE kind = 33334;" 2>/dev/null || echo "0")
|
|
if [ "$config_count" -eq 1 ]; then
|
|
print_success "Single configuration event stored (replaceable event working)"
|
|
else
|
|
print_failure "Multiple or no configuration events found: $config_count"
|
|
fi
|
|
fi
|
|
|
|
# TEST 9: Network Port Binding
|
|
print_test_header "Test 9: Network Port Availability and Binding"
|
|
|
|
relay_pid=$(start_relay_test "network_test" 10)
|
|
sleep 3
|
|
|
|
if kill -0 $relay_pid 2>/dev/null; then
|
|
# Check if port 8888 is being used
|
|
if netstat -tln 2>/dev/null | grep -q ":8888"; then
|
|
print_success "Relay successfully bound to network port 8888"
|
|
else
|
|
print_failure "Relay not bound to expected port 8888"
|
|
fi
|
|
stop_relay_test $relay_pid
|
|
else
|
|
print_failure "Relay failed to start for network test"
|
|
fi
|
|
|
|
# TEST 10: Multiple Startup Attempts (Port Conflict)
|
|
print_test_header "Test 10: Port Conflict Handling"
|
|
|
|
relay_pid1=$(start_relay_test "port_conflict_1" 10)
|
|
sleep 2
|
|
|
|
if kill -0 $relay_pid1 2>/dev/null; then
|
|
# Try to start a second relay (should fail due to port conflict)
|
|
relay_pid2=$(start_relay_test "port_conflict_2" 5)
|
|
sleep 1
|
|
|
|
if [ "$relay_pid2" = "0" ] || ! kill -0 $relay_pid2 2>/dev/null; then
|
|
print_success "Port conflict properly handled (second instance failed to start)"
|
|
else
|
|
print_failure "Multiple relay instances started (port conflict not handled)"
|
|
stop_relay_test $relay_pid2
|
|
fi
|
|
|
|
stop_relay_test $relay_pid1
|
|
else
|
|
print_failure "First relay instance failed to start"
|
|
fi
|
|
|
|
# Final cleanup
|
|
cleanup_test_files
|
|
|
|
# Test Results Summary
|
|
echo
|
|
echo "========================================"
|
|
echo "Test Results Summary"
|
|
echo "========================================"
|
|
echo "Tests Passed: $TESTS_PASSED"
|
|
echo "Tests Failed: $TESTS_FAILED"
|
|
echo "Total Tests: $TESTS_TOTAL"
|
|
echo
|
|
|
|
if [ $TESTS_FAILED -eq 0 ]; then
|
|
print_success "ALL TESTS PASSED! Event-based configuration system is robust."
|
|
exit 0
|
|
else
|
|
print_failure "$TESTS_FAILED tests failed. Review the results above."
|
|
echo
|
|
print_info "Check individual test log files (test_*.log) for detailed error information."
|
|
exit 1
|
|
fi |