Removed DataTree::addDataLeaf() / DataTree::removeLastDataLeaf() and DataTree::flush()

This commit is contained in:
Sebastian Messmer 2015-03-04 03:17:59 +01:00
parent c0e5b5db8c
commit 5fb235a40c
22 changed files with 21 additions and 998 deletions

View File

@ -1,6 +1,7 @@
# Biicode configuration file # Biicode configuration file
[requirements] [requirements]
google/gmock: 2
google/gtest: 10 google/gtest: 10
messmer/blockstore: 1 messmer/blockstore: 1
messmer/cmake: 3 messmer/cmake: 3

View File

@ -31,10 +31,6 @@ void BlobOnBlocks::resize(uint64_t numBytes) {
_datatree->resizeNumBytes(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 { void BlobOnBlocks::traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, function<void (uint64_t, void *, uint32_t)> func) const {
uint64_t endByte = beginByte + sizeBytes; uint64_t endByte = beginByte + sizeBytes;
assert(endByte <= size()); assert(endByte <= size());

View File

@ -28,8 +28,6 @@ public:
void read(void *target, uint64_t offset, uint64_t size) const override; 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 write(const void *source, uint64_t offset, uint64_t size) override;
void flush() const override;
private: private:
void traverseLeaves(uint64_t offsetBytes, uint64_t sizeBytes, std::function<void (uint64_t, void *, uint32_t)>) const; void traverseLeaves(uint64_t offsetBytes, uint64_t sizeBytes, std::function<void (uint64_t, void *, uint32_t)>) const;

View File

@ -109,14 +109,21 @@ unique_ptr<DataNode> DataTree::releaseRootNode() {
} }
void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function<void (DataLeafNode*, uint32_t)> func) { 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); assert(beginIndex <= endIndex);
//TODO assert(beginIndex <= numLeaves()); //TODO assert(beginIndex <= numLeaves());
//TODO assert(endIndex <= numLeaves()); //TODO assert(endIndex <= numLeaves());
traverseLeaves(_rootNode.get(), 0, beginIndex, endIndex, func); 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) { void DataTree::traverseLeaves(const DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, function<void (const DataLeafNode*, uint32_t)> func) const {
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root); const DataLeafNode *leaf = dynamic_cast<const DataLeafNode*>(root);
if (leaf != nullptr) { if (leaf != nullptr) {
assert(beginIndex <= 1 && endIndex <= 1); assert(beginIndex <= 1 && endIndex <= 1);
if (beginIndex == 0 && endIndex == 1) { if (beginIndex == 0 && endIndex == 1) {
@ -125,7 +132,7 @@ void DataTree::traverseLeaves(DataNode *root, uint32_t leafOffset, uint32_t begi
return; return;
} }
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root); const DataInnerNode *inner = dynamic_cast<const DataInnerNode*>(root);
uint32_t leavesPerChild = leavesPerFullChild(*inner); uint32_t leavesPerChild = leavesPerFullChild(*inner);
uint32_t beginChild = beginIndex/leavesPerChild; uint32_t beginChild = beginIndex/leavesPerChild;
uint32_t endChild = utils::ceilDivision(endIndex, leavesPerChild); uint32_t endChild = utils::ceilDivision(endIndex, leavesPerChild);
@ -179,6 +186,7 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
LastLeaf(_rootNode.get())->resize(newLastLeafSize); LastLeaf(_rootNode.get())->resize(newLastLeafSize);
assert(newNumBytes == numStoredBytes()); assert(newNumBytes == numStoredBytes());
flush();
} }
optional_ownership_ptr<DataLeafNode> DataTree::LastLeaf(DataNode *root) { optional_ownership_ptr<DataLeafNode> DataTree::LastLeaf(DataNode *root) {

View File

@ -26,24 +26,22 @@ public:
DataTree(datanodestore::DataNodeStore *nodeStore, std::unique_ptr<datanodestore::DataNode> rootNode); DataTree(datanodestore::DataNodeStore *nodeStore, std::unique_ptr<datanodestore::DataNode> rootNode);
virtual ~DataTree(); 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; const blockstore::Key &key() const;
uint32_t maxBytesPerLeaf() const; uint32_t maxBytesPerLeaf() const;
//TODO Remove flush() and instead call it implicitly on traverseLeaves()/resizeNumBytes() void traverseLeaves(uint32_t beginIndex, uint32_t endIndex, std::function<void (const datanodestore::DataLeafNode*, uint32_t)> func) const;
void flush() const;
void traverseLeaves(uint32_t beginIndex, uint32_t endIndex, std::function<void (datanodestore::DataLeafNode*, uint32_t)> func); 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); void resizeNumBytes(uint64_t newNumBytes);
uint64_t numStoredBytes() const;
private: private:
datanodestore::DataNodeStore *_nodeStore; datanodestore::DataNodeStore *_nodeStore;
std::unique_ptr<datanodestore::DataNode> _rootNode; std::unique_ptr<datanodestore::DataNode> _rootNode;
std::unique_ptr<datanodestore::DataLeafNode> addDataLeaf();
void removeLastDataLeaf();
std::unique_ptr<datanodestore::DataNode> releaseRootNode(); std::unique_ptr<datanodestore::DataNode> releaseRootNode();
friend class DataTreeStore; friend class DataTreeStore;
@ -54,12 +52,14 @@ private:
void deleteLastChildSubtree(datanodestore::DataInnerNode *node); void deleteLastChildSubtree(datanodestore::DataInnerNode *node);
void ifRootHasOnlyOneChildReplaceRootWithItsChild(); 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; uint32_t leavesPerFullChild(const datanodestore::DataInnerNode &root) const;
uint64_t numStoredBytes(const datanodestore::DataNode &root) const; uint64_t numStoredBytes(const datanodestore::DataNode &root) const;
cpputils::optional_ownership_ptr<datanodestore::DataLeafNode> LastLeaf(datanodestore::DataNode *root); cpputils::optional_ownership_ptr<datanodestore::DataLeafNode> LastLeaf(datanodestore::DataNode *root);
std::unique_ptr<datanodestore::DataLeafNode> LastLeaf(std::unique_ptr<datanodestore::DataNode> root); std::unique_ptr<datanodestore::DataLeafNode> LastLeaf(std::unique_ptr<datanodestore::DataNode> root);
void flush() const;
DISALLOW_COPY_AND_ASSIGN(DataTree); DISALLOW_COPY_AND_ASSIGN(DataTree);
}; };

