Skip to content

Commit 284f1df

Browse files
authoredOct 15, 2020
Rollup merge of rust-lang#77612 - ssomers:btree_cleanup_2, r=Mark-Simulacrum
BTreeMap: test invariants more thoroughly and more readably r? @Mark-Simulacrum
2 parents e16dee1 + f4034eb commit 284f1df

File tree

2 files changed

+115
-79
lines changed

2 files changed

+115
-79
lines changed
 

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

+10-79
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::super::{navigate::Position, node, DeterministicRng};
1+
use super::super::{node, DeterministicRng};
22
use super::Entry::{Occupied, Vacant};
33
use super::*;
44
use crate::boxed::Box;
@@ -7,7 +7,7 @@ use crate::rc::Rc;
77
use crate::string::{String, ToString};
88
use crate::vec::Vec;
99
use std::convert::TryFrom;
10-
use std::iter::FromIterator;
10+
use std::iter::{self, FromIterator};
1111
use std::mem;
1212
use std::ops::Bound::{self, Excluded, Included, Unbounded};
1313
use std::ops::RangeBounds;
@@ -42,19 +42,6 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>
4242
}
4343
}
4444

45-
struct SeriesChecker<T> {
46-
previous: Option<T>,
47-
}
48-
49-
impl<T: Copy + Debug + Ord> SeriesChecker<T> {
50-
fn is_ascending(&mut self, next: T) {
51-
if let Some(previous) = self.previous {
52-
assert!(previous < next, "{:?} >= {:?}", previous, next);
53-
}
54-
self.previous = Some(next);
55-
}
56-
}
57-
5845
impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
5946
/// Panics if the map (or the code navigating it) is corrupted.
6047
fn check(&self)
@@ -63,44 +50,10 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
6350
{
6451
if let Some(root) = &self.root {
6552
let root_node = root.node_as_ref();
66-
let mut checker = SeriesChecker { previous: None };
67-
let mut internal_length = 0;
68-
let mut internal_kv_count = 0;
69-
let mut leaf_length = 0;
70-
root_node.visit_nodes_in_order(|pos| match pos {
71-
Position::Leaf(node) => {
72-
let is_root = root_node.height() == 0;
73-
let min_len = if is_root { 0 } else { node::MIN_LEN };
74-
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
75-
76-
for idx in 0..node.len() {
77-
let key = *unsafe { node.key_at(idx) };
78-
checker.is_ascending(key);
79-
}
80-
leaf_length += node.len();
81-
}
82-
Position::Internal(node) => {
83-
let is_root = root_node.height() == node.height();
84-
let min_len = if is_root { 1 } else { node::MIN_LEN };
85-
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
86-
87-
for idx in 0..=node.len() {
88-
let edge = unsafe { node::Handle::new_edge(node, idx) };
89-
assert!(edge.descend().ascend().ok().unwrap() == edge);
90-
}
91-
92-
internal_length += node.len();
93-
}
94-
Position::InternalKV(kv) => {
95-
let key = *kv.into_kv().0;
96-
checker.is_ascending(key);
97-
98-
internal_kv_count += 1;
99-
}
100-
});
101-
assert_eq!(internal_length, internal_kv_count);
102-
assert_eq!(root_node.calc_length(), internal_length + leaf_length);
103-
assert_eq!(self.length, internal_length + leaf_length);
53+
assert!(root_node.ascend().is_err());
54+
root_node.assert_back_pointers();
55+
root_node.assert_ascending();
56+
assert_eq!(self.length, root_node.assert_and_add_lengths());
10457
} else {
10558
assert_eq!(self.length, 0);
10659
}
@@ -116,28 +69,7 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
11669
K: Debug,
11770
{
11871
if let Some(root) = self.root.as_ref() {
119-
let mut result = String::new();
120-
let root_node = root.node_as_ref();
121-
root_node.visit_nodes_in_order(|pos| match pos {
122-
Position::Leaf(leaf) => {
123-
let depth = root_node.height();
124-
let indent = " ".repeat(depth);
125-
result += &format!("\n{}", indent);
126-
for idx in 0..leaf.len() {
127-
if idx > 0 {
128-
result += ", ";
129-
}
130-
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
131-
}
132-
}
133-
Position::Internal(_) => {}
134-
Position::InternalKV(kv) => {
135-
let depth = root_node.height() - kv.into_node().height();
136-
let indent = " ".repeat(depth);
137-
result += &format!("\n{}{:?}", indent, kv.into_kv().0);
138-
}
139-
});
140-
result
72+
root.node_as_ref().dump_keys()
14173
} else {
14274
String::from("not yet allocated")
14375
}
@@ -170,7 +102,6 @@ fn test_levels() {
170102
let last_key = *map.last_key_value().unwrap().0;
171103
map.insert(last_key + 1, ());
172104
}
173-
println!("{}", map.dump_keys());
174105
map.check();
175106
// Structure:
176107
// - 1 element in internal root node with 2 children
@@ -372,7 +303,7 @@ fn test_iter_rev() {
372303
fn do_test_iter_mut_mutation<T>(size: usize)
373304
where
374305
T: Copy + Debug + Ord + TryFrom<usize>,
375-
<T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
306+
<T as TryFrom<usize>>::Error: Debug,
376307
{
377308
let zero = T::try_from(0).unwrap();
378309
let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
@@ -857,7 +788,7 @@ mod test_drain_filter {
857788
fn consuming_nothing() {
858789
let pairs = (0..3).map(|i| (i, i));
859790
let mut map: BTreeMap<_, _> = pairs.collect();
860-
assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
791+
assert!(map.drain_filter(|_, _| false).eq(iter::empty()));
861792
map.check();
862793
}
863794

@@ -878,7 +809,7 @@ mod test_drain_filter {
878809
*v += 6;
879810
false
880811
})
881-
.eq(std::iter::empty())
812+
.eq(iter::empty())
882813
);
883814
assert!(map.keys().copied().eq(0..3));
884815
assert!(map.values().copied().eq(6..9));

‎library/alloc/src/collections/btree/node/tests.rs

+105
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,109 @@
1+
use super::super::navigate;
12
use super::*;
3+
use crate::fmt::Debug;
4+
use crate::string::String;
5+
6+
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
7+
pub fn assert_back_pointers(self) {
8+
match self.force() {
9+
ForceResult::Leaf(_) => {}
10+
ForceResult::Internal(node) => {
11+
for idx in 0..=node.len() {
12+
let edge = unsafe { Handle::new_edge(node, idx) };
13+
let child = edge.descend();
14+
assert!(child.ascend().ok() == Some(edge));
15+
child.assert_back_pointers();
16+
}
17+
}
18+
}
19+
}
20+
21+
pub fn assert_ascending(self)
22+
where
23+
K: Copy + Debug + Ord,
24+
{
25+
struct SeriesChecker<T> {
26+
previous: Option<T>,
27+
}
28+
impl<T: Copy + Debug + Ord> SeriesChecker<T> {
29+
fn is_ascending(&mut self, next: T) {
30+
if let Some(previous) = self.previous {
31+
assert!(previous < next, "{:?} >= {:?}", previous, next);
32+
}
33+
self.previous = Some(next);
34+
}
35+
}
36+
37+
let mut checker = SeriesChecker { previous: None };
38+
self.visit_nodes_in_order(|pos| match pos {
39+
navigate::Position::Leaf(node) => {
40+
for idx in 0..node.len() {
41+
let key = *unsafe { node.key_at(idx) };
42+
checker.is_ascending(key);
43+
}
44+
}
45+
navigate::Position::InternalKV(kv) => {
46+
let key = *kv.into_kv().0;
47+
checker.is_ascending(key);
48+
}
49+
navigate::Position::Internal(_) => {}
50+
});
51+
}
52+
53+
pub fn assert_and_add_lengths(self) -> usize {
54+
let mut internal_length = 0;
55+
let mut internal_kv_count = 0;
56+
let mut leaf_length = 0;
57+
self.visit_nodes_in_order(|pos| match pos {
58+
navigate::Position::Leaf(node) => {
59+
let is_root = self.height() == 0;
60+
let min_len = if is_root { 0 } else { MIN_LEN };
61+
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
62+
leaf_length += node.len();
63+
}
64+
navigate::Position::Internal(node) => {
65+
let is_root = self.height() == node.height();
66+
let min_len = if is_root { 1 } else { MIN_LEN };
67+
assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
68+
internal_length += node.len();
69+
}
70+
navigate::Position::InternalKV(_) => {
71+
internal_kv_count += 1;
72+
}
73+
});
74+
assert_eq!(internal_length, internal_kv_count);
75+
let total = internal_length + leaf_length;
76+
assert_eq!(self.calc_length(), total);
77+
total
78+
}
79+
80+
pub fn dump_keys(self) -> String
81+
where
82+
K: Debug,
83+
{
84+
let mut result = String::new();
85+
self.visit_nodes_in_order(|pos| match pos {
86+
navigate::Position::Leaf(leaf) => {
87+
let depth = self.height();
88+
let indent = " ".repeat(depth);
89+
result += &format!("\n{}", indent);
90+
for idx in 0..leaf.len() {
91+
if idx > 0 {
92+
result += ", ";
93+
}
94+
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
95+
}
96+
}
97+
navigate::Position::Internal(_) => {}
98+
navigate::Position::InternalKV(kv) => {
99+
let depth = self.height() - kv.into_node().height();
100+
let indent = " ".repeat(depth);
101+
result += &format!("\n{}{:?}", indent, kv.into_kv().0);
102+
}
103+
});
104+
result
105+
}
106+
}
2107

3108
#[test]
4109
fn test_splitpoint() {

0 commit comments

Comments
 (0)
Please sign in to comment.