2016-02-11 15:19:58 +01:00
|
|
|
#include "blobstore/implementations/onblocks/datanodestore/DataInnerNode.h"
|
|
|
|
#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h"
|
|
|
|
#include "blobstore/implementations/onblocks/datanodestore/DataNode.h"
|
|
|
|
#include "blobstore/implementations/onblocks/datanodestore/DataNodeStore.h"
|
|
|
|
#include "blobstore/implementations/onblocks/BlobStoreOnBlocks.h"
|
|
|
|
#include <gtest/gtest.h>
|
2014-12-09 18:53:11 +01:00
|
|
|
|
2016-02-11 15:19:58 +01:00
|
|
|
#include <blockstore/implementations/testfake/FakeBlockStore.h>
|
|
|
|
#include <blockstore/implementations/testfake/FakeBlock.h>
|
|
|
|
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
|
2014-12-09 18:53:11 +01:00
|
|
|
|
|
|
|
using ::testing::Test;
|
2015-06-26 15:59:18 +02:00
|
|
|
using cpputils::unique_ref;
|
|
|
|
using cpputils::make_unique_ref;
|
2014-12-09 18:53:11 +01:00
|
|
|
using std::string;
|
2015-06-26 15:59:18 +02:00
|
|
|
using boost::none;
|
2014-12-09 18:53:11 +01:00
|
|
|
|
|
|
|
using blockstore::BlockStore;
|
2014-12-11 01:31:21 +01:00
|
|
|
using blockstore::testfake::FakeBlockStore;
|
2014-12-13 19:17:08 +01:00
|
|
|
using blockstore::Key;
|
2015-04-25 02:55:34 +02:00
|
|
|
using cpputils::Data;
|
2014-12-09 18:53:11 +01:00
|
|
|
using namespace blobstore;
|
|
|
|
using namespace blobstore::onblocks;
|
2014-12-13 19:17:08 +01:00
|
|
|
using namespace blobstore::onblocks::datanodestore;
|
2014-12-09 18:53:11 +01:00
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
class DataNodeStoreTest: public Test {
|
2014-12-09 18:53:11 +01:00
|
|
|
public:
|
2015-02-25 22:30:48 +01:00
|
|
|
static constexpr uint32_t BLOCKSIZE_BYTES = 1024;
|
|
|
|
|
2015-06-26 15:59:18 +02:00
|
|
|
unique_ref<BlockStore> _blockStore = make_unique_ref<FakeBlockStore>();
|
2014-12-13 17:43:02 +01:00
|
|
|
BlockStore *blockStore = _blockStore.get();
|
2015-06-26 15:59:18 +02:00
|
|
|
unique_ref<DataNodeStore> nodeStore = make_unique_ref<DataNodeStore>(std::move(_blockStore), BLOCKSIZE_BYTES);
|
2014-12-09 18:53:11 +01:00
|
|
|
};
|
|
|
|
|
2015-02-25 22:30:48 +01:00
|
|
|
constexpr uint32_t DataNodeStoreTest::BLOCKSIZE_BYTES;
|
|
|
|
|
2014-12-09 18:53:11 +01:00
|
|
|
#define EXPECT_IS_PTR_TYPE(Type, ptr) EXPECT_NE(nullptr, dynamic_cast<Type*>(ptr)) << "Given pointer cannot be cast to the given type"
|
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, CreateLeafNodeCreatesLeafNode) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto node = nodeStore->createNewLeafNode(Data(0));
|
2014-12-10 22:55:02 +01:00
|
|
|
EXPECT_IS_PTR_TYPE(DataLeafNode, node.get());
|
|
|
|
}
|
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, CreateInnerNodeCreatesInnerNode) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
2014-12-13 12:00:19 +01:00
|
|
|
|
2016-07-15 12:48:20 +02:00
|
|
|
auto node = nodeStore->createNewInnerNode(1, {leaf->key()});
|
2014-12-10 22:55:02 +01:00
|
|
|
EXPECT_IS_PTR_TYPE(DataInnerNode, node.get());
|
|
|
|
}
|
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, LeafNodeIsRecognizedAfterStoreAndLoad) {
|
2016-07-15 12:48:20 +02:00
|
|
|
Key key = nodeStore->createNewLeafNode(Data(0))->key();
|
2014-12-09 18:53:11 +01:00
|
|
|
|
2015-06-28 16:59:13 +02:00
|
|
|
auto loaded_node = nodeStore->load(key).value();
|
2014-12-09 18:53:11 +01:00
|
|
|
|
|
|
|
EXPECT_IS_PTR_TYPE(DataLeafNode, loaded_node.get());
|
|
|
|
}
|
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, InnerNodeWithDepth1IsRecognizedAfterStoreAndLoad) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
Key key = nodeStore->createNewInnerNode(1, {leaf->key()})->key();
|
2014-12-13 12:00:19 +01:00
|
|
|
|
2015-06-28 16:59:13 +02:00
|
|
|
auto loaded_node = nodeStore->load(key).value();
|
2014-12-13 12:00:19 +01:00
|
|
|
|
|
|
|
EXPECT_IS_PTR_TYPE(DataInnerNode, loaded_node.get());
|
|
|
|
}
|
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, InnerNodeWithDepth2IsRecognizedAfterStoreAndLoad) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
auto inner = nodeStore->createNewInnerNode(1, {leaf->key()});
|
|
|
|
Key key = nodeStore->createNewInnerNode(2, {inner->key()})->key();
|
2014-12-09 18:53:11 +01:00
|
|
|
|
2015-06-28 16:59:13 +02:00
|
|
|
auto loaded_node = nodeStore->load(key).value();
|
2014-12-09 18:53:11 +01:00
|
|
|
|
|
|
|
EXPECT_IS_PTR_TYPE(DataInnerNode, loaded_node.get());
|
|
|
|
}
|
2014-12-09 18:56:45 +01:00
|
|
|
|
2014-12-13 17:49:54 +01:00
|
|
|
TEST_F(DataNodeStoreTest, DataNodeCrashesOnLoadIfDepthIsTooHigh) {
|
2015-04-25 00:08:29 +02:00
|
|
|
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
2015-01-24 22:27:14 +01:00
|
|
|
Key key = block->key();
|
2014-12-10 16:48:00 +01:00
|
|
|
{
|
2015-01-24 22:27:14 +01:00
|
|
|
DataNodeView view(std::move(block));
|
2015-03-04 20:58:39 +01:00
|
|
|
view.setDepth(DataNodeStore::MAX_DEPTH + 1);
|
2014-12-10 16:48:00 +01:00
|
|
|
}
|
2014-12-09 18:56:45 +01:00
|
|
|
|
|
|
|
EXPECT_ANY_THROW(
|
2014-12-13 17:43:02 +01:00
|
|
|
nodeStore->load(key)
|
2014-12-09 18:56:45 +01:00
|
|
|
);
|
|
|
|
}
|
2015-01-23 02:41:55 +01:00
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, CreatedInnerNodeIsInitialized) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
auto node = nodeStore->createNewInnerNode(1, {leaf->key()});
|
2015-01-23 02:41:55 +01:00
|
|
|
EXPECT_EQ(1u, node->numChildren());
|
|
|
|
EXPECT_EQ(leaf->key(), node->getChild(0)->key());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, CreatedLeafNodeIsInitialized) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
2015-01-23 02:41:55 +01:00
|
|
|
EXPECT_EQ(0u, leaf->numBytes());
|
|
|
|
}
|
2015-02-24 16:52:11 +01:00
|
|
|
|
2015-02-24 16:54:44 +01:00
|
|
|
TEST_F(DataNodeStoreTest, NodeIsNotLoadableAfterDeleting) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto nodekey = nodeStore->createNewLeafNode(Data(0))->key();
|
2015-02-24 16:54:44 +01:00
|
|
|
auto node = nodeStore->load(nodekey);
|
2015-06-26 15:59:18 +02:00
|
|
|
EXPECT_NE(none, node);
|
|
|
|
nodeStore->remove(std::move(*node));
|
|
|
|
EXPECT_EQ(none, nodeStore->load(nodekey));
|
2015-02-24 16:54:44 +01:00
|
|
|
}
|
|
|
|
|
2015-02-24 16:52:11 +01:00
|
|
|
TEST_F(DataNodeStoreTest, NumNodesIsCorrectOnEmptyNodestore) {
|
2016-02-11 15:19:58 +01:00
|
|
|
EXPECT_EQ(0u, nodeStore->numNodes());
|
2015-02-24 16:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, NumNodesIsCorrectAfterAddingOneLeafNode) {
|
2016-07-15 12:48:20 +02:00
|
|
|
nodeStore->createNewLeafNode(Data(0));
|
2016-02-11 15:19:58 +01:00
|
|
|
EXPECT_EQ(1u, nodeStore->numNodes());
|
2015-02-24 16:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, NumNodesIsCorrectAfterRemovingTheLastNode) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
2015-02-24 16:52:11 +01:00
|
|
|
nodeStore->remove(std::move(leaf));
|
2016-02-11 15:19:58 +01:00
|
|
|
EXPECT_EQ(0u, nodeStore->numNodes());
|
2015-02-24 16:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, NumNodesIsCorrectAfterAddingTwoNodes) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
auto node = nodeStore->createNewInnerNode(1, {leaf->key()});
|
2016-02-11 15:19:58 +01:00
|
|
|
EXPECT_EQ(2u, nodeStore->numNodes());
|
2015-02-24 16:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, NumNodesIsCorrectAfterRemovingANode) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
auto node = nodeStore->createNewInnerNode(1, {leaf->key()});
|
2015-02-24 16:52:11 +01:00
|
|
|
nodeStore->remove(std::move(node));
|
2016-02-11 15:19:58 +01:00
|
|
|
EXPECT_EQ(1u, nodeStore->numNodes());
|
2015-02-24 16:52:11 +01:00
|
|
|
}
|
2016-03-16 20:30:26 +01:00
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, PhysicalBlockSize_Leaf) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
2016-03-16 20:30:26 +01:00
|
|
|
auto block = blockStore->load(leaf->key()).value();
|
|
|
|
EXPECT_EQ(BLOCKSIZE_BYTES, block->size());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataNodeStoreTest, PhysicalBlockSize_Inner) {
|
2016-07-15 12:48:20 +02:00
|
|
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
|
|
|
auto node = nodeStore->createNewInnerNode(1, {leaf->key()});
|
2016-03-16 20:30:26 +01:00
|
|
|
auto block = blockStore->load(node->key()).value();
|
|
|
|
EXPECT_EQ(BLOCKSIZE_BYTES, block->size());
|
|
|
|
}
|