1  use std::collections::BTreeSet;
2  use std::ops::Bound::{self, *};
3  
4  use quickcheck::{quickcheck, TestResult};
5  
6  /// Covers every `std::ops::Range*` plus variants with exclusive start.
7  type RangeAny<T> = (Bound<T>, Bound<T>);
8  
9  /// Mimic `RangeBounds::contains`, stabilized in Rust 1.35.
10  trait RangeBounds<T> {
contains(&self, _: &T) -> bool11      fn contains(&self, _: &T) -> bool;
12  }
13  
14  impl<T: PartialOrd> RangeBounds<T> for RangeAny<T> {
contains(&self, item: &T) -> bool15      fn contains(&self, item: &T) -> bool {
16          (match &self.0 {
17              Included(start) => start <= item,
18              Excluded(start) => start < item,
19              Unbounded => true,
20          }) && (match &self.1 {
21              Included(end) => item <= end,
22              Excluded(end) => item < end,
23              Unbounded => true,
24          })
25      }
26  }
27  
28  /// Checks conditions where `BTreeSet::range` panics:
29  /// - Panics if range start > end.
30  /// - Panics if range start == end and both bounds are Excluded.
panics<T: PartialOrd>(range: RangeAny<T>) -> bool31  fn panics<T: PartialOrd>(range: RangeAny<T>) -> bool {
32      match (&range.0, &range.1) {
33          (Excluded(start), Excluded(end)) => start >= end,
34          (Included(start), Excluded(end))
35          | (Excluded(start), Included(end))
36          | (Included(start), Included(end)) => start > end,
37          (Unbounded, _) | (_, Unbounded) => false,
38      }
39  }
40  
41  /// Checks that `BTreeSet::range` returns all items contained in the given `range`.
check_range(set: BTreeSet<i32>, range: RangeAny<i32>) -> TestResult42  fn check_range(set: BTreeSet<i32>, range: RangeAny<i32>) -> TestResult {
43      if panics(range) {
44          TestResult::discard()
45      } else {
46          let xs: BTreeSet<_> = set.range(range).cloned().collect();
47          TestResult::from_bool(
48              set.iter().all(|x| range.contains(x) == xs.contains(x)),
49          )
50      }
51  }
52  
main()53  fn main() {
54      quickcheck(check_range as fn(_, _) -> TestResult);
55  }
56