diff --git a/test/implementations/onblocks/datatreestore/DataTreeTest_ResizeNumBytes.cpp b/test/implementations/onblocks/datatreestore/DataTreeTest_ResizeNumBytes.cpp index 2bbc3e86..64c9a8bb 100644 --- a/test/implementations/onblocks/datatreestore/DataTreeTest_ResizeNumBytes.cpp +++ b/test/implementations/onblocks/datatreestore/DataTreeTest_ResizeNumBytes.cpp @@ -1,6 +1,7 @@ #include "testutils/DataTreeTest.h" #include "testutils/TwoLevelDataFixture.h" #include "../../../../implementations/onblocks/utils/Math.h" +#include #include @@ -11,6 +12,7 @@ using std::tuple; using std::get; using std::function; using std::mem_fn; +using cpputils::dynamic_pointer_move; using blobstore::onblocks::datanodestore::DataLeafNode; using blobstore::onblocks::datanodestore::DataInnerNode; @@ -19,6 +21,7 @@ using blobstore::onblocks::datanodestore::DataNodeLayout; using blobstore::onblocks::datatreestore::DataTree; using blobstore::onblocks::utils::ceilDivision; using blockstore::Key; +using blockstore::Data; using std::unique_ptr; @@ -93,14 +96,32 @@ public: tree(get<0>(GetParam())(this, oldLastLeafSize)), newNumberOfLeaves(get<2>(GetParam())), newLastLeafSize(get<3>(GetParam())), - newSize((newNumberOfLeaves-1) * LAYOUT.maxBytesPerLeaf() + newLastLeafSize) - {} + newSize((newNumberOfLeaves-1) * LAYOUT.maxBytesPerLeaf() + newLastLeafSize), + ZEROES(LAYOUT.maxBytesPerLeaf()) + { + ZEROES.FillWithZeroes(); + } + + void ResizeTree(const Key &key, uint64_t size) { + treeStore.load(key)->resizeNumBytes(size); + } + + unique_ptr LastLeaf(const Key &key) { + auto root = nodeStore->load(key); + auto leaf = dynamic_pointer_move(root); + if (leaf.get() != nullptr) { + return leaf; + } + auto inner = dynamic_pointer_move(root); + return LastLeaf(inner->LastChild()->key()); + } uint32_t oldLastLeafSize; unique_ptr tree; uint32_t newNumberOfLeaves; uint32_t newLastLeafSize; uint64_t newSize; + Data ZEROES; }; INSTANTIATE_TEST_CASE_P(DataTreeTest_ResizeNumBytes_P, DataTreeTest_ResizeNumBytes_P, Combine( @@ -174,14 +195,44 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, DataStaysIntact) { Key key = tree->key(); tree.reset(); data.FillInto(nodeStore->load(key).get()); - tree = treeStore.load(key); - tree->resizeNumBytes(newSize); - tree.reset(); + ResizeTree(key, newSize); - //TODO Also check last leaf - data.EXPECT_DATA_CORRECT(nodeStore->load(key).get(), std::min(oldNumberOfLeaves-1, newNumberOfLeaves-1)); + if (oldNumberOfLeaves < newNumberOfLeaves || (oldNumberOfLeaves == newNumberOfLeaves && oldLastLeafSize < newLastLeafSize)) { + data.EXPECT_DATA_CORRECT(nodeStore->load(key).get(), oldNumberOfLeaves, oldLastLeafSize); + } else { + data.EXPECT_DATA_CORRECT(nodeStore->load(key).get(), newNumberOfLeaves, newLastLeafSize); + } } -//TODO Test resizing to zero size -//TODO Test that rest data of last leaf is zeroes +TEST_P(DataTreeTest_ResizeNumBytes_P, UnusedEndOfLastLeafIsZero) { + 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()); + + ResizeTree(key, newSize); + + auto lastLeaf = LastLeaf(key); + EXPECT_EQ(0, std::memcmp(ZEROES.data(), (char*)lastLeaf->data()+lastLeaf->numBytes(), LAYOUT.maxBytesPerLeaf()-lastLeaf->numBytes())); +} + + +//Resize to zero is not caught in the parametrized test above, in the following, we test it separately. + +TEST_F(DataTreeTest_ResizeNumBytes, ResizeToZero_NumBytesIsCorrect) { + auto tree = CreateThreeLevelTreeWithThreeChildrenAndLastLeafSize(10u); + tree->resizeNumBytes(0); + Key key = tree->key(); + tree.reset(); + auto leaf = LoadLeafNode(key); + EXPECT_EQ(0u, leaf->numBytes()); +} + +TEST_F(DataTreeTest_ResizeNumBytes, ResizeToZero_KeyDoesntChange) { + auto tree = CreateThreeLevelTreeWithThreeChildrenAndLastLeafSize(10u); + Key key = tree->key(); + tree->resizeNumBytes(0); + EXPECT_EQ(key, tree->key()); +} diff --git a/test/implementations/onblocks/datatreestore/testutils/LeafDataFixture.h b/test/implementations/onblocks/datatreestore/testutils/LeafDataFixture.h index e16e1943..6bede4d6 100644 --- a/test/implementations/onblocks/datatreestore/testutils/LeafDataFixture.h +++ b/test/implementations/onblocks/datatreestore/testutils/LeafDataFixture.h @@ -18,9 +18,14 @@ public: std::memcpy(leaf->data(), _data.data(), _data.size()); } - void EXPECT_DATA_CORRECT(const blobstore::onblocks::datanodestore::DataLeafNode &leaf) const { - EXPECT_EQ(_data.size(), leaf.numBytes()); - EXPECT_EQ(0, std::memcmp(_data.data(), leaf.data(), _data.size())); + void EXPECT_DATA_CORRECT(const blobstore::onblocks::datanodestore::DataLeafNode &leaf, int onlyCheckNumBytes = -1) const { + if (onlyCheckNumBytes == -1) { + EXPECT_EQ(_data.size(), leaf.numBytes()); + EXPECT_EQ(0, std::memcmp(_data.data(), leaf.data(), _data.size())); + } else { + EXPECT_LE(onlyCheckNumBytes, leaf.numBytes()); + EXPECT_EQ(0, std::memcmp(_data.data(), leaf.data(), onlyCheckNumBytes)); + } } private: diff --git a/test/implementations/onblocks/datatreestore/testutils/TwoLevelDataFixture.h b/test/implementations/onblocks/datatreestore/testutils/TwoLevelDataFixture.h index e396253c..0de9bc4b 100644 --- a/test/implementations/onblocks/datatreestore/testutils/TwoLevelDataFixture.h +++ b/test/implementations/onblocks/datatreestore/testutils/TwoLevelDataFixture.h @@ -26,9 +26,14 @@ public: }); } - 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, leaf), leafIndex).EXPECT_DATA_CORRECT(*leaf); + void EXPECT_DATA_CORRECT(blobstore::onblocks::datanodestore::DataNode *node, int maxCheckedLeaves = 0, int lastLeafMaxCheckedBytes = -1) { + ForEachLeaf(node, _iv, _iv+maxCheckedLeaves, [this, maxCheckedLeaves, lastLeafMaxCheckedBytes] (blobstore::onblocks::datanodestore::DataLeafNode *leaf, int leafIndex) { + if (leafIndex == _iv+maxCheckedLeaves-1) { + // It is the last leaf + LeafDataFixture(size(leafIndex, leaf), leafIndex).EXPECT_DATA_CORRECT(*leaf, lastLeafMaxCheckedBytes); + } else { + LeafDataFixture(size(leafIndex, leaf), leafIndex).EXPECT_DATA_CORRECT(*leaf); + } }); }