From e2bbd17a02257a468bc5052dc1c30c8e812ccd96 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Sat, 12 Mar 2016 22:13:11 -0500 Subject: [PATCH] test: verify proper update of object map during rbd-mirror image sync Signed-off-by: Jason Dillaman --- src/test/librbd/mock/MockObjectMap.h | 5 +- .../image_sync/test_mock_ImageCopyRequest.cc | 10 - .../image_sync/test_mock_ObjectCopyRequest.cc | 191 ++++++++++++++---- .../test_mock_SnapshotCopyRequest.cc | 10 - src/test/rbd_mirror/test_ImageSync.cc | 10 - src/test/rbd_mirror/test_fixture.cc | 6 + src/test/rbd_mirror/test_fixture.h | 4 + src/test/rbd_mirror/test_mock_ImageSync.cc | 60 ++++-- src/test/rbd_mirror/test_mock_fixture.cc | 13 ++ src/test/rbd_mirror/test_mock_fixture.h | 6 + 10 files changed, 230 insertions(+), 85 deletions(-) diff --git a/src/test/librbd/mock/MockObjectMap.h b/src/test/librbd/mock/MockObjectMap.h index 2b81488b7a22..25d14ed3c085 100644 --- a/src/test/librbd/mock/MockObjectMap.h +++ b/src/test/librbd/mock/MockObjectMap.h @@ -17,7 +17,10 @@ struct MockObjectMap { MOCK_METHOD3(aio_resize, void(uint64_t new_size, uint8_t default_object_state, Context *on_finish)); - + MOCK_METHOD6(aio_update, void(uint64_t snap_id, uint64_t start_object_no, + uint64_t end_object_no, uint8_t new_state, + const boost::optional ¤t_state, + Context *on_finish)); MOCK_METHOD2(snapshot_add, void(uint64_t snap_id, Context *on_finish)); MOCK_METHOD2(snapshot_remove, void(uint64_t snap_id, Context *on_finish)); MOCK_METHOD2(rollback, void(uint64_t snap_id, Context *on_finish)); diff --git a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc index 302a4d62500b..ff3584e071fd 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc @@ -80,14 +80,6 @@ public: ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx)); - - m_threads = new rbd::mirror::Threads(reinterpret_cast( - m_local_io_ctx.cct())); - } - - virtual void TearDown() { - delete m_threads; - TestMockFixture::TearDown(); } void expect_get_snap_id(librbd::MockImageCtx &mock_image_ctx) { @@ -182,8 +174,6 @@ public: librbd::ImageCtx *m_local_image_ctx; librbd::journal::MirrorPeerClientMeta m_client_meta; MockImageCopyRequest::SnapMap m_snap_map; - - rbd::mirror::Threads *m_threads = nullptr; }; TEST_F(TestMockImageSyncImageCopyRequest, SimpleImage) { diff --git a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc index 7df68723e429..d99d7dfae1b0 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc @@ -4,11 +4,14 @@ #include "test/rbd_mirror/test_mock_fixture.h" #include "include/interval_set.h" #include "include/rbd/librbd.hpp" +#include "librbd/AioImageRequestWQ.h" #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" +#include "librbd/internal.h" #include "librbd/Operations.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librbd/mock/MockImageCtx.h" +#include "tools/rbd_mirror/Threads.h" #include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h" // template definitions @@ -22,15 +25,16 @@ namespace image_sync { using ::testing::_; using ::testing::DoDefault; using ::testing::InSequence; +using ::testing::Invoke; using ::testing::Return; +using ::testing::WithArg; namespace { -void scribble(librados::IoCtx &io_ctx, const std::string &oid, int num_ops, - size_t max_size, interval_set *what) +void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size, + interval_set *what) { - uint64_t object_size = 1 << 22; - librados::ObjectWriteOperation op; + uint64_t object_size = 1 << image_ctx->order; for (int i=0; iaio_work_queue->write(off, len, bl.c_str(), 0); + ASSERT_EQ(static_cast(len), r); interval_set w; w.insert(off, len); what->union_of(w); } - - ASSERT_EQ(0, io_ctx.operate(oid, &op)); std::cout << " wrote " << *what << std::endl; } @@ -152,6 +155,28 @@ public: } } + void expect_update_object_map(librbd::MockImageCtx &mock_image_ctx, + librbd::MockObjectMap &mock_object_map, + librados::snap_t snap_id, uint8_t state, + int r) { + if (mock_image_ctx.image_ctx->object_map != nullptr) { + auto &expect = EXPECT_CALL(mock_object_map, aio_update(snap_id, 0, 1, state, _, _)); + if (r < 0) { + expect.WillOnce(WithArg<5>(Invoke([this, r](Context *ctx) { + m_threads->work_queue->queue(ctx, r); + }))); + } else { + expect.WillOnce(WithArg<5>(Invoke([&mock_image_ctx, snap_id, state, r](Context *ctx) { + RWLock::RLocker snap_locker(mock_image_ctx.image_ctx->snap_lock); + RWLock::WLocker object_map_locker(mock_image_ctx.image_ctx->object_map_lock); + mock_image_ctx.image_ctx->object_map->aio_update(snap_id, 0, 1, + state, + boost::none, ctx); + }))); + } + } + } + using TestFixture::create_snap; int create_snap(const char* snap_name) { librados::snap_t remote_snap_id; @@ -174,47 +199,84 @@ public: m_snap_map.rbegin()->second.end()); } m_snap_map[remote_snap_id] = local_snap_ids; + m_local_snap_ids.push_back(local_snap_id); return 0; } + std::string get_snap_name(librbd::ImageCtx *image_ctx, + librados::snap_t snap_id) { + auto it = std::find_if(image_ctx->snap_ids.begin(), + image_ctx->snap_ids.end(), + [snap_id](const std::pair &pair) { + return (pair.second == snap_id); + }); + if (it == image_ctx->snap_ids.end()) { + return ""; + } + return it->first; + } + int compare_objects() { MockObjectCopyRequest::SnapMap snap_map(m_snap_map); if (snap_map.empty()) { return -ENOENT; } - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); - std::string local_oid(m_local_image_ctx->get_object_name(0)); - - librados::IoCtx remote_io_ctx; - remote_io_ctx.dup(m_remote_image_ctx->data_ctx); - - librados::IoCtx local_io_ctx; - local_io_ctx.dup(m_local_image_ctx->data_ctx); - + int r; + uint64_t object_size = 1 << m_remote_image_ctx->order; while (!snap_map.empty()) { librados::snap_t remote_snap_id = snap_map.begin()->first; librados::snap_t local_snap_id = *snap_map.begin()->second.begin(); snap_map.erase(snap_map.begin()); - std::cout << "comparing " << remote_snap_id << " to " << local_snap_id - << std::endl; - remote_io_ctx.snap_set_read(remote_snap_id); + std::string snap_name = get_snap_name(m_remote_image_ctx, remote_snap_id); + if (snap_name.empty()) { + return -ENOENT; + } + + std::cout << "comparing '" << snap_name << " (" << remote_snap_id + << " to " << local_snap_id << ")" << std::endl; + + r = librbd::snap_set(m_remote_image_ctx, snap_name.c_str()); + if (r < 0) { + return r; + } + + r = librbd::snap_set(m_local_image_ctx, snap_name.c_str()); + if (r < 0) { + return r; + } + bufferlist remote_bl; - int remote_r = remote_io_ctx.read(remote_oid, remote_bl, 1<<22, 0); + remote_bl.append(std::string(object_size, '1')); + r = m_remote_image_ctx->aio_work_queue->read(0, object_size, + remote_bl.c_str(), 0); + if (r < 0) { + return r; + } - local_io_ctx.snap_set_read(local_snap_id); bufferlist local_bl; - int local_r = local_io_ctx.read(local_oid, local_bl, 1<<22, 0); - - if (remote_r != local_r) { - return remote_r < 0 ? remote_r : local_r; + local_bl.append(std::string(object_size, '1')); + r = m_local_image_ctx->aio_work_queue->read(0, object_size, + local_bl.c_str(), 0); + if (r < 0) { + return r; } if (!remote_bl.contents_equal(local_bl)) { return -EBADMSG; } } + + r = librbd::snap_set(m_remote_image_ctx, nullptr); + if (r < 0) { + return r; + } + r = librbd::snap_set(m_local_image_ctx, nullptr); + if (r < 0) { + return r; + } + return 0; } @@ -222,7 +284,7 @@ public: librbd::ImageCtx *m_local_image_ctx; MockObjectCopyRequest::SnapMap m_snap_map; - + std::vector m_local_snap_ids; }; TEST_F(TestMockImageSyncObjectCopyRequest, DNE) { @@ -230,6 +292,11 @@ TEST_F(TestMockImageSyncObjectCopyRequest, DNE) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -246,14 +313,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, DNE) { TEST_F(TestMockImageSyncObjectCopyRequest, Write) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("sync")); librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -267,6 +338,8 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Write) { expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); expect_write(mock_local_io_ctx, 0, one.range_end(), 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[0], OBJECT_EXISTS, 0); request->send(); ASSERT_EQ(0, ctx.wait()); @@ -275,14 +348,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Write) { TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("sync")); librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -300,14 +377,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) { TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("sync")); librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -328,13 +409,12 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) { TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("one")); interval_set two; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &two); + scribble(m_remote_image_ctx, 10, 102400, &two); ASSERT_EQ(0, create_snap("two")); if (one.range_end() < two.range_end()) { @@ -347,6 +427,11 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) { librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -362,6 +447,12 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) { expect_write(mock_local_io_ctx, 0, one.range_end(), 0); expect_read(mock_remote_io_ctx, two, 0); expect_write(mock_local_io_ctx, two, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[0], OBJECT_EXISTS, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[1], OBJECT_EXISTS, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[2], OBJECT_EXISTS_CLEAN, 0); request->send(); ASSERT_EQ(0, ctx.wait()); @@ -370,19 +461,24 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) { TEST_F(TestMockImageSyncObjectCopyRequest, Trim) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("one")); // trim the object uint64_t trim_offset = rand() % one.range_end(); - ASSERT_EQ(0, m_remote_image_ctx->data_ctx.trunc(remote_oid, trim_offset)); + ASSERT_LE(0, m_remote_image_ctx->aio_work_queue->discard( + trim_offset, one.range_end() - trim_offset)); ASSERT_EQ(0, create_snap("sync")); librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -397,6 +493,10 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) { expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); expect_write(mock_local_io_ctx, 0, one.range_end(), 0); expect_truncate(mock_local_io_ctx, trim_offset, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[0], OBJECT_EXISTS, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[1], OBJECT_EXISTS, 0); request->send(); ASSERT_EQ(0, ctx.wait()); @@ -405,17 +505,22 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) { TEST_F(TestMockImageSyncObjectCopyRequest, Remove) { // scribble some data - std::string remote_oid(m_remote_image_ctx->get_object_name(0)); interval_set one; - scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + scribble(m_remote_image_ctx, 10, 102400, &one); ASSERT_EQ(0, create_snap("one")); // remove the object - ASSERT_EQ(0, m_remote_image_ctx->data_ctx.remove(remote_oid)); + uint64_t object_size = 1 << m_remote_image_ctx->order; + ASSERT_LE(0, m_remote_image_ctx->aio_work_queue->discard(0, object_size)); ASSERT_EQ(0, create_snap("sync")); librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + librbd::MockObjectMap mock_object_map; + mock_local_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_local_image_ctx); + C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, mock_local_image_ctx, &ctx); @@ -430,6 +535,10 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Remove) { expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); expect_write(mock_local_io_ctx, 0, one.range_end(), 0); expect_remove(mock_local_io_ctx, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[0], OBJECT_EXISTS, 0); + expect_update_object_map(mock_local_image_ctx, mock_object_map, + m_local_snap_ids[1], OBJECT_NONEXISTENT, 0); request->send(); ASSERT_EQ(0, ctx.wait()); diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc index 506eeddc90d8..10c3ac36ebc5 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc @@ -43,14 +43,6 @@ public: ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx)); - - m_threads = new rbd::mirror::Threads(reinterpret_cast( - m_local_io_ctx.cct())); - } - - virtual void TearDown() { - delete m_threads; - TestMockFixture::TearDown(); } void expect_snap_create(librbd::MockImageCtx &mock_image_ctx, @@ -118,8 +110,6 @@ public: MockSnapshotCopyRequest::SnapMap m_snap_map; librbd::journal::MirrorPeerClientMeta m_client_meta; - - rbd::mirror::Threads *m_threads = nullptr; }; TEST_F(TestMockImageSyncSnapshotCopyRequest, Empty) { diff --git a/src/test/rbd_mirror/test_ImageSync.cc b/src/test/rbd_mirror/test_ImageSync.cc index 7846fcae4920..10622a15856f 100644 --- a/src/test/rbd_mirror/test_ImageSync.cc +++ b/src/test/rbd_mirror/test_ImageSync.cc @@ -44,9 +44,6 @@ public: create_and_open(m_local_io_ctx, &m_local_image_ctx); create_and_open(m_remote_io_ctx, &m_remote_image_ctx); - m_threads = new rbd::mirror::Threads(reinterpret_cast( - m_local_io_ctx.cct())); - m_remote_journaler = new ::journal::Journaler( m_threads->work_queue, m_threads->timer, &m_threads->timer_lock, m_remote_io_ctx, m_remote_image_ctx->id, "mirror-uuid", 5); @@ -60,11 +57,6 @@ public: ASSERT_EQ(0, m_remote_journaler->register_client(client_data_bl)); } - virtual void TearDown() { - delete m_threads; - TestFixture::TearDown(); - } - void create_and_open(librados::IoCtx &io_ctx, librbd::ImageCtx **image_ctx) { librbd::RBD rbd; ASSERT_EQ(0, create_image(rbd, io_ctx, m_image_name, m_image_size)); @@ -90,8 +82,6 @@ public: librbd::ImageCtx *m_local_image_ctx; ::journal::Journaler *m_remote_journaler; librbd::journal::MirrorPeerClientMeta m_client_meta; - - rbd::mirror::Threads *m_threads = nullptr; }; TEST_F(TestImageSync, Empty) { diff --git a/src/test/rbd_mirror/test_fixture.cc b/src/test/rbd_mirror/test_fixture.cc index ab24353bd1c3..56620db0cd00 100644 --- a/src/test/rbd_mirror/test_fixture.cc +++ b/src/test/rbd_mirror/test_fixture.cc @@ -8,6 +8,7 @@ #include "librbd/ImageState.h" #include "librbd/Operations.h" #include "test/librados/test.h" +#include "tools/rbd_mirror/Threads.h" namespace rbd { namespace mirror { @@ -38,6 +39,9 @@ void TestFixture::SetUp() { ASSERT_EQ(0, _rados.ioctx_create(_local_pool_name.c_str(), m_local_io_ctx)); ASSERT_EQ(0, _rados.ioctx_create(_remote_pool_name.c_str(), m_remote_io_ctx)); m_image_name = get_temp_image_name(); + + m_threads = new rbd::mirror::Threads(reinterpret_cast( + m_local_io_ctx.cct())); } void TestFixture::TearDown() { @@ -47,6 +51,8 @@ void TestFixture::TearDown() { m_remote_io_ctx.close(); m_local_io_ctx.close(); + + delete m_threads; } int TestFixture::create_image(librbd::RBD &rbd, librados::IoCtx &ioctx, diff --git a/src/test/rbd_mirror/test_fixture.h b/src/test/rbd_mirror/test_fixture.h index 730ffc531136..79a6f86f73ee 100644 --- a/src/test/rbd_mirror/test_fixture.h +++ b/src/test/rbd_mirror/test_fixture.h @@ -17,6 +17,8 @@ class RBD; namespace rbd { namespace mirror { +class Threads; + class TestFixture : public ::testing::Test { public: TestFixture(); @@ -35,6 +37,8 @@ public: std::set m_image_ctxs; + Threads *m_threads = nullptr; + int create_image(librbd::RBD &rbd, librados::IoCtx &ioctx, const std::string &name, uint64_t size); int open_image(librados::IoCtx &io_ctx, const std::string &image_name, diff --git a/src/test/rbd_mirror/test_mock_ImageSync.cc b/src/test/rbd_mirror/test_mock_ImageSync.cc index 21892cff726c..726fa95c3232 100644 --- a/src/test/rbd_mirror/test_mock_ImageSync.cc +++ b/src/test/rbd_mirror/test_mock_ImageSync.cc @@ -6,6 +6,7 @@ #include "librbd/journal/Types.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librbd/mock/MockImageCtx.h" +#include "test/librbd/mock/MockObjectMap.h" #include "test/rbd_mirror/mock/MockJournaler.h" #include "tools/rbd_mirror/ImageSync.h" #include "tools/rbd_mirror/Threads.h" @@ -127,6 +128,8 @@ SyncPointPruneRequest* SyncPointPruneRequest( - m_local_io_ctx.cct())); - } - - virtual void TearDown() { - delete m_threads; - TestMockFixture::TearDown(); } - void expect_create_sync_point(MockSyncPointCreateRequest &mock_sync_point_create_request, + void expect_create_sync_point(librbd::MockImageCtx &mock_local_image_ctx, + MockSyncPointCreateRequest &mock_sync_point_create_request, int r) { EXPECT_CALL(mock_sync_point_create_request, send()) - .WillOnce(Invoke([this, &mock_sync_point_create_request, r]() { + .WillOnce(Invoke([this, &mock_local_image_ctx, &mock_sync_point_create_request, r]() { if (r == 0) { + mock_local_image_ctx.snap_ids["snap1"] = 123; m_client_meta.sync_points.emplace_back("snap1", boost::none); } m_threads->work_queue->queue(mock_sync_point_create_request.on_finish, r); @@ -180,6 +177,29 @@ public: })); } + void expect_rollback_object_map(librbd::MockObjectMap &mock_object_map, int r) { + if ((m_local_image_ctx->features & RBD_FEATURE_OBJECT_MAP) != 0) { + EXPECT_CALL(mock_object_map, rollback(_, _)) + .WillOnce(WithArg<1>(Invoke([this, r](Context *ctx) { + m_threads->work_queue->queue(ctx, r); + }))); + } + } + + void expect_create_object_map(librbd::MockImageCtx &mock_image_ctx, + librbd::MockObjectMap *mock_object_map) { + EXPECT_CALL(mock_image_ctx, create_object_map(CEPH_NOSNAP)) + .WillOnce(Return(mock_object_map)); + } + + void expect_open_object_map(librbd::MockImageCtx &mock_image_ctx, + librbd::MockObjectMap &mock_object_map) { + EXPECT_CALL(mock_object_map, open(_)) + .WillOnce(Invoke([this](Context *ctx) { + m_threads->work_queue->queue(ctx, 0); + })); + } + void expect_prune_sync_point(MockSyncPointPruneRequest &mock_sync_point_prune_request, bool sync_complete, int r) { EXPECT_CALL(mock_sync_point_prune_request, send()) @@ -211,8 +231,6 @@ public: librbd::ImageCtx *m_remote_image_ctx; librbd::ImageCtx *m_local_image_ctx; librbd::journal::MirrorPeerClientMeta m_client_meta; - - rbd::mirror::Threads *m_threads = nullptr; }; TEST_F(TestMockImageSync, SimpleSync) { @@ -224,10 +242,17 @@ TEST_F(TestMockImageSync, SimpleSync) { MockSyncPointCreateRequest mock_sync_point_create_request; MockSyncPointPruneRequest mock_sync_point_prune_request; + librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap(); + mock_local_image_ctx.object_map = mock_object_map; + expect_test_features(mock_local_image_ctx); + InSequence seq; - expect_create_sync_point(mock_sync_point_create_request, 0); + expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0); expect_copy_snapshots(mock_snapshot_copy_request, 0); expect_copy_image(mock_image_copy_request, 0); + expect_rollback_object_map(*mock_object_map, 0); + expect_create_object_map(mock_local_image_ctx, mock_object_map); + expect_open_object_map(mock_local_image_ctx, *mock_object_map); expect_prune_sync_point(mock_sync_point_prune_request, true, 0); C_SaferCond ctx; @@ -249,11 +274,20 @@ TEST_F(TestMockImageSync, RestartSync) { m_client_meta.sync_points = {{"snap1", boost::none}, {"snap2", "snap1", boost::none}}; + mock_local_image_ctx.snap_ids["snap1"] = 123; + mock_local_image_ctx.snap_ids["snap2"] = 234; + + librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap(); + mock_local_image_ctx.object_map = mock_object_map; + expect_test_features(mock_local_image_ctx); InSequence seq; expect_prune_sync_point(mock_sync_point_prune_request, false, 0); expect_copy_snapshots(mock_snapshot_copy_request, 0); expect_copy_image(mock_image_copy_request, 0); + expect_rollback_object_map(*mock_object_map, 0); + expect_create_object_map(mock_local_image_ctx, mock_object_map); + expect_open_object_map(mock_local_image_ctx, *mock_object_map); expect_prune_sync_point(mock_sync_point_prune_request, true, 0); C_SaferCond ctx; diff --git a/src/test/rbd_mirror/test_mock_fixture.cc b/src/test/rbd_mirror/test_mock_fixture.cc index 0863c40b909d..6f45ca9528d5 100644 --- a/src/test/rbd_mirror/test_mock_fixture.cc +++ b/src/test/rbd_mirror/test_mock_fixture.cc @@ -2,12 +2,18 @@ // vim: ts=8 sw=2 smarttab #include "test/rbd_mirror/test_mock_fixture.h" +#include "include/rbd/librbd.hpp" #include "test/librados_test_stub/LibradosTestStub.h" #include "test/librados_test_stub/MockTestMemRadosClient.h" +#include "test/librbd/mock/MockImageCtx.h" namespace rbd { namespace mirror { +using ::testing::_; +using ::testing::Invoke; +using ::testing::WithArg; + TestMockFixture::TestRadosClientPtr TestMockFixture::s_test_rados_client; ::testing::NiceMock * TestMockFixture::s_mock_rados_client = NULL; @@ -41,6 +47,13 @@ void TestMockFixture::TearDown() { s_mock_rados_client->default_to_dispatch(); } +void TestMockFixture::expect_test_features(librbd::MockImageCtx &mock_image_ctx) { + EXPECT_CALL(mock_image_ctx, test_features(_, _)) + .WillRepeatedly(WithArg<0>(Invoke([&mock_image_ctx](uint64_t features) { + return (mock_image_ctx.features & features) != 0; + }))); +} + } // namespace mirror } // namespace rbd diff --git a/src/test/rbd_mirror/test_mock_fixture.h b/src/test/rbd_mirror/test_mock_fixture.h index 2231095936b1..5ce1a748bd67 100644 --- a/src/test/rbd_mirror/test_mock_fixture.h +++ b/src/test/rbd_mirror/test_mock_fixture.h @@ -15,6 +15,10 @@ class MockTestMemIoCtxImpl; class MockTestMemRadosClient; } +namespace librbd { +class MockImageCtx; +} + ACTION_P(CompleteContext, r) { arg0->complete(r); } @@ -32,6 +36,8 @@ public: virtual void SetUp(); virtual void TearDown(); + void expect_test_features(librbd::MockImageCtx &mock_image_ctx); + ::testing::NiceMock &get_mock_rados_client() { return *s_mock_rados_client; } -- 2.47.3