From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/test/librbd/cache/pwl/test_WriteLogMap.cc | 338 ++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 src/test/librbd/cache/pwl/test_WriteLogMap.cc (limited to 'src/test/librbd/cache/pwl/test_WriteLogMap.cc') 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..1cafb00ff --- /dev/null +++ b/src/test/librbd/cache/pwl/test_WriteLogMap.cc @@ -0,0 +1,338 @@ +// -*- 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 { + +using namespace std; + +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> TestLogEntries; +typedef LogMapEntry TestMapEntry; +typedef LogMapEntries TestLogMapEntries; +typedef LogMap TestLogMap; + +class TestWriteLogMap : public TestFixture { +public: + void SetUp() override { + TestFixture::SetUp(); + m_cct = reinterpret_cast(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(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(4, 8); + map.add_log_entry(e0); + /* replaces block 4-7 of e0 */ + auto e1 = make_shared(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(0, 8); + map.add_log_entry(e0); + /* replaces block 4-7 of e0 */ + auto e1 = make_shared(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(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(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(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(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(0, 8); + map.add_log_entry(e0); + + /* Splits e0 at 1 */ + auto e1 = make_shared(1, 1); + map.add_log_entry(e1); + + /* Splits e0 again at 4 */ + auto e2 = make_shared(4, 2); + map.add_log_entry(e2); + + /* Replaces one block of e2, and one of e0 */ + auto e3 = make_shared(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 -- cgit v1.2.3