@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
33use std:: convert:: TryFrom ;
44use std:: fmt:: Debug ;
55use std:: iter:: FromIterator ;
6+ use std:: mem;
67use std:: ops:: Bound :: { self , Excluded , Included , Unbounded } ;
78use std:: ops:: RangeBounds ;
89use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
@@ -25,6 +26,20 @@ const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
2526// It's not the minimum size: removing an element from such a tree does not always reduce height.
2627const MIN_INSERTS_HEIGHT_2 : usize = NODE_CAPACITY + ( NODE_CAPACITY + 1 ) * NODE_CAPACITY + 1 ;
2728
29+ // Gather all references from a mutable iterator and make sure Miri notices if
30+ // using them is dangerous.
31+ fn test_all_refs < ' a , T : ' a > ( dummy : & mut T , iter : impl Iterator < Item = & ' a mut T > ) {
32+ // Gather all those references.
33+ let mut refs: Vec < & mut T > = iter. collect ( ) ;
34+ // Use them all. Twice, to be sure we got all interleavings.
35+ for r in refs. iter_mut ( ) {
36+ mem:: swap ( dummy, r) ;
37+ }
38+ for r in refs {
39+ mem:: swap ( dummy, r) ;
40+ }
41+ }
42+
2843#[ test]
2944fn test_basic_large ( ) {
3045 let mut map = BTreeMap :: new ( ) ;
@@ -268,7 +283,14 @@ fn test_iter_mut_mutation() {
268283}
269284
270285#[ test]
286+ #[ cfg_attr( miri, ignore) ] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
271287fn test_values_mut ( ) {
288+ let mut a: BTreeMap < _ , _ > = ( 0 ..MIN_INSERTS_HEIGHT_2 ) . map ( |i| ( i, i) ) . collect ( ) ;
289+ test_all_refs ( & mut 13 , a. values_mut ( ) ) ;
290+ }
291+
292+ #[ test]
293+ fn test_values_mut_mutation ( ) {
272294 let mut a = BTreeMap :: new ( ) ;
273295 a. insert ( 1 , String :: from ( "hello" ) ) ;
274296 a. insert ( 2 , String :: from ( "goodbye" ) ) ;
@@ -281,6 +303,36 @@ fn test_values_mut() {
281303 assert_eq ! ( values, [ String :: from( "hello!" ) , String :: from( "goodbye!" ) ] ) ;
282304}
283305
306+ #[ test]
307+ #[ cfg_attr( miri, ignore) ] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
308+ fn test_iter_entering_root_twice ( ) {
309+ let mut map: BTreeMap < _ , _ > = ( 0 ..2 ) . map ( |i| ( i, i) ) . collect ( ) ;
310+ let mut it = map. iter_mut ( ) ;
311+ let front = it. next ( ) . unwrap ( ) ;
312+ let back = it. next_back ( ) . unwrap ( ) ;
313+ assert_eq ! ( front, ( & 0 , & mut 0 ) ) ;
314+ assert_eq ! ( back, ( & 1 , & mut 1 ) ) ;
315+ * front. 1 = 24 ;
316+ * back. 1 = 42 ;
317+ assert_eq ! ( front, ( & 0 , & mut 24 ) ) ;
318+ assert_eq ! ( back, ( & 1 , & mut 42 ) ) ;
319+ }
320+
321+ #[ test]
322+ #[ cfg_attr( miri, ignore) ] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
323+ fn test_iter_descending_to_same_node_twice ( ) {
324+ let mut map: BTreeMap < _ , _ > = ( 0 ..MIN_INSERTS_HEIGHT_1 ) . map ( |i| ( i, i) ) . collect ( ) ;
325+ let mut it = map. iter_mut ( ) ;
326+ // Descend into first child.
327+ let front = it. next ( ) . unwrap ( ) ;
328+ // Descend into first child again, after running through second child.
329+ while it. next_back ( ) . is_some ( ) { }
330+ // Check immutable access.
331+ assert_eq ! ( front, ( & 0 , & mut 0 ) ) ;
332+ // Perform mutable access.
333+ * front. 1 = 42 ;
334+ }
335+
284336#[ test]
285337fn test_iter_mixed ( ) {
286338 // Miri is too slow
@@ -1283,6 +1335,34 @@ fn test_split_off_empty_left() {
12831335 assert ! ( right. into_iter( ) . eq( data) ) ;
12841336}
12851337
1338+ // In a tree with 3 levels, if all but a part of the first leaf node is split off,
1339+ // make sure fix_top eliminates both top levels.
1340+ #[ test]
1341+ fn test_split_off_tiny_left_height_2 ( ) {
1342+ let pairs = ( 0 ..MIN_INSERTS_HEIGHT_2 ) . map ( |i| ( i, i) ) ;
1343+ let mut left: BTreeMap < _ , _ > = pairs. clone ( ) . collect ( ) ;
1344+ let right = left. split_off ( & 1 ) ;
1345+ assert_eq ! ( left. len( ) , 1 ) ;
1346+ assert_eq ! ( right. len( ) , MIN_INSERTS_HEIGHT_2 - 1 ) ;
1347+ assert_eq ! ( * left. first_key_value( ) . unwrap( ) . 0 , 0 ) ;
1348+ assert_eq ! ( * right. first_key_value( ) . unwrap( ) . 0 , 1 ) ;
1349+ }
1350+
1351+ // In a tree with 3 levels, if only part of the last leaf node is split off,
1352+ // make sure fix_top eliminates both top levels.
1353+ #[ test]
1354+ fn test_split_off_tiny_right_height_2 ( ) {
1355+ let pairs = ( 0 ..MIN_INSERTS_HEIGHT_2 ) . map ( |i| ( i, i) ) ;
1356+ let last = MIN_INSERTS_HEIGHT_2 - 1 ;
1357+ let mut left: BTreeMap < _ , _ > = pairs. clone ( ) . collect ( ) ;
1358+ assert_eq ! ( * left. last_key_value( ) . unwrap( ) . 0 , last) ;
1359+ let right = left. split_off ( & last) ;
1360+ assert_eq ! ( left. len( ) , MIN_INSERTS_HEIGHT_2 - 1 ) ;
1361+ assert_eq ! ( right. len( ) , 1 ) ;
1362+ assert_eq ! ( * left. last_key_value( ) . unwrap( ) . 0 , last - 1 ) ;
1363+ assert_eq ! ( * right. last_key_value( ) . unwrap( ) . 0 , last) ;
1364+ }
1365+
12861366#[ test]
12871367fn test_split_off_large_random_sorted ( ) {
12881368 // Miri is too slow
0 commit comments