Files
foxhunt/tests/utils/mod.rs
jgrusewski 001624c5b2 fix: eliminate all 8,384 clippy warnings across workspace
Systematic clippy warning cleanup achieving zero warnings:

- Add domain-appropriate crate-level #![allow(...)] to 20+ crate roots
  for pedantic lints that are noise in HFT/ML code (float_arithmetic,
  indexing_slicing, missing_const_for_fn, cognitive_complexity, etc.)
- Fix attribute ordering in risk/src/lib.rs: move #![warn(clippy::pedantic)]
  before #![allow(...)] so individual allows correctly override pedantic
- Remove module-level #![warn(clippy::pedantic)] from 8 trading_engine
  submodules that were overriding crate-level allows
- Add 45+ workspace-level lint allows in Cargo.toml for common pedantic
  noise (mixed_attributes_style, cargo_common_metadata, etc.)
- Auto-fix 67 machine-applicable warnings (redundant_closure, clone_on_copy,
  unnecessary_cast, etc.) via cargo clippy --fix
- Fix 3 unsafe JSON indexing in risk/circuit_breaker.rs with safe .get()
- Fix unused variables, unused mut, unnecessary parens in 4 files
- Proto-generated code: suppress missing_const_for_fn, indexing_slicing,
  cognitive_complexity in ctrader-openapi and service crates

75 files changed across 20+ crates. All tests pass (3,122+ verified).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:16:35 +01:00

173 lines
5.0 KiB
Rust

//! Test Utilities Module
//!
//! Comprehensive test utilities for safe, reliable testing patterns
//! across the Foxhunt HFT trading system.
pub mod hft_utils;
pub mod test_safety;
// Re-export commonly used items for convenience (macros are exported at crate root)
// DO NOT RE-EXPORT - Use explicit imports at usage sites
// Note: test_assert and test_assert_eq macros are exported at crate root automatically
// DO NOT RE-EXPORT - Use explicit imports at usage sites
/// Macro to create a test with automatic error handling and context
#[macro_export]
macro_rules! safe_test {
($test_name:ident, $test_fn:expr) => {
#[tokio::test]
async fn $test_name() {
match $test_fn().await {
Ok(()) => {},
Err(e) => {
panic!("Test {} failed: {}", stringify!($test_name), e);
},
}
}
};
}
/// Macro to create a property based test
#[macro_export]
macro_rules! property_test {
($test_name:ident, $iterations:expr, $test_fn:expr) => {
#[tokio::test]
async fn $test_name() {
use $crate::utils::test_safety::property;
match property::run_property_test(stringify!($test_name), $iterations, $test_fn) {
Ok(()) => {},
Err(e) => {
panic!("Property test {} failed: {}", stringify!($test_name), e);
},
}
}
};
}
/// Macro to create a performance benchmark test
#[macro_export]
macro_rules! benchmark_test {
($test_name:ident, $operation:expr, $max_latency:expr) => {
#[tokio::test]
async fn $test_name() {
use $crate::utils::hft_utils::performance;
use std::time::Duration;
let measurements = performance::benchmark_operation(
$operation,
10, // warmup iterations
100, // measurement iterations
stringify!($test_name),
)
.await
.expect("Benchmark should complete");
let avg_latency = measurements.average().expect("Should have measurements");
let p99_latency = measurements.percentile(0.99).expect("Should have p99");
println!(
"Benchmark {}: avg={:?}, p99={:?}, max={:?}",
stringify!($test_name),
avg_latency,
p99_latency,
measurements.max().unwrap_or_default()
);
if avg_latency > $max_latency {
panic!(
"Benchmark {} failed: average latency {:?} exceeds maximum {:?}",
stringify!($test_name),
avg_latency,
$max_latency
);
}
}
};
}
/// Test configuration for different environments
#[derive(Debug, Clone)]
pub struct TestConfig {
pub enable_chaos: bool,
pub chaos_failure_rate: f64,
pub default_timeout: std::time::Duration,
pub hft_latency_requirement: std::time::Duration,
pub enable_performance_validation: bool,
}
impl Default for TestConfig {
fn default() -> Self {
Self {
enable_chaos: false,
chaos_failure_rate: 0.1,
default_timeout: std::time::Duration::from_secs(30),
hft_latency_requirement: std::time::Duration::from_micros(50),
enable_performance_validation: true,
}
}
}
impl TestConfig {
pub fn for_unit_tests() -> Self {
Self {
enable_chaos: false,
default_timeout: std::time::Duration::from_secs(5),
..Default::default()
}
}
pub fn for_integration_tests() -> Self {
Self {
enable_chaos: false,
default_timeout: std::time::Duration::from_secs(30),
..Default::default()
}
}
pub fn for_chaos_tests() -> Self {
Self {
enable_chaos: true,
chaos_failure_rate: 0.2,
default_timeout: std::time::Duration::from_secs(60),
..Default::default()
}
}
}
/// Global test configuration accessor
static TEST_CONFIG: std::sync::OnceLock<TestConfig> = std::sync::OnceLock::new();
pub fn get_test_config() -> &'static TestConfig {
TEST_CONFIG.get_or_init(|| {
std::env::var("TEST_MODE")
.map(|mode| match mode.as_str() {
"unit" => TestConfig::for_unit_tests(),
"integration" => TestConfig::for_integration_tests(),
"chaos" => TestConfig::for_chaos_tests(),
_ => TestConfig::default(),
})
.unwrap_or_default()
})
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_config_default() {
let config = TestConfig::default();
assert!(!config.enable_chaos);
assert_eq!(config.chaos_failure_rate, 0.1);
}
#[tokio::test]
async fn test_config_access() {
let config = get_test_config();
assert!(config.default_timeout.as_secs() > 0);
}
}