use super::*;
use std::collections::HashMap;
#[test]
fn test_decy_futex_regression() {
let mut baseline = HashMap::new();
baseline.insert(
"futex".to_string(),
vec![2.0, 3.0, 2.0, 3.0, 2.0], );
baseline.insert(
"mmap".to_string(),
vec![100.0, 102.0, 101.0, 103.0, 100.0], );
let mut current = HashMap::new();
current.insert(
"futex".to_string(),
vec![50.0, 52.0, 51.0, 53.0, 50.0], );
current.insert(
"mmap".to_string(),
vec![100.0, 102.0, 101.0, 103.0, 100.0], );
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
match assessment.verdict {
RegressionVerdict::Regression { ref regressed_syscalls, .. } => {
assert!(regressed_syscalls.contains(&"futex".to_string()));
assert!(!regressed_syscalls.contains(&"mmap".to_string())); }
_ => panic!("Expected Regression verdict for futex increase"),
}
}
#[test]
fn test_depyler_telemetry_regression() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
baseline.insert("read".to_string(), vec![50.0, 51.0, 50.0, 52.0, 50.0]);
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
current.insert("read".to_string(), vec![50.0, 51.0, 50.0, 52.0, 50.0]);
current.insert(
"socket".to_string(),
vec![5.0, 5.0, 5.0, 5.0, 5.0], );
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
assert_eq!(assessment.verdict, RegressionVerdict::NoRegression);
}
#[test]
fn test_no_false_positive_natural_variance() {
let mut baseline = HashMap::new();
baseline.insert(
"mmap".to_string(),
vec![100.0, 105.0, 98.0, 102.0, 101.0], );
let mut current = HashMap::new();
current.insert(
"mmap".to_string(),
vec![102.0, 106.0, 99.0, 103.0, 100.0], );
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
assert_eq!(assessment.verdict, RegressionVerdict::NoRegression);
}
#[test]
fn test_noise_filtering_removes_high_variance() {
let mut baseline = HashMap::new();
baseline.insert(
"mmap".to_string(),
vec![100.0, 102.0, 101.0, 103.0, 100.0], );
baseline.insert(
"socket".to_string(),
vec![5.0, 50.0, 3.0, 45.0, 2.0], );
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
current.insert("socket".to_string(), vec![6.0, 51.0, 4.0, 46.0, 3.0]);
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
assert!(assessment.filtered_syscalls.contains(&"socket".to_string()));
assert_eq!(assessment.tests.len(), 1);
assert!(assessment.tests.contains_key("mmap"));
}
#[test]
fn test_strict_config_reduces_false_positives() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![108.0, 110.0, 109.0, 111.0, 108.0]);
let default_config = RegressionConfig::default();
let default_assessment = assess_regression(&baseline, ¤t, &default_config).expect("test");
let strict_config = RegressionConfig::strict();
let strict_assessment = assess_regression(&baseline, ¤t, &strict_config).expect("test");
match (&default_assessment.verdict, &strict_assessment.verdict) {
(RegressionVerdict::Regression { .. }, RegressionVerdict::NoRegression) => {
}
(RegressionVerdict::NoRegression, RegressionVerdict::NoRegression) => {
}
(RegressionVerdict::Regression { .. }, RegressionVerdict::Regression { .. }) => {
}
(RegressionVerdict::NoRegression, RegressionVerdict::Regression { .. }) => {
panic!("Strict config should be more conservative than default");
}
_ => {
}
}
}
#[test]
fn test_insufficient_data() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![100.0]);
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![100.0]);
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
match assessment.verdict {
RegressionVerdict::InsufficientData { .. } => {
}
_ => panic!("Expected InsufficientData verdict"),
}
}
#[test]
fn test_report_generation() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![10.0, 11.0, 10.0, 12.0, 10.0]);
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![50.0, 52.0, 51.0, 53.0, 50.0]);
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
let report = assessment.to_report_string();
assert!(report.contains("REGRESSION"));
assert!(report.contains("mmap"));
assert!(report.contains("Statistical Tests"));
}
#[test]
fn test_permissive_config_increases_sensitivity() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
let mut current = HashMap::new();
current.insert("mmap".to_string(), vec![105.0, 107.0, 106.0, 108.0, 105.0]);
let permissive_config = RegressionConfig::permissive();
let permissive_assessment =
assess_regression(&baseline, ¤t, &permissive_config).expect("test");
match permissive_assessment.verdict {
RegressionVerdict::Regression { .. } | RegressionVerdict::NoRegression => {
}
_ => panic!("Unexpected verdict"),
}
}
#[test]
fn test_multiple_syscalls_mixed_results() {
let mut baseline = HashMap::new();
baseline.insert("mmap".to_string(), vec![100.0, 102.0, 101.0, 103.0, 100.0]);
baseline.insert("read".to_string(), vec![50.0, 51.0, 50.0, 52.0, 50.0]);
baseline.insert("write".to_string(), vec![30.0, 31.0, 30.0, 32.0, 30.0]);
let mut current = HashMap::new();
current.insert(
"mmap".to_string(),
vec![200.0, 202.0, 201.0, 203.0, 200.0], );
current.insert("read".to_string(), vec![50.0, 51.0, 50.0, 52.0, 50.0]); current.insert("write".to_string(), vec![30.0, 31.0, 30.0, 32.0, 30.0]);
let config = RegressionConfig::default();
let assessment = assess_regression(&baseline, ¤t, &config).expect("test");
match assessment.verdict {
RegressionVerdict::Regression { ref regressed_syscalls, .. } => {
assert!(regressed_syscalls.contains(&"mmap".to_string()));
assert!(!regressed_syscalls.contains(&"read".to_string()));
assert!(!regressed_syscalls.contains(&"write".to_string()));
}
_ => panic!("Expected Regression verdict"),
}
}
#[test]
#[allow(clippy::field_reassign_with_default)]
fn test_config_validation() {
let mut config = RegressionConfig::default();
assert!(config.validate().is_ok());
config.significance_level = 1.5;
assert!(config.validate().is_err());
config = RegressionConfig::default();
config.min_sample_size = 1;
assert!(config.validate().is_err());
config = RegressionConfig::default();
config.noise_threshold = -0.5;
assert!(config.validate().is_err());
}