BTreeMap: test split_off (and append) more thoroughly
This commit is contained in:
parent
c34c015fe2
commit
d473cbe75b
@ -81,15 +81,18 @@ impl<K, V> Root<K, V> {
|
||||
// the appended elements even if advancing the iterator panicks.
|
||||
*length += 1;
|
||||
}
|
||||
self.fix_right_edge();
|
||||
self.fix_right_border_of_plentiful();
|
||||
}
|
||||
|
||||
fn fix_right_edge(&mut self) {
|
||||
// Handle underfull nodes, start from the top.
|
||||
/// Stock up any underfull nodes on the right border of the tree.
|
||||
/// The other nodes, those that are not the root nor a rightmost edge,
|
||||
/// must have MIN_LEN elements to spare.
|
||||
fn fix_right_border_of_plentiful(&mut self) {
|
||||
let mut cur_node = self.borrow_mut();
|
||||
while let Internal(internal) = cur_node.force() {
|
||||
// Check if right-most child is underfull.
|
||||
let mut last_kv = internal.last_kv().consider_for_balancing();
|
||||
debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2);
|
||||
let right_child_len = last_kv.right_child_len();
|
||||
if right_child_len < MIN_LEN {
|
||||
// We need to steal.
|
||||
|
@ -1797,7 +1797,6 @@ fn test_append_ord_chaos() {
|
||||
}
|
||||
|
||||
fn rand_data(len: usize) -> Vec<(u32, u32)> {
|
||||
assert!(len * 2 <= 70029); // from that point on numbers repeat
|
||||
let mut rng = DeterministicRng::new();
|
||||
Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
|
||||
}
|
||||
@ -1862,6 +1861,25 @@ fn test_split_off_tiny_right_height_2() {
|
||||
assert_eq!(*right.last_key_value().unwrap().0, last);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_off_halfway() {
|
||||
let mut rng = DeterministicRng::new();
|
||||
for &len in &[NODE_CAPACITY, 25, 50, 75, 100] {
|
||||
let mut data = Vec::from_iter((0..len).map(|_| (rng.next(), ())));
|
||||
// Insertion in non-ascending order creates some variation in node length.
|
||||
let mut map = BTreeMap::from_iter(data.iter().copied());
|
||||
data.sort();
|
||||
let small_keys = data.iter().take(len / 2).map(|kv| kv.0);
|
||||
let large_keys = data.iter().skip(len / 2).map(|kv| kv.0);
|
||||
let split_key = large_keys.clone().next().unwrap();
|
||||
let right = map.split_off(&split_key);
|
||||
map.check();
|
||||
right.check();
|
||||
assert!(map.keys().copied().eq(small_keys));
|
||||
assert!(right.keys().copied().eq(large_keys));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_off_large_random_sorted() {
|
||||
// Miri is too slow
|
||||
|
@ -38,6 +38,7 @@ pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
|
||||
#[cfg(test)]
|
||||
/// XorShiftRng
|
||||
struct DeterministicRng {
|
||||
count: usize,
|
||||
x: u32,
|
||||
y: u32,
|
||||
z: u32,
|
||||
@ -47,11 +48,13 @@ struct DeterministicRng {
|
||||
#[cfg(test)]
|
||||
impl DeterministicRng {
|
||||
fn new() -> Self {
|
||||
DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
|
||||
DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
|
||||
}
|
||||
|
||||
/// Guarantees that the first 70029 results are unique.
|
||||
/// Guarantees that each returned number is unique.
|
||||
fn next(&mut self) -> u32 {
|
||||
self.count += 1;
|
||||
assert!(self.count <= 70029);
|
||||
let x = self.x;
|
||||
let t = x ^ (x << 11);
|
||||
self.x = self.y;
|
||||
|
@ -696,8 +696,10 @@ fn test_first_last() {
|
||||
assert_eq!(a.pop_last(), None);
|
||||
}
|
||||
|
||||
// Unlike the function with the same name in map/tests, returns no values.
|
||||
// Which also means it returns different predetermined pseudo-random keys,
|
||||
// and the test cases using this function explore slightly different trees.
|
||||
fn rand_data(len: usize) -> Vec<u32> {
|
||||
assert!(len <= 70029); // from that point on numbers repeat
|
||||
let mut rng = DeterministicRng::new();
|
||||
Vec::from_iter((0..len).map(|_| rng.next()))
|
||||
}
|
||||
|
@ -53,6 +53,9 @@ impl<K, V> Root<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stock up or merge away any underfull nodes on the right border of the
|
||||
/// tree. The other nodes, those that are not the root nor a rightmost edge,
|
||||
/// must already have at least MIN_LEN elements.
|
||||
fn fix_right_border(&mut self) {
|
||||
self.fix_top();
|
||||
|
||||
@ -72,6 +75,7 @@ impl<K, V> Root<K, V> {
|
||||
}
|
||||
cur_node = last_kv.into_right_child();
|
||||
}
|
||||
debug_assert!(cur_node.len() > MIN_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +102,7 @@ impl<K, V> Root<K, V> {
|
||||
}
|
||||
cur_node = first_kv.into_left_child();
|
||||
}
|
||||
debug_assert!(cur_node.len() > MIN_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user