#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_measurement_protocol_default() {
let protocol = MeasurementProtocol::default();
assert_eq!(protocol.latency_samples, 100);
assert_eq!(
protocol.latency_percentiles,
vec![50.0, 90.0, 95.0, 99.0, 99.9]
);
assert_eq!(protocol.throughput_duration, Duration::from_secs(60));
assert_eq!(protocol.throughput_ramp_up, Duration::from_secs(10));
assert_eq!(protocol.memory_samples, 10);
assert_eq!(protocol.memory_interval, Duration::from_secs(1));
}
#[test]
fn test_measurement_protocol_new() {
let protocol = MeasurementProtocol::new();
assert_eq!(protocol.latency_samples, 100);
}
#[test]
fn test_measurement_protocol_with_latency_samples() {
let protocol = MeasurementProtocol::new().with_latency_samples(200);
assert_eq!(protocol.latency_samples, 200);
}
#[test]
fn test_measurement_protocol_with_percentiles() {
let protocol = MeasurementProtocol::new().with_percentiles(vec![50.0, 99.0]);
assert_eq!(protocol.latency_percentiles, vec![50.0, 99.0]);
}
#[test]
fn test_measurement_protocol_with_throughput_duration() {
let protocol =
MeasurementProtocol::new().with_throughput_duration(Duration::from_secs(120));
assert_eq!(protocol.throughput_duration, Duration::from_secs(120));
}
#[test]
fn test_measurement_protocol_with_memory_samples() {
let protocol = MeasurementProtocol::new().with_memory_samples(20);
assert_eq!(protocol.memory_samples, 20);
}
#[test]
fn test_measurement_protocol_builder_chain() {
let protocol = MeasurementProtocol::new()
.with_latency_samples(50)
.with_percentiles(vec![90.0, 99.0])
.with_throughput_duration(Duration::from_secs(30))
.with_memory_samples(5);
assert_eq!(protocol.latency_samples, 50);
assert_eq!(protocol.latency_percentiles, vec![90.0, 99.0]);
assert_eq!(protocol.throughput_duration, Duration::from_secs(30));
assert_eq!(protocol.memory_samples, 5);
}
#[test]
fn test_latency_statistics_from_samples_uniform() {
let samples: Vec<Duration> = (1..=10).map(|i| Duration::from_millis(i * 10)).collect();
let stats = LatencyStatistics::from_samples(&samples);
assert_eq!(stats.samples, 10);
assert_eq!(stats.min, Duration::from_millis(10));
assert_eq!(stats.max, Duration::from_millis(100));
assert_eq!(stats.mean.as_millis(), 55);
}
#[test]
fn test_latency_statistics_from_samples_single() {
let samples = vec![Duration::from_millis(100)];
let stats = LatencyStatistics::from_samples(&samples);
assert_eq!(stats.samples, 1);
assert_eq!(stats.min, Duration::from_millis(100));
assert_eq!(stats.max, Duration::from_millis(100));
assert_eq!(stats.mean, Duration::from_millis(100));
assert_eq!(stats.p50, Duration::from_millis(100));
}
#[test]
fn test_latency_statistics_percentiles() {
let samples: Vec<Duration> = (1..=100).map(Duration::from_millis).collect();
let stats = LatencyStatistics::from_samples(&samples);
assert!(stats.p50.as_millis() >= 49 && stats.p50.as_millis() <= 51);
assert!(stats.p90.as_millis() >= 89 && stats.p90.as_millis() <= 91);
assert!(stats.p99.as_millis() >= 98 && stats.p99.as_millis() <= 100);
}
#[test]
#[should_panic(expected = "samples must not be empty")]
fn test_latency_statistics_empty_samples_panics() {
let samples: Vec<Duration> = vec![];
let _ = LatencyStatistics::from_samples(&samples);
}
#[test]
fn test_regression_detector_default() {
let detector = RegressionDetector::default();
assert!((detector.warning_threshold - 0.02).abs() < f64::EPSILON);
assert!((detector.failure_threshold - 0.05).abs() < f64::EPSILON);
}
#[test]
fn test_regression_detector_clone() {
let detector = RegressionDetector::default();
let cloned = detector.clone();
assert!((detector.warning_threshold - cloned.warning_threshold).abs() < f64::EPSILON);
assert!((detector.failure_threshold - cloned.failure_threshold).abs() < f64::EPSILON);
}
#[test]
fn test_welch_t_test_result_fields() {
let result = WelchTTestResult {
t_statistic: 2.5,
degrees_of_freedom: 18.0,
p_value: 0.02,
significant: true,
};
assert!((result.t_statistic - 2.5).abs() < f64::EPSILON);
assert!((result.degrees_of_freedom - 18.0).abs() < f64::EPSILON);
assert!((result.p_value - 0.02).abs() < f64::EPSILON);
assert!(result.significant);
}
#[test]
fn test_welch_t_test_same_samples() {
let a: Vec<f64> = (1..=20).map(|i| 100.0 + i as f64).collect();
let b: Vec<f64> = (1..=20).map(|i| 100.0 + i as f64).collect();
let result = welch_t_test(&a, &b, 0.05);
assert!(result.p_value > 0.05);
assert!(!result.significant);
}
#[test]
fn test_welch_t_test_different_samples() {
let a: Vec<f64> = (1..=30).map(|i| 100.0 + (i as f64 % 5.0)).collect();
let b: Vec<f64> = (1..=30).map(|i| 200.0 + (i as f64 % 5.0)).collect();
let result = welch_t_test(&a, &b, 0.05);
assert!(result.significant);
assert!(result.p_value < 0.05);
}
#[test]
fn test_welch_t_test_different_alpha() {
let a: Vec<f64> = (1..=20).map(|i| 100.0 + i as f64).collect();
let b: Vec<f64> = (1..=20).map(|i| 110.0 + i as f64).collect();
let result_05 = welch_t_test(&a, &b, 0.05);
let result_01 = welch_t_test(&a, &b, 0.01);
assert!((result_05.p_value - result_01.p_value).abs() < 0.001);
}
#[test]
fn test_gamma_ln_positive() {
let result = gamma_ln(1.0);
assert!(result.abs() < 0.01);
let result = gamma_ln(2.0);
assert!(result.abs() < 0.01);
let result = gamma_ln(5.0);
assert!((result - 3.178).abs() < 0.1);
}
#[test]
fn test_gamma_ln_negative_or_zero() {
assert!(gamma_ln(0.0).is_infinite());
assert!(gamma_ln(-1.0).is_infinite());
}
}