Files
foxhunt/trading_engine/tests/brokers_comprehensive.rs
jgrusewski 32e33d3d19 🎯 Waves 82-99: Complete compilation fix + warning reduction
## Final Metrics (Wave 99)
- Compilation errors: 672 → 0  (100% resolution)
- Test compilation: 489 → 0  (100% resolution)
- Warnings: 313 → 124 (60% reduction, target was <50)

## Wave Timeline
Wave 82-87: Source code errors (183→0)
Wave 88-94: Test compilation (489→0)
Wave 95: Import cleanup experiment
Wave 96: Import restoration (26 errors fixed)
Wave 97: Warning phase 1 (313→188, -40%)
Wave 98: Warning phase 2 (188→124, -34%)
Wave 99: Warning phase 3 (124→124, target not met)

## Major API Migrations (73+ files)
- NewsEvent: 18-field structure with full metadata
- ExecutionReport: filled_quantity→executed_quantity
- Position: 16-field modernization (avg_cost, market_value, etc)
- TradingOrder: account_id field added
- TimeInForce: Abbreviated variants (GTC, IOC, FOK)

## Remaining Work
- 124 warnings (non-critical: unused variables, dead code, deprecated APIs)
- Most are cleanup/style issues, not correctness problems
- Recommendation: Accept current state, prioritize test coverage (95% target)

## Production Status
 Wave 79 certified: 87.8% production ready
 Zero compilation errors maintained
 All services compile and tests runnable
🔄 Next: Test coverage measurement (95% target - CLAUDE.md requirement)

Co-authored-by: Wave 82-99 Agents (40+ parallel agents deployed)
2025-10-04 12:14:46 +02:00