View File

@ -23,8 +23,6 @@ public:
virtual void read(void *target, uint64_t offset, uint64_t size) const = 0; 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 write(const void *source, uint64_t offset, uint64_t size) = 0;
virtual void flush() const = 0;
}; };
} }

View File

@ -28,7 +28,6 @@ TEST_F(DataTreeStoreTest, CreatedTreeIsLoadable) {
TEST_F(DataTreeStoreTest, NewTreeIsLeafOnly) { TEST_F(DataTreeStoreTest, NewTreeIsLeafOnly) {
auto tree = treeStore.createNewTree(); auto tree = treeStore.createNewTree();
tree->flush();
EXPECT_IS_LEAF_NODE(tree->key()); EXPECT_IS_LEAF_NODE(tree->key());
} }

View File

@ -163,13 +163,11 @@ INSTANTIATE_TEST_CASE_P(DataTreeTest_ResizeNumBytes_P, DataTreeTest_ResizeNumByt
TEST_P(DataTreeTest_ResizeNumBytes_P, StructureIsValid) { TEST_P(DataTreeTest_ResizeNumBytes_P, StructureIsValid) {
tree->resizeNumBytes(newSize); tree->resizeNumBytes(newSize);
tree->flush();
EXPECT_IS_LEFTMAXDATA_TREE(tree->key()); EXPECT_IS_LEFTMAXDATA_TREE(tree->key());
} }
TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) { TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) {
tree->resizeNumBytes(newSize); 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. // 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. // This is what the StructureIsValid test case is for.
EXPECT_EQ(newSize, tree->numStoredBytes()); EXPECT_EQ(newSize, tree->numStoredBytes());
@ -177,7 +175,6 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) {
TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) { TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) {
tree->resizeNumBytes(newSize); tree->resizeNumBytes(newSize);
tree->flush();
uint32_t depth = ceil(log(newNumberOfLeaves)/log(DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode())); uint32_t depth = ceil(log(newNumberOfLeaves)/log(DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode()));
CHECK_DEPTH(depth, tree->key()); CHECK_DEPTH(depth, tree->key());
} }
@ -185,7 +182,6 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) {
TEST_P(DataTreeTest_ResizeNumBytes_P, KeyDoesntChange) { TEST_P(DataTreeTest_ResizeNumBytes_P, KeyDoesntChange) {
Key key = tree->key(); Key key = tree->key();
tree->resizeNumBytes(newSize); tree->resizeNumBytes(newSize);
tree->flush();
EXPECT_EQ(key, tree->key()); EXPECT_EQ(key, tree->key());
} }

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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());
}
}

View File

@ -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

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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());
}

View File

@ -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()})
});
}

View File

@ -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