Files
foxhunt/tests/harness/mod.rs
jgrusewski eb5fe84e22 🔥 COMPILATION SUCCESS: Complete resolution of all 543+ compilation errors
ARCHITECTURAL ACHIEVEMENTS:
 Zero compilation errors across entire workspace
 Complete elimination of circular dependencies
 Proper configuration architecture with centralized config crate
 Fixed all type mismatches and missing fields
 Restored proper crate structure (config at root level)

MAJOR FIXES:
- Fixed 19 critical data crate compilation errors
- Resolved configuration struct field mismatches
- Fixed enum variant naming (CSV → Csv)
- Corrected type conversions (FromPrimitive, compression types)
- Fixed HashMap key types (u32 vs usize)
- Resolved TLOBProcessor constructor issues

WORKSPACE STATUS:
- All services compile successfully
- Trading Service:  Ready
- Backtesting Service:  Ready
- ML Training Service:  Ready
- TLI Client:  Ready

Only documentation warnings remain (3,316 warnings to be addressed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 10:59:34 +02:00

194 lines
5.7 KiB
Rust

//! Test Harness for Foxhunt HFT Integration Testing
//!
//! Provides utilities for comprehensive end-to-end testing including:
//! - gRPC service clients
//! - Test data generation
//! - Database fixtures
//! - Performance monitoring
//! - Service orchestration
pub mod grpc_clients;
pub mod test_data;
pub mod fixtures;
pub mod performance;
pub mod docker_compose;
pub mod proto;
use std::sync::Arc;
use std::time::Duration;
use tokio::time::timeout;
use anyhow::Result;
/// Core test harness for managing service lifecycles and test execution
pub struct TestHarness {
pub grpc_clients: grpc_clients::GrpcClients,
pub test_data: test_data::TestDataGenerator,
pub fixtures: fixtures::TestFixtures,
pub performance: performance::PerformanceMonitor,
}
impl TestHarness {
/// Initialize test harness with all required components
pub async fn new() -> Result<Self> {
let grpc_clients = grpc_clients::GrpcClients::new().await?;
let test_data = test_data::TestDataGenerator::new();
let fixtures = fixtures::TestFixtures::new().await?;
let performance = performance::PerformanceMonitor::new();
Ok(Self {
grpc_clients,
test_data,
fixtures,
performance,
})
}
/// Setup test environment with all services
pub async fn setup(&mut self) -> Result<()> {
// Start database fixtures
self.fixtures.setup().await?;
// Wait for services to be ready
self.wait_for_services().await?;
// Generate test data
self.test_data.generate_synthetic_data().await?;
Ok(())
}
/// Cleanup test environment
pub async fn cleanup(&mut self) -> Result<()> {
self.fixtures.cleanup().await?;
Ok(())
}
/// Wait for all services to be healthy
async fn wait_for_services(&self) -> Result<()> {
let timeout_duration = Duration::from_secs(60);
timeout(timeout_duration, async {
loop {
if self.grpc_clients.are_all_healthy().await? {
break;
}
tokio::time::sleep(Duration::from_millis(500)).await;
}
Ok::<(), anyhow::Error>(())
}).await??;
Ok(())
}
/// Execute end-to-end test scenario with performance monitoring
pub async fn execute_scenario<F, Fut>(&mut self, name: &str, test_fn: F) -> Result<TestResult>
where
F: FnOnce(&mut TestHarness) -> Fut,
Fut: std::future::Future<Output = Result<()>>,
{
let start_time = std::time::Instant::now();
self.performance.start_scenario(name);
let result = match test_fn(self).await {
Ok(()) => TestResult::Success {
duration: start_time.elapsed(),
metrics: self.performance.get_metrics(name),
},
Err(e) => TestResult::Failure {
duration: start_time.elapsed(),
error: e.to_string(),
metrics: self.performance.get_metrics(name),
},
};
self.performance.end_scenario(name);
Ok(result)
}
}
/// Test execution result with performance metrics
#[derive(Debug)]
pub enum TestResult {
Success {
duration: Duration,
metrics: performance::ScenarioMetrics,
},
Failure {
duration: Duration,
error: String,
metrics: performance::ScenarioMetrics,
},
}
impl TestResult {
pub fn is_success(&self) -> bool {
matches!(self, TestResult::Success { .. })
}
pub fn duration(&self) -> Duration {
match self {
TestResult::Success { duration, .. } => *duration,
TestResult::Failure { duration, .. } => *duration,
}
}
pub fn metrics(&self) -> &performance::ScenarioMetrics {
match self {
TestResult::Success { metrics, .. } => metrics,
TestResult::Failure { metrics, .. } => metrics,
}
}
}
/// Test environment configuration
#[derive(Debug, Clone)]
pub struct TestConfig {
pub tli_endpoint: String,
pub ml_training_endpoint: String,
pub trading_service_endpoint: String,
pub database_url: String,
pub influxdb_url: String,
pub enable_gpu_tests: bool,
pub performance_baseline_file: Option<String>,
}
impl Default for TestConfig {
fn default() -> Self {
Self {
tli_endpoint: "http://localhost:50051".to_string(),
ml_training_endpoint: "http://localhost:50052".to_string(),
trading_service_endpoint: "http://localhost:50053".to_string(),
database_url: "postgresql://test:test@localhost:5432/foxhunt_test".to_string(),
influxdb_url: "http://localhost:8086".to_string(),
enable_gpu_tests: false,
performance_baseline_file: None,
}
}
}
/// Load test configuration from environment or config file
pub fn load_test_config() -> Result<TestConfig> {
let mut config = TestConfig::default();
// Override with environment variables if present
if let Ok(endpoint) = std::env::var("TLI_ENDPOINT") {
config.tli_endpoint = endpoint;
}
if let Ok(endpoint) = std::env::var("ML_TRAINING_ENDPOINT") {
config.ml_training_endpoint = endpoint;
}
if let Ok(endpoint) = std::env::var("TRADING_SERVICE_ENDPOINT") {
config.trading_service_endpoint = endpoint;
}
if let Ok(url) = std::env::var("DATABASE_URL") {
config.database_url = url;
}
if let Ok(url) = std::env::var("INFLUXDB_URL") {
config.influxdb_url = url;
}
if let Ok(_) = std::env::var("ENABLE_GPU_TESTS") {
config.enable_gpu_tests = true;
}
Ok(config)
}