[unit-tests] Add underfull nodes counting tests

This commit is contained in:
Ming-Hung Tsai 2020-08-22 16:40:33 +08:00
parent 61f07573e1
commit c932a76f08

View File

@ -28,11 +28,21 @@ namespace {
tm_(bm_, sm_) {
}
void check_nr_metadata_blocks_is_ge(unsigned n) {
block_counter bc;
size_t get_nr_metadata_blocks(bool ignore_non_fatal = false,
bool stop_on_error = false) {
block_counter bc(stop_on_error);
noop_value_counter<uint64_t> vc;
count_btree_blocks(*tree_, bc, vc);
ASSERT_THAT(bc.get_counts().size(), Ge(n));
count_btree_blocks(*tree_, bc, vc, ignore_non_fatal);
return bc.get_counts().size();
}
void damage_first_leaf_underfull() {
bcache::validator::ptr v = create_btree_node_validator();
block_address b = get_first_leaf();
block_manager::write_ref blk = bm_->write_lock(b, v);
btree<1, uint64_traits>::leaf_node n = to_node<uint64_traits>(blk);
n.set_nr_entries(1);
}
with_temp_directory dir_;
@ -53,6 +63,19 @@ namespace {
void commit() {
block_manager::write_ref superblock(bm_->superblock(SUPERBLOCK));
}
block_address get_first_leaf() {
bcache::validator::ptr v = create_btree_node_validator();
block_manager::read_ref root = bm_->read_lock(tree_->get_root(), v);
btree<1, uint64_traits>::internal_node n = to_node<block_traits>(root);
while (n.get_type() == INTERNAL) {
block_manager::read_ref internal = bm_->read_lock(n.value_at(0), v);
n = to_node<block_traits>(internal);
}
return n.get_block_nr();
}
};
}
@ -62,7 +85,7 @@ TEST_F(BTreeCounterTests, count_empty_tree)
{
tree_.reset(new btree<1, uint64_traits>(tm_, rc_));
tm_.get_bm()->flush();
check_nr_metadata_blocks_is_ge(1);
ASSERT_GE(get_nr_metadata_blocks(), 1u);
}
TEST_F(BTreeCounterTests, count_populated_tree)
@ -75,7 +98,44 @@ TEST_F(BTreeCounterTests, count_populated_tree)
}
tm_.get_bm()->flush();
check_nr_metadata_blocks_is_ge(40);
ASSERT_GE(get_nr_metadata_blocks(), 40u);
}
TEST_F(BTreeCounterTests, count_underfull_nodes)
{
tree_.reset(new btree<1, uint64_traits>(tm_, rc_));
for (unsigned i = 0; i < 10000; i++) {
uint64_t key[1] = {i};
tree_->insert(key, 0ull);
}
tm_.get_bm()->flush();
size_t nr_blocks = get_nr_metadata_blocks();
damage_first_leaf_underfull();
tm_.get_bm()->flush();
// underfull nodes are not counted
bool ignore_non_fatal = false;
bool stop_on_error = false;
ASSERT_EQ(get_nr_metadata_blocks(ignore_non_fatal, stop_on_error), nr_blocks - 1);
// underfull nodes are counted
ignore_non_fatal = true;
stop_on_error = false;
ASSERT_EQ(get_nr_metadata_blocks(ignore_non_fatal, stop_on_error), nr_blocks);
// logical errors like underfull nodes don't result in exceptions,
// therefore the stop_on_error flag has no effect.
// FIXME: is it necessary to stop the counting on logical errors?
ignore_non_fatal = false;
stop_on_error = true;
ASSERT_EQ(get_nr_metadata_blocks(ignore_non_fatal, stop_on_error), nr_blocks - 1);
ignore_non_fatal = true;
stop_on_error = true;
ASSERT_EQ(get_nr_metadata_blocks(ignore_non_fatal, stop_on_error), nr_blocks);
}
//----------------------------------------------------------------