Skip to content

Commit cff5953

Browse files
authored
Rollup merge of #74666 - ssomers:btree_cleanup_1, r=Mark-Simulacrum
More BTreeMap test cases, some exposing undefined behaviour Gathered from other ongoing PRs and all either blessed or ignored by Miri r? @Mark-Simulacrum
2 parents 1f6d5ce + 2152d18 commit cff5953

File tree

1 file changed

+80
-0
lines changed
  • src/liballoc/tests/btree

1 file changed

+80
-0
lines changed

src/liballoc/tests/btree/map.rs

+80
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
33
use std::convert::TryFrom;
44
use std::fmt::Debug;
55
use std::iter::FromIterator;
6+
use std::mem;
67
use std::ops::Bound::{self, Excluded, Included, Unbounded};
78
use std::ops::RangeBounds;
89
use 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.
2627
const 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]
2944
fn 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>
271287
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() {
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]
285337
fn 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]
12871367
fn test_split_off_large_random_sorted() {
12881368
// Miri is too slow

0 commit comments

Comments
 (0)