1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
6 #include "test/librados_test_stub/MockTestMemRadosClient.h"
7 #include "test/librbd/mock/MockImageCtx.h"
8 #include "test/rbd_mirror/mock/MockContextWQ.h"
9 #include "test/rbd_mirror/mock/MockSafeTimer.h"
10 #include "librbd/MirroringWatcher.h"
11 #include "tools/rbd_mirror/Threads.h"
12 #include "tools/rbd_mirror/PoolWatcher.h"
13 #include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.h"
14 #include "include/stringify.h"
19 struct MockTestImageCtx : public librbd::MockImageCtx {
20 MockTestImageCtx(librbd::ImageCtx &image_ctx)
21 : librbd::MockImageCtx(image_ctx) {
25 } // anonymous namespace
27 struct MockMirroringWatcher {
28 static MockMirroringWatcher *s_instance;
29 static MockMirroringWatcher &get_instance() {
30 assert(s_instance != nullptr);
34 MockMirroringWatcher() {
38 MOCK_CONST_METHOD0(is_unregistered, bool());
39 MOCK_METHOD1(register_watch, void(Context*));
40 MOCK_METHOD1(unregister_watch, void(Context*));
42 MOCK_CONST_METHOD0(get_oid, std::string());
46 struct MirroringWatcher<MockTestImageCtx> {
47 static MirroringWatcher *s_instance;
49 MirroringWatcher(librados::IoCtx &io_ctx, ::MockContextWQ *work_queue) {
52 virtual ~MirroringWatcher() {
55 static MirroringWatcher<MockTestImageCtx> &get_instance() {
56 assert(s_instance != nullptr);
60 virtual void handle_rewatch_complete(int r) = 0;
62 virtual void handle_mode_updated(cls::rbd::MirrorMode mirror_mode) = 0;
63 virtual void handle_image_updated(cls::rbd::MirrorImageState state,
64 const std::string &remote_image_id,
65 const std::string &global_image_id) = 0;
67 bool is_unregistered() const {
68 return MockMirroringWatcher::get_instance().is_unregistered();
70 void register_watch(Context *ctx) {
71 MockMirroringWatcher::get_instance().register_watch(ctx);
73 void unregister_watch(Context *ctx) {
74 MockMirroringWatcher::get_instance().unregister_watch(ctx);
76 std::string get_oid() const {
77 return MockMirroringWatcher::get_instance().get_oid();
81 MockMirroringWatcher *MockMirroringWatcher::s_instance = nullptr;
82 MirroringWatcher<MockTestImageCtx> *MirroringWatcher<MockTestImageCtx>::s_instance = nullptr;
90 struct Threads<librbd::MockTestImageCtx> {
94 MockContextWQ *work_queue;
96 Threads(Threads<librbd::ImageCtx> *threads)
97 : timer(new MockSafeTimer()),
98 timer_lock(threads->timer_lock),
99 work_queue(new MockContextWQ()) {
107 namespace pool_watcher {
110 struct RefreshImagesRequest<librbd::MockTestImageCtx> {
111 ImageIds *image_ids = nullptr;
112 Context *on_finish = nullptr;
113 static RefreshImagesRequest *s_instance;
114 static RefreshImagesRequest *create(librados::IoCtx &io_ctx,
116 Context *on_finish) {
117 assert(s_instance != nullptr);
118 s_instance->image_ids = image_ids;
119 s_instance->on_finish = on_finish;
123 MOCK_METHOD0(send, void());
125 RefreshImagesRequest() {
130 RefreshImagesRequest<librbd::MockTestImageCtx> *RefreshImagesRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
132 } // namespace pool_watcher
134 } // namespace mirror
137 // template definitions
138 #include "tools/rbd_mirror/PoolWatcher.cc"
144 using ::testing::DoAll;
145 using ::testing::InSequence;
146 using ::testing::Invoke;
147 using ::testing::Return;
148 using ::testing::ReturnArg;
149 using ::testing::StrEq;
150 using ::testing::WithArg;
151 using ::testing::WithoutArgs;
153 class TestMockPoolWatcher : public TestMockFixture {
155 typedef PoolWatcher<librbd::MockTestImageCtx> MockPoolWatcher;
156 typedef Threads<librbd::MockTestImageCtx> MockThreads;
157 typedef pool_watcher::RefreshImagesRequest<librbd::MockTestImageCtx> MockRefreshImagesRequest;
158 typedef librbd::MockMirroringWatcher MockMirroringWatcher;
159 typedef librbd::MirroringWatcher<librbd::MockTestImageCtx> MirroringWatcher;
161 struct MockListener : MockPoolWatcher::Listener {
162 TestMockPoolWatcher *test;
164 MockListener(TestMockPoolWatcher *test) : test(test) {
167 MOCK_METHOD3(mock_handle_update, void(const std::string &, const ImageIds &,
169 void handle_update(const std::string &mirror_uuid,
170 ImageIds &&added_image_ids,
171 ImageIds &&removed_image_ids) override {
172 mock_handle_update(mirror_uuid, added_image_ids, removed_image_ids);
176 TestMockPoolWatcher() : m_lock("TestMockPoolWatcher::m_lock") {
179 void expect_work_queue(MockThreads &mock_threads) {
180 EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
181 .WillRepeatedly(Invoke([this](Context *ctx, int r) {
182 m_threads->work_queue->queue(ctx, r);
186 void expect_mirroring_watcher_is_unregistered(MockMirroringWatcher &mock_mirroring_watcher,
188 EXPECT_CALL(mock_mirroring_watcher, is_unregistered())
189 .WillOnce(Return(unregistered));
192 void expect_mirroring_watcher_register(MockMirroringWatcher &mock_mirroring_watcher,
194 EXPECT_CALL(mock_mirroring_watcher, register_watch(_))
195 .WillOnce(CompleteContext(r));
198 void expect_mirroring_watcher_unregister(MockMirroringWatcher &mock_mirroring_watcher,
200 EXPECT_CALL(mock_mirroring_watcher, unregister_watch(_))
201 .WillOnce(CompleteContext(r));
204 void expect_refresh_images(MockRefreshImagesRequest &request,
205 const ImageIds &image_ids, int r) {
206 EXPECT_CALL(request, send())
207 .WillOnce(Invoke([&request, image_ids, r]() {
208 *request.image_ids = image_ids;
209 request.on_finish->complete(r);
213 void expect_listener_handle_update(MockListener &mock_listener,
214 const std::string &mirror_uuid,
215 const ImageIds &added_image_ids,
216 const ImageIds &removed_image_ids) {
217 EXPECT_CALL(mock_listener, mock_handle_update(mirror_uuid, added_image_ids,
219 .WillOnce(WithoutArgs(Invoke([this]() {
220 Mutex::Locker locker(m_lock);
226 void expect_mirror_uuid_get(librados::IoCtx &io_ctx,
227 const std::string &uuid, int r) {
229 ::encode(uuid, out_bl);
231 EXPECT_CALL(get_mock_io_ctx(io_ctx),
232 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_uuid_get"),
234 .WillOnce(DoAll(WithArg<5>(Invoke([this, out_bl](bufferlist *bl) {
240 void expect_timer_add_event(MockThreads &mock_threads) {
241 EXPECT_CALL(*mock_threads.timer, add_event_after(_, _))
242 .WillOnce(DoAll(WithArg<1>(Invoke([this](Context *ctx) {
244 new FunctionContext([this, ctx](int r) {
245 Mutex::Locker timer_locker(m_threads->timer_lock);
248 m_threads->work_queue->queue(wrapped_ctx, 0);
253 int when_shut_down(MockPoolWatcher &mock_pool_watcher) {
255 mock_pool_watcher.shut_down(&ctx);
259 bool wait_for_update(uint32_t count) {
260 Mutex::Locker locker(m_lock);
261 while (m_update_count < count) {
262 if (m_cond.WaitInterval(m_lock, utime_t(10, 0)) != 0) {
266 if (m_update_count < count) {
270 m_update_count -= count;
276 uint32_t m_update_count = 0;
279 TEST_F(TestMockPoolWatcher, EmptyPool) {
280 MockThreads mock_threads(m_threads);
281 expect_work_queue(mock_threads);
284 MockMirroringWatcher mock_mirroring_watcher;
285 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
286 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
288 MockRefreshImagesRequest mock_refresh_images_request;
289 expect_refresh_images(mock_refresh_images_request, {}, 0);
290 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
292 MockListener mock_listener(this);
293 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
295 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
298 mock_pool_watcher.init(&ctx);
299 ASSERT_EQ(0, ctx.wait());
301 ASSERT_TRUE(wait_for_update(1));
302 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
303 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
306 TEST_F(TestMockPoolWatcher, NonEmptyPool) {
307 MockThreads mock_threads(m_threads);
308 expect_work_queue(mock_threads);
311 MockMirroringWatcher mock_mirroring_watcher;
312 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
313 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
316 {"global id 1", "remote id 1"},
317 {"global id 2", "remote id 2"}};
318 MockRefreshImagesRequest mock_refresh_images_request;
319 expect_refresh_images(mock_refresh_images_request, image_ids, 0);
320 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
322 MockListener mock_listener(this);
323 expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
325 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
328 mock_pool_watcher.init(&ctx);
329 ASSERT_EQ(0, ctx.wait());
331 ASSERT_TRUE(wait_for_update(1));
332 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
333 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
336 TEST_F(TestMockPoolWatcher, NotifyDuringRefresh) {
337 MockThreads mock_threads(m_threads);
338 expect_work_queue(mock_threads);
341 MockMirroringWatcher mock_mirroring_watcher;
342 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
343 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
346 {"global id 1", "remote id 1"},
347 {"global id 2", "remote id 2"}};
348 MockRefreshImagesRequest mock_refresh_images_request;
349 bool refresh_sent = false;
350 EXPECT_CALL(mock_refresh_images_request, send())
351 .WillOnce(Invoke([this, &mock_refresh_images_request, &image_ids,
353 *mock_refresh_images_request.image_ids = image_ids;
355 Mutex::Locker locker(m_lock);
360 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
362 MockListener mock_listener(this);
364 {"global id 1", "remote id 1a"},
365 {"global id 3", "remote id 3"}};
366 expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
368 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
370 mock_pool_watcher.init(nullptr);
373 Mutex::Locker locker(m_lock);
374 while (!refresh_sent) {
379 MirroringWatcher::get_instance().handle_image_updated(
380 cls::rbd::MIRROR_IMAGE_STATE_DISABLING, "remote id 2", "global id 2");
381 MirroringWatcher::get_instance().handle_image_updated(
382 cls::rbd::MIRROR_IMAGE_STATE_ENABLED, "remote id 1a", "global id 1");
383 MirroringWatcher::get_instance().handle_image_updated(
384 cls::rbd::MIRROR_IMAGE_STATE_ENABLED, "remote id 3", "global id 3");
386 mock_refresh_images_request.on_finish->complete(0);
387 ASSERT_TRUE(wait_for_update(1));
389 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
390 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
393 TEST_F(TestMockPoolWatcher, Notify) {
394 MockThreads mock_threads(m_threads);
397 MockMirroringWatcher mock_mirroring_watcher;
398 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
399 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
402 {"global id 1", "remote id 1"},
403 {"global id 2", "remote id 2"}};
404 MockRefreshImagesRequest mock_refresh_images_request;
405 expect_refresh_images(mock_refresh_images_request, image_ids, 0);
406 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
408 EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
409 .WillOnce(Invoke([this](Context *ctx, int r) {
410 m_threads->work_queue->queue(ctx, r);
413 MockListener mock_listener(this);
414 expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
416 Context *notify_ctx = nullptr;
417 EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
418 .WillOnce(Invoke([this, ¬ify_ctx](Context *ctx, int r) {
419 Mutex::Locker locker(m_lock);
420 ASSERT_EQ(nullptr, notify_ctx);
424 expect_listener_handle_update(
425 mock_listener, "remote uuid",
426 {{"global id 1", "remote id 1a"}, {"global id 3", "remote id 3"}},
427 {{"global id 1", "remote id 1"}, {"global id 2", "remote id 2"}});
429 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
432 mock_pool_watcher.init(&ctx);
433 ASSERT_EQ(0, ctx.wait());
434 ASSERT_TRUE(wait_for_update(1));
436 C_SaferCond flush_ctx;
437 m_threads->work_queue->queue(&flush_ctx, 0);
438 ASSERT_EQ(0, flush_ctx.wait());
440 MirroringWatcher::get_instance().handle_image_updated(
441 cls::rbd::MIRROR_IMAGE_STATE_DISABLING, "remote id 2", "global id 2");
442 MirroringWatcher::get_instance().handle_image_updated(
443 cls::rbd::MIRROR_IMAGE_STATE_DISABLED, "remote id 2", "global id 2");
444 MirroringWatcher::get_instance().handle_image_updated(
445 cls::rbd::MIRROR_IMAGE_STATE_ENABLED, "remote id 1a", "global id 1");
446 MirroringWatcher::get_instance().handle_image_updated(
447 cls::rbd::MIRROR_IMAGE_STATE_ENABLED, "remote id 3", "global id 3");
448 notify_ctx->complete(0);
450 ASSERT_TRUE(wait_for_update(1));
452 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
453 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
456 TEST_F(TestMockPoolWatcher, RegisterWatcherBlacklist) {
457 MockThreads mock_threads(m_threads);
458 expect_work_queue(mock_threads);
461 MockMirroringWatcher mock_mirroring_watcher;
462 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
463 expect_mirroring_watcher_register(mock_mirroring_watcher, -EBLACKLISTED);
465 MockListener mock_listener(this);
466 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
469 mock_pool_watcher.init(&ctx);
470 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
471 ASSERT_TRUE(mock_pool_watcher.is_blacklisted());
473 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
474 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
477 TEST_F(TestMockPoolWatcher, RegisterWatcherMissing) {
478 MockThreads mock_threads(m_threads);
479 expect_work_queue(mock_threads);
482 MockMirroringWatcher mock_mirroring_watcher;
483 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
484 expect_mirroring_watcher_register(mock_mirroring_watcher, -ENOENT);
485 expect_timer_add_event(mock_threads);
487 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
488 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
490 MockRefreshImagesRequest mock_refresh_images_request;
491 expect_refresh_images(mock_refresh_images_request, {}, 0);
492 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
494 MockListener mock_listener(this);
495 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
497 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
500 mock_pool_watcher.init(&ctx);
501 ASSERT_EQ(0, ctx.wait());
503 ASSERT_TRUE(wait_for_update(1));
504 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
505 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
508 TEST_F(TestMockPoolWatcher, RegisterWatcherError) {
509 MockThreads mock_threads(m_threads);
510 expect_work_queue(mock_threads);
513 MockMirroringWatcher mock_mirroring_watcher;
514 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
515 expect_mirroring_watcher_register(mock_mirroring_watcher, -EINVAL);
516 expect_timer_add_event(mock_threads);
518 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
519 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
521 MockRefreshImagesRequest mock_refresh_images_request;
522 expect_refresh_images(mock_refresh_images_request, {}, 0);
523 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
525 MockListener mock_listener(this);
526 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
528 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
531 mock_pool_watcher.init(&ctx);
532 ASSERT_EQ(0, ctx.wait());
534 ASSERT_TRUE(wait_for_update(1));
535 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
536 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
539 TEST_F(TestMockPoolWatcher, RefreshBlacklist) {
540 MockThreads mock_threads(m_threads);
541 expect_work_queue(mock_threads);
544 MockMirroringWatcher mock_mirroring_watcher;
545 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
546 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
548 MockRefreshImagesRequest mock_refresh_images_request;
549 expect_refresh_images(mock_refresh_images_request, {}, -EBLACKLISTED);
551 MockListener mock_listener(this);
552 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
555 mock_pool_watcher.init(&ctx);
556 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
557 ASSERT_TRUE(mock_pool_watcher.is_blacklisted());
559 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
560 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
563 TEST_F(TestMockPoolWatcher, RefreshMissing) {
564 MockThreads mock_threads(m_threads);
565 expect_work_queue(mock_threads);
568 MockMirroringWatcher mock_mirroring_watcher;
569 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
570 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
572 MockRefreshImagesRequest mock_refresh_images_request;
573 expect_refresh_images(mock_refresh_images_request, {}, -ENOENT);
574 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
576 MockListener mock_listener(this);
577 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
579 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
582 mock_pool_watcher.init(&ctx);
583 ASSERT_EQ(0, ctx.wait());
585 ASSERT_TRUE(wait_for_update(1));
586 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
587 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
590 TEST_F(TestMockPoolWatcher, RefreshError) {
591 MockThreads mock_threads(m_threads);
592 expect_work_queue(mock_threads);
595 MockMirroringWatcher mock_mirroring_watcher;
596 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
597 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
599 MockRefreshImagesRequest mock_refresh_images_request;
600 expect_refresh_images(mock_refresh_images_request, {}, -EINVAL);
601 expect_timer_add_event(mock_threads);
603 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
604 expect_refresh_images(mock_refresh_images_request, {}, 0);
605 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
607 MockListener mock_listener(this);
608 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
610 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
613 mock_pool_watcher.init(&ctx);
614 ASSERT_EQ(0, ctx.wait());
616 ASSERT_TRUE(wait_for_update(1));
617 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
618 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
621 TEST_F(TestMockPoolWatcher, GetMirrorUuidBlacklist) {
622 MockThreads mock_threads(m_threads);
623 expect_work_queue(mock_threads);
626 MockMirroringWatcher mock_mirroring_watcher;
627 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
628 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
630 MockRefreshImagesRequest mock_refresh_images_request;
631 expect_refresh_images(mock_refresh_images_request, {}, 0);
632 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", -EBLACKLISTED);
634 MockListener mock_listener(this);
635 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
638 mock_pool_watcher.init(&ctx);
639 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
640 ASSERT_TRUE(mock_pool_watcher.is_blacklisted());
642 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
643 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
646 TEST_F(TestMockPoolWatcher, GetMirrorUuidMissing) {
647 MockThreads mock_threads(m_threads);
648 expect_work_queue(mock_threads);
651 MockMirroringWatcher mock_mirroring_watcher;
652 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
653 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
655 MockRefreshImagesRequest mock_refresh_images_request;
656 expect_refresh_images(mock_refresh_images_request, {}, 0);
657 expect_mirror_uuid_get(m_remote_io_ctx, "", -ENOENT);
658 expect_timer_add_event(mock_threads);
660 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
661 expect_refresh_images(mock_refresh_images_request, {}, 0);
662 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
664 MockListener mock_listener(this);
665 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
667 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
670 mock_pool_watcher.init(&ctx);
671 ASSERT_EQ(-ENOENT, ctx.wait());
673 ASSERT_TRUE(wait_for_update(1));
674 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
675 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
678 TEST_F(TestMockPoolWatcher, GetMirrorUuidError) {
679 MockThreads mock_threads(m_threads);
680 expect_work_queue(mock_threads);
683 MockMirroringWatcher mock_mirroring_watcher;
684 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
685 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
687 MockRefreshImagesRequest mock_refresh_images_request;
688 expect_refresh_images(mock_refresh_images_request, {}, 0);
689 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", -EINVAL);
690 expect_timer_add_event(mock_threads);
692 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
693 expect_refresh_images(mock_refresh_images_request, {}, 0);
694 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
696 MockListener mock_listener(this);
697 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
699 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
702 mock_pool_watcher.init(&ctx);
703 ASSERT_EQ(0, ctx.wait());
705 ASSERT_TRUE(wait_for_update(1));
706 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
707 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
710 TEST_F(TestMockPoolWatcher, Rewatch) {
711 MockThreads mock_threads(m_threads);
712 expect_work_queue(mock_threads);
715 MockMirroringWatcher mock_mirroring_watcher;
716 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
717 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
719 MockRefreshImagesRequest mock_refresh_images_request;
720 expect_refresh_images(mock_refresh_images_request, {}, 0);
721 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
723 MockListener mock_listener(this);
724 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
726 expect_timer_add_event(mock_threads);
727 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
728 expect_refresh_images(mock_refresh_images_request, {{"global id", "image id"}}, 0);
729 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
730 expect_listener_handle_update(mock_listener, "remote uuid",
731 {{"global id", "image id"}}, {});
733 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
736 mock_pool_watcher.init(&ctx);
737 ASSERT_EQ(0, ctx.wait());
738 ASSERT_TRUE(wait_for_update(1));
740 MirroringWatcher::get_instance().handle_rewatch_complete(0);
741 ASSERT_TRUE(wait_for_update(1));
743 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
744 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
747 TEST_F(TestMockPoolWatcher, RewatchBlacklist) {
748 MockThreads mock_threads(m_threads);
749 expect_work_queue(mock_threads);
752 MockMirroringWatcher mock_mirroring_watcher;
753 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
754 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
756 MockRefreshImagesRequest mock_refresh_images_request;
757 expect_refresh_images(mock_refresh_images_request, {}, 0);
758 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
760 MockListener mock_listener(this);
761 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
763 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
766 mock_pool_watcher.init(&ctx);
767 ASSERT_EQ(0, ctx.wait());
768 ASSERT_TRUE(wait_for_update(1));
770 MirroringWatcher::get_instance().handle_rewatch_complete(-EBLACKLISTED);
771 ASSERT_TRUE(mock_pool_watcher.is_blacklisted());
773 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
774 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
777 TEST_F(TestMockPoolWatcher, RewatchError) {
778 MockThreads mock_threads(m_threads);
779 expect_work_queue(mock_threads);
782 MockMirroringWatcher mock_mirroring_watcher;
783 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
784 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
786 MockRefreshImagesRequest mock_refresh_images_request;
787 expect_refresh_images(mock_refresh_images_request, {}, 0);
788 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
790 MockListener mock_listener(this);
791 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
793 expect_timer_add_event(mock_threads);
794 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
795 expect_refresh_images(mock_refresh_images_request, {{"global id", "image id"}}, 0);
796 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
797 expect_listener_handle_update(mock_listener, "remote uuid",
798 {{"global id", "image id"}}, {});
800 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
803 mock_pool_watcher.init(&ctx);
804 ASSERT_EQ(0, ctx.wait());
805 ASSERT_TRUE(wait_for_update(1));
807 MirroringWatcher::get_instance().handle_rewatch_complete(-EINVAL);
808 ASSERT_TRUE(wait_for_update(1));
810 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
811 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
814 TEST_F(TestMockPoolWatcher, DeferredRefresh) {
815 MockThreads mock_threads(m_threads);
816 expect_work_queue(mock_threads);
819 MockMirroringWatcher mock_mirroring_watcher;
820 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
821 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
823 MockRefreshImagesRequest mock_refresh_images_request;
825 EXPECT_CALL(mock_refresh_images_request, send())
826 .WillOnce(Invoke([&mock_refresh_images_request]() {
827 *mock_refresh_images_request.image_ids = {};
828 MirroringWatcher::get_instance().handle_rewatch_complete(0);
829 mock_refresh_images_request.on_finish->complete(0);
831 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
832 expect_timer_add_event(mock_threads);
834 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
835 expect_refresh_images(mock_refresh_images_request, {}, 0);
836 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
838 MockListener mock_listener(this);
839 expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
841 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
844 mock_pool_watcher.init(&ctx);
845 ASSERT_EQ(0, ctx.wait());
846 ASSERT_TRUE(wait_for_update(1));
848 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
849 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
852 TEST_F(TestMockPoolWatcher, MirrorUuidUpdated) {
853 MockThreads mock_threads(m_threads);
854 expect_work_queue(mock_threads);
857 MockMirroringWatcher mock_mirroring_watcher;
858 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
859 expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
862 {"global id 1", "remote id 1"},
863 {"global id 2", "remote id 2"}};
864 MockRefreshImagesRequest mock_refresh_images_request;
865 expect_refresh_images(mock_refresh_images_request, image_ids, 0);
866 expect_mirror_uuid_get(m_remote_io_ctx, "remote uuid", 0);
868 MockListener mock_listener(this);
869 expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
871 MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
874 mock_pool_watcher.init(&ctx);
875 ASSERT_EQ(0, ctx.wait());
877 ASSERT_TRUE(wait_for_update(1));
879 expect_timer_add_event(mock_threads);
880 ImageIds new_image_ids{
881 {"global id 1", "remote id 1"}};
882 expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
883 expect_refresh_images(mock_refresh_images_request, new_image_ids, 0);
884 expect_mirror_uuid_get(m_remote_io_ctx, "updated uuid", 0);
885 expect_listener_handle_update(mock_listener, "remote uuid", {}, image_ids);
886 expect_listener_handle_update(mock_listener, "updated uuid", new_image_ids,
889 MirroringWatcher::get_instance().handle_rewatch_complete(0);
890 ASSERT_TRUE(wait_for_update(2));
892 expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
893 ASSERT_EQ(0, when_shut_down(mock_pool_watcher));
896 } // namespace mirror