Add test cases for DataTree::resizeNumBytes()

This commit is contained in:
Sebastian Messmer 2015-03-04 02:05:03 +01:00
parent 13a76bd42a
commit 0e91d06a6f
7 changed files with 314 additions and 110 deletions

View File

@ -16,76 +16,6 @@ using std::unique_ptr;
class DataTreeTest_NumStoredBytes: public DataTreeTest {
public:
unique_ptr<DataLeafNode> CreateLeafWithSize(uint32_t size) {
auto leaf = CreateLeaf();
leaf->resize(size);
return leaf;
}
unique_ptr<DataInnerNode> CreateTwoLeafWithSecondLeafSize(uint32_t size) {
return CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
});
}
unique_ptr<DataInnerNode> CreateFullTwoLevelWithLastLeafSize(uint32_t size) {
auto root = CreateFullTwoLevel();
for (int i = 0; i < root->numChildren()-1; ++i) {
LoadLeafNode(root->getChild(i)->key())->resize(nodeStore->layout().maxBytesPerLeaf());
}
LoadLeafNode(root->LastChild()->key())->resize(size);
return root;
}
unique_ptr<DataInnerNode> CreateThreeLevelWithOneChildAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> CreateThreeLevelWithTwoChildrenAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> CreateThreeLevelWithThreeChildrenAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> CreateFullThreeLevelWithLastLeafSize(uint32_t size) {
auto root = CreateFullThreeLevel();
for (int i = 0; i < root->numChildren(); ++i) {
auto node = LoadInnerNode(root->getChild(i)->key());
for (int j = 0; j < node->numChildren(); ++j) {
LoadLeafNode(node->getChild(j)->key())->resize(nodeStore->layout().maxBytesPerLeaf());
}
}
LoadLeafNode(LoadInnerNode(root->LastChild()->key())->LastChild()->key())->resize(size);
return root;
}
unique_ptr<DataInnerNode> CreateFourLevelMinDataWithLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullThreeLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({CreateInner({CreateLeafWithSize(size)})})
});
}
};
TEST_F(DataTreeTest_NumStoredBytes, CreatedTreeIsEmpty) {

View File

@ -0,0 +1,187 @@
#include "testutils/DataTreeTest.h"
#include "testutils/TwoLevelDataFixture.h"
#include "../../../../implementations/onblocks/utils/Math.h"
#include <tuple>
using ::testing::WithParamInterface;
using ::testing::Values;
using ::testing::Combine;
using std::tuple;
using std::get;
using std::function;
using std::mem_fn;
using blobstore::onblocks::datanodestore::DataLeafNode;
using blobstore::onblocks::datanodestore::DataInnerNode;
using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataNodeLayout;
using blobstore::onblocks::datatreestore::DataTree;
using blobstore::onblocks::utils::ceilDivision;
using blockstore::Key;
using std::unique_ptr;
class DataTreeTest_ResizeNumBytes: public DataTreeTest {
public:
static constexpr DataNodeLayout LAYOUT = DataNodeLayout(BLOCKSIZE_BYTES);
unique_ptr<DataTree> CreateTree(unique_ptr<DataNode> root) {
Key key = root->key();
root.reset();
return treeStore.load(key);
}
unique_ptr<DataTree> CreateLeafTreeWithSize(uint32_t size) {
return CreateTree(CreateLeafWithSize(size));
}
unique_ptr<DataTree> CreateTwoLeafTreeWithSecondLeafSize(uint32_t size) {
return CreateTree(CreateTwoLeafWithSecondLeafSize(size));
}
unique_ptr<DataTree> CreateFullTwoLevelTreeWithLastLeafSize(uint32_t size) {
return CreateTree(CreateFullTwoLevelWithLastLeafSize(size));
}
unique_ptr<DataTree> CreateThreeLevelTreeWithTwoChildrenAndLastLeafSize(uint32_t size) {
return CreateTree(CreateThreeLevelWithTwoChildrenAndLastLeafSize(size));
}
unique_ptr<DataTree> CreateThreeLevelTreeWithThreeChildrenAndLastLeafSize(uint32_t size) {
return CreateTree(CreateThreeLevelWithThreeChildrenAndLastLeafSize(size));
}
unique_ptr<DataTree> CreateFullThreeLevelTreeWithLastLeafSize(uint32_t size) {
return CreateTree(CreateFullThreeLevelWithLastLeafSize(size));
}
unique_ptr<DataTree> CreateFourLevelMinDataTreeWithLastLeafSize(uint32_t size) {
return CreateTree(CreateFourLevelMinDataWithLastLeafSize(size));
}
void EXPECT_IS_LEFTMAXDATA_TREE(const Key &key) {
auto root = nodeStore->load(key);
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
if (inner != nullptr) {
for (int i = 0; i < inner->numChildren()-1; ++i) {
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->key());
}
EXPECT_IS_LEFTMAXDATA_TREE(inner->LastChild()->key());
}
}
void EXPECT_IS_MAXDATA_TREE(const Key &key) {
auto root = nodeStore->load(key);
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
if (inner != nullptr) {
for (int i = 0; i < inner->numChildren(); ++i) {
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->key());
}
} else {
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root.get());
EXPECT_EQ(nodeStore->layout().maxBytesPerLeaf(), leaf->numBytes());
}
}
};
constexpr DataNodeLayout DataTreeTest_ResizeNumBytes::LAYOUT;
class DataTreeTest_ResizeNumBytes_P: public DataTreeTest_ResizeNumBytes, public WithParamInterface<tuple<function<unique_ptr<DataTree>(DataTreeTest_ResizeNumBytes*, uint32_t)>, uint32_t, uint32_t, uint32_t>> {
public:
DataTreeTest_ResizeNumBytes_P()
: oldLastLeafSize(get<1>(GetParam())),
tree(get<0>(GetParam())(this, oldLastLeafSize)),
newNumberOfLeaves(get<2>(GetParam())),
newLastLeafSize(get<3>(GetParam())),
newSize((newNumberOfLeaves-1) * LAYOUT.maxBytesPerLeaf() + newLastLeafSize)
{}
uint32_t oldLastLeafSize;
unique_ptr<DataTree> tree;
uint32_t newNumberOfLeaves;
uint32_t newLastLeafSize;
uint64_t newSize;
};
INSTANTIATE_TEST_CASE_P(DataTreeTest_ResizeNumBytes_P, DataTreeTest_ResizeNumBytes_P,
Combine(
//Tree we're starting with
Values<function<unique_ptr<DataTree>(DataTreeTest_ResizeNumBytes*, uint32_t)>>(
mem_fn(&DataTreeTest_ResizeNumBytes::CreateLeafTreeWithSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateTwoLeafTreeWithSecondLeafSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateFullTwoLevelTreeWithLastLeafSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateThreeLevelTreeWithTwoChildrenAndLastLeafSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateThreeLevelTreeWithThreeChildrenAndLastLeafSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateFullThreeLevelTreeWithLastLeafSize),
mem_fn(&DataTreeTest_ResizeNumBytes::CreateFourLevelMinDataTreeWithLastLeafSize)
),
//Last leaf size of the start tree
Values(
0u,
1u,
10u,
DataTreeTest_ResizeNumBytes::LAYOUT.maxBytesPerLeaf()
),
//Number of leaves we're resizing to
Values(
1u,
2u,
DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode(), //Full two level tree
2* DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode(), //Three level tree with two children
3* DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode(), //Three level tree with three children
DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode() * DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode(), //Full three level tree
DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode() * DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode() + 1 //Four level mindata tree
),
//Last leaf size of the resized tree
Values(
1u,
10u,
DataTreeTest_ResizeNumBytes::LAYOUT.maxBytesPerLeaf()
)
)
);
TEST_P(DataTreeTest_ResizeNumBytes_P, StructureIsValid) {
tree->resizeNumBytes(newSize);
tree->flush();
EXPECT_IS_LEFTMAXDATA_TREE(tree->key());
}
TEST_P(DataTreeTest_ResizeNumBytes_P, NumBytesIsCorrect) {
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.
// This is what the StructureIsValid test case is for.
EXPECT_EQ(newSize, tree->numStoredBytes());
}
TEST_P(DataTreeTest_ResizeNumBytes_P, DepthFlagsAreCorrect) {
tree->resizeNumBytes(newSize);
tree->flush();
uint32_t depth = ceil(log(newNumberOfLeaves)/log(DataTreeTest_ResizeNumBytes::LAYOUT.maxChildrenPerInnerNode()));
CHECK_DEPTH(depth, tree->key());
}
TEST_P(DataTreeTest_ResizeNumBytes_P, KeyDoesntChange) {
Key key = tree->key();
tree->resizeNumBytes(newSize);
tree->flush();
EXPECT_EQ(key, tree->key());
}
TEST_P(DataTreeTest_ResizeNumBytes_P, DataStaysIntact) {
uint32_t oldNumberOfLeaves = std::max(1u, ceilDivision(tree->numStoredBytes(), nodeStore->layout().maxBytesPerLeaf()));
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Unchanged);
Key key = tree->key();
tree.reset();
data.FillInto(nodeStore->load(key).get());
tree = treeStore.load(key);
tree->resizeNumBytes(newSize);
tree.reset();
//TODO Also check last leaf
data.EXPECT_DATA_CORRECT(nodeStore->load(key).get(), std::min(oldNumberOfLeaves-1, newNumberOfLeaves-1));
}
//TODO Test resizing to zero size
//TODO Test that rest data of last leaf is zeroes

