]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc
update sources to v12.2.3
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / test_mock_PrepareRemoteImageRequest.cc
index 793811816e62d20421814640ccd7e6421cc624d6..73658b3fb8b31f14ab183b36c3bdbad18f784bfd 100644 (file)
@@ -4,8 +4,10 @@
 #include "test/rbd_mirror/test_mock_fixture.h"
 #include "cls/rbd/cls_rbd_types.h"
 #include "librbd/journal/TypeTraits.h"
+#include "tools/rbd_mirror/Threads.h"
 #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
 #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
+#include "test/journal/mock/MockJournaler.h"
 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
 #include "test/librbd/mock/MockImageCtx.h"
 
@@ -20,10 +22,32 @@ struct MockTestImageCtx : public librbd::MockImageCtx {
 };
 
 } // anonymous namespace
+
+namespace journal {
+
+template <>
+struct TypeTraits<MockTestImageCtx> {
+  typedef ::journal::MockJournalerProxy Journaler;
+};
+
+} // namespace journal
 } // namespace librbd
 
 namespace rbd {
 namespace mirror {
+
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+  Mutex &timer_lock;
+  SafeTimer *timer;
+  ContextWQ *work_queue;
+
+  Threads(Threads<librbd::ImageCtx> *threads)
+    : timer_lock(threads->timer_lock), timer(threads->timer),
+      work_queue(threads->work_queue) {
+  }
+};
+
 namespace image_replayer {
 
 template <>
@@ -72,6 +96,7 @@ using ::testing::WithArg;
 
 class TestMockImageReplayerPrepareRemoteImageRequest : public TestMockFixture {
 public:
+  typedef Threads<librbd::MockTestImageCtx> MockThreads;
   typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
   typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest;
 
@@ -96,49 +121,160 @@ public:
                                         })),
                       Return(r)));
   }
+
+  void expect_journaler_get_client(::journal::MockJournaler &mock_journaler,
+                                   const std::string &client_id,
+                                   cls::journal::Client &client, int r) {
+    EXPECT_CALL(mock_journaler, get_client(StrEq(client_id), _, _))
+      .WillOnce(DoAll(WithArg<1>(Invoke([client](cls::journal::Client *out_client) {
+                                          *out_client = client;
+                                        })),
+                      WithArg<2>(Invoke([this, r](Context *on_finish) {
+                                          m_threads->work_queue->queue(on_finish, r);
+                                        }))));
+  }
+
+  void expect_journaler_register_client(::journal::MockJournaler &mock_journaler,
+                                        const librbd::journal::ClientData &client_data,
+                                        int r) {
+    bufferlist bl;
+    ::encode(client_data, bl);
+
+    EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _))
+      .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
+                                    m_threads->work_queue->queue(on_finish, r);
+                                  })));
+  }
 };
 
 TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
   InSequence seq;
   expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
   MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
   expect_get_mirror_image_id(mock_get_mirror_image_id_request,
                              "remote image id", 0);
 
+  EXPECT_CALL(mock_remote_journaler, construct());
+
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+  mirror_peer_client_meta.image_id = "local image id";
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+  librbd::journal::ClientData client_data{mirror_peer_client_meta};
+  cls::journal::Client client;
+  client.state = cls::journal::CLIENT_STATE_DISCONNECTED;
+  ::encode(client_data, client.data);
+  expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
+                              client, 0);
+
   std::string remote_mirror_uuid;
   std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
   C_SaferCond ctx;
-  auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
                                                    "global image id",
+                                                   "local mirror uuid",
+                                                   "local image id",
                                                    &remote_mirror_uuid,
                                                    &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
                                                    &ctx);
   req->send();
 
   ASSERT_EQ(0, ctx.wait());
   ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
   ASSERT_EQ(std::string("remote image id"), remote_image_id);
