Source out GetLowestRightBorderNodeWithLessThanKChildrenOrNull and write test cases for it
This commit is contained in:
parent
03867bb8a2
commit
58ccf0495e
@ -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)
|
||||
|
@ -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<DataLeafNode> 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<DataLeafNode> DataTree::addDataLeaf() {
|
||||
}
|
||||
}
|
||||
|
||||
optional_ownership_ptr<DataInnerNode> DataTree::lowestRightBorderNodeWithLessThanKChildrenOrNull() {
|
||||
optional_ownership_ptr<DataInnerNode> currentNode = fspp::ptr::WithoutOwnership(dynamic_cast<DataInnerNode*>(_rootNode.get()));
|
||||
optional_ownership_ptr<DataInnerNode> result = fspp::ptr::null<DataInnerNode>();
|
||||
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<DataInnerNode> DataTree::getLastChildAsInnerNode(const DataInnerNode &node) {
|
||||
Key key = node.LastChild()->key();
|
||||
auto lastChild = _nodeStore->load(key);
|
||||
return dynamic_pointer_move<DataInnerNode>(lastChild);
|
||||
}
|
||||
|
||||
unique_ptr<DataLeafNode> DataTree::addDataLeafAt(DataInnerNode *insertPos) {
|
||||
auto new_leaf = _nodeStore->createNewLeafNode();
|
||||
auto chain = createChainOfInnerNodes(insertPos->depth()-1, new_leaf.get());
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <memory>
|
||||
#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<datanodestore::DataNode> _rootNode;
|
||||
|
||||
fspp::ptr::optional_ownership_ptr<datanodestore::DataInnerNode> lowestRightBorderNodeWithLessThanKChildrenOrNull();
|
||||
std::unique_ptr<datanodestore::DataInnerNode> getLastChildAsInnerNode(const datanodestore::DataInnerNode &node);
|
||||
std::unique_ptr<datanodestore::DataLeafNode> addDataLeafAt(datanodestore::DataInnerNode *insertPos);
|
||||
fspp::ptr::optional_ownership_ptr<datanodestore::DataNode> createChainOfInnerNodes(unsigned int num, datanodestore::DataLeafNode *leaf);
|
||||
std::unique_ptr<datanodestore::DataLeafNode> addDataLeafToFullTree();
|
||||
|
@ -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<DataInnerNode> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
|
||||
Key key = node.LastChild()->key();
|
||||
auto lastChild = nodeStore->load(key);
|
||||
return dynamic_pointer_move<DataInnerNode>(lastChild);
|
||||
}
|
||||
|
||||
optional_ownership_ptr<DataInnerNode> GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(DataNodeStore *nodeStore, DataNode *rootNode) {
|
||||
optional_ownership_ptr<DataInnerNode> currentNode = fspp::ptr::WithoutOwnership(dynamic_cast<DataInnerNode*>(rootNode));
|
||||
optional_ownership_ptr<DataInnerNode> result = fspp::ptr::null<DataInnerNode>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<datanodestore::DataInnerNode> run(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -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<FakeBlockStore>()) {
|
||||
}
|
||||
|
||||
unique_ptr<DataTree> CreateLeafOnlyTree() {
|
||||
auto leafnode = nodeStore.createNewLeafNode();
|
||||
return make_unique<DataTree>(&nodeStore, std::move(leafnode));
|
||||
}
|
||||
|
||||
DataNodeStore nodeStore;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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<FakeBlockStore>()) {
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user