@@ -14,6 +14,9 @@ use std::ops::RangeBounds;
1414use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
1515use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
1616
17+ mod ord_chaos;
18+ use ord_chaos:: { Cyclic3 , Governed , Governor } ;
19+
1720// Capacity of a tree with a single level,
1821// i.e., a tree who's root is a leaf node at height 0.
1922const NODE_CAPACITY : usize = node:: CAPACITY ;
@@ -28,7 +31,7 @@ const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
2831// It's not the minimum size: removing an element from such a tree does not always reduce height.
2932const MIN_INSERTS_HEIGHT_2 : usize = 89 ;
3033
31- // Gather all references from a mutable iterator and make sure Miri notices if
34+ // Gathers all references from a mutable iterator and makes sure Miri notices if
3235// using them is dangerous.
3336fn test_all_refs < ' a , T : ' a > ( dummy : & mut T , iter : impl Iterator < Item = & ' a mut T > ) {
3437 // Gather all those references.
@@ -43,28 +46,43 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>
4346}
4447
4548impl < K , V > BTreeMap < K , V > {
46- /// Panics if the map (or the code navigating it) is corrupted.
47- fn check ( & self )
48- where
49- K : Copy + Debug + Ord ,
50- {
49+ // Panics if the map (or the code navigating it) is corrupted.
50+ fn check_invariants ( & self ) {
5151 if let Some ( root) = & self . root {
5252 let root_node = root. node_as_ref ( ) ;
5353
54+ // Check the back pointers top-down, before we attempt to rely on
55+ // more serious navigation code.
5456 assert ! ( root_node. ascend( ) . is_err( ) ) ;
5557 root_node. assert_back_pointers ( ) ;
5658
59+ // Check consistenty of `length` and some of the navigation.
5760 assert_eq ! ( self . length, root_node. calc_length( ) ) ;
61+ assert_eq ! ( self . length, self . keys( ) . count( ) ) ;
5862
63+ // Lastly, check the invariant causing the least harm.
5964 root_node. assert_min_len ( if root_node. height ( ) > 0 { 1 } else { 0 } ) ;
6065 } else {
66+ // Check consistenty of `length` and some of the navigation.
6167 assert_eq ! ( self . length, 0 ) ;
68+ assert_eq ! ( self . length, self . keys( ) . count( ) ) ;
6269 }
70+ }
6371
64- self . assert_ascending ( ) ;
72+ // Panics if the map is corrupted or if the keys are not in strictly
73+ // ascending order, in the current opinion of the `Ord` implementation.
74+ // If the `Ord` implementation does not honor transitivity, this method
75+ // does not guarantee that all the keys are unique, just that adjacent
76+ // keys are unique.
77+ fn check ( & self )
78+ where
79+ K : Debug + Ord ,
80+ {
81+ self . check_invariants ( ) ;
82+ self . assert_strictly_ascending ( ) ;
6583 }
6684
67- /// Returns the height of the root, if any.
85+ // Returns the height of the root, if any.
6886 fn height ( & self ) -> Option < usize > {
6987 self . root . as_ref ( ) . map ( node:: Root :: height)
7088 }
@@ -80,22 +98,18 @@ impl<K, V> BTreeMap<K, V> {
8098 }
8199 }
82100
83- /// Asserts that the keys are in strictly ascending order.
84- fn assert_ascending ( & self )
101+ // Panics if the keys are not in strictly ascending order.
102+ fn assert_strictly_ascending ( & self )
85103 where
86- K : Copy + Debug + Ord ,
104+ K : Debug + Ord ,
87105 {
88- let mut num_seen = 0 ;
89106 let mut keys = self . keys ( ) ;
90107 if let Some ( mut previous) = keys. next ( ) {
91- num_seen = 1 ;
92108 for next in keys {
93109 assert ! ( previous < next, "{:?} >= {:?}" , previous, next) ;
94110 previous = next;
95- num_seen += 1 ;
96111 }
97112 }
98- assert_eq ! ( num_seen, self . len( ) ) ;
99113 }
100114}
101115
@@ -111,7 +125,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
111125 }
112126}
113127
114- // Test our value of MIN_INSERTS_HEIGHT_2. It may change according to the
128+ // Tests our value of MIN_INSERTS_HEIGHT_2. It may change according to the
115129// implementation of insertion, but it's best to be aware of when it does.
116130#[ test]
117131fn test_levels ( ) {
@@ -149,6 +163,25 @@ fn test_levels() {
149163 assert_eq ! ( map. len( ) , MIN_INSERTS_HEIGHT_2 , "{}" , map. dump_keys( ) ) ;
150164}
151165
166+ // Ensures the testing infrastructure usually notices order violations.
167+ #[ test]
168+ #[ should_panic]
169+ fn test_check_ord_chaos ( ) {
170+ let gov = Governor :: new ( ) ;
171+ let map: BTreeMap < _ , _ > = ( 0 ..2 ) . map ( |i| ( Governed ( i, & gov) , ( ) ) ) . collect ( ) ;
172+ gov. flip ( ) ;
173+ map. check ( ) ;
174+ }
175+
176+ // Ensures the testing infrastructure doesn't always mind order violations.
177+ #[ test]
178+ fn test_check_invariants_ord_chaos ( ) {
179+ let gov = Governor :: new ( ) ;
180+ let map: BTreeMap < _ , _ > = ( 0 ..2 ) . map ( |i| ( Governed ( i, & gov) , ( ) ) ) . collect ( ) ;
181+ gov. flip ( ) ;
182+ map. check_invariants ( ) ;
183+ }
184+
152185#[ test]
153186fn test_basic_large ( ) {
154187 let mut map = BTreeMap :: new ( ) ;
@@ -334,7 +367,7 @@ fn test_iter_rev() {
334367 test ( size, map. into_iter ( ) . rev ( ) ) ;
335368}
336369
337- /// Specifically tests iter_mut's ability to mutate the value of pairs in-line
370+ // Specifically tests iter_mut's ability to mutate the value of pairs in-line.
338371fn do_test_iter_mut_mutation < T > ( size : usize )
339372where
340373 T : Copy + Debug + Ord + TryFrom < usize > ,
@@ -439,6 +472,8 @@ fn test_iter_entering_root_twice() {
439472 * back. 1 = 42 ;
440473 assert_eq ! ( front, ( & 0 , & mut 24 ) ) ;
441474 assert_eq ! ( back, ( & 1 , & mut 42 ) ) ;
475+ assert_eq ! ( it. next( ) , None ) ;
476+ assert_eq ! ( it. next_back( ) , None ) ;
442477 map. check ( ) ;
443478}
444479
@@ -591,11 +626,12 @@ fn test_range_small() {
591626
592627#[ test]
593628fn test_range_height_1 ( ) {
594- // Tests tree with a root and 2 leaves. Depending on details we don't want or need
595- // to rely upon, the single key at the root will be 6 or 7 .
629+ // Tests tree with a root and 2 leaves. The single key in the root node is
630+ // close to the middle among the keys .
596631
597- let map: BTreeMap < _ , _ > = ( 1 ..=MIN_INSERTS_HEIGHT_1 as i32 ) . map ( |i| ( i, i) ) . collect ( ) ;
598- for & root in & [ 6 , 7 ] {
632+ let map: BTreeMap < _ , _ > = ( 0 ..MIN_INSERTS_HEIGHT_1 as i32 ) . map ( |i| ( i, i) ) . collect ( ) ;
633+ let middle = MIN_INSERTS_HEIGHT_1 as i32 / 2 ;
634+ for root in middle - 2 ..=middle + 2 {
599635 assert_eq ! ( range_keys( & map, ( Excluded ( root) , Excluded ( root + 1 ) ) ) , vec![ ] ) ;
600636 assert_eq ! ( range_keys( & map, ( Excluded ( root) , Included ( root + 1 ) ) ) , vec![ root + 1 ] ) ;
601637 assert_eq ! ( range_keys( & map, ( Included ( root) , Excluded ( root + 1 ) ) ) , vec![ root] ) ;
@@ -727,6 +763,19 @@ fn test_range_backwards_4() {
727763 map. range ( ( Excluded ( 3 ) , Excluded ( 2 ) ) ) ;
728764}
729765
766+ #[ test]
767+ #[ should_panic]
768+ fn test_range_backwards_5 ( ) {
769+ let mut map = BTreeMap :: new ( ) ;
770+ map. insert ( Cyclic3 :: B , ( ) ) ;
771+ // Lacking static_assert, call `range` conditionally, to emphasise that
772+ // we cause a different panic than `test_range_backwards_1` does.
773+ // A more refined `should_panic` would be welcome.
774+ if Cyclic3 :: C < Cyclic3 :: A {
775+ map. range ( Cyclic3 :: C ..=Cyclic3 :: A ) ;
776+ }
777+ }
778+
730779#[ test]
731780fn test_range_1000 ( ) {
732781 // Miri is too slow
@@ -820,18 +869,28 @@ mod test_drain_filter {
820869 }
821870
822871 #[ test]
823- fn consuming_nothing ( ) {
872+ fn consumed_keeping_all ( ) {
824873 let pairs = ( 0 ..3 ) . map ( |i| ( i, i) ) ;
825874 let mut map: BTreeMap < _ , _ > = pairs. collect ( ) ;
826875 assert ! ( map. drain_filter( |_, _| false ) . eq( iter:: empty( ) ) ) ;
827876 map. check ( ) ;
828877 }
829878
830879 #[ test]
831- fn consuming_all ( ) {
880+ fn consumed_removing_all ( ) {
832881 let pairs = ( 0 ..3 ) . map ( |i| ( i, i) ) ;
833882 let mut map: BTreeMap < _ , _ > = pairs. clone ( ) . collect ( ) ;
834883 assert ! ( map. drain_filter( |_, _| true ) . eq( pairs) ) ;
884+ assert ! ( map. is_empty( ) ) ;
885+ map. check ( ) ;
886+ }
887+
888+ #[ test]
889+ fn dropped_removing_all ( ) {
890+ let pairs = ( 0 ..3 ) . map ( |i| ( i, i) ) ;
891+ let mut map: BTreeMap < _ , _ > = pairs. collect ( ) ;
892+ map. drain_filter ( |_, _| true ) ;
893+ assert ! ( map. is_empty( ) ) ;
835894 map. check ( ) ;
836895 }
837896
@@ -1712,6 +1771,27 @@ fn test_append_drop_leak() {
17121771 assert_eq ! ( DROPS . load( Ordering :: SeqCst ) , 4 ) ; // Rust issue #47949 ate one little piggy
17131772}
17141773
1774+ #[ test]
1775+ fn test_append_ord_chaos ( ) {
1776+ let mut map1 = BTreeMap :: new ( ) ;
1777+ map1. insert ( Cyclic3 :: A , ( ) ) ;
1778+ map1. insert ( Cyclic3 :: B , ( ) ) ;
1779+ let mut map2 = BTreeMap :: new ( ) ;
1780+ map2. insert ( Cyclic3 :: A , ( ) ) ;
1781+ map2. insert ( Cyclic3 :: B , ( ) ) ;
1782+ map2. insert ( Cyclic3 :: C , ( ) ) ; // lands first, before A
1783+ map2. insert ( Cyclic3 :: B , ( ) ) ; // lands first, before C
1784+ map1. check ( ) ;
1785+ map2. check ( ) ; // keys are not unique but still strictly ascending
1786+ assert_eq ! ( map1. len( ) , 2 ) ;
1787+ assert_eq ! ( map2. len( ) , 4 ) ;
1788+ map1. append ( & mut map2) ;
1789+ assert_eq ! ( map1. len( ) , 5 ) ;
1790+ assert_eq ! ( map2. len( ) , 0 ) ;
1791+ map1. check ( ) ;
1792+ map2. check ( ) ;
1793+ }
1794+
17151795fn rand_data ( len : usize ) -> Vec < ( u32 , u32 ) > {
17161796 assert ! ( len * 2 <= 70029 ) ; // from that point on numbers repeat
17171797 let mut rng = DeterministicRng :: new ( ) ;
@@ -1874,11 +1954,27 @@ fn test_insert_remove_intertwined() {
18741954 let loops = if cfg ! ( miri) { 100 } else { 1_000_000 } ;
18751955 let mut map = BTreeMap :: new ( ) ;
18761956 let mut i = 1 ;
1957+ let offset = 165 ; // somewhat arbitrarily chosen to cover some code paths
18771958 for _ in 0 ..loops {
1878- i = ( i + 421 ) & 0xFF ;
1959+ i = ( i + offset ) & 0xFF ;
18791960 map. insert ( i, i) ;
18801961 map. remove ( & ( 0xFF - i) ) ;
18811962 }
1882-
18831963 map. check ( ) ;
18841964}
1965+
1966+ #[ test]
1967+ fn test_insert_remove_intertwined_ord_chaos ( ) {
1968+ let loops = if cfg ! ( miri) { 100 } else { 1_000_000 } ;
1969+ let gov = Governor :: new ( ) ;
1970+ let mut map = BTreeMap :: new ( ) ;
1971+ let mut i = 1 ;
1972+ let offset = 165 ; // more arbitrarily copied from above
1973+ for _ in 0 ..loops {
1974+ i = ( i + offset) & 0xFF ;
1975+ map. insert ( Governed ( i, & gov) , ( ) ) ;
1976+ map. remove ( & Governed ( 0xFF - i, & gov) ) ;
1977+ gov. flip ( ) ;
1978+ }
1979+ map. check_invariants ( ) ;
1980+ }
0 commit comments