use super::*;
use crate::primitives::Vector;
#[test]
fn falsify_dr_001_no_drift_on_identical() {
let reference = Vector::from_slice(&(0..50).map(|i| i as f32).collect::<Vec<_>>());
let current = Vector::from_slice(&(0..50).map(|i| i as f32).collect::<Vec<_>>());
let detector = DriftDetector::new(DriftConfig::default().with_min_samples(10));
let status = detector.detect_univariate(&reference, ¤t);
assert!(
matches!(status, DriftStatus::NoDrift),
"FALSIFIED DR-001: identical data triggered {:?}",
status
);
}
#[test]
fn falsify_dr_002_drift_on_shifted_data() {
let reference = Vector::from_slice(&(0..50).map(|i| i as f32).collect::<Vec<_>>());
let current = Vector::from_slice(&(0..50).map(|i| (i as f32) + 1000.0).collect::<Vec<_>>());
let detector = DriftDetector::new(DriftConfig::default().with_min_samples(10));
let status = detector.detect_univariate(&reference, ¤t);
assert!(
status.needs_retraining(),
"FALSIFIED DR-002: heavily shifted data did not trigger drift: {:?}",
status
);
}
#[test]
fn falsify_dr_003_score_nonneg() {
let reference = Vector::from_slice(&(0..50).map(|i| i as f32).collect::<Vec<_>>());
let current = Vector::from_slice(&(0..50).map(|i| (i as f32) * 2.0).collect::<Vec<_>>());
let detector = DriftDetector::new(DriftConfig::default().with_min_samples(10));
let status = detector.detect_univariate(&reference, ¤t);
if let Some(score) = status.score() {
assert!(
score >= 0.0,
"FALSIFIED DR-003: drift score={score}, expected >= 0.0"
);
}
}
mod dr_proptest_falsify {
use super::*;
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(15))]
#[test]
fn falsify_dr_001_prop_no_drift_identical(
n in 20..=50usize,
seed in 0..200u32,
) {
let data: Vec<f32> = (0..n)
.map(|i| ((i as f32 + seed as f32) * 0.37).sin() * 10.0)
.collect();
let reference = Vector::from_vec(data.clone());
let current = Vector::from_vec(data);
let detector = DriftDetector::new(DriftConfig::default().with_min_samples(10));
let status = detector.detect_univariate(&reference, ¤t);
prop_assert!(
matches!(status, DriftStatus::NoDrift),
"FALSIFIED DR-001-prop: identical data triggered {:?}",
status
);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(15))]
#[test]
fn falsify_dr_003_prop_score_nonneg(
n in 20..=50usize,
seed in 0..200u32,
) {
let ref_data: Vec<f32> = (0..n)
.map(|i| ((i as f32 + seed as f32) * 0.37).sin() * 10.0)
.collect();
let cur_data: Vec<f32> = (0..n)
.map(|i| ((i as f32 + seed as f32) * 0.37).sin() * 10.0 + 50.0)
.collect();
let reference = Vector::from_vec(ref_data);
let current = Vector::from_vec(cur_data);
let detector = DriftDetector::new(DriftConfig::default().with_min_samples(10));
let status = detector.detect_univariate(&reference, ¤t);
if let Some(score) = status.score() {
prop_assert!(
score >= 0.0,
"FALSIFIED DR-003-prop: drift score={} < 0",
score
);
}
}
}
}