Removed DataTree::addDataLeaf() / DataTree::removeLastDataLeaf() and DataTree::flush()
This commit is contained in:
parent
c0e5b5db8c
commit
5fb235a40c
@ -1,6 +1,7 @@
|
||||
# Biicode configuration file
|
||||
|
||||
[requirements]
|
||||
google/gmock: 2
|
||||
google/gtest: 10
|
||||
messmer/blockstore: 1
|
||||
messmer/cmake: 3
|
||||
|
@ -31,10 +31,6 @@ void BlobOnBlocks::resize(uint64_t numBytes) {
|
||||
_datatree->resizeNumBytes(numBytes);
|
||||
}
|
||||
|
||||
void BlobOnBlocks::flush() const {
|
||||
_datatree->flush();
|
||||
}
|
||||
|
||||
void BlobOnBlocks::traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, function<void (uint64_t, void *, uint32_t)> func) const {
|
||||
uint64_t endByte = beginByte + sizeBytes;
|
||||
assert(endByte <= size());
|
||||
|
@ -28,8 +28,6 @@ public:
|
||||
void read(void *target, uint64_t offset, uint64_t size) const override;
|
||||
void write(const void *source, uint64_t offset, uint64_t size) override;
|
||||
|
||||
void flush() const override;
|
||||
|
||||
private:
|
||||
void traverseLeaves(uint64_t offsetBytes, uint64_t sizeBytes, std::function<void (uint64_t, void *, uint32_t)>) const;
|
||||
|
||||
|
@ -109,14 +109,21 @@ unique_ptr<DataNode> DataTree::releaseRootNode() {
|
||||
}
|
||||
|
||||
void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function<void (DataLeafNode*, uint32_t)> func) {
|
||||
const_cast<const DataTree*>(this)->traverseLeaves(beginIndex, endIndex, [func](const DataLeafNode* leaf, uint32_t leafIndex) {
|
||||
func(const_cast<DataLeafNode*>(leaf), leafIndex);
|
||||
});
|
||||
flush();
|
||||
}
|
||||
|
||||
void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function<void (const DataLeafNode*, uint32_t)> func) const {
|
||||
assert(beginIndex <= endIndex);
|
||||
//TODO assert(beginIndex <= numLeaves());
|
||||
//TODO assert(endIndex <= numLeaves());
|
||||
traverseLeaves(_rootNode.get(), 0, beginIndex, endIndex, func);
|
||||
}
|
||||
|
||||
void DataTree::traverseLeaves(DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, function<void (DataLeafNode*, uint32_t)> func) {
|
||||
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root);
|
||||
void DataTree::traverseLeaves(const DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, function<void (const DataLeafNode*, uint32_t)> func) const {
|
||||
const DataLeafNode *leaf = dynamic_cast<const DataLeafNode*>(root);
|
||||
if (leaf != nullptr) {
|
||||
assert(beginIndex <= 1 && endIndex <= 1);
|
||||
if (beginIndex == 0 && endIndex == 1) {
|
||||
@ -125,7 +132,7 @@ void DataTree::traverseLeaves(DataNode *root, uint32_t leafOffset, uint32_t begi
|
||||
return;
|
||||
}
|
||||
|
||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root);
|
||||
const DataInnerNode *inner = dynamic_cast<const DataInnerNode*>(root);
|
||||
uint32_t leavesPerChild = leavesPerFullChild(*inner);
|
||||
uint32_t beginChild = beginIndex/leavesPerChild;
|
||||
uint32_t endChild = utils::ceilDivision(endIndex, leavesPerChild);
|
||||
@ -179,6 +186,7 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
|
||||
LastLeaf(_rootNode.get())->resize(newLastLeafSize);
|
||||
|
||||
assert(newNumBytes == numStoredBytes());
|
||||
flush();
|
||||
}
|
||||
|
||||
optional_ownership_ptr<DataLeafNode> DataTree::LastLeaf(DataNode *root) {
|
||||
|
@ -26,24 +26,22 @@ public:
|
||||
DataTree(datanodestore::DataNodeStore *nodeStore, std::unique_ptr<datanodestore::DataNode> rootNode);
|
||||
virtual ~DataTree();
|
||||
|
||||
//TODO Might be that we don't need addDataLeaf()/removeDataLeaf() to be public anymore
|
||||
std::unique_ptr<datanodestore::DataLeafNode> addDataLeaf();
|
||||
void removeLastDataLeaf();
|
||||
|
||||
const blockstore::Key &key() const;
|
||||
uint32_t maxBytesPerLeaf() const;
|
||||
|
||||
//TODO Remove flush() and instead call it implicitly on traverseLeaves()/resizeNumBytes()
|
||||
void flush() const;
|
||||
|
||||
void traverseLeaves(uint32_t beginIndex, uint32_t endIndex, std::function<void (const datanodestore::DataLeafNode*, uint32_t)> func) const;
|
||||
void traverseLeaves(uint32_t beginIndex, uint32_t endIndex, std::function<void (datanodestore::DataLeafNode*, uint32_t)> func);
|
||||
uint64_t numStoredBytes() const;
|
||||
void resizeNumBytes(uint64_t newNumBytes);
|
||||
|
||||
uint64_t numStoredBytes() const;
|
||||
|
||||
private:
|
||||
datanodestore::DataNodeStore *_nodeStore;
|
||||
std::unique_ptr<datanodestore::DataNode> _rootNode;
|
||||
|
||||
std::unique_ptr<datanodestore::DataLeafNode> addDataLeaf();
|
||||
void removeLastDataLeaf();
|
||||
|
||||
std::unique_ptr<datanodestore::DataNode> releaseRootNode();
|
||||
friend class DataTreeStore;
|
||||
|
||||
@ -54,12 +52,14 @@ private:
|
||||
void deleteLastChildSubtree(datanodestore::DataInnerNode *node);
|
||||
void ifRootHasOnlyOneChildReplaceRootWithItsChild();
|
||||
|
||||
void traverseLeaves(datanodestore::DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, std::function<void (datanodestore::DataLeafNode*, uint32_t)> func);
|
||||
void traverseLeaves(const datanodestore::DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, std::function<void (const datanodestore::DataLeafNode*, uint32_t)> func) const;
|
||||
uint32_t leavesPerFullChild(const datanodestore::DataInnerNode &root) const;
|
||||
uint64_t numStoredBytes(const datanodestore::DataNode &root) const;
|
||||
cpputils::optional_ownership_ptr<datanodestore::DataLeafNode> LastLeaf(datanodestore::DataNode *root);
|
||||
std::unique_ptr<datanodestore::DataLeafNode> LastLeaf(std::unique_ptr<datanodestore::DataNode> root);
|
||||
|
||||
void flush() const;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DataTree);
|
||||
};
|
||||
|
||||
|
@ -23,8 +23,6 @@ public:
|
||||
|
||||
virtual void read(void *target, uint64_t offset, uint64_t size) const = 0;
|
||||
virtual void write(const void *source, uint64_t offset, uint64_t size) = 0;
|
||||
|
||||
virtual void flush() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ TEST_F(DataTreeStoreTest, CreatedTreeIsLoadable) {
|
||||
|
||||
TEST_F(DataTreeStoreTest, NewTreeIsLeafOnly) {
|
||||
auto tree = treeStore.createNewTree();
|
||||
tree->flush();
|
||||
|
||||
EXPECT_IS_LEAF_NODE(tree->key());
|
||||
}
|
||||
|
@ -163,13 +163,11 @@ INSTANTIATE_TEST_CASE_P(DataTreeTest_ResizeNumBytes_P, DataTreeTest_ResizeNumByt
|
||||
|
||||
TEST_P(DataTreeTest_ResizeNumBytes_P, StructureIsValid) {
|
||||
tree->resizeNumBytes(newSize);
|
||||
tree->flush();
|
||||
EXPECT_IS_LEFTMAXDATA_TREE(tree->key());
|
||||
}
|
||||
|
||||
TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) {
|
||||
tree->resizeNumBytes(newSize);
|
||||
tree->flush();
|
||||
// tree->numStoredBytes() only goes down the right border nodes and expects the tree to be a left max data tree.
|
||||
// This is what the StructureIsValid test case is for.
|
||||
EXPECT_EQ(newSize, tree->numStoredBytes());
|
||||
@ -177,7 +175,6 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) {
|
||||
|
||||
TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) {
|
||||
tree->resizeNumBytes(newSize);
|
||||
tree->flush();
|
||||
uint32_t depth = ceil(log(newNumberOfLeaves)/log(DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode()));
|
||||
CHECK_DEPTH(depth, tree->key());
|
||||
}
|
||||
@ -185,7 +182,6 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) {
|
||||
TEST_P(DataTreeTest_ResizeNumBytes_P, KeyDoesntChange) {
|
||||
Key key = tree->key();
|
||||
tree->resizeNumBytes(newSize);
|
||||
tree->flush();
|
||||
EXPECT_EQ(key, tree->key());
|
||||
}
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
#include "testutils/DataTreeGrowingTest.h"
|
||||
|
||||
#include "../../../../testutils/DataBlockFixture.h"
|
||||
#include <messmer/cpp-utils/pointer.h>
|
||||
|
||||
using ::testing::WithParamInterface;
|
||||
using ::testing::Values;
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
|
||||
using cpputils::dynamic_pointer_move;
|
||||
using namespace blobstore::onblocks::datatreestore;
|
||||
|
||||
using blobstore::onblocks::datanodestore::DataNode;
|
||||
using blobstore::onblocks::datanodestore::DataNodeStore;
|
||||
using blobstore::onblocks::datanodestore::DataInnerNode;
|
||||
using blobstore::onblocks::datanodestore::DataLeafNode;
|
||||
using blockstore::Key;
|
||||
|
||||
TEST_F(DataTreeGrowingTest, GrowAOneNodeTree_FlushingWorks) {
|
||||
//Tests that after calling flush(), the complete grown tree structure is written to the blockstore
|
||||
auto tree = CreateLeafOnlyTree();
|
||||
tree->addDataLeaf();
|
||||
tree->flush();
|
||||
|
||||
EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(2, tree->key());
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
#include "testutils/DataTreeGrowingTest.h"
|
||||
#include "../testutils/LeafDataFixture.h"
|
||||
#include "../testutils/TwoLevelDataFixture.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
|
||||
using ::testing::WithParamInterface;
|
||||
using ::testing::Values;
|
||||
|
||||
using namespace blobstore::onblocks::datanodestore;
|
||||
using namespace blobstore::onblocks::datatreestore;
|
||||
|
||||
using blockstore::Key;
|
||||
using cpputils::dynamic_pointer_move;
|
||||
|
||||
class DataTreeGrowingTest_DataStaysIntact: public DataTreeGrowingTest {
|
||||
public:
|
||||
unique_ptr<DataTree> TreeWithData(unique_ptr<DataNode> root, TwoLevelDataFixture *data) {
|
||||
data->FillInto(root.get());
|
||||
Key key = root->key();
|
||||
root.reset();
|
||||
return treeStore.load(key);
|
||||
}
|
||||
|
||||
void TestDataStaysIntactOnGrowing(unique_ptr<DataNode> root, TwoLevelDataFixture *data) {
|
||||
uint32_t numLeaves = countLeaves(root.get());
|
||||
auto tree = TreeWithData(std::move(root), data);
|
||||
tree->addDataLeaf();
|
||||
tree->flush();
|
||||
|
||||
data->EXPECT_DATA_CORRECT(nodeStore->load(tree->key()).get(), numLeaves);
|
||||
}
|
||||
|
||||
uint32_t countLeaves(DataNode *node) {
|
||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(node);
|
||||
if (inner == nullptr) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t result = 0;
|
||||
for(int i = 0; i < inner->numChildren(); ++i) {
|
||||
result += countLeaves(nodeStore->load(inner->getChild(i)->key()).get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAFullTwoLevelTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnGrowing(CreateFullTwoLevel(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAFullTwoLevelTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnGrowing(CreateFullTwoLevel(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeLevelTreeWithLowerLevelFull_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
auto node = CreateInner({CreateFullTwoLevel()});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeLevelTreeWithLowerLevelFull_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
auto node = CreateInner({CreateFullTwoLevel()});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAOneNodeTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnGrowing(CreateLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAOneNodeTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnGrowing(CreateLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowATwoNodeTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
auto node = CreateInner({CreateLeaf()});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowATwoNodeTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
auto node = CreateInner({CreateLeaf()});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeNodeChainedTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
auto node = CreateInner({CreateInner({CreateLeaf()})});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeNodeChainedTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
auto node = CreateInner({CreateInner({CreateLeaf()})});
|
||||
TestDataStaysIntactOnGrowing(std::move(node), &data);
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
#include "testutils/DataTreeGrowingTest.h"
|
||||
|
||||
using blockstore::Key;
|
||||
|
||||
class DataTreeGrowingTest_DepthFlags: public DataTreeGrowingTest {
|
||||
public:
|
||||
};
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAOneNodeTree) {
|
||||
auto key = CreateTreeAddOneLeafReturnRootKey();
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowATwoNodeTree) {
|
||||
auto key = CreateTreeAddTwoLeavesReturnRootKey();
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowATwoLevelThreeNodeTree) {
|
||||
auto key = CreateTreeAddThreeLeavesReturnRootKey();
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAThreeNodeChainedTree) {
|
||||
auto key = CreateThreeNodeChainedTreeReturnRootKey();
|
||||
AddLeafTo(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAFullTwoLevelTree) {
|
||||
auto key = CreateFullTwoLevel()->key();
|
||||
AddLeafTo(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAThreeLevelTreeWithLowerLevelFull) {
|
||||
auto key = CreateThreeLevelTreeWithLowerLevelFullReturnRootKey();
|
||||
AddLeafTo(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAFullThreeLevelTree) {
|
||||
auto key = CreateFullThreeLevel()->key();
|
||||
AddLeafTo(key);
|
||||
CHECK_DEPTH(3, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_DepthFlags, GrowAThreeLevelTreeWithTwoFullSubtrees) {
|
||||
auto key = CreateThreeLevelTreeWithTwoFullSubtrees();
|
||||
AddLeafTo(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
#include "testutils/DataTreeGrowingTest.h"
|
||||
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
|
||||
class DataTreeGrowingTest_KeyDoesntChange: public DataTreeGrowingTest {
|
||||
public:
|
||||
void EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(const blockstore::Key &key) {
|
||||
auto tree = treeStore.load(key);
|
||||
tree->addDataLeaf();
|
||||
EXPECT_EQ(key, tree->key());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAOneNodeTree) {
|
||||
auto key = CreateLeafOnlyTree()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowATwoNodeTree) {
|
||||
auto key = CreateTreeAddOneLeafReturnRootKey();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowATwoLevelThreeNodeTree) {
|
||||
auto key = CreateTreeAddTwoLeavesReturnRootKey();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAThreeNodeChainedTree) {
|
||||
auto root_key = CreateThreeNodeChainedTreeReturnRootKey();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAThreeLevelTreeWithLowerLevelFull) {
|
||||
auto root_key = CreateThreeLevelTreeWithLowerLevelFullReturnRootKey();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAFullTwoLevelTree) {
|
||||
auto root_key = CreateFullTwoLevel()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAFullThreeLevelTree) {
|
||||
auto root_key = CreateFullThreeLevel()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_KeyDoesntChange, GrowAThreeLevelTreeWithTwoFullSubtrees) {
|
||||
auto root_key = CreateThreeLevelTreeWithTwoFullSubtrees();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
#include "testutils/DataTreeGrowingTest.h"
|
||||
|
||||
using blobstore::onblocks::datanodestore::DataInnerNode;
|
||||
using blockstore::Key;
|
||||
|
||||
class DataTreeGrowingTest_Structure: public DataTreeGrowingTest {};
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAOneNodeTree) {
|
||||
auto key = CreateTreeAddOneLeafReturnRootKey();
|
||||
EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowATwoNodeTree) {
|
||||
auto key = CreateTreeAddTwoLeavesReturnRootKey();
|
||||
EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(3, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowATwoLevelThreeNodeTree) {
|
||||
auto key = CreateTreeAddThreeLeavesReturnRootKey();
|
||||
EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(4, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAThreeNodeChainedTree) {
|
||||
auto key = CreateThreeNodeChainedTreeReturnRootKey();
|
||||
AddLeafTo(key);
|
||||
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(1u, root->numChildren());
|
||||
|
||||
EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(2, root->getChild(0)->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAFullTwoLevelTreeFromGroundUp) {
|
||||
auto key = CreateLeafOnlyTree()->key();
|
||||
for (int i = 1; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||
AddLeafTo(key);
|
||||
}
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAFullTwoLevelTree) {
|
||||
auto root_key = CreateFullTwoLevel()->key();
|
||||
AddLeafTo(root_key);
|
||||
|
||||
auto root = LoadInnerNode(root_key);
|
||||
EXPECT_EQ(2u, root->numChildren());
|
||||
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAThreeLevelTreeWithLowerLevelFull) {
|
||||
auto root_key = CreateThreeLevelTreeWithLowerLevelFullReturnRootKey();
|
||||
AddLeafTo(root_key);
|
||||
|
||||
auto root = LoadInnerNode(root_key);
|
||||
EXPECT_EQ(2u, root->numChildren());
|
||||
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAFullThreeLevelTreeFromGroundUp) {
|
||||
auto key = CreateLeafOnlyTree()->key();
|
||||
for (int i = 1; i < nodeStore->layout().maxChildrenPerInnerNode() * nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||
AddLeafTo(key);
|
||||
}
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAFullThreeLevelTree) {
|
||||
auto root_key = CreateFullThreeLevel()->key();
|
||||
AddLeafTo(root_key);
|
||||
|
||||
auto root = LoadInnerNode(root_key);
|
||||
EXPECT_EQ(2u, root->numChildren());
|
||||
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_THREENODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAThreeLevelTreeWithTwoFullSubtreesFromGroundUp) {
|
||||
auto key = CreateLeafOnlyTree()->key();
|
||||
for (int i = 1; i < 2 * nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||
AddLeafTo(key);
|
||||
}
|
||||
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2u, root->numChildren());
|
||||
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeGrowingTest_Structure, GrowAThreeLevelTreeWithTwoFullSubtrees) {
|
||||
auto key = CreateThreeLevelTreeWithTwoFullSubtrees();
|
||||
AddLeafTo(key);
|
||||
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(3u, root->numChildren());
|
||||
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(1)->key());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(2)->key());
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
#include "DataTreeGrowingTest.h"
|
||||
#include <messmer/cpp-utils/pointer.h>
|
||||
|
||||
using namespace blobstore::onblocks::datanodestore;
|
||||
|
||||
using std::unique_ptr;
|
||||
using cpputils::dynamic_pointer_move;
|
||||
using blockstore::Key;
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
|
||||
Key DataTreeGrowingTest::CreateTreeAddOneLeafReturnRootKey() {
|
||||
auto tree = CreateLeafOnlyTree();
|
||||
auto key = tree->key();
|
||||
tree->addDataLeaf();
|
||||
return key;
|
||||
}
|
||||
|
||||
Key DataTreeGrowingTest::CreateTreeAddTwoLeavesReturnRootKey() {
|
||||
auto tree = CreateLeafOnlyTree();
|
||||
auto key = tree->key();
|
||||
tree->addDataLeaf();
|
||||
tree->addDataLeaf();
|
||||
return key;
|
||||
}
|
||||
|
||||
Key DataTreeGrowingTest::CreateTreeAddThreeLeavesReturnRootKey() {
|
||||
auto tree = CreateLeafOnlyTree();
|
||||
auto key = tree->key();
|
||||
tree->addDataLeaf();
|
||||
tree->addDataLeaf();
|
||||
tree->addDataLeaf();
|
||||
return key;
|
||||
}
|
||||
|
||||
Key DataTreeGrowingTest::CreateThreeNodeChainedTreeReturnRootKey() {
|
||||
return CreateInner({CreateInner({CreateLeaf()})})->key();
|
||||
}
|
||||
|
||||
Key DataTreeGrowingTest::CreateThreeLevelTreeWithLowerLevelFullReturnRootKey() {
|
||||
return CreateInner({CreateFullTwoLevel()})->key();
|
||||
}
|
||||
|
||||
Key DataTreeGrowingTest::CreateThreeLevelTreeWithTwoFullSubtrees() {
|
||||
return CreateInner({CreateFullTwoLevel(), CreateFullTwoLevel()})->key();
|
||||
}
|
||||
|
||||
void DataTreeGrowingTest::AddLeafTo(const Key &key) {
|
||||
treeStore.load(key)->addDataLeaf();
|
||||
}
|
||||
|
||||
void DataTreeGrowingTest::EXPECT_IS_THREENODE_CHAIN(const Key &key) {
|
||||
auto node1 = LoadInnerNode(key);
|
||||
EXPECT_EQ(1u, node1->numChildren());
|
||||
auto node2 = LoadInnerNode(node1->getChild(0)->key());
|
||||
EXPECT_EQ(1u, node2->numChildren());
|
||||
EXPECT_IS_LEAF_NODE(node2->getChild(0)->key());
|
||||
}
|
||||
|
||||
void DataTreeGrowingTest::EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(unsigned int expectedNumberOfLeaves, const Key &key) {
|
||||
auto node = LoadInnerNode(key);
|
||||
EXPECT_EQ(expectedNumberOfLeaves, node->numChildren());
|
||||
for(unsigned int i=0;i<expectedNumberOfLeaves;++i) {
|
||||
EXPECT_IS_LEAF_NODE(node->getChild(i)->key());
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef BLOCKS_MESSMER_BLOBSTORE_TEST_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_GROWING_DATATREEGROWINGTEST_H_
|
||||
#define BLOCKS_MESSMER_BLOBSTORE_TEST_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_GROWING_DATATREEGROWINGTEST_H_
|
||||
|
||||
#include "../../testutils/DataTreeTest.h"
|
||||
|
||||
#include "../../../../../../implementations/onblocks/datanodestore/DataLeafNode.h"
|
||||
#include "../../../../../../implementations/onblocks/datanodestore/DataInnerNode.h"
|
||||
|
||||
class DataTreeGrowingTest: public DataTreeTest {
|
||||
public:
|
||||
|
||||
blockstore::Key CreateTreeAddOneLeafReturnRootKey();
|
||||
blockstore::Key CreateTreeAddTwoLeavesReturnRootKey();
|
||||
blockstore::Key CreateTreeAddThreeLeavesReturnRootKey();
|
||||
blockstore::Key CreateThreeNodeChainedTreeReturnRootKey();
|
||||
blockstore::Key CreateThreeLevelTreeWithLowerLevelFullReturnRootKey();
|
||||
blockstore::Key CreateThreeLevelTreeWithTwoFullSubtrees();
|
||||
void AddLeafTo(const blockstore::Key &key);
|
||||
|
||||
void EXPECT_IS_THREENODE_CHAIN(const blockstore::Key &key);
|
||||
void EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(unsigned int expectedNumberOfLeaves, const blockstore::Key &key);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,49 +0,0 @@
|
||||
#include "testutils/DataTreeShrinkingTest.h"
|
||||
|
||||
using ::testing::WithParamInterface;
|
||||
using ::testing::Values;
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
|
||||
using cpputils::dynamic_pointer_move;
|
||||
using namespace blobstore::onblocks::datatreestore;
|
||||
|
||||
using blobstore::onblocks::datanodestore::DataNode;
|
||||
using blobstore::onblocks::datanodestore::DataNodeStore;
|
||||
using blobstore::onblocks::datanodestore::DataInnerNode;
|
||||
using blobstore::onblocks::datanodestore::DataLeafNode;
|
||||
using blockstore::Key;
|
||||
|
||||
TEST_F(DataTreeShrinkingTest, ShrinkingALeafOnlyTreeCrashes) {
|
||||
Key key = CreateLeafOnlyTree()->key();
|
||||
auto tree = treeStore.load(key);
|
||||
EXPECT_DEATH(tree->removeLastDataLeaf(), "");
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest, ShrinkATwoLeafTree_FlushingWorks) {
|
||||
//Tests that after calling flush(), the complete grown tree structure is written to the blockstore
|
||||
auto tree = CreateTwoLeafTree();
|
||||
tree->removeLastDataLeaf();
|
||||
tree->flush();
|
||||
|
||||
EXPECT_IS_LEAF_NODE(tree->key());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest, ShrinkATwoLeafTree_LastLeafBlockIsDeleted) {
|
||||
auto tree = CreateTwoLeafTree();
|
||||
tree->flush();
|
||||
auto lastChildKey = LoadInnerNode(tree->key())->getChild(1)->key();
|
||||
|
||||
tree->removeLastDataLeaf();
|
||||
EXPECT_EQ(nullptr, nodeStore->load(lastChildKey));
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest, ShrinkATwoLeafTree_IntermediateBlocksAreDeleted) {
|
||||
auto tree = CreateTwoLeafTree();
|
||||
tree->flush();
|
||||
auto firstChildKey = LoadInnerNode(tree->key())->getChild(0)->key();
|
||||
|
||||
tree->removeLastDataLeaf();
|
||||
EXPECT_EQ(nullptr, nodeStore->load(firstChildKey));
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
#include "testutils/DataTreeShrinkingTest.h"
|
||||
#include "../testutils/TwoLevelDataFixture.h"
|
||||
|
||||
using blobstore::onblocks::datanodestore::DataInnerNode;
|
||||
using blobstore::onblocks::datanodestore::DataNode;
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
using blockstore::Key;
|
||||
|
||||
using std::make_unique;
|
||||
using std::unique_ptr;
|
||||
using std::function;
|
||||
|
||||
class DataTreeShrinkingTest_DataStaysIntact: public DataTreeShrinkingTest {
|
||||
public:
|
||||
unique_ptr<DataTree> TreeWithData(unique_ptr<DataNode> root, TwoLevelDataFixture *data) {
|
||||
data->FillInto(root.get());
|
||||
Key key = root->key();
|
||||
root.reset();
|
||||
return treeStore.load(key);
|
||||
}
|
||||
|
||||
void TestDataStaysIntactOnShrinking(unique_ptr<DataInnerNode> root, TwoLevelDataFixture *data) {
|
||||
auto tree = TreeWithData(std::move(root), data);
|
||||
tree->removeLastDataLeaf();
|
||||
tree->flush();
|
||||
|
||||
data->EXPECT_DATA_CORRECT(nodeStore->load(tree->key()).get());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoLeafTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoLeafTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourNodeThreeLeafTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateFourNodeThreeLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourNodeThreeLeafTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateFourNodeThreeLeaf(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeOneTwoLeavesTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeOneTwoLeaves(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeOneTwoLeavesTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeOneTwoLeaves(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeTwoOneLeavesTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeTwoOneLeaves(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeTwoOneLeavesTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeTwoOneLeaves(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelMinDataTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateThreeLevelMinData(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelMinDataTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateThreeLevelMinData(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelMinDataTree_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelMinData(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelMinDataTree_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelMinData(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves1_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves1(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves1_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves1(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves2_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves2(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves2_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves2(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot_FullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
|
||||
TestDataStaysIntactOnShrinking(CreateThreeLevelWithThreeChildrenOfRoot(), &data);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot_NonFullLeaves) {
|
||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
|
||||
TestDataStaysIntactOnShrinking(CreateThreeLevelWithThreeChildrenOfRoot(), &data);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#include "testutils/DataTreeShrinkingTest.h"
|
||||
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
using blockstore::Key;
|
||||
|
||||
class DataTreeShrinkingTest_DepthFlags: public DataTreeShrinkingTest {
|
||||
public:
|
||||
};
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkATwoLeafTree) {
|
||||
auto key = CreateTwoLeaf()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(0, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAFourNodeThreeLeafTree) {
|
||||
auto key = CreateFourNodeThreeLeaf()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkATwoInnerNodeOneTwoLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeOneTwoLeaves()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkATwoInnerNodeTwoOneLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeTwoOneLeaves()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAThreeLevelMinDataTree) {
|
||||
auto key = CreateThreeLevelMinData()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(1, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAFourLevelMinDataTree) {
|
||||
auto key = CreateFourLevelMinData()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAFourLevelTreeWithTwoSiblingLeaves1) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves1()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(3, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAFourLevelTreeWithTwoSiblingLeaves2) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves2()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(3, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel) {
|
||||
auto key = CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(3, key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_DepthFlags, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot) {
|
||||
auto key = CreateThreeLevelWithThreeChildrenOfRoot()->key();
|
||||
Shrink(key);
|
||||
CHECK_DEPTH(2, key);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
#include "testutils/DataTreeShrinkingTest.h"
|
||||
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
using blockstore::Key;
|
||||
|
||||
class DataTreeShrinkingTest_KeyDoesntChange: public DataTreeShrinkingTest {
|
||||
public:
|
||||
void EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(const Key &key) {
|
||||
auto tree = treeStore.load(key);
|
||||
tree->removeLastDataLeaf();
|
||||
EXPECT_EQ(key, tree->key());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkATwoLeafTree) {
|
||||
auto key = CreateTwoLeaf()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAFourNodeThreeLeafTree) {
|
||||
auto key = CreateFourNodeThreeLeaf()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkATwoInnerNodeOneTwoLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeOneTwoLeaves()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkATwoInnerNodeTwoOneLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeTwoOneLeaves()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAThreeLevelMinDataTree) {
|
||||
auto key = CreateThreeLevelMinData()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAFourLevelMinDataTree) {
|
||||
auto key = CreateFourLevelMinData()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAFourLevelTreeWithTwoSiblingLeaves1) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves1()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAFourLevelTreeWithTwoSiblingLeaves2) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves2()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel) {
|
||||
auto key = CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_KeyDoesntChange, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot) {
|
||||
auto key = CreateThreeLevelWithThreeChildrenOfRoot()->key();
|
||||
EXPECT_KEY_DOESNT_CHANGE_WHEN_SHRINKING(key);
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
#include "testutils/DataTreeShrinkingTest.h"
|
||||
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
using blobstore::onblocks::datanodestore::DataInnerNode;
|
||||
using blockstore::Key;
|
||||
|
||||
class DataTreeShrinkingTest_Structure: public DataTreeShrinkingTest {
|
||||
public:
|
||||
void EXPECT_IS_LEAF_ONLY_TREE(const Key &key) {
|
||||
EXPECT_IS_LEAF_NODE(key);
|
||||
}
|
||||
|
||||
void EXPECT_IS_TWO_LEAF_TREE(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_LEAF_NODE(root->getChild(0)->key());
|
||||
EXPECT_IS_LEAF_NODE(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_TWO_INNER_NODE_TREE_WITH_ONE_LEAF_EACH(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(0)->key());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_THREE_NODE_CHAIN(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(1, root->numChildren());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(0)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_THREELEVEL_MINDATA_TREE(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_TWONODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_FOURLEVEL_MINDATA_TREE(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_THREE_NODE_CHAIN(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_TREE_WITH_FIRST_CHILD_OF_ROOT_FULL_THREELEVEL_AND_SECOND_CHILD_MINDATA_THREELEVEL_TREE(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_THREELEVEL_MINDATA_TREE(root->getChild(1)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_TREE_WITH_FIRST_CHILD_OF_ROOT_FULL_THREELEVEL_AND_SECOND_CHILD_FULL_TWOLEVEL_TREE(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(root->getChild(0)->key());
|
||||
|
||||
auto secondChild = LoadInnerNode(root->getChild(1)->key());
|
||||
EXPECT_EQ(1, secondChild->numChildren());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(secondChild->getChild(0)->key());
|
||||
}
|
||||
|
||||
void EXPECT_IS_THREELEVEL_TREE_WITH_TWO_FULL_TWOLEVEL_TREES(const Key &key) {
|
||||
auto root = LoadInnerNode(key);
|
||||
EXPECT_EQ(2, root->numChildren());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(0)->key());
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(root->getChild(1)->key());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkATwoLeafTree) {
|
||||
auto key = CreateTwoLeaf()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_LEAF_ONLY_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFourNodeThreeLeafTree) {
|
||||
auto key = CreateFourNodeThreeLeaf()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_TWO_LEAF_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkATwoInnerNodeOneTwoLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeOneTwoLeaves()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_TWO_INNER_NODE_TREE_WITH_ONE_LEAF_EACH(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkATwoInnerNodeTwoOneLeavesTree) {
|
||||
auto key = CreateTwoInnerNodeTwoOneLeaves()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_TWO_LEAF_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAThreeLevelMinDataTree) {
|
||||
auto key = CreateThreeLevelMinData()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_FULL_TWOLEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFourLevelMinDataTree) {
|
||||
auto key = CreateFourLevelMinData()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_FULL_THREELEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFourLevelTreeWithTwoSiblingLeaves1) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves1()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_FOURLEVEL_MINDATA_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFourLevelTreeWithTwoSiblingLeaves2) {
|
||||
auto key = CreateFourLevelWithTwoSiblingLeaves2()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_TREE_WITH_FIRST_CHILD_OF_ROOT_FULL_THREELEVEL_AND_SECOND_CHILD_MINDATA_THREELEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel) {
|
||||
auto key = CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_TREE_WITH_FIRST_CHILD_OF_ROOT_FULL_THREELEVEL_AND_SECOND_CHILD_FULL_TWOLEVEL_TREE(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot) {
|
||||
auto key = CreateThreeLevelWithThreeChildrenOfRoot()->key();
|
||||
Shrink(key);
|
||||
EXPECT_IS_THREELEVEL_TREE_WITH_TWO_FULL_TWOLEVEL_TREES(key);
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFullTwoLevelTreeDownToOneLeaf) {
|
||||
auto key = CreateFullTwoLevel()->key();
|
||||
for (int i = 0; i < nodeStore->layout().maxChildrenPerInnerNode()-1; ++i) {
|
||||
Shrink(key);
|
||||
}
|
||||
EXPECT_IS_LEAF_NODE(key);
|
||||
EXPECT_EQ(1, nodeStore->numNodes());
|
||||
}
|
||||
|
||||
TEST_F(DataTreeShrinkingTest_Structure, ShrinkAFullThreeLevelTreeDownToOneLeaf) {
|
||||
auto key = CreateFullThreeLevel()->key();
|
||||
for (int i = 0; i < nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode()-1; ++i) {
|
||||
Shrink(key);
|
||||
}
|
||||
EXPECT_IS_LEAF_NODE(key);
|
||||
EXPECT_EQ(1, nodeStore->numNodes());
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
#include <messmer/blobstore/test/implementations/onblocks/datatreestore/shrinking/testutils/DataTreeShrinkingTest.h>
|
||||
|
||||
using namespace blobstore::onblocks::datanodestore;
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using cpputils::dynamic_pointer_move;
|
||||
using blockstore::Key;
|
||||
using blobstore::onblocks::datatreestore::DataTree;
|
||||
|
||||
void DataTreeShrinkingTest::Shrink(const Key &key) {
|
||||
treeStore.load(key)->removeLastDataLeaf();
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateFourNodeThreeLeaf() {
|
||||
return CreateInner({CreateLeaf(), CreateLeaf(), CreateLeaf()});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateTwoInnerNodeOneTwoLeaves() {
|
||||
return CreateInner({
|
||||
CreateInner({CreateLeaf()}),
|
||||
CreateInner({CreateLeaf(), CreateLeaf()})
|
||||
});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateTwoInnerNodeTwoOneLeaves() {
|
||||
return CreateInner({
|
||||
CreateInner({CreateLeaf(), CreateLeaf()}),
|
||||
CreateInner({CreateLeaf()})
|
||||
});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateFourLevelWithTwoSiblingLeaves1() {
|
||||
return CreateInner({
|
||||
CreateFullThreeLevel(),
|
||||
CreateInner({CreateTwoLeaf()})
|
||||
});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateFourLevelWithTwoSiblingLeaves2() {
|
||||
return CreateInner({
|
||||
CreateFullThreeLevel(),
|
||||
CreateInner({CreateFullTwoLevel(), CreateTwoLeaf()})
|
||||
});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel() {
|
||||
return CreateInner({
|
||||
CreateFullThreeLevel(),
|
||||
CreateThreeLevelMinData()
|
||||
});
|
||||
}
|
||||
|
||||
unique_ptr<DataInnerNode> DataTreeShrinkingTest::CreateThreeLevelWithThreeChildrenOfRoot() {
|
||||
return CreateInner({
|
||||
CreateFullTwoLevel(),
|
||||
CreateFullTwoLevel(),
|
||||
CreateInner({CreateLeaf()})
|
||||
});
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef BLOCKS_MESSMER_BLOBSTORE_TEST_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_GROWING_DATATREESHRINKINGTEST_H_
|
||||
#define BLOCKS_MESSMER_BLOBSTORE_TEST_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_GROWING_DATATREESHRINKINGTEST_H_
|
||||
|
||||
#include "../../testutils/DataTreeTest.h"
|
||||
|
||||
#include "../../../../../../implementations/onblocks/datanodestore/DataLeafNode.h"
|
||||
#include "../../../../../../implementations/onblocks/datanodestore/DataInnerNode.h"
|
||||
|
||||
#include "messmer/cpp-utils/pointer.h"
|
||||
|
||||
class DataTreeShrinkingTest: public DataTreeTest {
|
||||
public:
|
||||
void Shrink(const blockstore::Key &key);
|
||||
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFourNodeThreeLeaf();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateTwoInnerNodeOneTwoLeaves();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateTwoInnerNodeTwoOneLeaves();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFourLevelWithTwoSiblingLeaves1();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFourLevelWithTwoSiblingLeaves2();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel();
|
||||
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateThreeLevelWithThreeChildrenOfRoot();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user