Add test cases for DataTree::resizeNumBytes()
This commit is contained in:
parent
13a76bd42a
commit
0e91d06a6f
@ -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) {
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user