@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
3
3
use std:: convert:: TryFrom ;
4
4
use std:: fmt:: Debug ;
5
5
use std:: iter:: FromIterator ;
6
+ use std:: mem;
6
7
use std:: ops:: Bound :: { self , Excluded , Included , Unbounded } ;
7
8
use std:: ops:: RangeBounds ;
8
9
use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
@@ -25,6 +26,20 @@ const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
25
26
// It's not the minimum size: removing an element from such a tree does not always reduce height.
26
27
const MIN_INSERTS_HEIGHT_2 : usize = NODE_CAPACITY + ( NODE_CAPACITY + 1 ) * NODE_CAPACITY + 1 ;
27
28
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
+
28
43
#[ test]
29
44
fn test_basic_large ( ) {
30
45
let mut map = BTreeMap :: new ( ) ;
@@ -268,7 +283,14 @@ fn test_iter_mut_mutation() {
268
283
}
269
284
270
285
#[ test]
286
+ #[ cfg_attr( miri, ignore) ] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
271
287
fn 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 ( ) {
272
294
let mut a = BTreeMap :: new ( ) ;
273
295
a. insert ( 1 , String :: from ( "hello" ) ) ;
274
296
a. insert ( 2 , String :: from ( "goodbye" ) ) ;
@@ -281,6 +303,36 @@ fn test_values_mut() {
281
303
assert_eq ! ( values, [ String :: from( "hello!" ) , String :: from( "goodbye!" ) ] ) ;
282
304
}
283
305
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
+
284
336
#[ test]
285
337
fn test_iter_mixed ( ) {
286
338
// Miri is too slow
@@ -1283,6 +1335,34 @@ fn test_split_off_empty_left() {
1283
1335
assert ! ( right. into_iter( ) . eq( data) ) ;
1284
1336
}
1285
1337
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
+
1286
1366
#[ test]
1287
1367
fn test_split_off_large_random_sorted ( ) {
1288
1368
// Miri is too slow
0 commit comments