use std::ops::Range;
use aok::{OK, Void};
use jdb_pgm::Pgm;
#[static_init::constructor(0)]
extern "C" fn _log_init() {
log_init::init();
}
fn check_range(range: Range<usize>, expected: usize, len: usize, msg: &str) {
assert!(range.start <= range.end, "{msg}: start > end ({:?})", range);
assert!(
range.end <= len,
"{msg}: end > len ({:?}, len={})",
range,
len
);
assert!(
range.contains(&expected),
"{msg}: range {:?} does not contain expected {}",
range,
expected
);
}
#[test]
fn test_range_basic() -> Void {
let data: Vec<u64> = (0..10_000).collect();
let pgm = Pgm::new(&data, 32, true)?;
for &k in &[0u64, 100, 5000, 9999] {
let range = pgm.predict_range(k);
check_range(range, k as usize, data.len(), &format!("basic key={k}"));
}
OK
}
#[test]
fn test_range_epsilon_impact() -> Void {
let data: Vec<u64> = (0..1000).collect();
for &eps in &[4, 16, 64] {
let pgm = Pgm::new(&data, eps, true)?;
let range = pgm.predict_range(500);
check_range(range.clone(), 500, data.len(), &format!("eps={eps}"));
let size = range.end - range.start;
assert!(
size <= 2 * eps + 5,
"range too large for eps={}: size={}",
eps,
size
);
}
OK
}
#[test]
fn test_range_out_of_bounds() -> Void {
let data: Vec<u64> = (100..200).collect(); let pgm = Pgm::new(&data, 8, true)?;
let len = data.len();
let r_small = pgm.predict_range(0);
assert!(r_small.start <= r_small.end);
assert!(r_small.end <= len);
assert!(
r_small.contains(&0),
"small key should include 0, got {:?}",
r_small
);
let r_large = pgm.predict_range(999);
assert!(r_large.start <= r_large.end);
assert!(r_large.end <= len);
OK
}
#[test]
fn test_range_duplicates() -> Void {
let data = vec![10u64, 10, 10, 10, 20, 20, 30];
let pgm = Pgm::new(&data, 4, true)?;
let r10 = pgm.predict_range(10);
check_range(r10.clone(), 0, data.len(), "dup 10 first");
let r20 = pgm.predict_range(20);
check_range(r20, 4, data.len(), "dup 20");
OK
}
#[test]
fn test_range_single_element() -> Void {
let data = vec![42u64];
let pgm = Pgm::new(&data, 2, true)?;
let r = pgm.predict_range(42);
check_range(r, 0, 1, "single");
OK
}
#[test]
fn test_range_all_same() -> Void {
let data = vec![100u64; 100];
let pgm = Pgm::new(&data, 4, true)?;
let r = pgm.predict_range(100);
assert!(r.start < r.end);
assert!(r.end <= 100);
OK
}