From f115e10f6ddd8c0c4f274f142cf9b9afb2394377 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Wed, 28 Jan 2015 01:02:32 +0100 Subject: [PATCH] Implemented more tests for DataTreeTest --- .../implementations/onblocks/BlobOnBlocks.cpp | 4 + .../implementations/onblocks/BlobOnBlocks.h | 2 + .../onblocks/datanodestore/DataInnerNode.cpp | 2 + .../onblocks/datanodestore/DataNode.cpp | 4 + .../onblocks/datanodestore/DataNode.h | 2 + .../onblocks/datanodestore/DataNodeView.h | 4 + .../onblocks/datatreestore/DataTree.cpp | 4 + .../onblocks/datatreestore/DataTree.h | 2 + src/blobstore/interface/Blob.h | 2 + .../datatreestore/DataTreeGrowingTest.cpp | 271 ++++++++++++++++++ .../onblocks/datatreestore/DataTreeTest.cpp | 188 ------------ .../onblocks/datatreestore/DataTreeTest.h | 70 +++++ 12 files changed, 367 insertions(+), 188 deletions(-) create mode 100644 src/test/blobstore/implementations/onblocks/datatreestore/DataTreeGrowingTest.cpp delete mode 100644 src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp create mode 100644 src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.h diff --git a/src/blobstore/implementations/onblocks/BlobOnBlocks.cpp b/src/blobstore/implementations/onblocks/BlobOnBlocks.cpp index a8dcf096..74bd3711 100644 --- a/src/blobstore/implementations/onblocks/BlobOnBlocks.cpp +++ b/src/blobstore/implementations/onblocks/BlobOnBlocks.cpp @@ -22,5 +22,9 @@ size_t BlobOnBlocks::size() const { //return _rootnode->numBytesInThisNode(); } +void BlobOnBlocks::flush() const { + _rootnode->flush(); +} + } } diff --git a/src/blobstore/implementations/onblocks/BlobOnBlocks.h b/src/blobstore/implementations/onblocks/BlobOnBlocks.h index bf34bd82..d975cbfd 100644 --- a/src/blobstore/implementations/onblocks/BlobOnBlocks.h +++ b/src/blobstore/implementations/onblocks/BlobOnBlocks.h @@ -19,6 +19,8 @@ public: size_t size() const override; + void flush() const override; + private: std::unique_ptr _rootnode; }; diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataInnerNode.cpp b/src/blobstore/implementations/onblocks/datanodestore/DataInnerNode.cpp index 07730a69..0fb1b8b9 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataInnerNode.cpp +++ b/src/blobstore/implementations/onblocks/datanodestore/DataInnerNode.cpp @@ -11,6 +11,8 @@ namespace blobstore { namespace onblocks { namespace datanodestore { +constexpr uint32_t DataInnerNode::MAX_STORED_CHILDREN; + DataInnerNode::DataInnerNode(DataNodeView view) : DataNode(std::move(view)) { } diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNode.cpp b/src/blobstore/implementations/onblocks/datanodestore/DataNode.cpp index fb711e36..53e7f061 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNode.cpp +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNode.cpp @@ -47,6 +47,10 @@ unique_ptr DataNode::convertToNewInnerNode(unique_ptr n return innerNode; } +void DataNode::flush() const { + _node.flush(); +} + } } } diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNode.h b/src/blobstore/implementations/onblocks/datanodestore/DataNode.h index b5f67965..4d9578aa 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNode.h +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNode.h @@ -21,6 +21,8 @@ public: static std::unique_ptr convertToNewInnerNode(std::unique_ptr node, const DataNode &first_child); + void flush() const; + protected: DataNode(DataNodeView block); diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h b/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h index 90004654..97f82049 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h @@ -84,6 +84,10 @@ public: return _block->key(); } + void flush() const { + _block->flush(); + } + private: template const Type *GetOffset() const { diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp index 058fea50..438ebbdf 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp @@ -69,6 +69,10 @@ const Key &DataTree::key() const { return _rootNode->key(); } +void DataTree::flush() const { + _rootNode->flush(); +} + } } diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h index 5f35121c..325da044 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h @@ -27,6 +27,8 @@ public: std::unique_ptr addDataLeaf(); const blockstore::Key &key() const; + + void flush() const; private: datanodestore::DataNodeStore *_nodeStore; std::unique_ptr _rootNode; diff --git a/src/blobstore/interface/Blob.h b/src/blobstore/interface/Blob.h index b97b5336..4624acdd 100644 --- a/src/blobstore/interface/Blob.h +++ b/src/blobstore/interface/Blob.h @@ -11,6 +11,8 @@ public: virtual ~Blob() {} virtual size_t size() const = 0; + + virtual void flush() const = 0; }; } diff --git a/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeGrowingTest.cpp b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeGrowingTest.cpp new file mode 100644 index 00000000..ea8a7e99 --- /dev/null +++ b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeGrowingTest.cpp @@ -0,0 +1,271 @@ +#include "DataTreeTest.h" + +#include "blobstore/implementations/onblocks/datatreestore/DataTree.h" +#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h" +#include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h" + +#include "fspp/utils/pointer.h" + +using fspp::dynamic_pointer_move; + +using blobstore::onblocks::datanodestore::DataNode; +using blobstore::onblocks::datanodestore::DataInnerNode; +using blobstore::onblocks::datanodestore::DataLeafNode; +using blockstore::Key; + +using namespace blobstore::onblocks::datatreestore; + +class DataTreeGrowingTest: public DataTreeTest { +public: + + Key CreateTreeAddOneLeafReturnRootKey() { + auto tree = CreateLeafOnlyTree(); + auto key = tree->key(); + tree->addDataLeaf(); + return key; + } + + Key CreateTreeAddTwoLeavesReturnRootKey() { + auto tree = CreateLeafOnlyTree(); + auto key = tree->key(); + tree->addDataLeaf(); + tree->addDataLeaf(); + return key; + } + + Key CreateTreeAddThreeLeavesReturnRootKey() { + auto tree = CreateLeafOnlyTree(); + auto key = tree->key(); + tree->addDataLeaf(); + tree->addDataLeaf(); + tree->addDataLeaf(); + return key; + } + + Key CreateThreeNodeChainedTreeReturnRootKey() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + auto root = nodeStore.createNewInnerNode(*node); + return root->key(); + } + + Key CreateThreeLevelTreeWithLowerLevelFullReturnRootKey() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + FillNode(node.get()); + auto root = nodeStore.createNewInnerNode(*node); + return root->key(); + } + + Key CreateThreeLevelTreeWithTwoFullSubtrees() { + auto leaf1 = nodeStore.createNewLeafNode(); + auto leaf2 = nodeStore.createNewLeafNode(); + auto leaf3 = nodeStore.createNewLeafNode(); + auto node1 = nodeStore.createNewInnerNode(*leaf1); + FillNode(node1.get()); + auto node2 = nodeStore.createNewInnerNode(*leaf2); + FillNode(node2.get()); + auto root = nodeStore.createNewInnerNode(*node1); + root->addChild(*node2); + return root->key(); + } + + void AddLeafTo(const Key &key) { + DataTree tree(&nodeStore, nodeStore.load(key)); + tree.addDataLeaf(); + } + + unique_ptr LoadInnerNode(const Key &key) { + auto node = nodeStore.load(key); + auto casted = dynamic_pointer_move(node); + EXPECT_NE(nullptr, casted.get()) << "Is not an inner node"; + return casted; + } + + unique_ptr LoadLeafNode(const Key &key) { + auto node = nodeStore.load(key); + auto casted = dynamic_pointer_move(node); + EXPECT_NE(nullptr, casted.get()) << "Is not a leaf node"; + return casted; + } + + void EXPECT_IS_LEAF_NODE(const Key &key) { + auto node = LoadLeafNode(key); + EXPECT_NE(nullptr, node.get()); + } + + void EXPECT_IS_INNER_NODE(const Key &key) { + auto node = LoadInnerNode(key); + EXPECT_NE(nullptr, node.get()); + } + + void EXPECT_IS_FULL_TWOLEVEL_TREE(const Key &key) { + auto node = LoadInnerNode(key); + EXPECT_EQ(DataInnerNode::MAX_STORED_CHILDREN, node->numChildren()); + for (unsigned int i = 0; i < node->numChildren(); ++i) { + EXPECT_IS_LEAF_NODE(node->getChild(i)->key()); + } + } + + void EXPECT_IS_FULL_THREELEVEL_TREE(const Key &key) { + auto root = LoadInnerNode(key); + EXPECT_EQ(DataInnerNode::MAX_STORED_CHILDREN, root->numChildren()); + for (unsigned int i = 0; i < root->numChildren(); ++i) { + auto node = LoadInnerNode(root->getChild(i)->key()); + EXPECT_EQ(DataInnerNode::MAX_STORED_CHILDREN, node->numChildren()); + for (unsigned int j = 0; j < node->numChildren(); ++j) { + EXPECT_IS_LEAF_NODE(node->getChild(j)->key()); + } + } + } + + void EXPECT_IS_TWONODE_CHAIN(const Key &key) { + auto node = LoadInnerNode(key); + EXPECT_EQ(1u, node->numChildren()); + EXPECT_IS_LEAF_NODE(node->getChild(0)->key()); + } + + void 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 EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(const Key &key) { + DataTree tree(&nodeStore, nodeStore.load(key)); + tree.addDataLeaf(); + EXPECT_EQ(key, tree.key()); + } + + void 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;igetChild(i)->key()); + } + } +}; + +TEST_F(DataTreeGrowingTest, GrowAOneNodeTree_KeyDoesntChange) { + auto key = CreateLeafOnlyTree()->key(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key); +} + +TEST_F(DataTreeGrowingTest, GrowAOneNodeTree_Structure) { + auto key = CreateTreeAddOneLeafReturnRootKey(); + EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(2, 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()); +} + +TEST_F(DataTreeGrowingTest, GrowATwoNodeTree_KeyDoesntChange) { + auto key = CreateTreeAddOneLeafReturnRootKey(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key); +} + +TEST_F(DataTreeGrowingTest, GrowATwoNodeTree_Structure) { + auto key = CreateTreeAddTwoLeavesReturnRootKey(); + EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(3, key); +} + +TEST_F(DataTreeGrowingTest, GrowATwoLevelThreeNodeTree_KeyDoesntChange) { + auto key = CreateTreeAddTwoLeavesReturnRootKey(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(key); +} + +TEST_F(DataTreeGrowingTest, GrowATwoLevelThreeNodeTree_Structure) { + auto key = CreateTreeAddThreeLeavesReturnRootKey(); + EXPECT_INNER_NODE_NUMBER_OF_LEAVES_IS(4, key); +} + +TEST_F(DataTreeGrowingTest, GrowAThreeNodeChainedTree_KeyDoesntChange) { + auto root_key = CreateThreeNodeChainedTreeReturnRootKey(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key); +} + +TEST_F(DataTreeGrowingTest, GrowAThreeNodeChainedTree_Structure) { + 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, GrowAThreeLevelTreeWithLowerLevelFull_KeyDoesntChange) { + auto root_key = CreateThreeLevelTreeWithLowerLevelFullReturnRootKey(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key); +} + +TEST_F(DataTreeGrowingTest, GrowAThreeLevelTreeWithLowerLevelFull_Structure) { + 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, GrowAFullTwoLevelTree_KeyDoesntChange) { + auto root_key = CreateFullTwoLevelTree(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key); +} + +TEST_F(DataTreeGrowingTest, GrowAFullTwoLevelTree_Structure) { + auto root_key = CreateFullTwoLevelTree(); + 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, GrowAFullThreeLevelTree_KeyDoesntChange) { + auto root_key = CreateFullThreeLevelTree(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key); +} + +TEST_F(DataTreeGrowingTest, GrowAFullThreeLevelTree_Structure) { + auto root_key = CreateFullThreeLevelTree(); + 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, GrowAThreeLevelTreeWithTwoFullSubtrees_KeyDoesntChange) { + auto root_key = CreateThreeLevelTreeWithTwoFullSubtrees(); + EXPECT_KEY_DOESNT_CHANGE_WHEN_GROWING(root_key); +} + +TEST_F(DataTreeGrowingTest, GrowAThreeLevelTreeWithTwoFullSubtrees_Structure) { + auto root_key = CreateThreeLevelTreeWithTwoFullSubtrees(); + AddLeafTo(root_key); + + auto root = LoadInnerNode(root_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()); +} + +//TODO Test that when growing, the original leaf retains its data +//TODO Test tree depth diff --git a/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp deleted file mode 100644 index 7a253d74..00000000 --- a/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "gtest/gtest.h" - -#include "blockstore/implementations/testfake/FakeBlockStore.h" -#include "blobstore/implementations/onblocks/datanodestore/DataNodeStore.h" -#include "blobstore/implementations/onblocks/datatreestore/DataTree.h" -#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h" -#include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h" - -#include "fspp/utils/pointer.h" - -using ::testing::Test; -using std::unique_ptr; -using std::make_unique; -using fspp::dynamic_pointer_move; - -using blobstore::onblocks::datanodestore::DataNodeStore; -using blobstore::onblocks::datanodestore::DataNode; -using blobstore::onblocks::datanodestore::DataInnerNode; -using blobstore::onblocks::datanodestore::DataLeafNode; -using blockstore::testfake::FakeBlockStore; -using blockstore::BlockStore; -using blockstore::Key; - -namespace blobstore { -namespace onblocks { -namespace datatreestore { - -class DataTreeTest: public Test { -public: - DataTreeTest(): - nodeStore(make_unique()) { - } - - unique_ptr CreateLeafOnlyTree() { - auto leafnode = nodeStore.createNewLeafNode(); - return make_unique(&nodeStore, std::move(leafnode)); - } - - Key CreateTreeAddOneLeafReturnRootKey() { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - return key; - } - - Key CreateTreeAddTwoLeavesReturnRootKey() { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - tree->addDataLeaf(); - return key; - } - - Key CreateTreeAddThreeLeavesReturnRootKey() { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - tree->addDataLeaf(); - tree->addDataLeaf(); - return key; - } - - Key CreateThreeNodeChainedTreeReturnRootKey() { - auto leaf = nodeStore.createNewLeafNode(); - auto node = nodeStore.createNewInnerNode(*leaf); - auto root = nodeStore.createNewInnerNode(*node); - return root->key(); - } - - void AddLeafTo(const Key &key) { - DataTree tree(&nodeStore, nodeStore.load(key)); - tree.addDataLeaf(); - } - - unique_ptr LoadInnerNode(const Key &key) { - auto node = nodeStore.load(key); - return dynamic_pointer_move(node); - } - - unique_ptr LoadLeafNode(const Key &key) { - auto node = nodeStore.load(key); - return dynamic_pointer_move(node); - } - - void EXPECT_IS_LEAF_NODE(const Key &key) { - auto node = LoadLeafNode(key); - EXPECT_NE(nullptr, node.get()); - } - - void EXPECT_IS_INNER_NODE(const Key &key) { - auto node = LoadInnerNode(key); - EXPECT_NE(nullptr, node.get()); - } - - DataNodeStore nodeStore; -}; - -TEST_F(DataTreeTest, GrowAOneNodeTree_KeyDoesntChange) { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - EXPECT_EQ(key, tree->key()); -} - -TEST_F(DataTreeTest, GrowAOneNodeTree_Structure) { - auto key = CreateTreeAddOneLeafReturnRootKey(); - - EXPECT_IS_INNER_NODE(key); - auto root = LoadInnerNode(key); - - EXPECT_EQ(2u, root->numChildren()); - EXPECT_IS_LEAF_NODE(root->getChild(0)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(1)->key()); -} - -TEST_F(DataTreeTest, GrowATwoNodeTree_KeyDoesntChange) { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - tree->addDataLeaf(); - EXPECT_EQ(key, tree->key()); -} - -TEST_F(DataTreeTest, GrowATwoNodeTree_Structure) { - auto key = CreateTreeAddTwoLeavesReturnRootKey(); - - EXPECT_IS_INNER_NODE(key); - auto root = LoadInnerNode(key); - - EXPECT_EQ(3u, root->numChildren()); - EXPECT_IS_LEAF_NODE(root->getChild(0)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(1)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(2)->key()); -} - -TEST_F(DataTreeTest, GrowAThreeNodeTree_KeyDoesntChange) { - auto tree = CreateLeafOnlyTree(); - auto key = tree->key(); - tree->addDataLeaf(); - tree->addDataLeaf(); - tree->addDataLeaf(); - EXPECT_EQ(key, tree->key()); -} - -TEST_F(DataTreeTest, GrowAThreeNodeTree_Structure) { - auto key = CreateTreeAddThreeLeavesReturnRootKey(); - - EXPECT_IS_INNER_NODE(key); - auto root = LoadInnerNode(key); - - EXPECT_EQ(4u, root->numChildren()); - EXPECT_IS_LEAF_NODE(root->getChild(0)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(1)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(2)->key()); - EXPECT_IS_LEAF_NODE(root->getChild(3)->key()); -} - -TEST_F(DataTreeTest, GrowAThreeNodeChainedTree_KeyDoesntChange) { - auto root_key = CreateThreeNodeChainedTreeReturnRootKey(); - DataTree tree(&nodeStore, nodeStore.load(root_key)); - tree.addDataLeaf(); - EXPECT_EQ(root_key, tree.key()); -} - -TEST_F(DataTreeTest, GrowAThreeNodeChainedTree_Structure) { - auto key = CreateThreeNodeChainedTreeReturnRootKey(); - AddLeafTo(key); - - EXPECT_IS_INNER_NODE(key); - auto root = LoadInnerNode(key); - - EXPECT_EQ(1u, root->numChildren()); - EXPECT_IS_INNER_NODE(root->getChild(0)->key()); - auto node = LoadInnerNode(root->getChild(0)->key()); - - EXPECT_EQ(2u, node->numChildren()); - EXPECT_IS_LEAF_NODE(node->getChild(0)->key()); - EXPECT_IS_LEAF_NODE(node->getChild(1)->key()); -} - -//TODO Grow a full two-level tree -//TODO Grow a three-level tree -//TODO Go through some cases where the right border node chosen is special -//TODO Test that when growing, the original leaf retains its data - -} -} -} diff --git a/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.h b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.h new file mode 100644 index 00000000..c3ca3d70 --- /dev/null +++ b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.h @@ -0,0 +1,70 @@ +#pragma once +#ifndef TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_DATATREETEST_H_ +#define TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_DATATREETEST_H_ + +#include "gtest/gtest.h" + +#include "blobstore/implementations/onblocks/datanodestore/DataNodeStore.h" +#include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h" +#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h" +#include "blobstore/implementations/onblocks/datatreestore/DataTree.h" +#include "blockstore/implementations/testfake/FakeBlockStore.h" + +#include + +using blobstore::onblocks::datanodestore::DataNodeStore; +using blobstore::onblocks::datanodestore::DataInnerNode; +using blobstore::onblocks::datatreestore::DataTree; +using blockstore::testfake::FakeBlockStore; +using blockstore::Key; +using std::make_unique; +using std::unique_ptr; + +class DataTreeTest: public ::testing::Test { +public: + DataTreeTest(): + nodeStore(make_unique()) { + } + + unique_ptr CreateLeafOnlyTree() { + auto leafnode = nodeStore.createNewLeafNode(); + return make_unique(&nodeStore, std::move(leafnode)); + } + + void FillNode(DataInnerNode *node) { + for(unsigned int i=node->numChildren(); i < DataInnerNode::MAX_STORED_CHILDREN; ++i) { + node->addChild(*nodeStore.createNewLeafNode()); + } + } + + void FillNodeTwoLevel(DataInnerNode *node) { + for(unsigned int i=node->numChildren(); i < DataInnerNode::MAX_STORED_CHILDREN; ++i) { + auto inner_node = nodeStore.createNewInnerNode(*nodeStore.createNewLeafNode()); + for(unsigned int j = 1;j < DataInnerNode::MAX_STORED_CHILDREN; ++j) { + inner_node->addChild(*nodeStore.createNewLeafNode()); + } + node->addChild(*inner_node); + } + } + + Key CreateFullTwoLevelTree() { + auto leaf = nodeStore.createNewLeafNode(); + auto root = nodeStore.createNewInnerNode(*leaf); + FillNode(root.get()); + return root->key(); + } + + Key CreateFullThreeLevelTree() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + auto root = nodeStore.createNewInnerNode(*node); + FillNode(node.get()); + FillNodeTwoLevel(root.get()); + return root->key(); + } + + DataNodeStore nodeStore; +}; + + +#endif