Fix traversal and add test cases

This commit is contained in:
Sebastian Messmer 2016-07-13 00:22:35 +02:00
parent 845b0b5239
commit 508766d2f2
2 changed files with 29 additions and 2 deletions

View File

@ -32,14 +32,15 @@ namespace blobstore {
// numLeaves<beginIndex<endIndex, numLeaves<beginIndex=endIndex // numLeaves<beginIndex<endIndex, numLeaves<beginIndex=endIndex
uint32_t maxLeavesForDepth = _maxLeavesForTreeDepth(root->depth()); uint32_t maxLeavesForDepth = _maxLeavesForTreeDepth(root->depth());
bool increaseTreeDepth = endIndex > maxLeavesForDepth;
_traverseExistingSubtree(root.get(), std::min(beginIndex, maxLeavesForDepth), std::min(endIndex, maxLeavesForDepth), 0, false, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree); _traverseExistingSubtree(root.get(), std::min(beginIndex, maxLeavesForDepth), std::min(endIndex, maxLeavesForDepth), 0, increaseTreeDepth, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree);
// If the traversal goes too far right for a tree this depth, increase tree depth by one and continue traversal. // If the traversal goes too far right for a tree this depth, increase tree depth by one and continue traversal.
// This is recursive, i.e. will be repeated if the tree is still not deep enough. // This is recursive, i.e. will be repeated if the tree is still not deep enough.
// We don't increase to the full needed tree depth in one step, because we want the traversal to go as far as possible // We don't increase to the full needed tree depth in one step, because we want the traversal to go as far as possible
// and only then increase the depth - this causes the tree to be in consistent shape (balanced) for longer. // and only then increase the depth - this causes the tree to be in consistent shape (balanced) for longer.
if (endIndex > maxLeavesForDepth) { if (increaseTreeDepth) {
// TODO Test cases that increase tree depth by 0, 1, 2, ... levels // TODO Test cases that increase tree depth by 0, 1, 2, ... levels
auto newRoot = _increaseTreeDepth(std::move(root)); auto newRoot = _increaseTreeDepth(std::move(root));
return traverseAndReturnRoot(std::move(newRoot), std::max(beginIndex, maxLeavesForDepth), endIndex, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree); return traverseAndReturnRoot(std::move(newRoot), std::max(beginIndex, maxLeavesForDepth), endIndex, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree);

View File

@ -389,4 +389,30 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfFourLevelTree) {
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()+5, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() -1); TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()+5, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() -1);
} }
TEST_F(DataTreeTest_TraverseLeaves, LastLeafIsAlreadyResizedInCallback) {
auto root = CreateLeaf();
root->flush();
auto tree = treeStore.load(root->key()).value();
tree->traverseLeaves(0, 2, [this] (uint32_t leafIndex, DataLeafNode *leaf) {
if (leafIndex == 0) {
EXPECT_EQ(nodeStore->layout().maxBytesPerLeaf(), leaf->numBytes());
} else {
EXPECT_TRUE(false) << "only two nodes";
}
}, [this] (uint32_t /*nodeIndex*/) -> Data {
return Data(1);
});
}
TEST_F(DataTreeTest_TraverseLeaves, LastLeafIsAlreadyResizedInCallback_TwoLevel) {
auto root = CreateFullTwoLevelWithLastLeafSize(5);
root->flush();
auto tree = treeStore.load(root->key()).value();
tree->traverseLeaves(0, nodeStore->layout().maxChildrenPerInnerNode()+1, [this] (uint32_t leafIndex, DataLeafNode *leaf) {
EXPECT_EQ(nodeStore->layout().maxBytesPerLeaf(), leaf->numBytes());
}, [this] (uint32_t /*nodeIndex*/) -> Data {
return Data(1);
});
}
//TODO Refactor the test cases that are too long //TODO Refactor the test cases that are too long