From 7c0cce160a4cc4c3fcf605fae76c91db55254c26 Mon Sep 17 00:00:00 2001 From: Manuel Raimann Date: Thu, 12 Feb 2026 16:18:55 +0100 Subject: [PATCH] test(stress): add ignored stress tests for large-scale scenarios - 10k sequential trials with RandomSampler - 128 parameters with TPE sampler - 128 concurrent workers with optimize_parallel - 5k trials with TPE and 32 parallel workers --- tests/stress_tests.rs | 129 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 tests/stress_tests.rs diff --git a/tests/stress_tests.rs b/tests/stress_tests.rs new file mode 100644 index 0000000..b652b90 --- /dev/null +++ b/tests/stress_tests.rs @@ -0,0 +1,129 @@ +//! Stress and large-scale tests for the optimizer library. +//! +//! All tests are `#[ignore]`-gated so they don't run in normal CI. +//! Run with: `cargo test --features async -- --ignored` + +use std::collections::HashSet; + +use optimizer::parameter::{FloatParam, Parameter}; +use optimizer::sampler::random::RandomSampler; +use optimizer::sampler::tpe::TpeSampler; +use optimizer::{Direction, Error, Study}; + +fn make_float_params(n: usize) -> Vec { + (0..n) + .map(|i| FloatParam::new(-5.0, 5.0).name(format!("x{i}"))) + .collect() +} + +fn sphere(trial: &mut optimizer::Trial, params: &[FloatParam]) -> Result { + let mut sum = 0.0; + for p in params { + let v = p.suggest(trial)?; + sum += v * v; + } + Ok(sum) +} + +#[test] +#[ignore] +fn stress_many_trials_random() { + let sampler = RandomSampler::with_seed(42); + let study: Study = Study::with_sampler(Direction::Minimize, sampler); + let params = make_float_params(5); + + study + .optimize(10_000, |trial: &mut optimizer::Trial| { + sphere(trial, ¶ms) + }) + .expect("10k trials should complete"); + + assert_eq!(study.n_trials(), 10_000); + let best = study.best_value().expect("should have a best value"); + assert!(best.is_finite(), "best value should be finite"); + assert!(best >= 0.0, "sphere function is non-negative"); +} + +#[test] +#[ignore] +fn stress_many_params_tpe() { + let sampler = TpeSampler::builder() + .seed(42) + .n_startup_trials(10) + .build() + .unwrap(); + let study: Study = Study::with_sampler(Direction::Minimize, sampler); + let params = make_float_params(128); + + study + .optimize(200, |trial: &mut optimizer::Trial| sphere(trial, ¶ms)) + .expect("200 trials with 128 params should complete"); + + assert_eq!(study.n_trials(), 200); + + let best = study.best_trial().expect("should have a best trial"); + assert_eq!(best.params.len(), 128, "best trial should have 128 params"); + assert!(best.value.is_finite(), "best value should be finite"); + for v in best.params.values() { + let f = match v { + optimizer::param::ParamValue::Float(f) => *f, + other => panic!("expected Float param, got {other}"), + }; + assert!(f.is_finite(), "all param values should be finite"); + } +} + +#[cfg(feature = "async")] +#[tokio::test] +#[ignore] +async fn stress_high_concurrency_parallel() { + let sampler = RandomSampler::with_seed(42); + let study: Study = Study::with_sampler(Direction::Minimize, sampler); + let params = make_float_params(10); + + study + .optimize_parallel(1_000, 128, move |trial: &mut optimizer::Trial| { + sphere(trial, ¶ms) + }) + .await + .expect("1k trials with 128 workers should complete"); + + assert_eq!(study.n_trials(), 1_000); + + let trials = study.trials(); + let ids: HashSet = trials.iter().map(|t| t.id).collect(); + assert_eq!(ids.len(), 1_000, "all trial IDs should be unique"); + + let best = study.best_value().expect("should have a best value"); + assert!(best.is_finite(), "best value should be finite"); +} + +#[cfg(feature = "async")] +#[tokio::test] +#[ignore] +async fn stress_long_running_tpe_parallel() { + let sampler = TpeSampler::builder() + .seed(42) + .n_startup_trials(20) + .build() + .unwrap(); + let study: Study = Study::with_sampler(Direction::Minimize, sampler); + let params = make_float_params(20); + + study + .optimize_parallel(5_000, 32, move |trial: &mut optimizer::Trial| { + sphere(trial, ¶ms) + }) + .await + .expect("5k trials with TPE and 32 workers should complete"); + + assert_eq!(study.n_trials(), 5_000); + + let trials = study.trials(); + let ids: HashSet = trials.iter().map(|t| t.id).collect(); + assert_eq!(ids.len(), 5_000, "all trial IDs should be unique"); + + let best = study.best_trial().expect("should have a best trial"); + assert!(best.value.is_finite(), "best value should be finite"); + assert_eq!(best.params.len(), 20, "best trial should have 20 params"); +}