Files
c-relay/tests/event_config_tests.sh

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