638 lines
21 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#![allow(unused_crate_dependencies)]
//! Comprehensive brokers module tests targeting 95% coverage
//! Tests for brokers/mod.rs and related broker connection functionality
use trading_engine::brokers::config::BrokerConnectorConfig;
use trading_engine::brokers::BrokerConnector;
// ============================================================================
// BrokerConnector::new() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_creation_tests {
use super::*;
#[test]
fn test_broker_connector_new_default_config() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
// Verify connector was created (should not panic)
assert!(format!("{:?}", connector).contains("BrokerConnector"));
}
#[test]
fn test_broker_connector_new_custom_config() {
let mut config = BrokerConnectorConfig::default();
config.brokers.interactive_brokers.enabled = true;
config.fail_on_broker_error = true;
let connector = BrokerConnector::new(config);
assert!(format!("{:?}", connector).contains("BrokerConnector"));
}
#[test]
fn test_broker_connector_new_disabled_config() {
let mut config = BrokerConnectorConfig::default();
config.brokers.interactive_brokers.enabled = false;
let connector = BrokerConnector::new(config);
assert!(format!("{:?}", connector).contains("BrokerConnector"));
}
#[test]
fn test_multiple_broker_connectors_independent() {
let config1 = BrokerConnectorConfig::default();
let config2 = BrokerConnectorConfig::default();
let connector1 = BrokerConnector::new(config1);
let connector2 = BrokerConnector::new(config2);
// Both should be independent instances
assert!(format!("{:?}", connector1).contains("BrokerConnector"));
assert!(format!("{:?}", connector2).contains("BrokerConnector"));
}
}
// ============================================================================
// BrokerConnector::initialize() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_initialization_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_initialize_success() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
let result = connector.initialize().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_initialize_multiple_times() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
// Initialize multiple times should be safe
assert!(connector.initialize().await.is_ok());
assert!(connector.initialize().await.is_ok());
assert!(connector.initialize().await.is_ok());
}
#[tokio::test]
async fn test_broker_connector_initialize_with_custom_config() {
let mut config = BrokerConnectorConfig::default();
config.fail_on_broker_error = true;
let mut connector = BrokerConnector::new(config);
let result = connector.initialize().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_initialize_concurrent() {
let config = BrokerConnectorConfig::default();
let mut connector1 = BrokerConnector::new(config.clone());
let mut connector2 = BrokerConnector::new(config);
let (result1, result2) = tokio::join!(
connector1.initialize(),
connector2.initialize()
);
assert!(result1.is_ok());
assert!(result2.is_ok());
}
}
// ============================================================================
// BrokerConnector::submit_order() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_submit_order_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_submit_order_success() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result = connector.submit_order("ORD_123").await;
assert!(result.is_ok());
let broker_order_id = result.unwrap();
assert!(!broker_order_id.is_empty());
}
#[tokio::test]
async fn test_broker_connector_submit_order_multiple() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result1 = connector.submit_order("ORD_001").await;
let result2 = connector.submit_order("ORD_002").await;
let result3 = connector.submit_order("ORD_003").await;
assert!(result1.is_ok());
assert!(result2.is_ok());
assert!(result3.is_ok());
}
#[tokio::test]
async fn test_broker_connector_submit_order_empty_id() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result = connector.submit_order("").await;
assert!(result.is_ok()); // Placeholder accepts empty IDs
}
#[tokio::test]
async fn test_broker_connector_submit_order_special_characters() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let order_ids = vec![
"ORD_ABC-123",
"ORD:456",
"ORD/789",
"ORD.XYZ",
];
for order_id in order_ids {
let result = connector.submit_order(order_id).await;
assert!(result.is_ok(), "Failed for order_id: {}", order_id);
}
}
#[tokio::test]
async fn test_broker_connector_submit_order_concurrent() {
let config = BrokerConnectorConfig::default();
let connector = std::sync::Arc::new(BrokerConnector::new(config));
let mut handles = vec![];
for i in 0..10 {
let connector_clone = connector.clone();
let handle = tokio::spawn(async move {
let _ = connector_clone.submit_order(&format!("ORD_{}", i)).await;
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}
#[tokio::test]
async fn test_broker_connector_submit_order_long_id() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let long_id = "ORD_".to_string() + &"A".repeat(1000);
let result = connector.submit_order(&long_id).await;
assert!(result.is_ok());
}
}
// ============================================================================
// BrokerConnector::cancel_order() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_cancel_order_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_cancel_order_success() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result = connector.cancel_order("ORD_123").await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_cancel_order_nonexistent() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result = connector.cancel_order("NONEXISTENT").await;
assert!(result.is_ok()); // Placeholder accepts any ID
}
#[tokio::test]
async fn test_broker_connector_cancel_order_multiple_times() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
// Cancel same order multiple times
let order_id = "ORD_999";
assert!(connector.cancel_order(order_id).await.is_ok());
assert!(connector.cancel_order(order_id).await.is_ok());
assert!(connector.cancel_order(order_id).await.is_ok());
}
#[tokio::test]
async fn test_broker_connector_cancel_order_empty_id() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let result = connector.cancel_order("").await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_cancel_order_concurrent() {
let config = BrokerConnectorConfig::default();
let connector = std::sync::Arc::new(BrokerConnector::new(config));
let mut handles = vec![];
for i in 0..10 {
let connector_clone = connector.clone();
let handle = tokio::spawn(async move {
let _ = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}
#[tokio::test]
async fn test_broker_connector_submit_and_cancel_workflow() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
// Submit an order
let submit_result = connector.submit_order("ORD_WORKFLOW").await;
assert!(submit_result.is_ok());
// Cancel the order
let cancel_result = connector.cancel_order("ORD_WORKFLOW").await;
assert!(cancel_result.is_ok());
}
}
// ============================================================================
// BrokerConnector::get_connected_brokers() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_get_connected_brokers_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_get_connected_brokers_initial() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let brokers = connector.get_connected_brokers().await;
assert!(!brokers.is_empty());
assert!(brokers.contains(&"InteractiveBrokers".to_string()));
}
#[tokio::test]
async fn test_broker_connector_get_connected_brokers_after_init() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
connector.initialize().await.unwrap();
let brokers = connector.get_connected_brokers().await;
assert!(!brokers.is_empty());
}
#[tokio::test]
async fn test_broker_connector_get_connected_brokers_multiple_calls() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let brokers1 = connector.get_connected_brokers().await;
let brokers2 = connector.get_connected_brokers().await;
let brokers3 = connector.get_connected_brokers().await;
assert_eq!(brokers1, brokers2);
assert_eq!(brokers2, brokers3);
}
#[tokio::test]
async fn test_broker_connector_get_connected_brokers_concurrent() {
let config = BrokerConnectorConfig::default();
let connector = std::sync::Arc::new(BrokerConnector::new(config));
let mut handles = vec![];
for _ in 0..5 {
let connector_clone = connector.clone();
let handle = tokio::spawn(async move {
connector_clone.get_connected_brokers().await
});
handles.push(handle);
}
for handle in handles {
let brokers = handle.await.unwrap();
assert!(!brokers.is_empty());
}
}
}
// ============================================================================
// BrokerConnector::shutdown() Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_shutdown_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_shutdown_success() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
connector.initialize().await.unwrap();
let result = connector.shutdown().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_shutdown_without_init() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
let result = connector.shutdown().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_broker_connector_shutdown_multiple_times() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
connector.initialize().await.unwrap();
assert!(connector.shutdown().await.is_ok());
assert!(connector.shutdown().await.is_ok());
assert!(connector.shutdown().await.is_ok());
}
#[tokio::test]
async fn test_broker_connector_init_shutdown_cycle() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
// Multiple init-shutdown cycles
for _ in 0..3 {
assert!(connector.initialize().await.is_ok());
assert!(connector.shutdown().await.is_ok());
}
}
}
// ============================================================================
// BrokerConfig Tests
// ============================================================================
#[cfg(test)]
mod broker_config_tests {
use super::*;
#[test]
fn test_broker_config_default() {
let config = BrokerConnectorConfig::default();
assert!(format!("{:?}", config).contains("BrokerConnectorConfig"));
}
#[test]
fn test_broker_config_enabled_flag() {
let mut config = BrokerConnectorConfig::default();
config.brokers.interactive_brokers.enabled = true;
assert!(config.brokers.interactive_brokers.enabled);
config.brokers.interactive_brokers.enabled = false;
assert!(!config.brokers.interactive_brokers.enabled);
}
#[test]
fn test_broker_config_fail_on_broker_error_flag() {
let mut config = BrokerConnectorConfig::default();
config.fail_on_broker_error = true;
assert!(config.fail_on_broker_error);
config.fail_on_broker_error = false;
assert!(!config.fail_on_broker_error);
}
#[test]
fn test_broker_config_clone() {
let config1 = BrokerConnectorConfig::default();
let config2 = config1.clone();
assert_eq!(config1.brokers.interactive_brokers.enabled, config2.brokers.interactive_brokers.enabled);
assert_eq!(config1.fail_on_broker_error, config2.fail_on_broker_error);
}
}
// ============================================================================
// Integration and Workflow Tests
// ============================================================================
#[cfg(test)]
mod broker_connector_integration_tests {
use super::*;
#[tokio::test]
async fn test_broker_connector_complete_workflow() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
// Initialize
assert!(connector.initialize().await.is_ok());
// Get connected brokers
let brokers = connector.get_connected_brokers().await;
assert!(!brokers.is_empty());
// Submit orders
let order1 = connector.submit_order("ORD_001").await;
let order2 = connector.submit_order("ORD_002").await;
assert!(order1.is_ok());
assert!(order2.is_ok());
// Cancel orders
assert!(connector.cancel_order("ORD_001").await.is_ok());
assert!(connector.cancel_order("ORD_002").await.is_ok());
// Shutdown
assert!(connector.shutdown().await.is_ok());
}
#[tokio::test]
async fn test_broker_connector_high_volume_orders() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
connector.initialize().await.unwrap();
// Submit 100 orders
for i in 0..100 {
let result = connector.submit_order(&format!("ORD_{:04}", i)).await;
assert!(result.is_ok());
}
connector.shutdown().await.unwrap();
}
#[tokio::test]
async fn test_broker_connector_concurrent_operations() {
let config = BrokerConnectorConfig::default();
let connector = std::sync::Arc::new(BrokerConnector::new(config));
let submit_handles: Vec<_> = (0..10)
.map(|i| {
let connector_clone = connector.clone();
tokio::spawn(async move {
let _ = connector_clone.submit_order(&format!("ORD_{}", i)).await;
})
})
.collect();
let cancel_handles: Vec<_> = (0..10)
.map(|i| {
let connector_clone = connector.clone();
tokio::spawn(async move {
let _ = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
})
})
.collect();
let broker_handles: Vec<_> = (0..5)
.map(|_| {
let connector_clone = connector.clone();
tokio::spawn(async move {
connector_clone.get_connected_brokers().await
})
})
.collect();
// All operations should succeed
for handle in submit_handles {
handle.await.unwrap();
}
for handle in cancel_handles {
handle.await.unwrap();
}
for handle in broker_handles {
let brokers = handle.await.unwrap();
assert!(!brokers.is_empty());
}
}
#[tokio::test]
async fn test_broker_connector_stress_test() {
let config = BrokerConnectorConfig::default();
let connector = std::sync::Arc::new(BrokerConnector::new(config));
// Simulate high concurrent load
let mut handles = vec![];
for i in 0..50 {
let connector_clone = connector.clone();
let handle = tokio::spawn(async move {
match i % 3 {
0 => {
let _ = connector_clone.submit_order(&format!("ORD_{}", i)).await;
}
1 => {
let _ = connector_clone.cancel_order(&format!("ORD_{}", i)).await;
}
_ => {
connector_clone.get_connected_brokers().await;
}
}
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}
}
// ============================================================================
// Edge Cases and Error Conditions
// ============================================================================
#[cfg(test)]
mod broker_connector_edge_cases {
use super::*;
#[tokio::test]
async fn test_broker_connector_operations_before_init() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
// Operations should work even without explicit initialization
assert!(connector.submit_order("ORD_123").await.is_ok());
assert!(connector.cancel_order("ORD_123").await.is_ok());
assert!(!connector.get_connected_brokers().await.is_empty());
}
#[tokio::test]
async fn test_broker_connector_operations_after_shutdown() {
let config = BrokerConnectorConfig::default();
let mut connector = BrokerConnector::new(config);
connector.initialize().await.unwrap();
connector.shutdown().await.unwrap();
// Operations should still work after shutdown (placeholder behavior)
assert!(connector.submit_order("ORD_123").await.is_ok());
assert!(connector.cancel_order("ORD_123").await.is_ok());
}
#[tokio::test]
async fn test_broker_connector_unicode_order_ids() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let unicode_ids = vec![
"ORD_日本語",
"ORD_中文",
"ORD_한글",
"ORD_العربية",
];
for order_id in unicode_ids {
let submit_result = connector.submit_order(order_id).await;
assert!(submit_result.is_ok(), "Failed for order_id: {}", order_id);
let cancel_result = connector.cancel_order(order_id).await;
assert!(cancel_result.is_ok(), "Failed to cancel: {}", order_id);
}
}
#[tokio::test]
async fn test_broker_connector_very_long_order_id() {
let config = BrokerConnectorConfig::default();
let connector = BrokerConnector::new(config);
let long_id = "ORD_".to_string() + &"X".repeat(10000);
let submit_result = connector.submit_order(&long_id).await;
assert!(submit_result.is_ok());
let cancel_result = connector.cancel_order(&long_id).await;
assert!(cancel_result.is_ok());
}
}