#![allow(clippy::all)]
#![allow(clippy::needless_question_mark)]
use armature_testing::load::*;
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== Load Testing Example ===\n");
println!("1. Basic Load Test (10 concurrent, 100 requests):");
println!(" Starting load test...");
let basic_config = LoadTestConfig::new(10, 100).with_timeout(Duration::from_secs(5));
let basic_runner = LoadTestRunner::new(basic_config, || async {
tokio::time::sleep(Duration::from_millis(50)).await;
Ok(())
});
let stats = basic_runner.run().await?;
stats.print();
assert_eq!(
stats.total_requests, 100,
"all 100 requests must be counted"
);
assert_eq!(stats.successful, 100);
assert_eq!(stats.failed, 0);
assert!(stats.min_response_time <= stats.median_response_time);
assert!(stats.median_response_time <= stats.p95_response_time);
assert!(stats.p95_response_time <= stats.p99_response_time);
assert!(stats.p99_response_time <= stats.max_response_time);
println!("\n2. Duration-Based Load Test (5 concurrent, 3 seconds):");
println!(" Starting duration-based test...");
let duration_config = LoadTestConfig::new(5, u64::MAX)
.with_duration(Duration::from_secs(3))
.with_timeout(Duration::from_secs(5));
let duration_runner = LoadTestRunner::new(duration_config, || async {
tokio::time::sleep(Duration::from_millis(30)).await;
Ok(())
});
let stats = duration_runner.run().await?;
stats.print();
assert!(stats.total_requests > 0, "duration-based run must do work");
assert!(stats.duration >= Duration::from_secs(3));
println!("\n3. Load Test with Some Failures:");
println!(" Starting load test with 20% failure rate...");
let failure_count = Arc::new(AtomicU32::new(0));
let failure_config = LoadTestConfig::new(5, 50).with_timeout(Duration::from_secs(5));
let failure_count_clone = failure_count.clone();
let failure_runner = LoadTestRunner::new(failure_config, move || {
let count = failure_count_clone.clone();
async move {
let current = count.fetch_add(1, Ordering::SeqCst);
tokio::time::sleep(Duration::from_millis(40)).await;
if current % 5 == 0 {
Err(LoadTestError::TestFailed("Simulated failure".to_string()))
} else {
Ok(())
}
}
});
let stats = failure_runner.run().await?;
stats.print();
assert_eq!(stats.total_requests, 50);
assert_eq!(
stats.failed, 10,
"20% of 50 requests must be recorded failed"
);
assert_eq!(stats.successful, 40);
println!("\n4. Stress Test (1 → 20 concurrent, step by 5, 2 seconds per step):");
println!(" Starting stress test...");
let stress_runner = StressTestRunner::new(
1, 20, 5, Duration::from_secs(2), || async {
tokio::time::sleep(Duration::from_millis(30)).await;
Ok(())
},
);
let stress_results = stress_runner.run().await?;
assert!(
!stress_results.is_empty(),
"a stress test must produce at least one step"
);
let concurrencies: Vec<_> = stress_results.iter().map(|(c, _)| *c).collect();
assert!(
concurrencies.windows(2).all(|w| w[0] < w[1]),
"each step must raise concurrency: {concurrencies:?}"
);
assert!(
concurrencies.iter().all(|c| *c <= 20),
"no step may exceed the configured maximum: {concurrencies:?}"
);
println!("\nStress Test Summary:");
println!("┌─────────────┬──────────┬────────────┬────────────┐");
println!("│ Concurrency │ RPS │ Avg (ms) │ p95 (ms) │");
println!("├─────────────┼──────────┼────────────┼────────────┤");
for (concurrency, stats) in stress_results {
println!(
"│ {:11} │ {:8.2} │ {:10.2} │ {:10.2} │",
concurrency,
stats.rps,
stats.avg_response_time.as_millis(),
stats.p95_response_time.as_millis()
);
}
println!("└─────────────┴──────────┴────────────┴────────────┘");
println!("\n5. Real-World Example: API Endpoint Load Test");
println!(" (Simulated - replace with actual HTTP client)");
let api_config = LoadTestConfig::new(20, 200).with_timeout(Duration::from_secs(10));
let api_runner = LoadTestRunner::new(api_config, || async {
tokio::time::sleep(Duration::from_millis(100)).await;
Ok(())
});
let stats = api_runner.run().await?;
stats.print();
println!("=== Load Testing Complete ===\n");
println!("💡 Tips:");
println!(" - Use LoadTestRunner for fixed request counts");
println!(" - Use duration-based tests for sustained load");
println!(" - Use StressTestRunner to find breaking points");
println!(" - Monitor p95/p99 latencies for SLA compliance");
println!();
Ok(())
}