use std::collections::BTreeSet; use std::ops::Bound::{self, *}; use quickcheck::{quickcheck, TestResult}; /// Covers every `std::ops::Range*` plus variants with exclusive start. type RangeAny = (Bound, Bound); /// Mimic `RangeBounds::contains`, stabilized in Rust 1.35. trait RangeBounds { fn contains(&self, _: &T) -> bool; } impl RangeBounds for RangeAny { fn contains(&self, item: &T) -> bool { (match &self.0 { Included(start) => start <= item, Excluded(start) => start < item, Unbounded => true, }) && (match &self.1 { Included(end) => item <= end, Excluded(end) => item < end, Unbounded => true, }) } } /// Checks conditions where `BTreeSet::range` panics: /// - Panics if range start > end. /// - Panics if range start == end and both bounds are Excluded. fn panics(range: RangeAny) -> bool { match (&range.0, &range.1) { (Excluded(start), Excluded(end)) => start >= end, (Included(start), Excluded(end)) | (Excluded(start), Included(end)) | (Included(start), Included(end)) => start > end, (Unbounded, _) | (_, Unbounded) => false, } } /// Checks that `BTreeSet::range` returns all items contained in the given `range`. fn check_range(set: BTreeSet, range: RangeAny) -> TestResult { if panics(range) { TestResult::discard() } else { let xs: BTreeSet<_> = set.range(range).cloned().collect(); TestResult::from_bool( set.iter().all(|x| range.contains(x) == xs.contains(x)), ) } } fn main() { quickcheck(check_range as fn(_, _) -> TestResult); }