use super::super::{inter::*, leaf::*, node::*, *};
use super::{CounterI32, alive_count, reset_alive_count};
use core::cell::UnsafeCell;
#[test]
fn test_inter_underflow_merge_right_height_3_2() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_2 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_3 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_4 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
leaf_2.insert_no_split(CounterI32::new((10 + i) * 2), CounterI32::new((10 + i) * 10));
leaf_3.insert_no_split(CounterI32::new((20 + i) * 2), CounterI32::new((20 + i) * 10));
leaf_4.insert_no_split(CounterI32::new((30 + i) * 2), CounterI32::new((30 + i) * 10));
}
let leaf_1_first = leaf_1.get_keys()[0].clone();
let leaf_2_first = leaf_2.get_keys()[0].clone();
let leaf_3_first = leaf_3.get_keys()[0].clone();
(*leaf_1.brothers()).next = leaf_2.get_ptr();
(*leaf_2.brothers()).prev = leaf_1.get_ptr();
(*leaf_2.brothers()).next = leaf_3.get_ptr();
(*leaf_3.brothers()).prev = leaf_2.get_ptr();
(*leaf_3.brothers()).next = leaf_4.get_ptr();
(*leaf_4.brothers()).prev = leaf_3.get_ptr();
let mut internal_a = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_a.set_left_ptr(leaf_1.get_ptr());
internal_a.insert_no_split(leaf_2_first, leaf_2.get_ptr());
debug_assert_eq!(internal_a.key_count(), 1);
let mut internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_b.set_left_ptr(leaf_3.get_ptr());
internal_b.insert_no_split(leaf_4.get_keys()[0].clone(), leaf_4.get_ptr());
debug_assert_eq!(internal_b.key_count(), 1);
let mut root = InterNode::<CounterI32, CounterI32>::alloc(2);
root.set_left_ptr(internal_a.get_ptr());
root.insert_no_split(leaf_3_first, internal_b.get_ptr());
debug_assert_eq!(root.key_count(), 1);
let alive_before = alive_count();
println!("Alive count before handle_inter_underflow: {}", alive_before);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 12,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 4,
#[cfg(feature = "trace_log")]
triggers: 0,
};
assert_eq!(map.height(), 3);
let cache = map.get_cache();
cache.clear();
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, &leaf_1_first);
let (popped_node, _) = cache.pop().unwrap();
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 1);
assert_eq!(popped_node, internal_a);
map.handle_inter_underflow(internal_a);
map.validate();
assert_eq!(map.height(), 2, "Tree height should be 2 after merge");
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
assert!(
map.contains_key(&CounterI32::new((10 + i) * 2)),
"Key {} should exist",
(10 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((20 + i) * 2)),
"Key {} should exist",
(20 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((30 + i) * 2)),
"Key {} should exist",
(30 + i) * 2
);
}
assert_eq!(map.height(), 2);
assert_eq!(map.leaf_count, 4);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, TestFlag::InterMergeRight as u32);
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}
#[test]
fn test_inter_underflow_merge_left_height_3_2() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_2 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_3 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_4 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
leaf_2.insert_no_split(CounterI32::new((10 + i) * 2), CounterI32::new((10 + i) * 10));
leaf_3.insert_no_split(CounterI32::new((20 + i) * 2), CounterI32::new((20 + i) * 10));
leaf_4.insert_no_split(CounterI32::new((30 + i) * 2), CounterI32::new((30 + i) * 10));
}
let _leaf_1_first = leaf_1.get_keys()[0].clone();
let leaf_2_first = leaf_2.get_keys()[0].clone();
let leaf_3_first = leaf_3.get_keys()[0].clone();
(*leaf_1.brothers()).next = leaf_2.get_ptr();
(*leaf_2.brothers()).prev = leaf_1.get_ptr();
(*leaf_2.brothers()).next = leaf_3.get_ptr();
(*leaf_3.brothers()).prev = leaf_2.get_ptr();
(*leaf_3.brothers()).next = leaf_4.get_ptr();
(*leaf_4.brothers()).prev = leaf_3.get_ptr();
let mut internal_a = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_a.set_left_ptr(leaf_1.get_ptr());
internal_a.insert_no_split(leaf_2_first, leaf_2.get_ptr());
debug_assert_eq!(internal_a.key_count(), 1);
let mut internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_b.set_left_ptr(leaf_3.get_ptr());
internal_b.insert_no_split(leaf_4.get_keys()[0].clone(), leaf_4.get_ptr());
debug_assert_eq!(internal_b.key_count(), 1);
let mut root = InterNode::<CounterI32, CounterI32>::alloc(2);
root.set_left_ptr(internal_a.get_ptr());
root.insert_no_split(leaf_3_first, internal_b.get_ptr());
debug_assert_eq!(root.key_count(), 1);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 12,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 4,
#[cfg(feature = "trace_log")]
triggers: 0,
};
assert_eq!(map.height(), 3);
let cache = map.get_cache();
cache.clear();
let leaf_3_lookup = &leaf_3.get_keys()[0];
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, leaf_3_lookup);
let (popped_node, _) = cache.pop().unwrap();
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 1);
assert_eq!(popped_node, internal_b);
map.handle_inter_underflow(internal_b);
map.validate();
assert_eq!(map.height(), 2, "Tree height should be 2 after merge");
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
assert!(
map.contains_key(&CounterI32::new((10 + i) * 2)),
"Key {} should exist",
(10 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((20 + i) * 2)),
"Key {} should exist",
(20 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((30 + i) * 2)),
"Key {} should exist",
(30 + i) * 2
);
}
assert_eq!(map.height(), 2);
assert_eq!(map.leaf_count, 4);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, TestFlag::InterMergeLeft as u32);
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}
#[test]
fn test_inter_underflow_merge_right_height_3() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_2 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_3 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_4 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_5 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_6 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
leaf_2.insert_no_split(CounterI32::new((10 + i) * 2), CounterI32::new((10 + i) * 10));
leaf_3.insert_no_split(CounterI32::new((20 + i) * 2), CounterI32::new((20 + i) * 10));
leaf_4.insert_no_split(CounterI32::new((30 + i) * 2), CounterI32::new((30 + i) * 10));
leaf_5.insert_no_split(CounterI32::new((40 + i) * 2), CounterI32::new((40 + i) * 10));
leaf_6.insert_no_split(CounterI32::new((50 + i) * 2), CounterI32::new((50 + i) * 10));
}
let _leaf_1_first = leaf_1.get_keys()[0].clone();
let leaf_2_first = leaf_2.get_keys()[0].clone();
let leaf_3_first = leaf_3.get_keys()[0].clone();
let leaf_4_first = leaf_4.get_keys()[0].clone();
let leaf_5_first = leaf_5.get_keys()[0].clone();
let leaf_6_first = leaf_6.get_keys()[0].clone();
(*leaf_1.brothers()).next = leaf_2.get_ptr();
(*leaf_2.brothers()).prev = leaf_1.get_ptr();
(*leaf_2.brothers()).next = leaf_3.get_ptr();
(*leaf_3.brothers()).prev = leaf_2.get_ptr();
(*leaf_3.brothers()).next = leaf_4.get_ptr();
(*leaf_4.brothers()).prev = leaf_3.get_ptr();
(*leaf_4.brothers()).next = leaf_5.get_ptr();
(*leaf_5.brothers()).prev = leaf_4.get_ptr();
(*leaf_5.brothers()).next = leaf_6.get_ptr();
(*leaf_6.brothers()).prev = leaf_5.get_ptr();
let mut internal_a = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_a.set_left_ptr(leaf_1.get_ptr());
internal_a.insert_no_split(leaf_2_first, leaf_2.get_ptr());
debug_assert_eq!(internal_a.key_count(), 1);
let mut internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_b.set_left_ptr(leaf_3.get_ptr());
internal_b.insert_no_split(leaf_4_first, leaf_4.get_ptr());
debug_assert_eq!(internal_b.key_count(), 1);
let mut internal_c = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_c.set_left_ptr(leaf_5.get_ptr());
internal_c.insert_no_split(leaf_6_first, leaf_6.get_ptr());
debug_assert_eq!(internal_c.key_count(), 1);
let mut root = InterNode::<CounterI32, CounterI32>::alloc(2);
root.set_left_ptr(internal_a.get_ptr());
root.insert_no_split(leaf_3_first, internal_b.get_ptr());
root.insert_no_split(leaf_5_first, internal_c.get_ptr());
debug_assert_eq!(root.key_count(), 2);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 18,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 6,
#[cfg(feature = "trace_log")]
triggers: 0,
};
assert_eq!(map.height(), 3, "Tree height should remain 3");
let cache = map.get_cache();
cache.clear();
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, &leaf_1.get_keys()[0]);
let (popped_node, _) = cache.pop().unwrap();
assert_eq!(popped_node, internal_a);
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 1);
map.handle_inter_underflow(internal_a);
map.validate();
assert_eq!(map.height(), 3, "Tree height should remain 3");
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
assert!(
map.contains_key(&CounterI32::new((10 + i) * 2)),
"Key {} should exist",
(10 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((20 + i) * 2)),
"Key {} should exist",
(20 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((30 + i) * 2)),
"Key {} should exist",
(30 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((40 + i) * 2)),
"Key {} should exist",
(40 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((50 + i) * 2)),
"Key {} should exist",
(50 + i) * 2
);
assert_eq!(map.leaf_count, 6);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, TestFlag::InterMergeRight as u32);
}
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}
#[test]
fn test_inter_underflow_merge_left_height_3() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_2 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_3 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_4 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_5 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_6 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
leaf_2.insert_no_split(CounterI32::new((10 + i) * 2), CounterI32::new((10 + i) * 10));
leaf_3.insert_no_split(CounterI32::new((20 + i) * 2), CounterI32::new((20 + i) * 10));
leaf_4.insert_no_split(CounterI32::new((30 + i) * 2), CounterI32::new((30 + i) * 10));
leaf_5.insert_no_split(CounterI32::new((40 + i) * 2), CounterI32::new((40 + i) * 10));
leaf_6.insert_no_split(CounterI32::new((50 + i) * 2), CounterI32::new((50 + i) * 10));
}
let _leaf_1_first = leaf_1.get_keys()[0].clone();
let leaf_2_first = leaf_2.get_keys()[0].clone();
let leaf_3_first = leaf_3.get_keys()[0].clone();
let leaf_4_first = leaf_4.get_keys()[0].clone();
let leaf_5_first = leaf_5.get_keys()[0].clone();
let leaf_6_first = leaf_6.get_keys()[0].clone();
(*leaf_1.brothers()).next = leaf_2.get_ptr();
(*leaf_2.brothers()).prev = leaf_1.get_ptr();
(*leaf_2.brothers()).next = leaf_3.get_ptr();
(*leaf_3.brothers()).prev = leaf_2.get_ptr();
(*leaf_3.brothers()).next = leaf_4.get_ptr();
(*leaf_4.brothers()).prev = leaf_3.get_ptr();
(*leaf_4.brothers()).next = leaf_5.get_ptr();
(*leaf_5.brothers()).prev = leaf_4.get_ptr();
(*leaf_5.brothers()).next = leaf_6.get_ptr();
(*leaf_6.brothers()).prev = leaf_5.get_ptr();
let mut internal_a = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_a.set_left_ptr(leaf_1.get_ptr());
internal_a.insert_no_split(leaf_2_first, leaf_2.get_ptr());
debug_assert_eq!(internal_a.key_count(), 1);
let mut internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_b.set_left_ptr(leaf_3.get_ptr());
internal_b.insert_no_split(leaf_4_first, leaf_4.get_ptr());
debug_assert_eq!(internal_b.key_count(), 1);
let mut internal_c = InterNode::<CounterI32, CounterI32>::alloc(1);
internal_c.set_left_ptr(leaf_5.get_ptr());
internal_c.insert_no_split(leaf_6_first, leaf_6.get_ptr());
debug_assert_eq!(internal_c.key_count(), 1);
let mut root = InterNode::<CounterI32, CounterI32>::alloc(2);
root.set_left_ptr(internal_a.get_ptr());
root.insert_no_split(leaf_3_first, internal_b.get_ptr());
root.insert_no_split(leaf_5_first, internal_c.get_ptr());
debug_assert_eq!(root.key_count(), 2);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 18,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 6,
#[cfg(feature = "trace_log")]
triggers: 0,
};
assert_eq!(map.height(), 3, "Tree height should remain 3");
let cache = map.get_cache();
cache.clear();
let leaf_3_lookup = &leaf_3.get_keys()[0];
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, leaf_3_lookup);
let (popped_node, _) = cache.pop().unwrap();
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 1);
assert_eq!(popped_node, internal_b);
map.handle_inter_underflow(internal_b);
map.validate();
assert_eq!(map.height(), 3, "Tree height should remain 3");
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
assert!(
map.contains_key(&CounterI32::new((10 + i) * 2)),
"Key {} should exist",
(10 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((20 + i) * 2)),
"Key {} should exist",
(20 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((30 + i) * 2)),
"Key {} should exist",
(30 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((40 + i) * 2)),
"Key {} should exist",
(40 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((50 + i) * 2)),
"Key {} should exist",
(50 + i) * 2
);
assert_eq!(map.leaf_count, 6);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, TestFlag::InterMergeLeft as u32);
}
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}
#[test]
fn test_inter_underflow_root_becomes_leaf() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
}
let leaf_1_first = leaf_1.get_keys()[0].clone();
let internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
(*internal_b.child_ptr(0)) = leaf_1.get_ptr();
debug_assert_eq!(internal_b.key_count(), 0);
let internal_a = InterNode::<CounterI32, CounterI32>::alloc(2);
(*internal_a.child_ptr(0)) = internal_b.get_ptr();
debug_assert_eq!(internal_a.key_count(), 0);
let root = InterNode::<CounterI32, CounterI32>::alloc(3);
(*root.child_ptr(0)) = internal_a.get_ptr();
debug_assert_eq!(root.key_count(), 0);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 3,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 1,
#[cfg(feature = "trace_log")]
triggers: 0,
};
let cache = map.get_cache();
cache.clear();
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, &leaf_1_first);
let (popped_node, _) = cache.pop().unwrap();
assert_eq!(popped_node, internal_b);
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 0);
map.handle_inter_underflow(internal_b);
map.validate();
assert_eq!(map.height(), 1, "Root should become leaf after cascade merge");
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
}
assert_eq!(map.leaf_count, 1);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, 0);
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}
#[test]
fn test_inter_underflow_single_leaf_inter_nodes_height_3() {
reset_alive_count();
unsafe {
let _inter_cap = InterNode::<CounterI32, CounterI32>::cap();
let _leaf_cap = LeafNode::<CounterI32, CounterI32>::cap();
let mut leaf_1 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_2 = LeafNode::<CounterI32, CounterI32>::alloc();
let mut leaf_3 = LeafNode::<CounterI32, CounterI32>::alloc();
for i in 0..3 {
leaf_1.insert_no_split(CounterI32::new(i * 2), CounterI32::new(i * 10));
leaf_2.insert_no_split(CounterI32::new((10 + i) * 2), CounterI32::new((10 + i) * 10));
leaf_3.insert_no_split(CounterI32::new((20 + i) * 2), CounterI32::new((20 + i) * 10));
}
let leaf_1_first = leaf_1.get_keys()[0].clone();
let leaf_2_first = leaf_2.get_keys()[0].clone();
let leaf_3_first = leaf_3.get_keys()[0].clone();
(*leaf_1.brothers()).next = leaf_2.get_ptr();
(*leaf_2.brothers()).prev = leaf_1.get_ptr();
(*leaf_2.brothers()).next = leaf_3.get_ptr();
(*leaf_3.brothers()).prev = leaf_2.get_ptr();
let internal_a = InterNode::<CounterI32, CounterI32>::alloc(1);
(*internal_a.child_ptr(0)) = leaf_1.get_ptr();
debug_assert_eq!(internal_a.key_count(), 0);
let internal_b = InterNode::<CounterI32, CounterI32>::alloc(1);
(*internal_b.child_ptr(0)) = leaf_2.get_ptr();
debug_assert_eq!(internal_b.key_count(), 0);
let internal_c = InterNode::<CounterI32, CounterI32>::alloc(1);
(*internal_c.child_ptr(0)) = leaf_3.get_ptr();
debug_assert_eq!(internal_c.key_count(), 0);
let mut root = InterNode::<CounterI32, CounterI32>::alloc(2);
root.set_left_ptr(internal_a.get_ptr());
root.insert_no_split(leaf_2_first, internal_b.get_ptr());
root.insert_no_split(leaf_3_first, internal_c.get_ptr());
debug_assert_eq!(root.key_count(), 2);
let mut map = BTreeMap::<CounterI32, CounterI32> {
root: Some(Node::Inter(root)),
len: 9,
cache: UnsafeCell::new(PathCache::new()),
leaf_count: 3,
#[cfg(feature = "trace_log")]
triggers: 0,
};
assert_eq!(map.height(), 3, "Tree height should be 3");
let cache = map.get_cache();
cache.clear();
let _ = map.root.as_ref().unwrap().find_leaf_with_cache(cache, &leaf_1_first);
let (popped_node, _) = cache.pop().unwrap();
assert_eq!(popped_node, internal_a);
debug_assert_eq!(popped_node.height(), 1);
debug_assert_eq!(popped_node.key_count(), 0);
let alive_before = alive_count();
println!("Alive count before handle_inter_underflow: {}", alive_before);
map.handle_inter_underflow(internal_a);
map.validate();
assert_eq!(map.height(), 3, "Tree height should remain 3");
println!("Alive count after handle_inter_underflow: {}", alive_count());
for i in 0..3 {
assert!(map.contains_key(&CounterI32::new(i * 2)), "Key {} should exist", i * 2);
assert!(
map.contains_key(&CounterI32::new((10 + i) * 2)),
"Key {} should exist",
(10 + i) * 2
);
assert!(
map.contains_key(&CounterI32::new((20 + i) * 2)),
"Key {} should exist",
(20 + i) * 2
);
}
assert_eq!(map.leaf_count, 3);
#[cfg(feature = "trace_log")]
assert_eq!(map.triggers, 0);
}
assert_eq!(alive_count(), 0, "All CounterI32 should be dropped after cleanup");
}