use linreg_core::diagnostics::{
anderson_darling_test, anderson_darling_test_raw, jarque_bera_test, shapiro_wilk_test,
shapiro_wilk_test_raw, DiagnosticTestResult,
};
use linreg_core::error::Error;
fn approx_eq(a: f64, b: f64, tol: f64) -> bool {
(a - b).abs() < tol
}
fn approx_eq_rel(a: f64, b: f64, rel: f64) -> bool {
let diff = (a - b).abs();
let max_val = a.abs().max(b.abs());
if max_val == 0.0 {
true
} else {
diff / max_val < rel
}
}
fn approx_eq_combined(a: f64, b: f64, rel: f64, abs_tol: f64) -> bool {
let diff = (a - b).abs();
if diff < abs_tol {
return true;
}
let max_val = a.abs().max(b.abs());
if max_val == 0.0 {
false
} else {
diff / max_val < rel
}
}
#[test]
fn test_jarque_bera_insufficient_data() {
let y = vec![1.0, 2.0];
let x = vec![1.0, 2.0];
let result = jarque_bera_test(&y, &[x]);
match result {
Err(Error::InsufficientData {
required,
available,
}) => {
assert_eq!(required, 3);
assert_eq!(available, 2);
}
_ => panic!("Expected InsufficientData error"),
}
}
#[test]
fn test_jarque_bera_perfect_fit() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let result = jarque_bera_test(&y, &[x]).unwrap();
assert!(result.statistic >= 0.0 && result.statistic < 1.0);
assert!(result.p_value > 0.05); assert_eq!(result.test_name, "Jarque-Bera Test for Normality");
}
#[test]
fn test_jarque_bera_r_reference() {
let y = vec![1.1, 2.2, 2.9, 4.1, 4.9, 6.1, 7.0, 7.9, 9.1, 10.0];
let x: Vec<f64> = (1..=10).map(|i| i as f64).collect();
let result = jarque_bera_test(&y, &[x]).unwrap();
assert!(result.statistic >= 0.0);
assert!(result.p_value > 0.5); assert_eq!(result.passed, result.p_value > 0.05);
}
#[test]
fn test_jarque_bera_skewed_data() {
let y: Vec<f64> = (1..=20).map(|i| (i as f64).exp()).collect();
let x: Vec<f64> = (1..=20).map(|i| i as f64).collect();
let result = jarque_bera_test(&y, &[x]).unwrap();
assert!(result.statistic > 1.0);
assert!(result.p_value < 0.05); assert_eq!(result.passed, false);
}
#[test]
fn test_jarque_bera_output_structure() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let result = jarque_bera_test(&y, &[x]).unwrap();
assert!(!result.test_name.is_empty());
assert!(result.statistic.is_finite());
assert!(result.p_value.is_finite());
assert!(result.p_value >= 0.0 && result.p_value <= 1.0);
assert!(!result.interpretation.is_empty());
assert!(!result.guidance.is_empty());
}
#[test]
fn test_shapiro_wilk_insufficient_data() {
let y = vec![1.0, 2.0];
let x = vec![1.0, 2.0];
let result = shapiro_wilk_test(&y, &[x]);
match result {
Err(Error::InsufficientData {
required,
available,
}) => {
assert_eq!(required, 3);
assert_eq!(available, 2);
}
_ => panic!("Expected InsufficientData error"),
}
}
#[test]
fn test_shapiro_wilk_maximum_sample_size() {
let y: Vec<f64> = (1..=5001).map(|i| i as f64).collect();
let x: Vec<f64> = (1..=5001).map(|i| i as f64).collect();
let result = shapiro_wilk_test(&y, &[x]);
match result {
Err(Error::InvalidInput { .. }) => (),
_ => panic!("Expected InvalidInput error for n > 5000"),
}
}
#[test]
fn test_shapiro_wilk_perfect_normal() {
let normal_data = vec![
0.1, -0.5, 0.3, 1.2, -0.8, 0.4, -0.2, 0.9, -0.3, 0.6, -0.1, 0.7, -0.4, 0.2, 1.1, -0.6,
0.8, -0.9, 0.5, -0.7,
];
let x_data: Vec<f64> = (1..=normal_data.len()).map(|i| i as f64).collect();
let result = shapiro_wilk_test(&normal_data, &[x_data]).unwrap();
assert!(result.statistic >= 0.0 && result.statistic <= 1.0);
assert!(result.p_value > 0.05);
assert_eq!(result.passed, true);
assert_eq!(result.test_name, "Shapiro-Wilk Test for Normality");
}
#[test]
fn test_shapiro_wilk_uniform_data() {
let uniform_data: Vec<f64> = (1..=20).map(|i| i as f64 / 20.0).collect();
let result = shapiro_wilk_test(&uniform_data, &[uniform_data.clone()]).unwrap();
assert!(result.statistic >= 0.0 && result.statistic <= 1.0);
assert!(result.p_value.is_finite());
}
#[test]
fn test_shapiro_wilk_raw_with_known_sample() {
let sample = vec![
0.1, -0.5, 0.3, 1.2, -0.8, 0.4, -0.2, 0.9, -0.3, 0.6,
];
let result = shapiro_wilk_test_raw(&sample).unwrap();
assert!(result.statistic > 0.9); assert!(result.p_value > 0.01); assert_eq!(result.test_name, "Shapiro-Wilk Test for Normality");
}
#[test]
fn test_shapiro_wilk_monotonicity() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let result = shapiro_wilk_test(&y, &[x]).unwrap();
assert!(result.statistic >= 0.0 && result.statistic <= 1.0);
}
#[test]
fn test_anderson_darling_insufficient_data() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let result = anderson_darling_test(&y, &[x]);
match result {
Err(Error::InsufficientData {
required,
available,
}) => {
assert_eq!(required, 8);
assert_eq!(available, 7);
}
_ => panic!("Expected InsufficientData error"),
}
}
#[test]
fn test_anderson_darling_normal_sample() {
let normal_data = vec![
0.1, -0.5, 0.3, 1.2, -0.8, 0.4, -0.2, 0.9, -0.3, 0.6, -0.1, 0.7, -0.4, 0.2, 1.1, -0.6,
0.8, -0.9, 0.5, -0.7, 0.0, 0.3, -0.4, 0.6,
];
let x_data: Vec<f64> = (1..=normal_data.len()).map(|i| i as f64).collect();
let result = anderson_darling_test(&normal_data, &[x_data]).unwrap();
assert!(result.statistic >= 0.0);
assert!(result.p_value > 0.001);
assert_eq!(result.passed, result.p_value > 0.05);
assert_eq!(result.test_name, "Anderson-Darling Test for Normality");
}
#[test]
fn test_anderson_darling_raw_with_normal() {
let normal_data = vec![
0.1, -0.5, 0.3, 1.2, -0.8, 0.4, -0.2, 0.9, -0.3, 0.6, -0.1, 0.7, -0.4, 0.2, 1.1, -0.6,
0.8, -0.9, 0.5, -0.7,
];
let result = anderson_darling_test_raw(&normal_data).unwrap();
assert!(result.statistic >= 0.0);
assert!(result.p_value > 0.01);
}
#[test]
fn test_anderson_darling_exponential_data() {
let exp_data: Vec<f64> = (1..=20).map(|i| (i as f64) * 0.5).collect();
let result = anderson_darling_test(&exp_data, &[exp_data.clone()]).unwrap();
assert!(result.statistic > 0.5);
assert!(result.p_value < 0.05); assert_eq!(result.passed, false);
}
#[test]
fn test_anderson_darling_statistic_non_negative() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let result = anderson_darling_test(&y, &[x]).unwrap();
assert!(result.statistic >= 0.0);
}
#[test]
fn test_all_normality_tests_agree_on_perfect_fit() {
let y = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let x = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
let jb = jarque_bera_test(&y, &[x.clone()]).unwrap();
let sw = shapiro_wilk_test(&y, &[x.clone()]).unwrap();
let ad = anderson_darling_test(&y, &[x]).unwrap();
assert!(jb.statistic.is_finite());
assert!(sw.statistic.is_finite());
assert!(ad.statistic.is_finite());
assert!(jb.p_value >= 0.0 && jb.p_value <= 1.0);
assert!(sw.p_value >= 0.0 && sw.p_value <= 1.0);
assert!(ad.p_value >= 0.0 && ad.p_value <= 1.0);
}