From 58ccf0495e0e40d3031d40af87bb6e25d8f46bfd Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Mon, 26 Jan 2015 00:38:06 +0100 Subject: [PATCH] Source out GetLowestRightBorderNodeWithLessThanKChildrenOrNull and write test cases for it --- .../onblocks/datatreestore/CMakeLists.txt | 2 +- .../onblocks/datatreestore/DataTree.cpp | 24 +-- .../onblocks/datatreestore/DataTree.h | 4 +- ...tBorderNodeWithLessThanKChildrenOrNull.cpp | 46 ++++++ ...ghtBorderNodeWithLessThanKChildrenOrNull.h | 27 ++++ .../onblocks/datatreestore/DataTreeTest.cpp | 36 +++++ ...derNodeWithLessThanKChildrenOrNullTest.cpp | 153 ++++++++++++++++++ 7 files changed, 267 insertions(+), 25 deletions(-) create mode 100644 src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.cpp create mode 100644 src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h create mode 100644 src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp create mode 100644 src/test/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest.cpp diff --git a/src/blobstore/implementations/onblocks/datatreestore/CMakeLists.txt b/src/blobstore/implementations/onblocks/datatreestore/CMakeLists.txt index 9f219c7d..2c507bd5 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/CMakeLists.txt +++ b/src/blobstore/implementations/onblocks/datatreestore/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(blobstore_onblocks_datatreestore DataTree.cpp DataTreeStore.cpp) +add_library(blobstore_onblocks_datatreestore DataTree.cpp DataTreeStore.cpp impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull) target_link_libraries(blobstore_onblocks_datatreestore blobstore_onblocks_datanodestore) diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp index 86441a4c..c8c43c05 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp @@ -4,6 +4,8 @@ #include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h" #include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h" +#include "impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" + #include "fspp/utils/pointer.h" using blockstore::Key; @@ -31,7 +33,7 @@ DataTree::~DataTree() { } unique_ptr DataTree::addDataLeaf() { - auto insertPosOrNull = lowestRightBorderNodeWithLessThanKChildrenOrNull(); + auto insertPosOrNull = impl::GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(_nodeStore, _rootNode.get()); if (insertPosOrNull) { return addDataLeafAt(insertPosOrNull.get()); } else { @@ -39,26 +41,6 @@ unique_ptr DataTree::addDataLeaf() { } } -optional_ownership_ptr DataTree::lowestRightBorderNodeWithLessThanKChildrenOrNull() { - optional_ownership_ptr currentNode = fspp::ptr::WithoutOwnership(dynamic_cast(_rootNode.get())); - optional_ownership_ptr result = fspp::ptr::null(); - for (unsigned int i=0; i < _rootNode->depth(); ++i) { - auto lastChild = getLastChildAsInnerNode(*currentNode); - if (currentNode->numChildren() < DataInnerNode::MAX_STORED_CHILDREN) { - result = std::move(currentNode); - } - currentNode = std::move(lastChild); - } - - return result; -} - -unique_ptr DataTree::getLastChildAsInnerNode(const DataInnerNode &node) { - Key key = node.LastChild()->key(); - auto lastChild = _nodeStore->load(key); - return dynamic_pointer_move(lastChild); -} - unique_ptr DataTree::addDataLeafAt(DataInnerNode *insertPos) { auto new_leaf = _nodeStore->createNewLeafNode(); auto chain = createChainOfInnerNodes(insertPos->depth()-1, new_leaf.get()); diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h index 02055a86..99cc653b 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h @@ -4,7 +4,7 @@ #include #include "fspp/utils/macros.h" -#include "fspp/utils/OptionalOwnershipPointer.h" +#include "impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" namespace blobstore { namespace onblocks { @@ -26,8 +26,6 @@ private: datanodestore::DataNodeStore *_nodeStore; std::unique_ptr _rootNode; - fspp::ptr::optional_ownership_ptr lowestRightBorderNodeWithLessThanKChildrenOrNull(); - std::unique_ptr getLastChildAsInnerNode(const datanodestore::DataInnerNode &node); std::unique_ptr addDataLeafAt(datanodestore::DataInnerNode *insertPos); fspp::ptr::optional_ownership_ptr createChainOfInnerNodes(unsigned int num, datanodestore::DataLeafNode *leaf); std::unique_ptr addDataLeafToFullTree(); diff --git a/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.cpp b/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.cpp new file mode 100644 index 00000000..491633ef --- /dev/null +++ b/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.cpp @@ -0,0 +1,46 @@ +#include "GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" + +#include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h" +#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h" +#include "blobstore/implementations/onblocks/datanodestore/DataNodeStore.h" + +#include "fspp/utils/pointer.h" + +using std::unique_ptr; +using fspp::dynamic_pointer_move; +using fspp::ptr::optional_ownership_ptr; +using blobstore::onblocks::datanodestore::DataNode; +using blobstore::onblocks::datanodestore::DataInnerNode; +using blobstore::onblocks::datanodestore::DataLeafNode; +using blobstore::onblocks::datanodestore::DataNodeStore; +using blockstore::Key; + +namespace blobstore { +namespace onblocks { +namespace datatreestore { +namespace impl { + +unique_ptr getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) { + Key key = node.LastChild()->key(); + auto lastChild = nodeStore->load(key); + return dynamic_pointer_move(lastChild); +} + +optional_ownership_ptr GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(DataNodeStore *nodeStore, DataNode *rootNode) { + optional_ownership_ptr currentNode = fspp::ptr::WithoutOwnership(dynamic_cast(rootNode)); + optional_ownership_ptr result = fspp::ptr::null(); + for (unsigned int i=0; i < rootNode->depth(); ++i) { + auto lastChild = getLastChildAsInnerNode(nodeStore, *currentNode); + if (currentNode->numChildren() < DataInnerNode::MAX_STORED_CHILDREN) { + result = std::move(currentNode); + } + currentNode = std::move(lastChild); + } + + return result; +} + +} +} +} +} diff --git a/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h b/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h new file mode 100644 index 00000000..357e3d5b --- /dev/null +++ b/src/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h @@ -0,0 +1,27 @@ +#pragma once +#ifndef TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_GETLOWESTRIGHTBORDERNODEWITHLESSTHANKCHILDRENORNULL_H_ +#define TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_GETLOWESTRIGHTBORDERNODEWITHLESSTHANKCHILDRENORNULL_H_ + +#include "fspp/utils/OptionalOwnershipPointer.h" + +namespace blobstore { +namespace onblocks { +namespace datanodestore { +class DataNode; +class DataInnerNode; +class DataNodeStore; +} +namespace datatreestore { +namespace impl { + +class GetLowestRightBorderNodeWithLessThanKChildrenOrNull { +public: + static fspp::ptr::optional_ownership_ptr run(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode); +}; + +} +} +} +} + +#endif diff --git a/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp new file mode 100644 index 00000000..b70194df --- /dev/null +++ b/src/test/blobstore/implementations/onblocks/datatreestore/DataTreeTest.cpp @@ -0,0 +1,36 @@ +#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" + +using ::testing::Test; +using std::unique_ptr; +using std::make_unique; + +using blobstore::onblocks::datanodestore::DataNodeStore; +using blobstore::onblocks::datanodestore::DataNode; +using blockstore::testfake::FakeBlockStore; + +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)); + } + + DataNodeStore nodeStore; +}; + +} +} +} diff --git a/src/test/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest.cpp b/src/test/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest.cpp new file mode 100644 index 00000000..de8c165f --- /dev/null +++ b/src/test/blobstore/implementations/onblocks/datatreestore/impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest.cpp @@ -0,0 +1,153 @@ +#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" + +using ::testing::Test; +using std::unique_ptr; +using std::make_unique; +using std::pair; +using std::make_pair; + +using blobstore::onblocks::datanodestore::DataNodeStore; +using blobstore::onblocks::datanodestore::DataNode; +using blobstore::onblocks::datanodestore::DataInnerNode; +using blockstore::testfake::FakeBlockStore; +using blockstore::Key; +using blobstore::onblocks::datatreestore::impl::GetLowestRightBorderNodeWithLessThanKChildrenOrNull; + +namespace blobstore { +namespace onblocks { +namespace datatreestore { + +class GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest: public Test { +public: + GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest(): + nodeStore(make_unique()) { + } + + struct TestData { + TestData(Key rootNode_, Key expectedResult_): rootNode(rootNode_), expectedResult(expectedResult_) {} + Key rootNode; + Key expectedResult; + }; + + void check(const TestData &testData) { + auto root = nodeStore.load(testData.rootNode); + auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); + EXPECT_EQ(testData.expectedResult, result->key()); + } + + 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); + } + } + + TestData CreateTwoRightBorderNodes() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + return TestData(node->key(), node->key()); + } + + TestData CreateThreeRightBorderNodes() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + auto root = nodeStore.createNewInnerNode(*node); + return TestData(root->key(), node->key()); + } + + TestData CreateThreeRightBorderNodes_LastFull() { + auto leaf = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + FillNode(node.get()); + auto root = nodeStore.createNewInnerNode(*node); + return TestData(root->key(), root->key()); + } + + TestData CreateLargerTree() { + auto leaf = nodeStore.createNewLeafNode(); + auto leaf2 = nodeStore.createNewLeafNode(); + auto leaf3 = nodeStore.createNewLeafNode(); + auto node = nodeStore.createNewInnerNode(*leaf); + FillNode(node.get()); + auto node2 = nodeStore.createNewInnerNode(*leaf2); + node2->addChild(*leaf3); + auto root = nodeStore.createNewInnerNode(*node); + root->addChild(*node2); + return TestData(root->key(), node2->key()); + } + + 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; +}; + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, Leaf) { + auto leaf = nodeStore.createNewLeafNode(); + auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, leaf.get()); + EXPECT_EQ(nullptr, result.get()); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, TwoRightBorderNodes) { + auto testData = CreateTwoRightBorderNodes(); + check(testData); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes) { + auto testData = CreateThreeRightBorderNodes(); + check(testData); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes_LastFull) { + auto testData = CreateThreeRightBorderNodes_LastFull(); + check(testData); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, LargerTree) { + auto testData = CreateLargerTree(); + check(testData); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, FullTwoLevelTree) { + auto root = nodeStore.load(CreateFullTwoLevelTree()); + auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); + EXPECT_EQ(nullptr, result.get()); +} + +TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, FullThreeLevelTree) { + auto root = nodeStore.load(CreateFullThreeLevelTree()); + auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); + EXPECT_EQ(nullptr, result.get()); +} + +} +} +}