]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: ensure threads are mockable for testing
authorJason Dillaman <dillaman@redhat.com>
Fri, 21 Jul 2017 19:40:03 +0000 (15:40 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 7 Aug 2017 14:13:34 +0000 (10:13 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/journal/mock/MockJournaler.h
src/test/rbd_mirror/mock/MockSafeTimer.h
src/test/rbd_mirror/test_mock_ImageReplayer.cc
src/test/rbd_mirror/test_mock_InstanceReplayer.cc
src/tools/rbd_mirror/ImageReplayer.cc
src/tools/rbd_mirror/ImageReplayer.h

index e37d3550ba61233ca6a4a4653fa2a8cc2cc76459..2182c8db4fc1a3471d3404b5b7fd14e18f82ee27 100644 (file)
@@ -13,9 +13,7 @@
 #include <string>
 
 class Context;
-class ContextWQ;
 class Mutex;
-class SafeTimer;
 
 namespace journal {
 
@@ -146,8 +144,10 @@ struct MockJournalerProxy {
     MockJournaler::get_instance().construct();
   }
 
-  MockJournalerProxy(ContextWQ *work_queue, SafeTimer *timer, Mutex *timer_lock,
-                     librados::IoCtx &header_ioctx, const std::string &journal_id,
+  template <typename WorkQueue, typename Timer>
+  MockJournalerProxy(WorkQueue *work_queue, Timer *timer, Mutex *timer_lock,
+                     librados::IoCtx &header_ioctx,
+                     const std::string &journal_id,
                      const std::string &client_id, const Settings&) {
     MockJournaler::get_instance().construct();
   }
index 4926660b9ea36ced357245796b4f96b0f6542367..3de5fbcdbf5cc4e24a5c83fc2fba6bfc63a1300b 100644 (file)
@@ -10,7 +10,7 @@ struct Context;
 
 struct MockSafeTimer {
   MOCK_METHOD2(add_event_after, void(double, Context*));
-  MOCK_METHOD1(cancel_event, void(Context *));
+  MOCK_METHOD1(cancel_event, bool(Context *));
 };
 
 #endif // CEPH_MOCK_SAFE_TIMER_H
index 8344fc6deade7a93253fbbc2efee93a730cfb31d..cb0e464bba2cef14cb69d76693f6b2c90c5b0322 100644 (file)
@@ -7,6 +7,7 @@
 #include "tools/rbd_mirror/ImageDeleter.h"
 #include "tools/rbd_mirror/ImageReplayer.h"
 #include "tools/rbd_mirror/InstanceWatcher.h"
+#include "tools/rbd_mirror/Threads.h"
 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
 #include "tools/rbd_mirror/image_replayer/EventPreprocessor.h"
@@ -16,6 +17,8 @@
 #include "test/journal/mock/MockJournaler.h"
 #include "test/librbd/mock/MockImageCtx.h"
 #include "test/librbd/mock/MockJournal.h"
+#include "test/rbd_mirror/mock/MockContextWQ.h"
+#include "test/rbd_mirror/mock/MockSafeTimer.h"
 
 namespace librbd {
 
@@ -62,6 +65,24 @@ struct MirrorPeerClientMeta;
 namespace rbd {
 namespace mirror {
 
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+  MockSafeTimer *timer;
+  Mutex &timer_lock;
+
+  MockContextWQ *work_queue;
+
+  Threads(Threads<librbd::ImageCtx> *threads)
+    : timer(new MockSafeTimer()),
+      timer_lock(threads->timer_lock),
+      work_queue(new MockContextWQ()) {
+  }
+  ~Threads() {
+    delete timer;
+    delete work_queue;
+  }
+};
+
 template <>
 struct ImageDeleter<librbd::MockTestImageCtx> {
   MOCK_METHOD4(schedule_image_delete, void(RadosRef, int64_t,
@@ -98,7 +119,7 @@ struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
                                           const std::string &global_image_id,
                                           std::string *local_image_id,
                                           std::string *tag_owner,
-                                          ContextWQ *work_queue,
+                                          MockContextWQ *work_queue,
                                           Context *on_finish) {
     assert(s_instance != nullptr);
     s_instance->local_image_id = local_image_id;
@@ -152,8 +173,9 @@ struct BootstrapRequest<librbd::MockTestImageCtx> {
       rbd::mirror::InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
       librbd::MockTestImageCtx **local_image_ctx,
       const std::string &local_image_name, const std::string &remote_image_id,
-      const std::string &global_image_id, ContextWQ *work_queue,
-      SafeTimer *timer, Mutex *timer_lock, const std::string &local_mirror_uuid,
+      const std::string &global_image_id, MockContextWQ *work_queue,
+      MockSafeTimer *timer, Mutex *timer_lock,
+      const std::string &local_mirror_uuid,
       const std::string &remote_mirror_uuid,
       ::journal::MockJournalerProxy *journaler,
       librbd::journal::MirrorPeerClientMeta *client_meta,
@@ -225,7 +247,7 @@ struct EventPreprocessor<librbd::MockTestImageCtx> {
                                    ::journal::MockJournalerProxy &remote_journaler,
                                    const std::string &local_mirror_uuid,
                                    librbd::journal::MirrorPeerClientMeta *client_meta,
-                                   ContextWQ *work_queue) {
+                                   MockContextWQ *work_queue) {
     assert(s_instance != nullptr);
     return s_instance;
   }
@@ -292,6 +314,7 @@ namespace mirror {
 
 class TestMockImageReplayer : public TestMockFixture {
 public:
+  typedef Threads<librbd::MockTestImageCtx> MockThreads;
   typedef ImageDeleter<librbd::MockTestImageCtx> MockImageDeleter;
   typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
   typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
@@ -323,6 +346,26 @@ public:
     ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
   }
 
+  void expect_work_queue_repeatedly(MockThreads &mock_threads) {
+    EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
+      .WillRepeatedly(Invoke([this](Context *ctx, int r) {
+          m_threads->work_queue->queue(ctx, r);
+        }));
+  }
+
+  void expect_add_event_after_repeatedly(MockThreads &mock_threads) {
+    EXPECT_CALL(*mock_threads.timer, add_event_after(_, _))
+      .WillRepeatedly(
+        Invoke([this](double seconds, Context *ctx) {
+          m_threads->timer->add_event_after(seconds, ctx);
+        }));
+    EXPECT_CALL(*mock_threads.timer, cancel_event(_))
+      .WillRepeatedly(
+        Invoke([this](Context *ctx) {
+          return m_threads->timer->cancel_event(ctx);
+        }));
+  }
+
   void expect_wait_for_scheduled_deletion(MockImageDeleter& mock_image_deleter,
                                           const std::string& global_image_id,
                                           int r) {
@@ -506,9 +549,10 @@ public:
                       WithArg<2>(CompleteContext(on_commit_r))));
   }
 
-  void create_image_replayer(MockImageDeleter &mock_image_deleter) {
+  void create_image_replayer(MockThreads &mock_threads,
+                             MockImageDeleter &mock_image_deleter) {
     m_image_replayer = new MockImageReplayer(
-      m_threads, &mock_image_deleter, &m_instance_watcher,
+      &mock_threads, &mock_image_deleter, &m_instance_watcher,
       rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
       "local_mirror_uuid", m_local_io_ctx.get_id(), "global image id");
     m_image_replayer->add_peer("peer_uuid", m_remote_io_ctx);
@@ -530,6 +574,10 @@ TEST_F(TestMockImageReplayer, StartStop) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -560,7 +608,7 @@ TEST_F(TestMockImageReplayer, StartStop) {
 
   EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -593,6 +641,10 @@ TEST_F(TestMockImageReplayer, LocalImagePrimary) {
   create_local_image();
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockReplayStatusFormatter mock_replay_status_formatter;
@@ -604,7 +656,7 @@ TEST_F(TestMockImageReplayer, LocalImagePrimary) {
   expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
               "", 0);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -616,6 +668,10 @@ TEST_F(TestMockImageReplayer, LocalImageDNE) {
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -635,7 +691,7 @@ TEST_F(TestMockImageReplayer, LocalImageDNE) {
   EXPECT_CALL(mock_remote_journaler, remove_listener(_));
   expect_shut_down(mock_remote_journaler, 0);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -646,6 +702,10 @@ TEST_F(TestMockImageReplayer, PrepareLocalImageError) {
   create_local_image();
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockReplayStatusFormatter mock_replay_status_formatter;
@@ -657,7 +717,7 @@ TEST_F(TestMockImageReplayer, PrepareLocalImageError) {
   expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
               "remote mirror uuid", -EINVAL);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -668,6 +728,10 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdDNE) {
   create_local_image();
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -682,7 +746,7 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdDNE) {
   expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
               "", -ENOENT);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -693,6 +757,10 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdNonLinkedDNE) {
   create_local_image();
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -707,7 +775,7 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdNonLinkedDNE) {
   expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
               "", -ENOENT);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -718,6 +786,10 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdError) {
   create_local_image();
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -732,7 +804,7 @@ TEST_F(TestMockImageReplayer, GetRemoteImageIdError) {
   expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
               m_remote_image_ctx->id, -EINVAL);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -745,6 +817,10 @@ TEST_F(TestMockImageReplayer, BootstrapError) {
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -765,7 +841,7 @@ TEST_F(TestMockImageReplayer, BootstrapError) {
   EXPECT_CALL(mock_remote_journaler, remove_listener(_));
   expect_shut_down(mock_remote_journaler, 0);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -782,6 +858,10 @@ TEST_F(TestMockImageReplayer, StartExternalReplayError) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -817,7 +897,7 @@ TEST_F(TestMockImageReplayer, StartExternalReplayError) {
   EXPECT_CALL(mock_remote_journaler, remove_listener(_));
   expect_shut_down(mock_remote_journaler, 0);
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -836,6 +916,10 @@ TEST_F(TestMockImageReplayer, StopError) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -866,7 +950,7 @@ TEST_F(TestMockImageReplayer, StopError) {
 
   EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -901,6 +985,10 @@ TEST_F(TestMockImageReplayer, Replay) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -934,7 +1022,7 @@ TEST_F(TestMockImageReplayer, Replay) {
 
   EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -1007,6 +1095,10 @@ TEST_F(TestMockImageReplayer, DecodeError) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -1039,7 +1131,7 @@ TEST_F(TestMockImageReplayer, DecodeError) {
 
   EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
@@ -1104,6 +1196,10 @@ TEST_F(TestMockImageReplayer, DelayedReplay) {
   mock_local_image_ctx.journal = &mock_local_journal;
 
   journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+  expect_work_queue_repeatedly(mock_threads);
+  expect_add_event_after_repeatedly(mock_threads);
+
   MockImageDeleter mock_image_deleter;
   MockPrepareLocalImageRequest mock_prepare_local_image_request;
   MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
@@ -1137,7 +1233,7 @@ TEST_F(TestMockImageReplayer, DelayedReplay) {
 
   EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
 
-  create_image_replayer(mock_image_deleter);
+  create_image_replayer(mock_threads, mock_image_deleter);
 
   C_SaferCond start_ctx;
   m_image_replayer->start(&start_ctx);
index f12fcf2989effe811bb218f0b65dd36c592c569c..21bf07a87dd8e69e50438d586acabd1af03797b4 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "test/librbd/mock/MockImageCtx.h"
 #include "test/rbd_mirror/test_mock_fixture.h"
+#include "test/rbd_mirror/mock/MockContextWQ.h"
+#include "test/rbd_mirror/mock/MockSafeTimer.h"
 #include "tools/rbd_mirror/ImageDeleter.h"
 #include "tools/rbd_mirror/ImageReplayer.h"
 #include "tools/rbd_mirror/InstanceWatcher.h"
@@ -30,13 +32,20 @@ namespace mirror {
 
 template <>
 struct Threads<librbd::MockTestImageCtx> {
+  MockSafeTimer *timer;
   Mutex &timer_lock;
-  SafeTimer *timer;
-  ContextWQ *work_queue;
+  Cond timer_cond;
+
+  MockContextWQ *work_queue;
 
   Threads(Threads<librbd::ImageCtx> *threads)
-    : timer_lock(threads->timer_lock), timer(threads->timer),
-      work_queue(threads->work_queue) {
+    : timer(new MockSafeTimer()),
+      timer_lock(threads->timer_lock),
+      work_queue(new MockContextWQ()) {
+  }
+  ~Threads() {
+    delete timer;
+    delete work_queue;
   }
 };
 
@@ -117,57 +126,75 @@ using ::testing::WithArg;
 
 class TestMockInstanceReplayer : public TestMockFixture {
 public:
+  typedef Threads<librbd::MockTestImageCtx> MockThreads;
   typedef ImageDeleter<librbd::MockTestImageCtx> MockImageDeleter;
   typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
   typedef InstanceReplayer<librbd::MockTestImageCtx> MockInstanceReplayer;
   typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
   typedef ServiceDaemon<librbd::MockTestImageCtx> MockServiceDaemon;
-  typedef Threads<librbd::MockTestImageCtx> MockThreads;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
 
-    m_mock_threads = new MockThreads(m_threads);
+  void expect_work_queue(MockThreads &mock_threads) {
+    EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
+      .WillOnce(Invoke([this](Context *ctx, int r) {
+          m_threads->work_queue->queue(ctx, r);
+        }));
   }
 
-  void TearDown() override {
-    delete m_mock_threads;
-    TestMockFixture::TearDown();
+  void expect_add_event_after(MockThreads &mock_threads,
+                              Context** timer_ctx = nullptr) {
+    EXPECT_CALL(*mock_threads.timer, add_event_after(_, _))
+      .WillOnce(WithArg<1>(
+        Invoke([this, &mock_threads, timer_ctx](Context *ctx) {
+          assert(mock_threads.timer_lock.is_locked());
+          if (timer_ctx != nullptr) {
+            *timer_ctx = ctx;
+            mock_threads.timer_cond.SignalOne();
+          } else {
+            m_threads->work_queue->queue(
+              new FunctionContext([&mock_threads, ctx](int) {
+                Mutex::Locker timer_lock(mock_threads.timer_lock);
+                ctx->complete(0);
+              }), 0);
+          }
+        })));
   }
 
-  MockThreads *m_mock_threads;
+  void expect_cancel_event(MockThreads &mock_threads, bool canceled) {
+    EXPECT_CALL(*mock_threads.timer, cancel_event(_))
+      .WillOnce(Return(canceled));
+  }
 };
 
 TEST_F(TestMockInstanceReplayer, AcquireReleaseImage) {
+  MockThreads mock_threads(m_threads);
   MockServiceDaemon mock_service_daemon;
   MockImageDeleter mock_image_deleter;
   MockInstanceWatcher mock_instance_watcher;
   MockImageReplayer mock_image_replayer;
   MockInstanceReplayer instance_replayer(
-    m_mock_threads, &mock_service_daemon, &mock_image_deleter,
+    &mock_threads, &mock_service_daemon, &mock_image_deleter,
     rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
     "local_mirror_uuid", m_local_io_ctx.get_id());
-
   std::string global_image_id("global_image_id");
 
   EXPECT_CALL(mock_image_replayer, get_global_image_id())
     .WillRepeatedly(ReturnRef(global_image_id));
-  EXPECT_CALL(mock_image_replayer, is_blacklisted())
-    .WillRepeatedly(Return(false));
 
   InSequence seq;
-
+  expect_work_queue(mock_threads);
+  Context *timer_ctx = nullptr;
+  expect_add_event_after(mock_threads, &timer_ctx);
   instance_replayer.init();
   instance_replayer.add_peer("peer_uuid", m_remote_io_ctx);
 
   // Acquire
 
   C_SaferCond on_acquire;
-
   EXPECT_CALL(mock_image_replayer, add_peer("peer_uuid", _));
-  EXPECT_CALL(mock_image_replayer, is_stopped())
-    .WillOnce(Return(true));
+  EXPECT_CALL(mock_image_replayer, is_stopped()).WillOnce(Return(true));
+  EXPECT_CALL(mock_image_replayer, is_blacklisted()).WillOnce(Return(false));
   EXPECT_CALL(mock_image_replayer, start(nullptr, false));
+  expect_work_queue(mock_threads);
 
   instance_replayer.acquire_image(&mock_instance_watcher, global_image_id,
                                   &on_acquire);
@@ -181,20 +208,30 @@ TEST_F(TestMockInstanceReplayer, AcquireReleaseImage) {
     .WillOnce(Return(false));
   EXPECT_CALL(mock_image_replayer, is_running())
     .WillOnce(Return(false));
+  expect_work_queue(mock_threads);
+  expect_add_event_after(mock_threads);
+  expect_work_queue(mock_threads);
   EXPECT_CALL(mock_image_replayer, is_stopped())
     .WillOnce(Return(false));
   EXPECT_CALL(mock_image_replayer, is_running())
     .WillOnce(Return(true));
   EXPECT_CALL(mock_image_replayer, stop(_, false))
     .WillOnce(CompleteContext(0));
+  expect_work_queue(mock_threads);
   EXPECT_CALL(mock_image_replayer, is_stopped())
     .WillOnce(Return(true));
+  expect_work_queue(mock_threads);
   EXPECT_CALL(mock_image_replayer, destroy());
 
   instance_replayer.release_image("global_image_id", &on_release);
   ASSERT_EQ(0, on_release.wait());
 
+  expect_work_queue(mock_threads);
+  expect_cancel_event(mock_threads, true);
+  expect_work_queue(mock_threads);
   instance_replayer.shut_down();
+  ASSERT_TRUE(timer_ctx != nullptr);
+  delete timer_ctx;
 }
 
 } // namespace mirror
index 2cba8ed06193cb7ed2f8072dc1314d837ba30f85..4de783e15616f9511fdd8ff87147a7ed3e2db9bc 100644 (file)
@@ -272,7 +272,7 @@ void ImageReplayer<I>::RemoteJournalerListener::handle_update(
 }
 
 template <typename I>
-ImageReplayer<I>::ImageReplayer(Threads<librbd::ImageCtx> *threads,
+ImageReplayer<I>::ImageReplayer(Threads<I> *threads,
                                 ImageDeleter<I>* image_deleter,
                                 InstanceWatcher<I> *instance_watcher,
                                 RadosRef local,
index c0d7cd17a43b4fc01c6e9705e20fc92b42ff7ee1..8705fc09ac219692ff5d2791558f9ba7099aac1a 100644 (file)
@@ -62,7 +62,7 @@ template <typename ImageCtxT = librbd::ImageCtx>
 class ImageReplayer {
 public:
   static ImageReplayer *create(
-    Threads<librbd::ImageCtx> *threads, ImageDeleter<ImageCtxT>* image_deleter,
+    Threads<ImageCtxT> *threads, ImageDeleter<ImageCtxT>* image_deleter,
     InstanceWatcher<ImageCtxT> *instance_watcher,
     RadosRef local, const std::string &local_mirror_uuid, int64_t local_pool_id,
     const std::string &global_image_id) {
@@ -74,7 +74,7 @@ public:
     delete this;
   }
 
-  ImageReplayer(Threads<librbd::ImageCtx> *threads,
+  ImageReplayer(Threads<ImageCtxT> *threads,
                 ImageDeleter<ImageCtxT>* image_deleter,
                 InstanceWatcher<ImageCtxT> *instance_watcher,
                 RadosRef local, const std::string &local_mirror_uuid,
@@ -265,7 +265,7 @@ private:
     ImageReplayer<ImageCtxT> *replayer;
   };
 
-  Threads<librbd::ImageCtx> *m_threads;
+  Threads<ImageCtxT> *m_threads;
   ImageDeleter<ImageCtxT>* m_image_deleter;
   InstanceWatcher<ImageCtxT> *m_instance_watcher;