#!/bin/bash # Database Validation Script for Foxhunt HFT Trading System # Validates PostgreSQL, Redis, SQLite, and InfluxDB connections and performance set -e echo "🚀 Foxhunt Database Layer Validation" echo "====================================" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration POSTGRES_URL="${DATABASE_URL:-postgresql://postgres:password@localhost:5432/foxhunt_test}" REDIS_URL="${REDIS_URL:-localhost:6379}" INFLUX_URL="${INFLUX_URL:-localhost:8086}" SQLITE_DB="validation_test.db" # Counters TESTS_PASSED=0 TESTS_FAILED=0 TOTAL_TESTS=0 # Helper functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[PASS]${NC} $1" ((TESTS_PASSED++)) ((TOTAL_TESTS++)) } log_warning() { echo -e "${YELLOW}[WARN]${NC} $1" ((TOTAL_TESTS++)) } log_error() { echo -e "${RED}[FAIL]${NC} $1" ((TESTS_FAILED++)) ((TOTAL_TESTS++)) } # Test PostgreSQL test_postgresql() { echo "" log_info "🔍 Testing PostgreSQL..." # Check if PostgreSQL is accessible if command -v psql >/dev/null 2>&1; then # Test connection if psql "$POSTGRES_URL" -c "SELECT 1;" >/dev/null 2>&1; then log_success "PostgreSQL connection successful" # Performance test - measure simple query latency local start_time=$(date +%s%N) for i in {1..100}; do psql "$POSTGRES_URL" -t -c "SELECT 1;" >/dev/null 2>&1 done local end_time=$(date +%s%N) local total_time=$((end_time - start_time)) local avg_latency_ms=$((total_time / 100000000)) # Convert to ms log_info "Average query latency: ${avg_latency_ms}ms" if [ $avg_latency_ms -lt 10 ]; then log_success "PostgreSQL performance meets requirements (<10ms)" else log_warning "PostgreSQL performance suboptimal (${avg_latency_ms}ms > 10ms)" fi # Test ACID transaction psql "$POSTGRES_URL" >/dev/null 2>&1 << EOF BEGIN; CREATE TABLE IF NOT EXISTS acid_test_$$ (id SERIAL PRIMARY KEY, value INTEGER); INSERT INTO acid_test_$$ (value) VALUES (100); ROLLBACK; EOF # Verify rollback worked local count=$(psql "$POSTGRES_URL" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_name='acid_test_$$';" 2>/dev/null | tr -d ' ' || echo "0") if [ "$count" = "0" ]; then log_success "ACID transaction rollback test passed" else log_error "ACID transaction rollback test failed" fi else log_error "PostgreSQL connection failed" fi else log_warning "psql not available - skipping PostgreSQL tests" fi } # Test Redis test_redis() { echo "" log_info "🔍 Testing Redis..." if command -v redis-cli >/dev/null 2>&1; then # Test connection if redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" ping >/dev/null 2>&1; then log_success "Redis connection successful" # Performance test local start_time=$(date +%s%N) for i in {1..100}; do redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" set "test_key_$i" "test_value_$i" >/dev/null 2>&1 redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" get "test_key_$i" >/dev/null 2>&1 done local end_time=$(date +%s%N) local total_time=$((end_time - start_time)) local avg_latency_ms=$((total_time / 100000000)) log_info "Average operation latency: ${avg_latency_ms}ms" if [ $avg_latency_ms -lt 5 ]; then log_success "Redis performance meets requirements (<5ms)" else log_warning "Redis performance suboptimal (${avg_latency_ms}ms > 5ms)" fi # Test TTL functionality redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" set ttl_test_key ttl_test_value >/dev/null 2>&1 redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" expire ttl_test_key 1 >/dev/null 2>&1 sleep 2 local exists=$(redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" exists ttl_test_key 2>/dev/null) if [ "$exists" = "0" ]; then log_success "Redis TTL functionality working" else log_error "Redis TTL functionality failed" fi # Cleanup test keys for i in {1..100}; do redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" del "test_key_$i" >/dev/null 2>&1 done else log_error "Redis connection failed" fi else log_warning "redis-cli not available - skipping Redis tests" fi } # Test SQLite test_sqlite() { echo "" log_info "🔍 Testing SQLite..." if command -v sqlite3 >/dev/null 2>&1; then # Remove existing test database rm -f "$SQLITE_DB" # Test database creation and operations if sqlite3 "$SQLITE_DB" "CREATE TABLE config_test (key TEXT PRIMARY KEY, value TEXT, updated_at INTEGER);" >/dev/null 2>&1; then log_success "SQLite database creation successful" # Performance test local start_time=$(date +%s%N) for i in {1..50}; do sqlite3 "$SQLITE_DB" "INSERT OR REPLACE INTO config_test (key, value, updated_at) VALUES ('key_$i', 'value_$i', $i);" >/dev/null 2>&1 sqlite3 "$SQLITE_DB" "SELECT value FROM config_test WHERE key='key_$i';" >/dev/null 2>&1 done local end_time=$(date +%s%N) local total_time=$((end_time - start_time)) local avg_latency_ms=$((total_time / 50000000)) log_info "Average operation latency: ${avg_latency_ms}ms" if [ $avg_latency_ms -lt 20 ]; then log_success "SQLite performance acceptable (<20ms)" else log_warning "SQLite performance suboptimal (${avg_latency_ms}ms > 20ms)" fi # Test hot-reload simulation sqlite3 "$SQLITE_DB" "INSERT OR REPLACE INTO config_test (key, value, updated_at) VALUES ('hot_reload_test', 'initial_value', 1);" >/dev/null 2>&1 sqlite3 "$SQLITE_DB" "UPDATE config_test SET value='updated_value', updated_at=2 WHERE key='hot_reload_test';" >/dev/null 2>&1 local updated_value=$(sqlite3 "$SQLITE_DB" "SELECT value FROM config_test WHERE key='hot_reload_test';" 2>/dev/null) if [ "$updated_value" = "updated_value" ]; then log_success "SQLite configuration hot-reload simulation successful" else log_error "SQLite configuration hot-reload simulation failed" fi else log_error "SQLite database creation failed" fi # Cleanup rm -f "$SQLITE_DB" else log_warning "sqlite3 not available - skipping SQLite tests" fi } # Test InfluxDB test_influxdb() { echo "" log_info "🔍 Testing InfluxDB..." if command -v curl >/dev/null 2>&1; then # Test health endpoint if curl -s -o /dev/null -w "%{http_code}" "http://${INFLUX_URL}/health" | grep -q "200"; then log_success "InfluxDB health check successful" # Test write operation (simplified) local timestamp=$(date +%s%N) local line_protocol="test_measurement,tag1=value1 field1=123 $timestamp" local write_url="http://${INFLUX_URL}/api/v2/write?org=test&bucket=test" if curl -s -o /dev/null -w "%{http_code}" -X POST "$write_url" \ -H "Content-Type: text/plain" \ -d "$line_protocol" | grep -q "204\|200"; then log_success "InfluxDB write test successful (or acceptable without auth)" else log_warning "InfluxDB write test failed (may need authentication)" fi elif curl -s -o /dev/null -w "%{http_code}" "http://${INFLUX_URL}/ping" | grep -q "204"; then log_success "InfluxDB ping successful (legacy endpoint)" else log_error "InfluxDB connection failed" fi else log_warning "curl not available - skipping InfluxDB tests" fi } # Test backup capabilities test_backup_capabilities() { echo "" log_info "🔍 Testing backup capabilities..." # Check if backup tools are available local backup_tools=("pg_dump" "redis-cli" "influxd" "tar") local available_tools=0 for tool in "${backup_tools[@]}"; do if command -v "$tool" >/dev/null 2>&1; then ((available_tools++)) log_success "$tool available for backups" else log_warning "$tool not available for backups" fi done if [ $available_tools -gt 2 ]; then log_success "Sufficient backup tools available ($available_tools/4)" else log_warning "Limited backup capabilities ($available_tools/4 tools available)" fi } # Test health monitoring test_health_monitoring() { echo "" log_info "🔍 Testing health monitoring capabilities..." # Check if monitoring tools are available local monitoring_tools=("systemctl" "ps" "netstat" "ss") local available_tools=0 for tool in "${monitoring_tools[@]}"; do if command -v "$tool" >/dev/null 2>&1; then ((available_tools++)) fi done if [ $available_tools -gt 2 ]; then log_success "Health monitoring tools available ($available_tools/4)" else log_warning "Limited health monitoring capabilities ($available_tools/4)" fi # Test basic system health local load_avg=$(uptime | awk '{print $(NF-2)}' | sed 's/,//') if (( $(echo "$load_avg < 2.0" | bc -l 2>/dev/null || echo "1") )); then log_success "System load acceptable ($load_avg)" else log_warning "High system load detected ($load_avg)" fi # Test memory usage local mem_usage=$(free | awk '/Mem:/ { printf("%.1f", $3/$2 * 100.0) }') if (( $(echo "$mem_usage < 80.0" | bc -l 2>/dev/null || echo "1") )); then log_success "Memory usage acceptable (${mem_usage}%)" else log_warning "High memory usage detected (${mem_usage}%)" fi } # Main execution main() { local start_time=$(date +%s) log_info "Starting database validation at $(date)" log_info "Configuration:" log_info " PostgreSQL: $POSTGRES_URL" log_info " Redis: $REDIS_URL" log_info " InfluxDB: $INFLUX_URL" log_info " SQLite: $SQLITE_DB" # Run all tests test_postgresql test_redis test_sqlite test_influxdb test_backup_capabilities test_health_monitoring local end_time=$(date +%s) local total_duration=$((end_time - start_time)) # Generate summary echo "" echo "📊 VALIDATION SUMMARY" echo "====================" echo "Total Time: ${total_duration}s" echo "Tests Passed: $TESTS_PASSED" echo "Tests Failed: $TESTS_FAILED" echo "Total Tests: $TOTAL_TESTS" echo "" if [ $TESTS_FAILED -eq 0 ]; then log_success "🎉 All database validation tests completed successfully!" echo "" echo "✅ Database Layer Status:" echo " - PostgreSQL: Connection and ACID transactions working" echo " - Redis: Caching and TTL functionality working" echo " - SQLite: Configuration storage and hot-reload ready" echo " - InfluxDB: Metrics storage capability verified" echo " - Backup/Recovery: Tools available for data protection" echo " - Health Monitoring: System monitoring capabilities ready" echo "" echo "🚀 The database layer is ready for HFT operations!" exit 0 else log_error "💥 Database validation completed with $TESTS_FAILED failures" echo "" echo "❌ Issues found:" echo " - $TESTS_FAILED out of $TOTAL_TESTS tests failed" echo " - Review the logs above for specific failure details" echo " - Consider addressing failed tests before production deployment" echo "" exit 1 fi } # Execute main function main "$@"