//! Chaos engineering tests for Foxhunt HFT system. use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use tokio::time::sleep; use rand::{Rng, SeedableRng}; use rand::rngs::StdRng; /// Test system behavior under random failures #[tokio::test] async fn test_random_service_failures() { let success_count = Arc::new(AtomicUsize::new(0)); let failure_count = Arc::new(AtomicUsize::new(0)); let mut handles = vec![]; // Spawn multiple concurrent tasks that randomly fail for i in 0..10 { let success_count = Arc::clone(&success_count); let failure_count = Arc::clone(&failure_count); let handle = tokio::spawn(async move { let mut rng = StdRng::from_entropy(); sleep(Duration::from_millis(rng.gen_range(1..100))).await; // Randomly fail 30% of the time if rng.gen_bool(0.3) { failure_count.fetch_add(1, Ordering::Relaxed); panic!("Simulated chaos failure in task {}", i); } else { success_count.fetch_add(1, Ordering::Relaxed); } }); handles.push(handle); } // Wait for all tasks to complete for handle in handles { let _ = handle.await; // Ignore panics } let successes = success_count.load(Ordering::Relaxed); let failures = failure_count.load(Ordering::Relaxed); // Verify we had both successes and failures (chaos) println!("Chaos test results: {} successes, {} failures", successes, failures); assert!(successes + failures == 10); } /// Test system resilience under high load #[tokio::test] async fn test_load_resilience() { let request_count = Arc::new(AtomicUsize::new(0)); let mut handles = vec![]; // Simulate high concurrent load for _ in 0..50 { let request_count = Arc::clone(&request_count); let handle = tokio::spawn(async move { // Simulate work let mut rng = StdRng::from_entropy(); sleep(Duration::from_millis(rng.gen_range(1..20))).await; request_count.fetch_add(1, Ordering::Relaxed); }); handles.push(handle); } // Wait for all requests to complete for handle in handles { handle.await.expect("Task should not panic under load"); } assert_eq!(request_count.load(Ordering::Relaxed), 50); } /// Test resource exhaustion scenarios #[tokio::test] async fn test_resource_limits() { // Simulate memory pressure by creating many allocations let mut allocations = Vec::new(); for i in 0..1000 { let data = vec![i; 1000]; // 1KB allocation allocations.push(data); // Add some delay to prevent overwhelming the system if i % 100 == 0 { tokio::task::yield_now().await; } } // Verify we can still function under memory pressure assert_eq!(allocations.len(), 1000); // Clean up allocations.clear(); }