//! Test framework utilities for Foxhunt HFT system #![allow(unused_crate_dependencies)] use rust_decimal::Decimal; /// Test framework for setting up common test infrastructure pub struct TestFramework { pub config: TestConfig, } /// Configuration for test setup #[derive(Debug, Clone)] pub struct TestConfig { pub initial_capital: Decimal, pub test_symbols: Vec, pub enable_logging: bool, } impl Default for TestConfig { fn default() -> Self { Self { initial_capital: Decimal::from(100000), test_symbols: vec!["BTCUSD".to_string(), "ETHUSD".to_string()], enable_logging: false, } } } impl TestFramework { pub fn new(config: TestConfig) -> Self { Self { config } } pub fn with_default() -> Self { Self::new(TestConfig::default()) } pub async fn setup(&self) -> anyhow::Result<()> { if self.config.enable_logging { // Structured logging (tracing_subscriber) is not a dep of this // integration crate; tests rely on stdout println!. Callers // that want structured logs should run via the workspace // test harness which initialises tracing at its entry point. println!("Logging enabled (tracing_subscriber not available)"); } Ok(()) } } /// Test safety module for error-free testing pub mod test_safety { use std::fmt::Debug; use std::time::Duration; /// Safe test result type pub type TestResult = Result; /// Test safety error types #[derive(Debug, Clone)] pub enum TestSafetyError { AssertionFailed { field: String, expected: String, actual: String, }, ThreadJoinFailed { thread_type: String, }, Timeout { operation: String, timeout_ms: u64, }, CalculationFailed { operation: String, details: String, }, } impl std::fmt::Display for TestSafetyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TestSafetyError::AssertionFailed { field, expected, actual, } => { write!( f, "Assertion failed for {}: expected {}, got {}", field, expected, actual ) }, TestSafetyError::ThreadJoinFailed { thread_type } => { write!(f, "Thread join failed for: {}", thread_type) }, TestSafetyError::Timeout { operation, timeout_ms, } => { write!( f, "Operation {} timed out after {}ms", operation, timeout_ms ) }, TestSafetyError::CalculationFailed { operation, details } => { write!(f, "Calculation failed for {}: {}", operation, details) }, } } } impl std::error::Error for TestSafetyError {} /// Safe assertion function pub fn safe_assert( condition: bool, field: &str, expected: &str, actual: impl std::fmt::Display, ) -> TestResult<()> { if condition { Ok(()) } else { Err(TestSafetyError::AssertionFailed { field: field.to_string(), expected: expected.to_string(), actual: actual.to_string(), }) } } /// Safe equality assertion pub fn safe_assert_eq( actual: &T, expected: &T, field: &str, ) -> TestResult<()> { if actual == expected { Ok(()) } else { Err(TestSafetyError::AssertionFailed { field: field.to_string(), expected: format!("{:?}", expected), actual: format!("{:?}", actual), }) } } /// HFT Performance validator pub struct HftPerformanceValidator { pub max_latency_micros: u64, pub min_throughput_ops_per_sec: u64, } impl HftPerformanceValidator { pub fn new() -> Self { Self { max_latency_micros: 50, // 50μs max latency min_throughput_ops_per_sec: 10_000, // 10k ops/sec min } } pub fn validate_latency(&self, duration: Duration) -> TestResult<()> { let micros = duration.as_micros() as u64; safe_assert( micros <= self.max_latency_micros, "latency", &format!("≤{}μs", self.max_latency_micros), format!("{}μs", micros), ) } pub fn validate_throughput(&self, ops_per_sec: u64) -> TestResult<()> { safe_assert( ops_per_sec >= self.min_throughput_ops_per_sec, "throughput", &format!("≥{} ops/sec", self.min_throughput_ops_per_sec), format!("{} ops/sec", ops_per_sec), ) } } impl Default for HftPerformanceValidator { fn default() -> Self { Self::new() } } }