test: add proptest arbitrary as a feature
This commit is contained in:
parent
00b03a509f
commit
7c8c833469
4 changed files with 9 additions and 178 deletions
|
|
@ -264,7 +264,7 @@ impl ExprBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
pub mod arbitrary {
|
||||
//! Helper functions to generate arbitrary expressions using [`proptest`].
|
||||
use proptest::prelude::*;
|
||||
|
|
|
|||
|
|
@ -268,10 +268,8 @@ impl<T> BaseSignal for ConstantSignal<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
pub mod arbitrary {
|
||||
|
||||
use itertools::Itertools;
|
||||
use proptest::prelude::*;
|
||||
use proptest::sample::SizeRange;
|
||||
|
||||
|
|
@ -308,7 +306,7 @@ pub mod arbitrary {
|
|||
ts.into_iter()
|
||||
.map(Duration::from_secs)
|
||||
.zip(values.clone().into_iter())
|
||||
.collect_vec()
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,173 +173,3 @@ where
|
|||
|
||||
(start, end)
|
||||
}
|
||||
|
||||
/// More precise intersection of two ranges from point of the first range
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Intersection {
|
||||
/// The self is below the other
|
||||
Below,
|
||||
/// The self is below but overlaping
|
||||
BelowOverlap,
|
||||
/// The self is within the other
|
||||
Within,
|
||||
/// The self is same as the other
|
||||
Same,
|
||||
/// The self is over the other, the other is within the self
|
||||
Over,
|
||||
/// The self is above but overlaping
|
||||
AboveOverlap,
|
||||
/// The self is above the other
|
||||
Above,
|
||||
}
|
||||
|
||||
impl Intersection {
|
||||
/// Test if there is any intersection
|
||||
pub fn is_any(&self) -> bool {
|
||||
!matches!(self, Intersection::Below | Intersection::Above)
|
||||
}
|
||||
/// Test if the range is fully within the other
|
||||
pub fn is_within(&self) -> bool {
|
||||
matches!(self, Intersection::Within | Intersection::Same)
|
||||
}
|
||||
|
||||
/// Test if the range is fully over the other
|
||||
pub fn is_over(&self) -> bool {
|
||||
matches!(self, Intersection::Over | Intersection::Same)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Intersect<T, U>
|
||||
where
|
||||
T: PartialOrd,
|
||||
U: RangeBounds<T>,
|
||||
{
|
||||
/// Test two ranges for an intersection
|
||||
fn check_intersect(&self, other: &U) -> Intersection;
|
||||
}
|
||||
|
||||
impl<T, U, R> Intersect<T, U> for R
|
||||
where
|
||||
T: PartialOrd + PartialEq,
|
||||
U: RangeBounds<T>,
|
||||
R: RangeBounds<T>,
|
||||
{
|
||||
fn check_intersect(&self, other: &U) -> Intersection {
|
||||
use core::cmp::Ordering::*;
|
||||
use core::ops::Bound::*;
|
||||
|
||||
// We find where the start of self is with respect to that of other
|
||||
let (left_rel_pos, me_start) = match (self.start_bound(), other.start_bound()) {
|
||||
(Included(me), Excluded(them)) if me == them => (Less, Some(me)), // [a, _} left of (a, }
|
||||
//
|
||||
(Excluded(me), Included(them)) if me == them => (Greater, Some(me)), // (a, _} right of [a, }
|
||||
|
||||
// If both are consistently open or close, or they are not equal then we
|
||||
// just compare them
|
||||
(Included(me), Excluded(them))
|
||||
| (Excluded(me), Included(them))
|
||||
| (Included(me), Included(them))
|
||||
| (Excluded(me), Excluded(them)) => (me.partial_cmp(them).unwrap(), Some(me)),
|
||||
|
||||
// start of self > start of other
|
||||
(Included(me), Unbounded) | (Excluded(me), Unbounded) => (Greater, Some(me)),
|
||||
|
||||
(Unbounded, Unbounded) => (Equal, None), // unbounded start
|
||||
|
||||
(Unbounded, _) => (Less, None), // start of self < start of other
|
||||
};
|
||||
|
||||
// We find where the end of self is with respect to that of other
|
||||
let (right_rel_pos, me_end) = match (self.end_bound(), other.end_bound()) {
|
||||
(Included(me), Excluded(them)) if me == them => (Greater, Some(me)), // {_, a] right of {_, a)
|
||||
|
||||
(Excluded(me), Included(them)) if me == them => (Less, Some(me)), // {_, a) right of {_, a]
|
||||
|
||||
// If both are consistently open or close, or they are not equal then we just compare them
|
||||
(Included(me), Excluded(them))
|
||||
| (Excluded(me), Included(them))
|
||||
| (Included(me), Included(them))
|
||||
| (Excluded(me), Excluded(them)) => (me.partial_cmp(them).unwrap(), Some(me)),
|
||||
|
||||
(Included(me), Unbounded) | (Excluded(me), Unbounded) => (Less, Some(me)), // end of self < end of other
|
||||
|
||||
(Unbounded, Unbounded) => (Equal, None), // unbounded end
|
||||
|
||||
(Unbounded, _) => (Greater, None), // end of self > end of other
|
||||
};
|
||||
|
||||
// We have gotten the relative position of the ends. But we need to check if one
|
||||
// of the ends are contained within the bounds of the other.
|
||||
|
||||
match (left_rel_pos, right_rel_pos) {
|
||||
(Less, Less) => {
|
||||
// Check if the end of self is contained within other's domain
|
||||
// NOTE: Since right is less than, me_end must not be None
|
||||
assert!(me_end.is_some());
|
||||
if other.contains(me_end.unwrap()) {
|
||||
// self is below but overlaps
|
||||
Intersection::BelowOverlap
|
||||
} else {
|
||||
// self is strictly below
|
||||
Intersection::Below
|
||||
}
|
||||
}
|
||||
(Greater, Greater) => {
|
||||
// Check if the start of self is contained within other's domain
|
||||
// NOTE: Since left is greater than, me_start must not be None
|
||||
assert!(me_start.is_some());
|
||||
if other.contains(me_start.unwrap()) {
|
||||
// self is to the right of but overlaps other
|
||||
Intersection::AboveOverlap
|
||||
} else {
|
||||
// self is strictly above
|
||||
Intersection::Above
|
||||
}
|
||||
}
|
||||
(Less, Greater) | (Equal, Greater) | (Less, Equal) => Intersection::Over, // self contains other
|
||||
(Equal, Less) | (Greater, Equal) | (Greater, Less) => Intersection::Within, // self within other
|
||||
(Equal, Equal) => Intersection::Same, // The ranges are equal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::ops::Range;
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn range_range_intersection(r1 in any::<Range<i32>>(), r2 in any::<Range<i32>>()) {
|
||||
use Intersection::*;
|
||||
let intersect_p = r1.check_intersect(&r2);
|
||||
match intersect_p {
|
||||
Below => assert!(r1.end < r2.start, "Expected strict below"),
|
||||
BelowOverlap => {
|
||||
assert!(r1.start < r2.start, "Expected below with overlap");
|
||||
assert!(r2.contains(&r1.end), "Expected below with overlap");
|
||||
},
|
||||
Within => {
|
||||
assert!(r2.contains(&r1.end), "Expected to be contained");
|
||||
assert!(r2.contains(&r1.start), "Expected to be contained");
|
||||
}
|
||||
Same => {
|
||||
assert!(r1.start == r2.start, "Expected to be same");
|
||||
assert!(r1.end == r2.end, "Expected to be same");
|
||||
}
|
||||
Over => {
|
||||
assert!(r1.contains(&r2.start), "Expected to cover");
|
||||
assert!(r1.contains(&r2.end), "Expected to cover");
|
||||
}
|
||||
AboveOverlap => {
|
||||
assert!(r2.contains(&r1.start), "Expected above with overlap");
|
||||
assert!(r1.end > r2.end, "Expected above with overlap");
|
||||
}
|
||||
Above => assert!(r1.start > r2.end, "Expected strict above"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue