summaryrefslogtreecommitdiffstats
path: root/src/test/librbd/cache/pwl/test_WriteLogMap.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/librbd/cache/pwl/test_WriteLogMap.cc')
-rw-r--r--src/test/librbd/cache/pwl/test_WriteLogMap.cc336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/test/librbd/cache/pwl/test_WriteLogMap.cc b/src/test/librbd/cache/pwl/test_WriteLogMap.cc
new file mode 100644
index 000000000..7263d0831
--- /dev/null
+++ b/src/test/librbd/cache/pwl/test_WriteLogMap.cc
@@ -0,0 +1,336 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
+
+#include "librbd/cache/pwl/LogMap.cc"
+
+void register_test_write_log_map() {
+}
+
+namespace librbd {
+namespace cache {
+namespace pwl {
+
+struct TestLogEntry {
+ uint64_t image_offset_bytes;
+ uint64_t write_bytes;
+ uint32_t referring_map_entries = 0;
+ TestLogEntry(const uint64_t image_offset_bytes, const uint64_t write_bytes)
+ : image_offset_bytes(image_offset_bytes), write_bytes(write_bytes) {
+ }
+ uint64_t get_offset_bytes() {
+ return image_offset_bytes;
+ }
+ uint64_t get_write_bytes() {
+ return write_bytes;
+ }
+ BlockExtent block_extent() {
+ return BlockExtent(image_offset_bytes, image_offset_bytes + write_bytes);
+ }
+ uint32_t get_map_ref() {
+ return referring_map_entries;
+ }
+ void inc_map_ref() {
+ referring_map_entries++;
+ }
+ void dec_map_ref() {
+ referring_map_entries--;
+ }
+ friend std::ostream &operator<<(std::ostream &os,
+ const TestLogEntry &entry) {
+ os << "referring_map_entries=" << entry.referring_map_entries << ", "
+ << "image_offset_bytes=" << entry.image_offset_bytes << ", "
+ << "write_bytes=" << entry.write_bytes;
+ return os;
+ };
+};
+
+typedef std::list<std::shared_ptr<TestLogEntry>> TestLogEntries;
+typedef LogMapEntry<TestLogEntry> TestMapEntry;
+typedef LogMapEntries<TestLogEntry> TestLogMapEntries;
+typedef LogMap<TestLogEntry> TestLogMap;
+
+class TestWriteLogMap : public TestFixture {
+public:
+ void SetUp() override {
+ TestFixture::SetUp();
+ m_cct = reinterpret_cast<CephContext*>(m_ioctx.cct());
+ }
+
+ CephContext *m_cct;
+};
+
+TEST_F(TestWriteLogMap, Simple) {
+ TestLogEntries es;
+ TestLogMapEntries lme;
+ TestLogMap map(m_cct);
+
+ /* LogEntry takes offset, length, in bytes */
+ auto e1 = make_shared<TestLogEntry>(4, 8);
+ TestLogEntry *e1_ptr = e1.get();
+ ASSERT_EQ(4, e1_ptr->get_offset_bytes());
+ ASSERT_EQ(8, e1_ptr->get_write_bytes());
+ map.add_log_entry(e1);
+
+ /* BlockExtent takes first, last, in blocks */
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
+ int numfound = found0.size();
+ /* Written range includes the single write above */
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+
+ /* Nothing before that */
+ found0 = map.find_map_entries(BlockExtent(0, 3));
+ numfound = found0.size();
+ ASSERT_EQ(0, numfound);
+
+ /* Nothing after that */
+ found0 = map.find_map_entries(BlockExtent(12, 99));
+ numfound = found0.size();
+ ASSERT_EQ(0, numfound);
+
+ /* 4-11 will be e1 */
+ for (int i=4; i<12; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ }
+
+ map.remove_log_entry(e1);
+ /* Nothing should be found */
+ for (int i=4; i<12; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(0, numfound);
+ }
+}
+
+TEST_F(TestWriteLogMap, OverlapFront) {
+ TestLogMap map(m_cct);
+
+ auto e0 = make_shared<TestLogEntry>(4, 8);
+ map.add_log_entry(e0);
+ /* replaces block 4-7 of e0 */
+ auto e1 = make_shared<TestLogEntry>(0, 8);
+ map.add_log_entry(e1);
+
+ /* Written range includes the two writes above */
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
+ int numfound = found0.size();
+ ASSERT_EQ(2, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ ASSERT_EQ(0, found0.front().block_extent.block_start);
+ ASSERT_EQ(8, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e0, found0.front().log_entry);
+ ASSERT_EQ(8, found0.front().block_extent.block_start);
+ ASSERT_EQ(12, found0.front().block_extent.block_end);
+
+ /* 0-7 will be e1 */
+ for (int i=0; i<8; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ }
+
+ /* 8-11 will be e0 */
+ for (int i=8; i<12; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ }
+}
+
+TEST_F(TestWriteLogMap, OverlapBack) {
+ TestLogMap map(m_cct);
+
+ auto e0 = make_shared<TestLogEntry>(0, 8);
+ map.add_log_entry(e0);
+ /* replaces block 4-7 of e0 */
+ auto e1 = make_shared<TestLogEntry>(4, 8);
+ map.add_log_entry(e1);
+
+ /* Written range includes the two writes above */
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
+ int numfound = found0.size();
+ ASSERT_EQ(2, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ ASSERT_EQ(0, found0.front().block_extent.block_start);
+ ASSERT_EQ(4, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e1, found0.front().log_entry);
+ ASSERT_EQ(4, found0.front().block_extent.block_start);
+ ASSERT_EQ(12, found0.front().block_extent.block_end);
+
+ /* 0-3 will be e0 */
+ for (int i=0; i<4; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ }
+
+ /* 4-11 will be e1 */
+ for (int i=4; i<12; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ }
+
+ map.remove_log_entry(e0);
+
+ /* 0-3 will find nothing */
+ for (int i=0; i<4; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(0, numfound);
+ }
+
+ /* 4-11 will still be e1 */
+ for (int i=4; i<12; i++) {
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(i, i + 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ }
+
+}
+
+TEST_F(TestWriteLogMap, OverlapMiddle) {
+ TestLogMap map(m_cct);
+
+ auto e0 = make_shared<TestLogEntry>(0, 1);
+ map.add_log_entry(e0);
+
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 1));
+ int numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ TestLogEntries entries = map.find_log_entries(BlockExtent(0, 1));
+ int entriesfound = entries.size();
+ ASSERT_EQ(1, entriesfound);
+ ASSERT_EQ(e0, entries.front());
+
+ auto e1 = make_shared<TestLogEntry>(1, 1);
+ map.add_log_entry(e1);
+
+ found0 = map.find_map_entries(BlockExtent(1, 2));
+ numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e1, found0.front().log_entry);
+ entries = map.find_log_entries(BlockExtent(1, 2));
+ entriesfound = entries.size();
+ ASSERT_EQ(1, entriesfound);
+ ASSERT_EQ(e1, entries.front());
+
+ auto e2 = make_shared<TestLogEntry>(2, 1);
+ map.add_log_entry(e2);
+
+ found0 = map.find_map_entries(BlockExtent(2, 3));
+ numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e2, found0.front().log_entry);
+ entries = map.find_log_entries(BlockExtent(2, 3));
+ entriesfound = entries.size();
+ ASSERT_EQ(1, entriesfound);
+ ASSERT_EQ(e2, entries.front());
+
+ /* replaces e1 */
+ auto e3 = make_shared<TestLogEntry>(1, 1);
+ map.add_log_entry(e3);
+
+ found0 = map.find_map_entries(BlockExtent(1, 2));
+ numfound = found0.size();
+ ASSERT_EQ(1, numfound);
+ ASSERT_EQ(e3, found0.front().log_entry);
+ entries = map.find_log_entries(BlockExtent(1, 2));
+ entriesfound = entries.size();
+ ASSERT_EQ(1, entriesfound);
+ ASSERT_EQ(e3, entries.front());
+
+ found0 = map.find_map_entries(BlockExtent(0, 100));
+ numfound = found0.size();
+ ASSERT_EQ(3, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ found0.pop_front();
+ ASSERT_EQ(e3, found0.front().log_entry);
+ found0.pop_front();
+ ASSERT_EQ(e2, found0.front().log_entry);
+ entries = map.find_log_entries(BlockExtent(0, 100));
+ entriesfound = entries.size();
+ ASSERT_EQ(3, entriesfound);
+ ASSERT_EQ(e0, entries.front());
+ entries.pop_front();
+ ASSERT_EQ(e3, entries.front());
+ entries.pop_front();
+ ASSERT_EQ(e2, entries.front());
+
+ entries.clear();
+ entries.emplace_back(e0);
+ entries.emplace_back(e1);
+ map.remove_log_entries(entries);
+
+ found0 = map.find_map_entries(BlockExtent(0, 100));
+ numfound = found0.size();
+ ASSERT_EQ(2, numfound);
+ ASSERT_EQ(e3, found0.front().log_entry);
+ found0.pop_front();
+ ASSERT_EQ(e2, found0.front().log_entry);
+}
+
+TEST_F(TestWriteLogMap, OverlapSplit) {
+ TestLogMap map(m_cct);
+
+ auto e0 = make_shared<TestLogEntry>(0, 8);
+ map.add_log_entry(e0);
+
+ /* Splits e0 at 1 */
+ auto e1 = make_shared<TestLogEntry>(1, 1);
+ map.add_log_entry(e1);
+
+ /* Splits e0 again at 4 */
+ auto e2 = make_shared<TestLogEntry>(4, 2);
+ map.add_log_entry(e2);
+
+ /* Replaces one block of e2, and one of e0 */
+ auto e3 = make_shared<TestLogEntry>(5, 2);
+ map.add_log_entry(e3);
+
+ /* Expecting: 0:e0, 1:e1, 2..3:e0, 4:e2, 5..6:e3, 7:e0 */
+ TestLogMapEntries found0 = map.find_map_entries(BlockExtent(0, 100));
+ int numfound = found0.size();
+ ASSERT_EQ(6, numfound);
+ ASSERT_EQ(e0, found0.front().log_entry);
+ ASSERT_EQ(0, found0.front().block_extent.block_start);
+ ASSERT_EQ(1, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e1, found0.front().log_entry);
+ ASSERT_EQ(1, found0.front().block_extent.block_start);
+ ASSERT_EQ(2, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e0, found0.front().log_entry);
+ ASSERT_EQ(2, found0.front().block_extent.block_start);
+ ASSERT_EQ(4, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e2, found0.front().log_entry);
+ ASSERT_EQ(4, found0.front().block_extent.block_start);
+ ASSERT_EQ(5, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e3, found0.front().log_entry);
+ ASSERT_EQ(5, found0.front().block_extent.block_start);
+ ASSERT_EQ(7, found0.front().block_extent.block_end);
+ found0.pop_front();
+ ASSERT_EQ(e0, found0.front().log_entry);
+ ASSERT_EQ(7, found0.front().block_extent.block_start);
+ ASSERT_EQ(8, found0.front().block_extent.block_end);
+}
+
+} // namespace pwl
+} // namespace cache
+} // namespace librbd