use crate::i128::tests::{
set::test_support::build,
test_support::{build_from_vec, interval_pair, iv},
};
#[test]
fn coverage_empty_set_has_zero_covered_len() {
let set = build([]);
let query = iv(10, 20);
assert_eq!(set.covered_len(query), 0);
assert_eq!(set.uncovered_len(query), query.len());
assert_eq!(set.coverage_ratio(query), 0.0);
}
#[test]
fn coverage_full_cover_has_full_covered_len() {
let set = build([(10, 20)]);
let query = iv(10, 20);
assert_eq!(set.covered_len(query), 10);
assert_eq!(set.uncovered_len(query), 0);
assert_eq!(set.coverage_ratio(query), 1.0);
}
#[test]
fn coverage_partial_cover_inside_single_interval() {
let set = build([(10, 20)]);
let query = iv(15, 25);
assert_eq!(set.covered_len(query), 5);
assert_eq!(set.uncovered_len(query), 5);
assert_eq!(set.coverage_ratio(query), 0.5);
}
#[test]
fn coverage_gap_only_query_has_zero_covered_len() {
let set = build([(10, 20), (30, 40)]);
let query = iv(20, 30);
assert_eq!(set.covered_len(query), 0);
assert_eq!(set.uncovered_len(query), 10);
assert_eq!(set.coverage_ratio(query), 0.0);
}
#[test]
fn coverage_across_multiple_intervals() {
let set = build([(-50, -40), (-20, -10), (10, 20)]);
let query = iv(-45, 15);
assert_eq!(
set.intersections(query).collect::<Vec<_>>(),
vec![iv(-45, -40), iv(-20, -10), iv(10, 15)]
);
assert_eq!(set.covered_len(query), 20);
assert_eq!(set.uncovered_len(query), 40);
assert_eq!(set.coverage_ratio(query), 20.0 / 60.0);
}
#[test]
fn coverage_uses_canonical_merged_intervals() {
let set = build([(-20, -15), (-15, -10), (-5, 5), (0, 10)]);
assert_eq!(set.as_slice(), &[iv(-20, -10), iv(-5, 10)]);
let query = iv(-12, 0);
assert_eq!(
set.intersections(query).collect::<Vec<_>>(),
vec![iv(-12, -10), iv(-5, 0)]
);
assert_eq!(set.covered_len(query), 7);
assert_eq!(set.uncovered_len(query), 5);
assert_eq!(set.coverage_ratio(query), 7.0 / 12.0);
}
#[test]
fn coverage_query_containing_all_intervals() {
let set = build([(10, 20), (30, 40)]);
let query = iv(0, 50);
assert_eq!(set.covered_len(query), 20);
assert_eq!(set.uncovered_len(query), 30);
assert_eq!(set.coverage_ratio(query), 0.4);
}
#[test]
fn coverage_handles_domain_edges() {
let set = build([(i128::MIN, i128::MIN + 1), (i128::MAX - 1, i128::MAX)]);
let left_query = iv(i128::MIN, i128::MIN + 2);
let right_query = iv(i128::MAX - 2, i128::MAX);
assert_eq!(set.covered_len(left_query), 1);
assert_eq!(set.uncovered_len(left_query), 1);
assert_eq!(set.coverage_ratio(left_query), 0.5);
assert_eq!(set.covered_len(right_query), 1);
assert_eq!(set.uncovered_len(right_query), 1);
assert_eq!(set.coverage_ratio(right_query), 0.5);
}
#[test]
fn coverage_lengths_add_up_to_query_len() {
let set = build([(10, 20), (30, 40), (50, 60)]);
for query in [
iv(0, 10),
iv(9, 11),
iv(15, 35),
iv(20, 30),
iv(35, 55),
iv(55, 61),
iv(i128::MIN, i128::MIN + 1),
iv(i128::MAX - 1, i128::MAX),
] {
assert_eq!(
set.covered_len(query) + set.uncovered_len(query),
query.len(),
"query = {query:?}"
);
}
}
#[test]
fn coverage_ratio_matches_covered_len_over_query_len() {
let set = build([(10, 20), (30, 40), (50, 60)]);
for query in [
iv(0, 10),
iv(9, 11),
iv(15, 35),
iv(20, 30),
iv(35, 55),
iv(55, 61),
iv(i128::MIN, i128::MIN + 1),
iv(i128::MAX - 1, i128::MAX),
] {
let expected = set.covered_len(query) as f32 / query.len() as f32;
assert_eq!(set.coverage_ratio(query), expected, "query = {query:?}");
}
}
use proptest::prelude::*;
proptest! {
#[test]
fn prop_coverage_lengths_partition_query(
xs in prop::collection::vec(interval_pair(), 0..64),
query in interval_pair(),
) {
let set = build_from_vec(xs);
let query = iv(query.0, query.1);
prop_assert_eq!(
set.covered_len(query) + set.uncovered_len(query),
query.len()
);
}
#[test]
fn prop_covered_len_matches_intersection_predicate(
xs in prop::collection::vec(interval_pair(), 0..64),
query in interval_pair(),
) {
let set = build_from_vec(xs);
let query = iv(query.0, query.1);
prop_assert_eq!(
set.covered_len(query) > 0,
set.intersects_interval(query)
);
}
}