use super::*;
mod unit_tests {
use super::*;
#[inline]
fn iv(start: u64, end_excl: u64) -> U64CO {
U64CO::try_new(start, end_excl).unwrap()
}
mod interval_count_tests {
use super::*;
#[test]
fn empty_set() {
let set = U64COBatchSet::default();
assert_eq!(set.interval_count(), 0);
}
#[test]
fn single_interval() {
let set = U64COBatchSet::from([iv(3, 7)]);
assert_eq!(set.interval_count(), 1);
}
#[test]
fn multi_interval() {
let set = U64COBatchSet::from([iv(1, 3), iv(5, 8), iv(10, 11)]);
assert_eq!(set.interval_count(), 3);
}
#[test]
fn normalized_count_after_merge() {
let set = U64COBatchSet::from([iv(5, 7), iv(1, 3), iv(3, 5), iv(10, 12)]);
assert_eq!(set.interval_count(), 2);
}
}
mod point_count_tests {
use super::*;
#[test]
fn empty_set() {
let set = U64COBatchSet::default();
assert_eq!(set.point_count(), 0);
}
#[test]
fn single_interval() {
let set = U64COBatchSet::from([iv(3, 7)]);
assert_eq!(set.point_count(), 4);
}
#[test]
fn multi_interval() {
let set = U64COBatchSet::from([iv(1, 3), iv(5, 8), iv(10, 11)]);
assert_eq!(set.point_count(), 2 + 3 + 1);
}
#[test]
fn normalized_point_count_after_merge() {
let set = U64COBatchSet::from([iv(5, 7), iv(1, 3), iv(3, 5), iv(10, 12)]);
assert_eq!(set.point_count(), 6 + 2);
}
}
mod coverage_len_of_tests {
use super::*;
#[test]
fn empty_set() {
let set = U64COBatchSet::default();
assert_eq!(set.coverage_len_of(iv(0, 1)), 0);
assert_eq!(set.coverage_len_of(iv(10, 20)), 0);
}
#[test]
fn query_before_all_intervals() {
let set = U64COBatchSet::from([iv(5, 8), iv(10, 12)]);
assert_eq!(set.coverage_len_of(iv(0, 4)), 0);
}
#[test]
fn query_after_all_intervals() {
let set = U64COBatchSet::from([iv(1, 3), iv(5, 8)]);
assert_eq!(set.coverage_len_of(iv(10, 20)), 0);
}
#[test]
fn single_interval_basic() {
let set = U64COBatchSet::from([iv(5, 10)]);
assert_eq!(set.coverage_len_of(iv(0, 5)), 0);
assert_eq!(set.coverage_len_of(iv(0, 6)), 1);
assert_eq!(set.coverage_len_of(iv(5, 6)), 1);
assert_eq!(set.coverage_len_of(iv(6, 9)), 3);
assert_eq!(set.coverage_len_of(iv(9, 12)), 1);
assert_eq!(set.coverage_len_of(iv(10, 12)), 0);
assert_eq!(set.coverage_len_of(iv(0, 20)), 5);
}
#[test]
fn multi_interval_with_gaps() {
let set = U64COBatchSet::from([iv(1, 3), iv(5, 7), iv(9, 11)]);
assert_eq!(set.coverage_len_of(iv(0, 12)), 2 + 2 + 2);
assert_eq!(set.coverage_len_of(iv(2, 10)), 1 + 2 + 1);
assert_eq!(set.coverage_len_of(iv(3, 5)), 0);
assert_eq!(set.coverage_len_of(iv(3, 6)), 1);
assert_eq!(set.coverage_len_of(iv(7, 9)), 0);
assert_eq!(set.coverage_len_of(iv(8, 10)), 1);
}
#[test]
fn query_spans_multiple_segments() {
let set = U64COBatchSet::from([iv(2, 4), iv(7, 9), iv(12, 15)]);
assert_eq!(set.coverage_len_of(iv(3, 13)), 1 + 2 + 1);
assert_eq!(set.coverage_len_of(iv(0, 20)), 2 + 2 + 3);
}
#[test]
fn normalized_set_coverage() {
let set = U64COBatchSet::from([iv(5, 7), iv(1, 3), iv(3, 5), iv(10, 12)]);
assert_eq!(set.coverage_len_of(iv(0, 20)), 6 + 2);
assert_eq!(set.coverage_len_of(iv(2, 6)), 4);
assert_eq!(set.coverage_len_of(iv(6, 10)), 1);
assert_eq!(set.coverage_len_of(iv(7, 10)), 0);
assert_eq!(set.coverage_len_of(iv(6, 11)), 1 + 1);
}
#[test]
fn matches_pointwise_semantics() {
let set = U64COBatchSet::from([iv(1, 4), iv(6, 9), iv(20, 30)]);
let queries = [
iv(0, 1),
iv(0, 2),
iv(3, 6),
iv(4, 6),
iv(8, 10),
iv(10, 20),
iv(19, 31),
];
for q in queries {
let expect = q.iter().filter(|&x| set.contains_point(x)).count() as u64;
assert_eq!(set.coverage_len_of(q), expect, "q={q:?}");
}
}
}
mod coverage_ratio_of_tests {
use super::*;
#[inline]
fn assert_f32_eq(a: f32, b: f32) {
assert!((a - b).abs() <= 1e-6, "left={a}, right={b}");
}
#[test]
fn empty_set() {
let set = U64COBatchSet::default();
assert_f32_eq(set.coverage_ratio_of(iv(0, 1)), 0.0);
assert_f32_eq(set.coverage_ratio_of(iv(10, 20)), 0.0);
}
#[test]
fn fully_covered_query() {
let set = U64COBatchSet::from([iv(3, 9)]);
assert_f32_eq(set.coverage_ratio_of(iv(3, 9)), 1.0);
assert_f32_eq(set.coverage_ratio_of(iv(4, 8)), 1.0);
}
#[test]
fn partially_covered_query() {
let set = U64COBatchSet::from([iv(5, 10)]);
assert_f32_eq(set.coverage_ratio_of(iv(0, 6)), 1.0 / 6.0);
assert_f32_eq(set.coverage_ratio_of(iv(6, 9)), 1.0);
assert_f32_eq(set.coverage_ratio_of(iv(9, 12)), 1.0 / 3.0);
assert_f32_eq(set.coverage_ratio_of(iv(0, 20)), 5.0 / 20.0);
}
#[test]
fn multi_interval_with_gaps() {
let set = U64COBatchSet::from([iv(1, 3), iv(5, 7), iv(9, 11)]);
assert_f32_eq(set.coverage_ratio_of(iv(0, 12)), 6.0 / 12.0);
assert_f32_eq(set.coverage_ratio_of(iv(2, 10)), 4.0 / 8.0);
assert_f32_eq(set.coverage_ratio_of(iv(3, 5)), 0.0);
assert_f32_eq(set.coverage_ratio_of(iv(3, 6)), 1.0 / 3.0);
}
#[test]
fn normalized_set_ratio() {
let set = U64COBatchSet::from([iv(5, 7), iv(1, 3), iv(3, 5), iv(10, 12)]);
assert_f32_eq(set.coverage_ratio_of(iv(0, 20)), 8.0 / 20.0);
assert_f32_eq(set.coverage_ratio_of(iv(2, 6)), 1.0);
assert_f32_eq(set.coverage_ratio_of(iv(7, 10)), 0.0);
assert_f32_eq(set.coverage_ratio_of(iv(6, 11)), 2.0 / 5.0);
}
#[test]
fn ratio_matches_len_div_query_len() {
let set = U64COBatchSet::from([iv(1, 4), iv(6, 9), iv(20, 30)]);
let queries = [iv(1, 2), iv(0, 10), iv(3, 8), iv(10, 20), iv(25, 31)];
for q in queries {
let expect = set.coverage_len_of(q) as f32 / q.len() as f32;
assert_f32_eq(set.coverage_ratio_of(q), expect);
}
}
}
mod normalized_statistics_tests {
use super::*;
#[test]
fn normalized_set_statistics_are_consistent() {
let set = U64COBatchSet::from([iv(8, 10), iv(1, 3), iv(3, 5), iv(5, 8), iv(20, 21)]);
assert_eq!(set.interval_count(), 2);
assert_eq!(set.point_count(), 9 + 1);
assert_eq!(set.coverage_len_of(iv(0, 30)), 10);
assert_eq!(set.coverage_len_of(iv(2, 9)), 7);
assert_eq!(set.coverage_len_of(iv(10, 20)), 0);
let ratio = set.coverage_ratio_of(iv(0, 30));
assert!((ratio - 10.0 / 30.0).abs() <= 1e-6);
}
}
}