|
1 | 1 | use core::assert_matches; |
2 | | -use std::iter; |
3 | 2 | use std::ops::Bound::{Excluded, Included, Unbounded}; |
4 | 3 | use std::panic::{AssertUnwindSafe, catch_unwind}; |
5 | 4 | use std::sync::atomic::AtomicUsize; |
6 | 5 | use std::sync::atomic::Ordering::SeqCst; |
| 6 | +use std::{cmp, iter}; |
7 | 7 |
|
8 | 8 | use super::*; |
9 | 9 | use crate::boxed::Box; |
@@ -2128,6 +2128,76 @@ create_append_test!(test_append_239, 239); |
2128 | 2128 | #[cfg(not(miri))] // Miri is too slow |
2129 | 2129 | create_append_test!(test_append_1700, 1700); |
2130 | 2130 |
|
| 2131 | +macro_rules! create_merge_test { |
| 2132 | + ($name:ident, $len:expr) => { |
| 2133 | + #[test] |
| 2134 | + fn $name() { |
| 2135 | + let mut a = BTreeMap::new(); |
| 2136 | + for i in 0..8 { |
| 2137 | + a.insert(i, i); |
| 2138 | + } |
| 2139 | + |
| 2140 | + let mut b = BTreeMap::new(); |
| 2141 | + for i in 5..$len { |
| 2142 | + b.insert(i, 2 * i); |
| 2143 | + } |
| 2144 | + |
| 2145 | + a.merge(b, |_, a_val, b_val| a_val + b_val); |
| 2146 | + |
| 2147 | + assert_eq!(a.len(), cmp::max($len, 8)); |
| 2148 | + |
| 2149 | + for i in 0..cmp::max($len, 8) { |
| 2150 | + if i < 5 { |
| 2151 | + assert_eq!(a[&i], i); |
| 2152 | + } else { |
| 2153 | + if i < cmp::min($len, 8) { |
| 2154 | + assert_eq!(a[&i], i + 2 * i); |
| 2155 | + } else if i >= $len { |
| 2156 | + assert_eq!(a[&i], i); |
| 2157 | + } else { |
| 2158 | + assert_eq!(a[&i], 2 * i); |
| 2159 | + } |
| 2160 | + } |
| 2161 | + } |
| 2162 | + |
| 2163 | + a.check(); |
| 2164 | + assert_eq!( |
| 2165 | + a.remove(&($len - 1)), |
| 2166 | + if $len >= 5 && $len < 8 { |
| 2167 | + Some(($len - 1) + 2 * ($len - 1)) |
| 2168 | + } else { |
| 2169 | + Some(2 * ($len - 1)) |
| 2170 | + } |
| 2171 | + ); |
| 2172 | + assert_eq!(a.insert($len - 1, 20), None); |
| 2173 | + a.check(); |
| 2174 | + } |
| 2175 | + }; |
| 2176 | +} |
| 2177 | + |
| 2178 | +// These are mostly for testing the algorithm that "fixes" the right edge after insertion. |
| 2179 | +// Single node, merge conflicting key values. |
| 2180 | +create_merge_test!(test_merge_7, 7); |
| 2181 | +// Single node. |
| 2182 | +create_merge_test!(test_merge_9, 9); |
| 2183 | +// Two leafs that don't need fixing. |
| 2184 | +create_merge_test!(test_merge_17, 17); |
| 2185 | +// Two leafs where the second one ends up underfull and needs stealing at the end. |
| 2186 | +create_merge_test!(test_merge_14, 14); |
| 2187 | +// Two leafs where the second one ends up empty because the insertion finished at the root. |
| 2188 | +create_merge_test!(test_merge_12, 12); |
| 2189 | +// Three levels; insertion finished at the root. |
| 2190 | +create_merge_test!(test_merge_144, 144); |
| 2191 | +// Three levels; insertion finished at leaf while there is an empty node on the second level. |
| 2192 | +create_merge_test!(test_merge_145, 145); |
| 2193 | +// Tests for several randomly chosen sizes. |
| 2194 | +create_merge_test!(test_merge_170, 170); |
| 2195 | +create_merge_test!(test_merge_181, 181); |
| 2196 | +#[cfg(not(miri))] // Miri is too slow |
| 2197 | +create_merge_test!(test_merge_239, 239); |
| 2198 | +#[cfg(not(miri))] // Miri is too slow |
| 2199 | +create_merge_test!(test_merge_1700, 1700); |
| 2200 | + |
2131 | 2201 | #[test] |
2132 | 2202 | #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] |
2133 | 2203 | fn test_append_drop_leak() { |
@@ -2615,3 +2685,19 @@ fn test_id_based_append() { |
2615 | 2685 |
|
2616 | 2686 | assert_eq!(lhs.pop_first().unwrap().0.name, "lhs_k".to_string()); |
2617 | 2687 | } |
| 2688 | + |
| 2689 | +#[test] |
| 2690 | +fn test_id_based_merge() { |
| 2691 | + let mut lhs = BTreeMap::new(); |
| 2692 | + let mut rhs = BTreeMap::new(); |
| 2693 | + |
| 2694 | + lhs.insert(IdBased { id: 0, name: "lhs_k".to_string() }, "1".to_string()); |
| 2695 | + rhs.insert(IdBased { id: 0, name: "rhs_k".to_string() }, "2".to_string()); |
| 2696 | + |
| 2697 | + lhs.merge(rhs, |_, mut lhs_val, rhs_val| { |
| 2698 | + lhs_val.push_str(&rhs_val); |
| 2699 | + lhs_val |
| 2700 | + }); |
| 2701 | + |
| 2702 | + assert_eq!(lhs.pop_first().unwrap().0.name, "lhs_k".to_string()); |
| 2703 | +} |
0 commit comments