From 0bc1c51a6725508aff7933e69d55e738fc752f2c Mon Sep 17 00:00:00 2001 From: Patrick Elsen Date: Wed, 7 Feb 2024 23:40:35 +0100 Subject: [PATCH 1/3] Expands tests --- src/inclusive_map.rs | 27 +++++++++++++++++++++++++++ src/inclusive_set.rs | 27 +++++++++++++++++++++++++++ src/map.rs | 27 +++++++++++++++++++++++++++ src/set.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/src/inclusive_map.rs b/src/inclusive_map.rs index 752da0a..edf4076 100644 --- a/src/inclusive_map.rs +++ b/src/inclusive_map.rs @@ -1026,6 +1026,33 @@ mod tests { } } + #[proptest] + #[allow(deprecated)] + fn test_hash(left: RangeInclusiveMap, right: RangeInclusiveMap) { + use core::hash::{Hash, Hasher, SipHasher}; + + let hash = |set: &RangeInclusiveMap<_, _>| { + let mut hasher = SipHasher::new(); + set.hash(&mut hasher); + hasher.finish() + }; + + if left == right { + assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + } + + // if the hashes are equal the values might not be the same (collision) + if hash(&left) != hash(&right) { + assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + } + } + + #[proptest] + fn test_ord(left: RangeInclusiveMap, right: RangeInclusiveMap) { + assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); + assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + } + #[test] fn test_from_array() { let mut map = RangeInclusiveMap::new(); diff --git a/src/inclusive_set.rs b/src/inclusive_set.rs index e82e320..e8483c2 100644 --- a/src/inclusive_set.rs +++ b/src/inclusive_set.rs @@ -551,6 +551,33 @@ mod tests { } } + #[proptest] + #[allow(deprecated)] + fn test_hash(left: RangeInclusiveSet, right: RangeInclusiveSet) { + use core::hash::{Hash, Hasher, SipHasher}; + + let hash = |set: &RangeInclusiveSet<_>| { + let mut hasher = SipHasher::new(); + set.hash(&mut hasher); + hasher.finish() + }; + + if left == right { + assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + } + + // if the hashes are equal the values might not be the same (collision) + if hash(&left) != hash(&right) { + assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + } + } + + #[proptest] + fn test_ord(left: RangeInclusiveSet, right: RangeInclusiveSet) { + assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); + assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + } + #[test] fn test_from_array() { let mut set = RangeInclusiveSet::new(); diff --git a/src/map.rs b/src/map.rs index a160962..50a1f56 100644 --- a/src/map.rs +++ b/src/map.rs @@ -911,6 +911,33 @@ mod tests { } } + #[proptest] + #[allow(deprecated)] + fn test_hash(left: RangeMap, right: RangeMap) { + use core::hash::{Hash, Hasher, SipHasher}; + + let hash = |set: &RangeMap<_, _>| { + let mut hasher = SipHasher::new(); + set.hash(&mut hasher); + hasher.finish() + }; + + if left == right { + assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + } + + // if the hashes are equal the values might not be the same (collision) + if hash(&left) != hash(&right) { + assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + } + } + + #[proptest] + fn test_ord(left: RangeMap, right: RangeMap) { + assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); + assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + } + #[test] fn test_from_array() { let mut map = RangeMap::new(); diff --git a/src/set.rs b/src/set.rs index 874379c..c69ef14 100644 --- a/src/set.rs +++ b/src/set.rs @@ -515,6 +515,33 @@ mod tests { } } + #[proptest] + #[allow(deprecated)] + fn test_hash(left: RangeSet, right: RangeSet) { + use core::hash::{Hash, Hasher, SipHasher}; + + let hash = |set: &RangeSet<_>| { + let mut hasher = SipHasher::new(); + set.hash(&mut hasher); + hasher.finish() + }; + + if left == right { + assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + } + + // if the hashes are equal the values might not be the same (collision) + if hash(&left) != hash(&right) { + assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + } + } + + #[proptest] + fn test_ord(left: RangeSet, right: RangeSet) { + assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); + assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + } + #[test] fn test_from_array() { let mut set = RangeSet::new(); From fa1aa5f6f02777679112db001aae8ae992d449fd Mon Sep 17 00:00:00 2001 From: Patrick Elsen Date: Thu, 8 Feb 2024 00:01:00 +0100 Subject: [PATCH 2/3] Expands test coverage --- src/inclusive_map.rs | 37 +++++++++++++++++++++---- src/inclusive_set.rs | 64 +++++++++++++++++++++++++------------------- src/map.rs | 34 +++++++++++++++++++---- src/set.rs | 63 ++++++++++++++++++++++++++++--------------- 4 files changed, 138 insertions(+), 60 deletions(-) diff --git a/src/inclusive_map.rs b/src/inclusive_map.rs index edf4076..9f17534 100644 --- a/src/inclusive_map.rs +++ b/src/inclusive_map.rs @@ -958,6 +958,16 @@ mod tests { } } + #[proptest] + fn test_len(mut map: RangeInclusiveMap) { + assert_eq!(map.len(), map.iter().count()); + assert_eq!(map.is_empty(), map.len() == 0); + map.clear(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert_eq!(map.iter().count(), 0); + } + #[proptest] fn test_first(set: RangeInclusiveMap) { assert_eq!( @@ -1038,19 +1048,33 @@ mod tests { }; if left == right { - assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + assert!( + hash(&left) == hash(&right), + "if two values are equal, their hash must be equal" + ); } // if the hashes are equal the values might not be the same (collision) if hash(&left) != hash(&right) { - assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + assert!( + left != right, + "if two value's hashes are not equal, they must not be equal" + ); } } #[proptest] fn test_ord(left: RangeInclusiveMap, right: RangeInclusiveMap) { - assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); - assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + assert_eq!( + left == right, + left.cmp(&right).is_eq(), + "ordering and equality must match" + ); + assert_eq!( + left.cmp(&right), + left.partial_cmp(&right).unwrap(), + "ordering is total for ordered parameters" + ); } #[test] @@ -1066,7 +1090,10 @@ mod tests { #[test] fn test_macro() { - assert_eq!(range_inclusive_map![], RangeInclusiveMap::::new()); + assert_eq!( + range_inclusive_map![], + RangeInclusiveMap::::default() + ); assert_eq!( range_inclusive_map!(0..=100 => "abc", 100..=200 => "def", 200..=300 => "ghi"), [(0..=100, "abc"), (100..=200, "def"), (200..=300, "ghi")] diff --git a/src/inclusive_set.rs b/src/inclusive_set.rs index e8483c2..cefe339 100644 --- a/src/inclusive_set.rs +++ b/src/inclusive_set.rs @@ -496,6 +496,16 @@ mod tests { assert_eq!(set.first(), set.iter().min_by_key(|range| range.start())); } + #[proptest] + fn test_len(mut map: RangeInclusiveSet) { + assert_eq!(map.len(), map.iter().count()); + assert_eq!(map.is_empty(), map.len() == 0); + map.clear(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert_eq!(map.iter().count(), 0); + } + #[proptest] fn test_last(set: RangeInclusiveSet) { assert_eq!(set.last(), set.iter().max_by_key(|range| range.end())); @@ -563,19 +573,33 @@ mod tests { }; if left == right { - assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + assert!( + hash(&left) == hash(&right), + "if two values are equal, their hash must be equal" + ); } // if the hashes are equal the values might not be the same (collision) if hash(&left) != hash(&right) { - assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + assert!( + left != right, + "if two value's hashes are not equal, they must not be equal" + ); } } #[proptest] fn test_ord(left: RangeInclusiveSet, right: RangeInclusiveSet) { - assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); - assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + assert_eq!( + left == right, + left.cmp(&right).is_eq(), + "ordering and equality must match" + ); + assert_eq!( + left.cmp(&right), + left.partial_cmp(&right).unwrap(), + "ordering is total for ordered parameters" + ); } #[test] @@ -588,7 +612,7 @@ mod tests { #[test] fn test_macro() { - assert_eq!(range_inclusive_set![], RangeInclusiveSet::::new()); + assert_eq!(range_inclusive_set![], RangeInclusiveSet::::default()); assert_eq!( range_inclusive_set![0..=100, 200..=300, 400..=500], [0..=100, 200..=300, 400..=500].iter().cloned().collect(), @@ -596,10 +620,7 @@ mod tests { } #[proptest] - fn test_union_overlaps_u8(left: Vec>, right: Vec>) { - let left: RangeInclusiveSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeInclusiveSet<_> = filter_ranges(right).into_iter().collect(); - + fn test_union_overlaps_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { let mut union = RangeInclusiveSet::new(); for range in left.union(&right) { // there should not be any overlaps in the ranges returned by the union @@ -609,10 +630,8 @@ mod tests { } #[proptest] - fn test_union_contains_u8(left: Vec>, right: Vec>) { - let left: RangeInclusiveSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeInclusiveSet<_> = filter_ranges(right).into_iter().collect(); - let union: RangeInclusiveSet<_> = left.union(&right).collect(); + fn test_union_contains_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { + let union = (&left) | (&right); // value should be in the union if and only if it is in either set for value in 0..u8::MAX { @@ -624,31 +643,20 @@ mod tests { } #[proptest] - fn test_intersection_contains_u8( - left: Vec>, - right: Vec>, - ) { - let left: RangeInclusiveSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeInclusiveSet<_> = filter_ranges(right).into_iter().collect(); - let union: RangeInclusiveSet<_> = left.intersection(&right).collect(); + fn test_intersection_contains_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { + let intersection = (&left) & (&right); // value should be in the union if and only if it is in either set for value in 0..u8::MAX { assert_eq!( - union.contains(&value), + intersection.contains(&value), left.contains(&value) && right.contains(&value) ); } } #[proptest] - fn test_intersection_overlaps_u8( - left: Vec>, - right: Vec>, - ) { - let left: RangeInclusiveSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeInclusiveSet<_> = filter_ranges(right).into_iter().collect(); - + fn test_intersection_overlaps_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { let mut union = RangeInclusiveSet::new(); for range in left.intersection(&right) { // there should not be any overlaps in the ranges returned by the diff --git a/src/map.rs b/src/map.rs index 50a1f56..9b0aabd 100644 --- a/src/map.rs +++ b/src/map.rs @@ -854,6 +854,16 @@ mod tests { ); } + #[proptest] + fn test_len(mut map: RangeMap) { + assert_eq!(map.len(), map.iter().count()); + assert_eq!(map.is_empty(), map.len() == 0); + map.clear(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert_eq!(map.iter().count(), 0); + } + #[proptest] fn test_last(set: RangeMap) { assert_eq!( @@ -923,19 +933,33 @@ mod tests { }; if left == right { - assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + assert!( + hash(&left) == hash(&right), + "if two values are equal, their hash must be equal" + ); } // if the hashes are equal the values might not be the same (collision) if hash(&left) != hash(&right) { - assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + assert!( + left != right, + "if two value's hashes are not equal, they must not be equal" + ); } } #[proptest] fn test_ord(left: RangeMap, right: RangeMap) { - assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); - assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + assert_eq!( + left == right, + left.cmp(&right).is_eq(), + "ordering and equality must match" + ); + assert_eq!( + left.cmp(&right), + left.partial_cmp(&right).unwrap(), + "ordering is total for ordered parameters" + ); } #[test] @@ -951,7 +975,7 @@ mod tests { #[test] fn test_macro() { - assert_eq!(range_map![], RangeMap::::new()); + assert_eq!(range_map![], RangeMap::::default()); assert_eq!( range_map!(0..100 => "abc", 100..200 => "def", 200..300 => "ghi"), [(0..100, "abc"), (100..200, "def"), (200..300, "ghi")] diff --git a/src/set.rs b/src/set.rs index c69ef14..f85758b 100644 --- a/src/set.rs +++ b/src/set.rs @@ -452,7 +452,12 @@ mod tests { fn arbitrary_with(_parameters: Self::Parameters) -> Self::Strategy { any::>>() - .prop_map(|ranges| ranges.into_iter().collect::>()) + .prop_map(|ranges| { + ranges + .into_iter() + .filter(|range| range.start != range.end) + .collect::>() + }) .boxed() } } @@ -462,6 +467,16 @@ mod tests { assert_eq!(set.first(), set.iter().min_by_key(|range| range.start)); } + #[proptest] + fn test_len(mut map: RangeSet) { + assert_eq!(map.len(), map.iter().count()); + assert_eq!(map.is_empty(), map.len() == 0); + map.clear(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert_eq!(map.iter().count(), 0); + } + #[proptest] fn test_last(set: RangeSet) { assert_eq!(set.last(), set.iter().max_by_key(|range| range.end)); @@ -527,19 +542,33 @@ mod tests { }; if left == right { - assert!(hash(&left) == hash(&right), "if two values are equal, their hash must be equal"); + assert!( + hash(&left) == hash(&right), + "if two values are equal, their hash must be equal" + ); } // if the hashes are equal the values might not be the same (collision) if hash(&left) != hash(&right) { - assert!(left != right, "if two value's hashes are not equal, they must not be equal"); + assert!( + left != right, + "if two value's hashes are not equal, they must not be equal" + ); } } #[proptest] fn test_ord(left: RangeSet, right: RangeSet) { - assert_eq!(left == right, left.cmp(&right).is_eq(), "ordering and equality must match"); - assert_eq!(left.cmp(&right), left.partial_cmp(&right).unwrap(), "ordering is total for ordered parameters"); + assert_eq!( + left == right, + left.cmp(&right).is_eq(), + "ordering and equality must match" + ); + assert_eq!( + left.cmp(&right), + left.partial_cmp(&right).unwrap(), + "ordering is total for ordered parameters" + ); } #[test] @@ -560,10 +589,7 @@ mod tests { } #[proptest] - fn test_union_overlaps_u8(left: Vec>, right: Vec>) { - let left: RangeSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeSet<_> = filter_ranges(right).into_iter().collect(); - + fn test_union_overlaps_u8(left: RangeSet, right: RangeSet) { let mut union = RangeSet::new(); for range in left.union(&right) { // there should not be any overlaps in the ranges returned by the union @@ -573,10 +599,8 @@ mod tests { } #[proptest] - fn test_union_contains_u8(left: Vec>, right: Vec>) { - let left: RangeSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeSet<_> = filter_ranges(right).into_iter().collect(); - let union: RangeSet<_> = left.union(&right).collect(); + fn test_union_contains_u8(left: RangeSet, right: RangeSet) { + let union = (&left) | (&right); // value should be in the union if and only if it is in either set for value in 0..u8::MAX { @@ -588,25 +612,20 @@ mod tests { } #[proptest] - fn test_intersection_contains_u8(left: Vec>, right: Vec>) { - let left: RangeSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeSet<_> = filter_ranges(right).into_iter().collect(); - let union: RangeSet<_> = left.intersection(&right).collect(); + fn test_intersection_contains_u8(left: RangeSet, right: RangeSet) { + let intersection = (&left) & (&right); // value should be in the union if and only if it is in either set for value in 0..u8::MAX { assert_eq!( - union.contains(&value), + intersection.contains(&value), left.contains(&value) && right.contains(&value) ); } } #[proptest] - fn test_intersection_overlaps_u8(left: Vec>, right: Vec>) { - let left: RangeSet<_> = filter_ranges(left).into_iter().collect(); - let right: RangeSet<_> = filter_ranges(right).into_iter().collect(); - + fn test_intersection_overlaps_u8(left: RangeSet, right: RangeSet) { let mut union = RangeSet::new(); for range in left.intersection(&right) { // there should not be any overlaps in the ranges returned by the From ae6b9c088fe2a102467b3602351548902c49d88e Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Thu, 8 Feb 2024 19:23:11 +1100 Subject: [PATCH 3/3] Fix some comment typos Not actually part of this PR, but noticed them while reviewing it. --- src/inclusive_set.rs | 2 +- src/set.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inclusive_set.rs b/src/inclusive_set.rs index cefe339..c46aa79 100644 --- a/src/inclusive_set.rs +++ b/src/inclusive_set.rs @@ -646,7 +646,7 @@ mod tests { fn test_intersection_contains_u8(left: RangeInclusiveSet, right: RangeInclusiveSet) { let intersection = (&left) & (&right); - // value should be in the union if and only if it is in either set + // value should be in the intersection if and only if it is in both sets for value in 0..u8::MAX { assert_eq!( intersection.contains(&value), diff --git a/src/set.rs b/src/set.rs index f85758b..a672f38 100644 --- a/src/set.rs +++ b/src/set.rs @@ -615,7 +615,7 @@ mod tests { fn test_intersection_contains_u8(left: RangeSet, right: RangeSet) { let intersection = (&left) & (&right); - // value should be in the union if and only if it is in either set + // value should be in the intersection if and only if it is in both sets for value in 0..u8::MAX { assert_eq!( intersection.contains(&value),