+  ASSERT_TRUE(remote_journaler != nullptr);
+  ASSERT_EQ(cls::journal::CLIENT_STATE_DISCONNECTED, client_state);
+}
+
+TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
+  InSequence seq;
+  expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
+  MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
+  expect_get_mirror_image_id(mock_get_mirror_image_id_request,
+                             "remote image id", 0);
+
+  EXPECT_CALL(mock_remote_journaler, construct());
+
+  cls::journal::Client client;
+  expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
+                              client, -ENOENT);
+
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+  mirror_peer_client_meta.image_id = "local image id";
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+  librbd::journal::ClientData client_data{mirror_peer_client_meta};
+  expect_journaler_register_client(mock_remote_journaler, client_data, 0);
+
+  std::string remote_mirror_uuid;
+  std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
+  C_SaferCond ctx;
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
+                                                   "global image id",
+                                                   "local mirror uuid",
+                                                   "local image id",
+                                                   &remote_mirror_uuid,
+                                                   &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
+                                                   &ctx);
+  req->send();
+
+  ASSERT_EQ(0, ctx.wait());
+  ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
+  ASSERT_EQ(std::string("remote image id"), remote_image_id);
+  ASSERT_TRUE(remote_journaler != nullptr);
+  ASSERT_EQ(cls::journal::CLIENT_STATE_CONNECTED, client_state);
 }
 
 TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorUuidError) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
   InSequence seq;
   expect_mirror_uuid_get(m_remote_io_ctx, "", -EINVAL);
 
   std::string remote_mirror_uuid;
   std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
   C_SaferCond ctx;
-  auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
                                                    "global image id",
+                                                   "local mirror uuid",
+                                                   "",
                                                    &remote_mirror_uuid,
                                                    &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
                                                    &ctx);
   req->send();
 
   ASSERT_EQ(-EINVAL, ctx.wait());
   ASSERT_EQ(std::string(""), remote_mirror_uuid);
+  ASSERT_TRUE(remote_journaler == nullptr);
 }
 
 TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
   InSequence seq;
   expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
   MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
@@ -146,16 +282,111 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
 
   std::string remote_mirror_uuid;
   std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
   C_SaferCond ctx;
-  auto req = MockPrepareRemoteImageRequest::create(m_remote_io_ctx,
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
                                                    "global image id",
+                                                   "local mirror uuid",
+                                                   "",
                                                    &remote_mirror_uuid,
                                                    &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
                                                    &ctx);
   req->send();
 
   ASSERT_EQ(-EINVAL, ctx.wait());
   ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
+  ASSERT_TRUE(remote_journaler == nullptr);
+}
+
+TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
+  InSequence seq;
+  expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
+  MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
+  expect_get_mirror_image_id(mock_get_mirror_image_id_request,
+                             "remote image id", 0);
+
+  EXPECT_CALL(mock_remote_journaler, construct());
+
+  cls::journal::Client client;
+  expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
+                              client, -EINVAL);
+
+  std::string remote_mirror_uuid;
+  std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
+  C_SaferCond ctx;
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
+                                                   "global image id",
+                                                   "local mirror uuid",
+                                                   "local image id",
+                                                   &remote_mirror_uuid,
+                                                   &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
+                                                   &ctx);
+  req->send();
+
+  ASSERT_EQ(-EINVAL, ctx.wait());
+  ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
+  ASSERT_EQ(std::string("remote image id"), remote_image_id);
+  ASSERT_TRUE(remote_journaler == nullptr);
+}
+
+TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
+  InSequence seq;
+  expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
+  MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
+  expect_get_mirror_image_id(mock_get_mirror_image_id_request,
+                             "remote image id", 0);
+
+  EXPECT_CALL(mock_remote_journaler, construct());
+
+  cls::journal::Client client;
+  expect_journaler_get_client(mock_remote_journaler, "local mirror uuid",
+                              client, -ENOENT);
+
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+  mirror_peer_client_meta.image_id = "local image id";
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+  librbd::journal::ClientData client_data{mirror_peer_client_meta};
+  expect_journaler_register_client(mock_remote_journaler, client_data, -EINVAL);
+
+  std::string remote_mirror_uuid;
+  std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
+  C_SaferCond ctx;
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
+                                                   "global image id",
+                                                   "local mirror uuid",
+                                                   "local image id",
+                                                   &remote_mirror_uuid,
+                                                   &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
+                                                   &ctx);
+  req->send();
+
+  ASSERT_EQ(-EINVAL, ctx.wait());
+  ASSERT_EQ(std::string("remote mirror uuid"), remote_mirror_uuid);
+  ASSERT_EQ(std::string("remote image id"), remote_image_id);
+  ASSERT_TRUE(remote_journaler == nullptr);
 }
 
 } // namespace image_replayer