#![cfg(not(miri))]
mod common;
use cdflib::{ContinuousCdf, DiscreteCdf, SearchError};
use common::{assert_close, assert_close_eps, read_csv};
use std::f64::consts::PI;
#[test]
fn assert_close_passes_when_within_default_tol() {
assert_close(1.0 + 1e-15, 1.0);
assert_close(-PI, -PI);
}
#[test]
fn assert_close_handles_boundary_values() {
assert_close_eps(1e-310, 0.0, 1e-14, 1e-300);
assert_close_eps(1.0, 1.0, 1e-14, 1e-300);
}
#[test]
#[should_panic(expected = "rel diff")]
fn assert_close_fails_outside_tol() {
assert_close_eps(1.0, 2.0, 1e-14, 1e-300);
}
#[test]
#[should_panic(expected = "NaN mismatch")]
fn assert_close_fails_on_nan_mismatch() {
assert_close_eps(f64::NAN, 0.0, 1e-14, 1e-300);
}
#[test]
fn assert_close_accepts_both_nan() {
assert_close_eps(f64::NAN, f64::NAN, 1e-14, 1e-300);
}
#[test]
#[should_panic(expected = "infinity mismatch")]
fn assert_close_fails_on_infinity_mismatch() {
assert_close_eps(f64::INFINITY, 1e308, 1e-14, 1e-300);
}
#[test]
#[cfg_attr(miri, ignore)] fn read_csv_parses_a_simple_table() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let path = std::path::Path::new(manifest_dir).join("tests/data/_self_test.csv");
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(
&path,
"# header line\n1.0, 2.0, 3.0\n# comment in the middle\n4.5,5.5,6.5\n\n",
)
.unwrap();
let rows = read_csv("tests/data/_self_test.csv");
assert_eq!(rows, vec![vec![1.0, 2.0, 3.0], vec![4.5, 5.5, 6.5]]);
let _ = std::fs::remove_file(&path);
}
#[test]
fn search_error_displays_useful_messages() {
let e = SearchError::AnswerBelowLowerBound { bound: -1.0 };
assert!(e.to_string().contains("-1"), "got: {e}");
let e = SearchError::AnswerAboveUpperBound { bound: 1.0 };
assert!(e.to_string().contains('1'), "got: {e}");
}
#[derive(Debug)]
struct StubContinuous;
impl ContinuousCdf for StubContinuous {
type Error = SearchError;
fn cdf(&self, x: f64) -> f64 {
x.clamp(0.0, 1.0)
}
fn inverse_cdf(&self, p: f64) -> Result<f64, SearchError> {
Ok(p.clamp(0.0, 1.0))
}
fn ccdf(&self, x: f64) -> f64 {
1.0 - self.cdf(x)
}
}
#[test]
fn continuous_cdf_trait_shape_compiles() {
let d = StubContinuous;
assert_close(d.ccdf(0.3), 0.7);
assert_close(d.inverse_cdf(0.3).unwrap(), 0.3);
}
#[derive(Debug)]
struct StubDiscrete;
impl DiscreteCdf for StubDiscrete {
type Error = SearchError;
fn cdf(&self, x: u64) -> f64 {
if x >= 1 {
1.0
} else {
0.0
}
}
fn ccdf(&self, x: u64) -> f64 {
if x >= 1 {
0.0
} else {
1.0
}
}
fn inverse_cdf(&self, p: f64) -> Result<u64, SearchError> {
Ok(if p > 0.0 { 1 } else { 0 })
}
}
#[test]
fn discrete_cdf_trait_shape_compiles() {
let d = StubDiscrete;
assert_close(d.ccdf(0), 1.0);
assert_close(d.ccdf(1), 0.0);
assert_eq!(d.inverse_cdf(1.0).unwrap(), 1);
assert_eq!(d.inverse_cdf(0.0).unwrap(), 0);
}