//! Smoke Tests - End-to-End System Validation //! //! Automated smoke tests to validate complete system functionality after deployment. //! Tests are organized by category and can run selectively based on service availability. //! //! ## Test Categories //! - Infrastructure Health (PostgreSQL, Redis, Vault, InfluxDB) //! - Service Health (API Gateway, Trading, Backtesting, ML Training) //! - Authentication Flow (JWT, MFA, Session Management) //! - Basic Order Flow (Submit, Query, Cancel, Positions) //! - Market Data (Streaming, Historical Queries) //! - ML Inference (Predictions, Feature Engineering) //! - Compliance (Audit Logs, Best Execution, Risk Checks) //! - Metrics and Monitoring (Prometheus, Grafana) //! //! ## Usage //! ```bash //! # Run all smoke tests //! cargo test --test smoke_tests //! //! # Run specific category //! cargo test --test smoke_tests infrastructure_health //! cargo test --test smoke_tests service_health //! cargo test --test smoke_tests basic_order_flow //! //! # Run with logging //! RUST_LOG=debug cargo test --test smoke_tests -- --nocapture //! ``` pub mod infrastructure_health; pub mod service_health; pub mod authentication_flow; pub mod basic_order_flow; /// Common test utilities and helpers pub mod common { use std::time::Duration; use tokio::time::timeout; /// Standard timeout for smoke tests (10 seconds) pub const SMOKE_TEST_TIMEOUT: Duration = Duration::from_secs(10); /// Standard timeout for infrastructure checks (5 seconds) pub const INFRA_TEST_TIMEOUT: Duration = Duration::from_secs(5); /// Load database URL from environment pub fn database_url() -> String { std::env::var("DATABASE_URL") .unwrap_or_else(|_| "postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt".to_string()) } /// Load Redis URL from environment pub fn redis_url() -> String { std::env::var("REDIS_URL") .unwrap_or_else(|_| "redis://localhost:6379".to_string()) } /// Load Vault URL from environment pub fn vault_url() -> String { std::env::var("VAULT_ADDR") .unwrap_or_else(|_| "http://localhost:8200".to_string()) } /// Load InfluxDB URL from environment pub fn influxdb_url() -> String { std::env::var("INFLUXDB_URL") .unwrap_or_else(|_| "http://localhost:8086".to_string()) } /// Load API Gateway URL from environment pub fn api_url() -> String { std::env::var("API_GATEWAY_URL") .unwrap_or_else(|_| "http://localhost:50051".to_string()) } /// Load Trading Service URL from environment pub fn trading_service_url() -> String { std::env::var("TRADING_SERVICE_URL") .unwrap_or_else(|_| "http://localhost:50052".to_string()) } /// Load Backtesting Service URL from environment pub fn backtesting_service_url() -> String { std::env::var("BACKTESTING_SERVICE_URL") .unwrap_or_else(|_| "http://localhost:50053".to_string()) } /// Load ML Training Service URL from environment pub fn ml_training_service_url() -> String { std::env::var("ML_TRAINING_SERVICE_URL") .unwrap_or_else(|_| "http://localhost:50054".to_string()) } /// Load Prometheus URL from environment pub fn prometheus_url() -> String { std::env::var("PROMETHEUS_URL") .unwrap_or_else(|_| "http://localhost:9090".to_string()) } /// Load Grafana URL from environment pub fn grafana_url() -> String { std::env::var("GRAFANA_URL") .unwrap_or_else(|_| "http://localhost:3000".to_string()) } /// Run a test with timeout pub async fn with_timeout(future: F) -> Result> where F: std::future::Future>>, { match timeout(SMOKE_TEST_TIMEOUT, future).await { Ok(result) => result, Err(_) => Err("Test timed out after 10 seconds".into()), } } /// Skip test if service is not available /// /// This allows tests to be skipped gracefully when services are down #[macro_export] macro_rules! skip_if_unavailable { ($service:expr, $test:block) => { match $test { Ok(result) => result, Err(e) if e.to_string().contains("connection refused") || e.to_string().contains("connection reset") || e.to_string().contains("timed out") => { eprintln!("⏭️ Skipping test - {} not available: {}", $service, e); return; } Err(e) => panic!("Test failed: {}", e), } }; } }