View File

@ -46,57 +46,57 @@ public:
};
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAFullTwoLevelTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnGrowing(CreateFullTwoLevel(), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAFullTwoLevelTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnGrowing(CreateFullTwoLevel(), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeLevelTreeWithLowerLevelFull_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
auto node = CreateInner({CreateFullTwoLevel()});
TestDataStaysIntactOnGrowing(std::move(node), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeLevelTreeWithLowerLevelFull_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
auto node = CreateInner({CreateFullTwoLevel()});
TestDataStaysIntactOnGrowing(std::move(node), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAOneNodeTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnGrowing(CreateLeaf(), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAOneNodeTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnGrowing(CreateLeaf(), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowATwoNodeTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
auto node = CreateInner({CreateLeaf()});
TestDataStaysIntactOnGrowing(std::move(node), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowATwoNodeTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
auto node = CreateInner({CreateLeaf()});
TestDataStaysIntactOnGrowing(std::move(node), &data);
}
TEST_F(DataTreeGrowingTest_DataStaysIntact, GrowAThreeNodeChainedTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
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, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
auto node = CreateInner({CreateInner({CreateLeaf()})});
TestDataStaysIntactOnGrowing(std::move(node), &data);
}

View File

@ -29,101 +29,101 @@ public:
};
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoLeafTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateTwoLeaf(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoLeafTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateTwoLeaf(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourNodeThreeLeafTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateFourNodeThreeLeaf(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourNodeThreeLeafTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateFourNodeThreeLeaf(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeOneTwoLeavesTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeOneTwoLeaves(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeOneTwoLeavesTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeOneTwoLeaves(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeTwoOneLeavesTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeTwoOneLeaves(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATwoInnerNodeTwoOneLeavesTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateTwoInnerNodeTwoOneLeaves(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelMinDataTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateThreeLevelMinData(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelMinDataTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateThreeLevelMinData(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelMinDataTree_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateFourLevelMinData(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelMinDataTree_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateFourLevelMinData(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves1_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves1(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves1_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves1(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves2_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves2(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAFourLevelTreeWithTwoSiblingLeaves2_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateFourLevelWithTwoSiblingLeaves2(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkATreeWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateWithFirstChildOfRootFullThreelevelAndSecondChildMindataThreelevel(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot_FullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, true);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Full);
TestDataStaysIntactOnShrinking(CreateThreeLevelWithThreeChildrenOfRoot(), &data);
}
TEST_F(DataTreeShrinkingTest_DataStaysIntact, ShrinkAThreeLevelTreeWithThreeChildrenOfRoot_NonFullLeaves) {
TwoLevelDataFixture data(nodeStore, 0, false);
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Random);
TestDataStaysIntactOnShrinking(CreateThreeLevelWithThreeChildrenOfRoot(), &data);
}

View File

@ -113,6 +113,77 @@ unique_ptr<DataTree> DataTreeTest::CreateTwoLeafTree() {
return treeStore.load(key);
}
unique_ptr<DataLeafNode> DataTreeTest::CreateLeafWithSize(uint32_t size) {
auto leaf = CreateLeaf();
leaf->resize(size);
return leaf;
}
unique_ptr<DataInnerNode> DataTreeTest::CreateTwoLeafWithSecondLeafSize(uint32_t size) {
return CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
});
}
unique_ptr<DataInnerNode> DataTreeTest::CreateFullTwoLevelWithLastLeafSize(uint32_t size) {
auto root = CreateFullTwoLevel();
for (int i = 0; i < root->numChildren()-1; ++i) {
LoadLeafNode(root->getChild(i)->key())->resize(nodeStore->layout().maxBytesPerLeaf());
}
LoadLeafNode(root->LastChild()->key())->resize(size);
return root;
}
unique_ptr<DataInnerNode> DataTreeTest::CreateThreeLevelWithOneChildAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> DataTreeTest::CreateThreeLevelWithTwoChildrenAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> DataTreeTest::CreateThreeLevelWithThreeChildrenAndLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateFullTwoLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({
CreateLeafWithSize(nodeStore->layout().maxBytesPerLeaf()),
CreateLeafWithSize(size)
})
});
}
unique_ptr<DataInnerNode> DataTreeTest::CreateFullThreeLevelWithLastLeafSize(uint32_t size) {
auto root = CreateFullThreeLevel();
for (int i = 0; i < root->numChildren(); ++i) {
auto node = LoadInnerNode(root->getChild(i)->key());
for (int j = 0; j < node->numChildren(); ++j) {
LoadLeafNode(node->getChild(j)->key())->resize(nodeStore->layout().maxBytesPerLeaf());
}
}
LoadLeafNode(LoadInnerNode(root->LastChild()->key())->LastChild()->key())->resize(size);
return root;
}
unique_ptr<DataInnerNode> DataTreeTest::CreateFourLevelMinDataWithLastLeafSize(uint32_t size) {
return CreateInner({
CreateFullThreeLevelWithLastLeafSize(nodeStore->layout().maxBytesPerLeaf()),
CreateInner({CreateInner({CreateLeafWithSize(size)})})
});
}
void DataTreeTest::EXPECT_IS_LEAF_NODE(const Key &key) {
auto node = LoadLeafNode(key);
EXPECT_NE(nullptr, node.get());

View File

@ -14,7 +14,7 @@ class DataTreeTest: public ::testing::Test {
public:
DataTreeTest();
static constexpr uint32_t BLOCKSIZE_BYTES = 1024;
static constexpr uint32_t BLOCKSIZE_BYTES = 256;
std::unique_ptr<blobstore::onblocks::datanodestore::DataLeafNode> CreateLeaf();
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateInner(std::vector<const blobstore::onblocks::datanodestore::DataNode *> children);
@ -35,6 +35,15 @@ public:
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> LoadInnerNode(const blockstore::Key &key);
std::unique_ptr<blobstore::onblocks::datanodestore::DataLeafNode> LoadLeafNode(const blockstore::Key &key);
std::unique_ptr<blobstore::onblocks::datanodestore::DataLeafNode> CreateLeafWithSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateTwoLeafWithSecondLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFullTwoLevelWithLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateThreeLevelWithOneChildAndLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateThreeLevelWithTwoChildrenAndLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateThreeLevelWithThreeChildrenAndLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFullThreeLevelWithLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataInnerNode> CreateFourLevelMinDataWithLastLeafSize(uint32_t size);
std::unique_ptr<blobstore::onblocks::datanodestore::DataNodeStore> _nodeStore;
blobstore::onblocks::datanodestore::DataNodeStore *nodeStore;
blobstore::onblocks::datatreestore::DataTreeStore treeStore;

View File

@ -12,18 +12,23 @@
// and given an inner node can check, whether the data stored is correct.
class TwoLevelDataFixture {
public:
TwoLevelDataFixture(blobstore::onblocks::datanodestore::DataNodeStore *dataNodeStore, int iv=0, bool useFullSizeLeaves = false): _dataNodeStore(dataNodeStore), _iv(iv), _useFullSizeLeaves(useFullSizeLeaves) {}
enum class SizePolicy {
Random,
Full,
Unchanged
};
TwoLevelDataFixture(blobstore::onblocks::datanodestore::DataNodeStore *dataNodeStore, SizePolicy sizePolicy, int iv=0): _dataNodeStore(dataNodeStore), _iv(iv), _sizePolicy(sizePolicy) {}
void FillInto(blobstore::onblocks::datanodestore::DataNode *node) {
// _iv-1 means there is no endLeafIndex - we fill all leaves.
ForEachLeaf(node, _iv, _iv-1, [this] (blobstore::onblocks::datanodestore::DataLeafNode *leaf, int leafIndex) {
LeafDataFixture(size(leafIndex), leafIndex).FillInto(leaf);
LeafDataFixture(size(leafIndex, leaf), leafIndex).FillInto(leaf);
});
}
void EXPECT_DATA_CORRECT(blobstore::onblocks::datanodestore::DataNode *node, int maxCheckedLeaves = 0) {
ForEachLeaf(node, _iv, _iv+maxCheckedLeaves, [this] (blobstore::onblocks::datanodestore::DataLeafNode *leaf, int leafIndex) {
LeafDataFixture(size(leafIndex), leafIndex).EXPECT_DATA_CORRECT(*leaf);
LeafDataFixture(size(leafIndex, leaf), leafIndex).EXPECT_DATA_CORRECT(*leaf);
});
}
@ -49,14 +54,16 @@ private:
blobstore::onblocks::datanodestore::DataNodeStore *_dataNodeStore;
int _iv;
bool _useFullSizeLeaves;
SizePolicy _sizePolicy;
int size(int childIndex) {
if (_useFullSizeLeaves) {
int size(int childIndex, blobstore::onblocks::datanodestore::DataLeafNode *leaf) {
switch (_sizePolicy) {
case SizePolicy::Full:
return _dataNodeStore->layout().maxBytesPerLeaf();
} else {
uint32_t maxBytesPerLeaf = _dataNodeStore->layout().maxBytesPerLeaf();
return mod(maxBytesPerLeaf - childIndex, maxBytesPerLeaf);
case SizePolicy::Random:
return mod(_dataNodeStore->layout().maxBytesPerLeaf() - childIndex, _dataNodeStore->layout().maxBytesPerLeaf());
case SizePolicy::Unchanged:
return leaf->numBytes();
}
}