Skip to content

Commit 1b29082

Browse files
committed
Squashed doctests and merge test commits
1 parent 2f926de commit 1b29082

3 files changed

Lines changed: 91 additions & 5 deletions

File tree

library/alloc/src/collections/btree/map.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,12 +1243,12 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
12431243
/// Moves all elements from `other` into `self`, leaving `other` empty.
12441244
///
12451245
/// If a key from `other` is already present in `self`, then the `conflict`
1246-
/// closure is used to return a value to `self`. For clarity, the `conflict`
1246+
/// closure is used to return a value to `self`. The `conflict`
12471247
/// closure takes in a borrow of `self`'s key, `self`'s value, and `other`'s value
12481248
/// in that order.
12491249
///
12501250
/// An example of why one might use this method over [`append`]
1251-
/// is to merge `self`'s value with `other`'s value when their keys conflict.
1251+
/// is to combine `self`'s value with `other`'s value when their keys conflict.
12521252
///
12531253
/// Similar to [`insert`], though, the key is not overwritten,
12541254
/// which matters for types that can be `==` without being identical.
@@ -1278,8 +1278,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
12781278
/// format!("{a_val}{b_val}")
12791279
/// });
12801280
///
1281-
/// assert_eq!(a.len(), 5);
1282-
/// assert_eq!(b.len(), 0);
1281+
/// assert_eq!(a.len(), 5); // all of b's keys in a
12831282
///
12841283
/// assert_eq!(a[&1], "a");
12851284
/// assert_eq!(a[&2], "b");

library/alloc/src/collections/btree/map/tests.rs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use core::assert_matches;
2-
use std::iter;
32
use std::ops::Bound::{Excluded, Included, Unbounded};
43
use std::panic::{AssertUnwindSafe, catch_unwind};
54
use std::sync::atomic::AtomicUsize;
65
use std::sync::atomic::Ordering::SeqCst;
6+
use std::{cmp, iter};
77

88
use super::*;
99
use crate::boxed::Box;
@@ -2128,6 +2128,76 @@ create_append_test!(test_append_239, 239);
21282128
#[cfg(not(miri))] // Miri is too slow
21292129
create_append_test!(test_append_1700, 1700);
21302130

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+
21312201
#[test]
21322202
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
21332203
fn test_append_drop_leak() {
@@ -2615,3 +2685,19 @@ fn test_id_based_append() {
26152685

26162686
assert_eq!(lhs.pop_first().unwrap().0.name, "lhs_k".to_string());
26172687
}
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+
}

library/alloctests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(allocator_api)]
22
#![feature(binary_heap_pop_if)]
3+
#![feature(btree_merge)]
34
#![feature(const_heap)]
45
#![feature(deque_extend_front)]
56
#![feature(iter_array_chunks)]

0 commit comments

Comments
 (0)