]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/test_mock_ImageReplayer.cc
update sources to 12.2.7
[ceph.git] / ceph / src / test / rbd_mirror / test_mock_ImageReplayer.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "cls/journal/cls_journal_types.h"
5#include "librbd/journal/Replay.h"
6#include "librbd/journal/Types.h"
c07f9fc5 7#include "tools/rbd_mirror/ImageDeleter.h"
7c673cae 8#include "tools/rbd_mirror/ImageReplayer.h"
31f18b77 9#include "tools/rbd_mirror/InstanceWatcher.h"
d2e6a577 10#include "tools/rbd_mirror/Threads.h"
7c673cae
FG
11#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
12#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
13#include "tools/rbd_mirror/image_replayer/EventPreprocessor.h"
14#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
d2e6a577 15#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
7c673cae
FG
16#include "test/rbd_mirror/test_mock_fixture.h"
17#include "test/journal/mock/MockJournaler.h"
18#include "test/librbd/mock/MockImageCtx.h"
19#include "test/librbd/mock/MockJournal.h"
d2e6a577
FG
20#include "test/rbd_mirror/mock/MockContextWQ.h"
21#include "test/rbd_mirror/mock/MockSafeTimer.h"
7c673cae
FG
22
23namespace librbd {
24
25namespace {
26
27struct MockTestJournal;
28
29struct MockTestImageCtx : public MockImageCtx {
30 MockTestImageCtx(librbd::ImageCtx &image_ctx)
31 : librbd::MockImageCtx(image_ctx) {
32 }
33 MockTestJournal *journal = nullptr;
34};
35
36struct MockTestJournal : public MockJournal {
37 MOCK_METHOD2(start_external_replay, void(journal::Replay<MockTestImageCtx> **,
38 Context *on_start));
39 MOCK_METHOD0(stop_external_replay, void());
40};
41
42} // anonymous namespace
43
44namespace journal {
45
46template<>
47struct Replay<MockTestImageCtx> {
48 MOCK_METHOD2(decode, int(bufferlist::iterator *, EventEntry *));
49 MOCK_METHOD3(process, void(const EventEntry &, Context *, Context *));
50 MOCK_METHOD1(flush, void(Context*));
51 MOCK_METHOD2(shut_down, void(bool, Context*));
52};
53
54template <>
55struct TypeTraits<MockTestImageCtx> {
56 typedef ::journal::MockJournalerProxy Journaler;
57 typedef ::journal::MockReplayEntryProxy ReplayEntry;
58};
59
60struct MirrorPeerClientMeta;
61
62} // namespace journal
63} // namespace librbd
64
65namespace rbd {
66namespace mirror {
67
d2e6a577
FG
68template <>
69struct Threads<librbd::MockTestImageCtx> {
70 MockSafeTimer *timer;
71 Mutex &timer_lock;
72
73 MockContextWQ *work_queue;
74
75 Threads(Threads<librbd::ImageCtx> *threads)
76 : timer(new MockSafeTimer()),
77 timer_lock(threads->timer_lock),
78 work_queue(new MockContextWQ()) {
79 }
80 ~Threads() {
81 delete timer;
82 delete work_queue;
83 }
84};
85
c07f9fc5
FG
86template <>
87struct ImageDeleter<librbd::MockTestImageCtx> {
88 MOCK_METHOD4(schedule_image_delete, void(RadosRef, int64_t,
89 const std::string&, bool));
d2e6a577
FG
90 MOCK_METHOD4(wait_for_scheduled_deletion,
91 void(int64_t, const std::string&, Context*, bool));
92 MOCK_METHOD2(cancel_waiter, void(int64_t, const std::string&));
c07f9fc5
FG
93};
94
7c673cae 95template<>
31f18b77 96class InstanceWatcher<librbd::MockTestImageCtx> {
7c673cae
FG
97};
98
99namespace image_replayer {
100
101using ::testing::_;
102using ::testing::AtLeast;
103using ::testing::DoAll;
104using ::testing::InSequence;
105using ::testing::Invoke;
106using ::testing::MatcherCast;
107using ::testing::Return;
3efd9988 108using ::testing::ReturnArg;
7c673cae
FG
109using ::testing::SetArgPointee;
110using ::testing::WithArg;
111
112template<>
113struct PrepareLocalImageRequest<librbd::MockTestImageCtx> {
114 static PrepareLocalImageRequest* s_instance;
115 std::string *local_image_id = nullptr;
28e407b8 116 std::string *local_image_name = nullptr;
7c673cae
FG
117 std::string *tag_owner = nullptr;
118 Context *on_finish = nullptr;
119
120 static PrepareLocalImageRequest* create(librados::IoCtx &,
121 const std::string &global_image_id,
122 std::string *local_image_id,
28e407b8 123 std::string *local_image_name,
7c673cae 124 std::string *tag_owner,
d2e6a577 125 MockContextWQ *work_queue,
7c673cae
FG
126 Context *on_finish) {
127 assert(s_instance != nullptr);
128 s_instance->local_image_id = local_image_id;
28e407b8 129 s_instance->local_image_name = local_image_name;
7c673cae
FG
130 s_instance->tag_owner = tag_owner;
131 s_instance->on_finish = on_finish;
132 return s_instance;
133 }
134
135 PrepareLocalImageRequest() {
136 s_instance = this;
137 }
138
139 MOCK_METHOD0(send, void());
140};
141
d2e6a577
FG
142template<>
143struct PrepareRemoteImageRequest<librbd::MockTestImageCtx> {
144 static PrepareRemoteImageRequest* s_instance;
145 std::string *remote_mirror_uuid = nullptr;
146 std::string *remote_image_id = nullptr;
b32b8144
FG
147 cls::journal::ClientState *client_state;
148 ::journal::MockJournalerProxy **remote_journaler = nullptr;
149 librbd::journal::MirrorPeerClientMeta *client_meta = nullptr;
d2e6a577
FG
150 Context *on_finish = nullptr;
151
b32b8144
FG
152 static PrepareRemoteImageRequest* create(Threads<librbd::MockTestImageCtx> *threads,
153 librados::IoCtx &,
d2e6a577 154 const std::string &global_image_id,
b32b8144
FG
155 const std::string &local_mirror_uuid,
156 const std::string &local_image_id,
d2e6a577
FG
157 std::string *remote_mirror_uuid,
158 std::string *remote_image_id,
b32b8144
FG
159 ::journal::MockJournalerProxy **remote_journaler,
160 cls::journal::ClientState *client_state,
161 librbd::journal::MirrorPeerClientMeta *client_meta,
d2e6a577
FG
162 Context *on_finish) {
163 assert(s_instance != nullptr);
164 s_instance->remote_mirror_uuid = remote_mirror_uuid;
165 s_instance->remote_image_id = remote_image_id;
b32b8144
FG
166 s_instance->remote_journaler = remote_journaler;
167 s_instance->client_state = client_state;
168 s_instance->client_meta = client_meta;
d2e6a577
FG
169 s_instance->on_finish = on_finish;
170 return s_instance;
171 }
172
173 PrepareRemoteImageRequest() {
174 s_instance = this;
175 }
176
177 MOCK_METHOD0(send, void());
178};
179
7c673cae
FG
180template<>
181struct BootstrapRequest<librbd::MockTestImageCtx> {
182 static BootstrapRequest* s_instance;
183 librbd::MockTestImageCtx **image_ctx = nullptr;
184 Context *on_finish = nullptr;
185 bool *do_resync = nullptr;
186
31f18b77
FG
187 static BootstrapRequest* create(
188 librados::IoCtx &local_io_ctx, librados::IoCtx &remote_io_ctx,
189 rbd::mirror::InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
190 librbd::MockTestImageCtx **local_image_ctx,
191 const std::string &local_image_name, const std::string &remote_image_id,
d2e6a577
FG
192 const std::string &global_image_id, MockContextWQ *work_queue,
193 MockSafeTimer *timer, Mutex *timer_lock,
194 const std::string &local_mirror_uuid,
31f18b77
FG
195 const std::string &remote_mirror_uuid,
196 ::journal::MockJournalerProxy *journaler,
b32b8144 197 cls::journal::ClientState *client_state,
31f18b77
FG
198 librbd::journal::MirrorPeerClientMeta *client_meta,
199 Context *on_finish, bool *do_resync,
200 rbd::mirror::ProgressContext *progress_ctx = nullptr) {
7c673cae
FG
201 assert(s_instance != nullptr);
202 s_instance->image_ctx = local_image_ctx;
203 s_instance->on_finish = on_finish;
204 s_instance->do_resync = do_resync;
205 return s_instance;
206 }
207
208 BootstrapRequest() {
209 assert(s_instance == nullptr);
210 s_instance = this;
211 }
212
213 ~BootstrapRequest() {
214 assert(s_instance == this);
215 s_instance = nullptr;
216 }
217
218 void put() {
219 }
220
221 void get() {
222 }
223
c07f9fc5
FG
224 inline bool is_syncing() const {
225 return false;
226 }
227
7c673cae
FG
228 MOCK_METHOD0(send, void());
229 MOCK_METHOD0(cancel, void());
230};
231
232template<>
233struct CloseImageRequest<librbd::MockTestImageCtx> {
234 static CloseImageRequest* s_instance;
235 librbd::MockTestImageCtx **image_ctx = nullptr;
236 Context *on_finish = nullptr;
237
238 static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
239 Context *on_finish) {
240 assert(s_instance != nullptr);
241 s_instance->image_ctx = image_ctx;
242 s_instance->on_finish = on_finish;
243 return s_instance;
244 }
245
246 CloseImageRequest() {
247 assert(s_instance == nullptr);
248 s_instance = this;
249 }
250
251 ~CloseImageRequest() {
252 assert(s_instance == this);
253 s_instance = nullptr;
254 }
255
256 MOCK_METHOD0(send, void());
257};
258
259template<>
260struct EventPreprocessor<librbd::MockTestImageCtx> {
261 static EventPreprocessor *s_instance;
262
263 static EventPreprocessor *create(librbd::MockTestImageCtx &local_image_ctx,
264 ::journal::MockJournalerProxy &remote_journaler,
265 const std::string &local_mirror_uuid,
266 librbd::journal::MirrorPeerClientMeta *client_meta,
d2e6a577 267 MockContextWQ *work_queue) {
7c673cae
FG
268 assert(s_instance != nullptr);
269 return s_instance;
270 }
271
272 static void destroy(EventPreprocessor* processor) {
273 }
274
275 EventPreprocessor() {
276 assert(s_instance == nullptr);
277 s_instance = this;
278 }
279
280 ~EventPreprocessor() {
281 assert(s_instance == this);
282 s_instance = nullptr;
283 }
284
285 MOCK_METHOD1(is_required, bool(const librbd::journal::EventEntry &));
286 MOCK_METHOD2(preprocess, void(librbd::journal::EventEntry *, Context *));
287};
288
289template<>
290struct ReplayStatusFormatter<librbd::MockTestImageCtx> {
291 static ReplayStatusFormatter* s_instance;
292
293 static ReplayStatusFormatter* create(::journal::MockJournalerProxy *journaler,
294 const std::string &mirror_uuid) {
295 assert(s_instance != nullptr);
296 return s_instance;
297 }
298
299 static void destroy(ReplayStatusFormatter* formatter) {
300 }
301
302 ReplayStatusFormatter() {
303 assert(s_instance == nullptr);
304 s_instance = this;
305 }
306
307 ~ReplayStatusFormatter() {
308 assert(s_instance == this);
309 s_instance = nullptr;
310 }
311
312 MOCK_METHOD2(get_or_send_update, bool(std::string *description, Context *on_finish));
313};
314
315BootstrapRequest<librbd::MockTestImageCtx>* BootstrapRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
316CloseImageRequest<librbd::MockTestImageCtx>* CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
317EventPreprocessor<librbd::MockTestImageCtx>* EventPreprocessor<librbd::MockTestImageCtx>::s_instance = nullptr;
318PrepareLocalImageRequest<librbd::MockTestImageCtx>* PrepareLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
d2e6a577 319PrepareRemoteImageRequest<librbd::MockTestImageCtx>* PrepareRemoteImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
7c673cae
FG
320ReplayStatusFormatter<librbd::MockTestImageCtx>* ReplayStatusFormatter<librbd::MockTestImageCtx>::s_instance = nullptr;
321
322} // namespace image_replayer
323} // namespace mirror
324} // namespace rbd
325
326// template definitions
327#include "tools/rbd_mirror/ImageReplayer.cc"
7c673cae
FG
328
329namespace rbd {
330namespace mirror {
331
332class TestMockImageReplayer : public TestMockFixture {
333public:
d2e6a577 334 typedef Threads<librbd::MockTestImageCtx> MockThreads;
c07f9fc5 335 typedef ImageDeleter<librbd::MockTestImageCtx> MockImageDeleter;
7c673cae
FG
336 typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
337 typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
338 typedef EventPreprocessor<librbd::MockTestImageCtx> MockEventPreprocessor;
339 typedef PrepareLocalImageRequest<librbd::MockTestImageCtx> MockPrepareLocalImageRequest;
d2e6a577 340 typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest;
7c673cae
FG
341 typedef ReplayStatusFormatter<librbd::MockTestImageCtx> MockReplayStatusFormatter;
342 typedef librbd::journal::Replay<librbd::MockTestImageCtx> MockReplay;
343 typedef ImageReplayer<librbd::MockTestImageCtx> MockImageReplayer;
31f18b77 344 typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
7c673cae
FG
345
346 void SetUp() override {
347 TestMockFixture::SetUp();
348
349 librbd::RBD rbd;
350 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
351 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
7c673cae
FG
352 }
353
354 void TearDown() override {
355 delete m_image_replayer;
356
357 TestMockFixture::TearDown();
358 }
359
360 void create_local_image() {
361 librbd::RBD rbd;
362 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
363 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
364 }
365
d2e6a577
FG
366 void expect_work_queue_repeatedly(MockThreads &mock_threads) {
367 EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
368 .WillRepeatedly(Invoke([this](Context *ctx, int r) {
369 m_threads->work_queue->queue(ctx, r);
370 }));
371 }
372
373 void expect_add_event_after_repeatedly(MockThreads &mock_threads) {
374 EXPECT_CALL(*mock_threads.timer, add_event_after(_, _))
375 .WillRepeatedly(
3efd9988
FG
376 DoAll(Invoke([this](double seconds, Context *ctx) {
377 m_threads->timer->add_event_after(seconds, ctx);
378 }),
379 ReturnArg<1>()));
d2e6a577
FG
380 EXPECT_CALL(*mock_threads.timer, cancel_event(_))
381 .WillRepeatedly(
382 Invoke([this](Context *ctx) {
383 return m_threads->timer->cancel_event(ctx);
384 }));
385 }
386
387 void expect_wait_for_scheduled_deletion(MockImageDeleter& mock_image_deleter,
388 const std::string& global_image_id,
389 int r) {
390 EXPECT_CALL(mock_image_deleter,
391 wait_for_scheduled_deletion(_, global_image_id, _, false))
392 .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
393 m_threads->work_queue->queue(ctx, r);
394 })));
395 }
396
397 void expect_cancel_waiter(MockImageDeleter& mock_image_deleter) {
398 EXPECT_CALL(mock_image_deleter, cancel_waiter(m_local_io_ctx.get_id(),
399 "global image id"));
400 }
401
402 void expect_schedule_image_delete(MockImageDeleter& mock_image_deleter,
403 const std::string& global_image_id,
404 bool ignore_orphan) {
405 EXPECT_CALL(mock_image_deleter,
406 schedule_image_delete(_, _, global_image_id, ignore_orphan));
407 }
408
7c673cae
FG
409 bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
410 bufferlist bl;
411 ::encode(tag_data, bl);
412 return bl;
413 }
414
415 void expect_get_or_send_update(
416 MockReplayStatusFormatter &mock_replay_status_formatter) {
417 EXPECT_CALL(mock_replay_status_formatter, get_or_send_update(_, _))
418 .WillRepeatedly(DoAll(WithArg<1>(CompleteContext(-EEXIST)),
419 Return(true)));
420 }
421
422 void expect_send(MockPrepareLocalImageRequest &mock_request,
423 const std::string &local_image_id,
28e407b8 424 const std::string &local_image_name,
7c673cae
FG
425 const std::string &tag_owner,
426 int r) {
427 EXPECT_CALL(mock_request, send())
28e407b8 428 .WillOnce(Invoke([&mock_request, local_image_id, local_image_name, tag_owner, r]() {
7c673cae
FG
429 if (r == 0) {
430 *mock_request.local_image_id = local_image_id;
28e407b8 431 *mock_request.local_image_name = local_image_name;
7c673cae
FG
432 *mock_request.tag_owner = tag_owner;
433 }
434 mock_request.on_finish->complete(r);
435 }));
436 }
437
d2e6a577
FG
438 void expect_send(MockPrepareRemoteImageRequest& mock_request,
439 const std::string& mirror_uuid, const std::string& image_id,
440 int r) {
441 EXPECT_CALL(mock_request, send())
442 .WillOnce(Invoke([&mock_request, image_id, mirror_uuid, r]() {
b32b8144
FG
443 if (r >= 0) {
444 *mock_request.remote_journaler = new ::journal::MockJournalerProxy();
445 }
446
d2e6a577
FG
447 *mock_request.remote_mirror_uuid = mirror_uuid;
448 *mock_request.remote_image_id = image_id;
449 mock_request.on_finish->complete(r);
450 }));
451 }
452
7c673cae
FG
453 void expect_send(MockBootstrapRequest &mock_bootstrap_request,
454 librbd::MockTestImageCtx &mock_local_image_ctx,
455 bool do_resync, int r) {
456 EXPECT_CALL(mock_bootstrap_request, send())
457 .WillOnce(Invoke([&mock_bootstrap_request, &mock_local_image_ctx,
458 do_resync, r]() {
459 if (r == 0) {
460 *mock_bootstrap_request.image_ctx = &mock_local_image_ctx;
461 *mock_bootstrap_request.do_resync = do_resync;
462 }
463 mock_bootstrap_request.on_finish->complete(r);
464 }));
465 }
466
467 void expect_start_external_replay(librbd::MockTestJournal &mock_journal,
468 MockReplay *mock_replay, int r) {
469 EXPECT_CALL(mock_journal, start_external_replay(_, _))
470 .WillOnce(DoAll(SetArgPointee<0>(mock_replay),
471 WithArg<1>(CompleteContext(r))));
472 }
473
474 void expect_init(::journal::MockJournaler &mock_journaler, int r) {
475 EXPECT_CALL(mock_journaler, init(_))
476 .WillOnce(CompleteContext(r));
477 }
478
479 void expect_get_cached_client(::journal::MockJournaler &mock_journaler,
480 int r) {
481 librbd::journal::ImageClientMeta image_client_meta;
482 image_client_meta.tag_class = 0;
483
484 librbd::journal::ClientData client_data;
485 client_data.client_meta = image_client_meta;
486
487 cls::journal::Client client;
488 ::encode(client_data, client.data);
489
490 EXPECT_CALL(mock_journaler, get_cached_client("local_mirror_uuid", _))
491 .WillOnce(DoAll(SetArgPointee<1>(client),
492 Return(r)));
493 }
494
495 void expect_stop_replay(::journal::MockJournaler &mock_journaler, int r) {
496 EXPECT_CALL(mock_journaler, stop_replay(_))
497 .WillOnce(CompleteContext(r));
498 }
499
31f18b77
FG
500 void expect_flush(MockReplay &mock_replay, int r) {
501 EXPECT_CALL(mock_replay, flush(_)).WillOnce(CompleteContext(r));
502 }
503
7c673cae
FG
504 void expect_shut_down(MockReplay &mock_replay, bool cancel_ops, int r) {
505 EXPECT_CALL(mock_replay, shut_down(cancel_ops, _))
506 .WillOnce(WithArg<1>(CompleteContext(r)));
507 }
508
509 void expect_shut_down(journal::MockJournaler &mock_journaler, int r) {
510 EXPECT_CALL(mock_journaler, shut_down(_))
511 .WillOnce(CompleteContext(r));
512 }
513
514 void expect_send(MockCloseImageRequest &mock_close_image_request, int r) {
515 EXPECT_CALL(mock_close_image_request, send())
516 .WillOnce(Invoke([&mock_close_image_request, r]() {
517 *mock_close_image_request.image_ctx = nullptr;
518 mock_close_image_request.on_finish->complete(r);
519 }));
520 }
521
522 void expect_get_commit_tid_in_debug(
523 ::journal::MockReplayEntry &mock_replay_entry) {
524 // It is used in debug messages and depends on debug level
525 EXPECT_CALL(mock_replay_entry, get_commit_tid())
526 .Times(AtLeast(0))
527 .WillRepeatedly(Return(0));
528 }
529
530 void expect_committed(::journal::MockJournaler &mock_journaler, int times) {
531 EXPECT_CALL(mock_journaler, committed(
532 MatcherCast<const ::journal::MockReplayEntryProxy&>(_)))
533 .Times(times);
534 }
535
536 void expect_try_pop_front(::journal::MockJournaler &mock_journaler,
537 uint64_t replay_tag_tid, bool entries_available) {
538 EXPECT_CALL(mock_journaler, try_pop_front(_, _))
539 .WillOnce(DoAll(SetArgPointee<0>(::journal::MockReplayEntryProxy()),
540 SetArgPointee<1>(replay_tag_tid),
541 Return(entries_available)));
542 }
543
544 void expect_try_pop_front_return_no_entries(
545 ::journal::MockJournaler &mock_journaler, Context *on_finish) {
546 EXPECT_CALL(mock_journaler, try_pop_front(_, _))
547 .WillOnce(DoAll(Invoke([on_finish](::journal::MockReplayEntryProxy *e,
548 uint64_t *t) {
549 on_finish->complete(0);
550 }),
551 Return(false)));
552 }
553
554 void expect_get_tag(::journal::MockJournaler &mock_journaler,
555 const cls::journal::Tag &tag, int r) {
556 EXPECT_CALL(mock_journaler, get_tag(_, _, _))
557 .WillOnce(DoAll(SetArgPointee<1>(tag),
558 WithArg<2>(CompleteContext(r))));
559 }
560
561 void expect_allocate_tag(librbd::MockTestJournal &mock_journal, int r) {
562 EXPECT_CALL(mock_journal, allocate_tag(_, _, _))
563 .WillOnce(WithArg<2>(CompleteContext(r)));
564 }
565
566 void expect_preprocess(MockEventPreprocessor &mock_event_preprocessor,
567 bool required, int r) {
568 EXPECT_CALL(mock_event_preprocessor, is_required(_))
569 .WillOnce(Return(required));
570 if (required) {
571 EXPECT_CALL(mock_event_preprocessor, preprocess(_, _))
572 .WillOnce(WithArg<1>(CompleteContext(r)));
573 }
574 }
575
576 void expect_process(MockReplay &mock_replay,
577 int on_ready_r, int on_commit_r) {
578 EXPECT_CALL(mock_replay, process(_, _, _))
579 .WillOnce(DoAll(WithArg<1>(CompleteContext(on_ready_r)),
580 WithArg<2>(CompleteContext(on_commit_r))));
581 }
582
d2e6a577
FG
583 void create_image_replayer(MockThreads &mock_threads,
584 MockImageDeleter &mock_image_deleter) {
c07f9fc5 585 m_image_replayer = new MockImageReplayer(
d2e6a577 586 &mock_threads, &mock_image_deleter, &m_instance_watcher,
c07f9fc5
FG
587 rbd::mirror::RadosRef(new librados::Rados(m_local_io_ctx)),
588 "local_mirror_uuid", m_local_io_ctx.get_id(), "global image id");
d2e6a577 589 m_image_replayer->add_peer("peer_uuid", m_remote_io_ctx);
c07f9fc5
FG
590 }
591
7c673cae
FG
592 librbd::ImageCtx *m_remote_image_ctx;
593 librbd::ImageCtx *m_local_image_ctx = nullptr;
31f18b77 594 MockInstanceWatcher m_instance_watcher;
c07f9fc5 595 MockImageReplayer *m_image_replayer = nullptr;
7c673cae
FG
596};
597
598TEST_F(TestMockImageReplayer, StartStop) {
599 // START
600
601 create_local_image();
602 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
603
604 librbd::MockTestJournal mock_local_journal;
605 mock_local_image_ctx.journal = &mock_local_journal;
606
607 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
608 MockThreads mock_threads(m_threads);
609 expect_work_queue_repeatedly(mock_threads);
610 expect_add_event_after_repeatedly(mock_threads);
611
612 MockImageDeleter mock_image_deleter;
7c673cae 613 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 614 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
615 MockBootstrapRequest mock_bootstrap_request;
616 MockReplay mock_local_replay;
617 MockEventPreprocessor mock_event_preprocessor;
618 MockReplayStatusFormatter mock_replay_status_formatter;
619
620 expect_get_or_send_update(mock_replay_status_formatter);
621
622 InSequence seq;
d2e6a577 623 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 624 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 625 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
626 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
627 m_remote_image_ctx->id, 0);
7c673cae
FG
628 EXPECT_CALL(mock_remote_journaler, construct());
629 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
630
631 EXPECT_CALL(mock_local_journal, add_listener(_));
632
633 expect_init(mock_remote_journaler, 0);
634
635 EXPECT_CALL(mock_remote_journaler, add_listener(_));
636 expect_get_cached_client(mock_remote_journaler, 0);
637
638 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
639
640 EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
641
d2e6a577 642 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 643
7c673cae
FG
644 C_SaferCond start_ctx;
645 m_image_replayer->start(&start_ctx);
646 ASSERT_EQ(0, start_ctx.wait());
c07f9fc5
FG
647 ASSERT_EQ(image_replayer::HEALTH_STATE_OK,
648 m_image_replayer->get_health_state());
7c673cae
FG
649
650 // STOP
651
652 MockCloseImageRequest mock_close_local_image_request;
653
d2e6a577 654 expect_cancel_waiter(mock_image_deleter);
7c673cae 655 expect_shut_down(mock_local_replay, true, 0);
7c673cae
FG
656 EXPECT_CALL(mock_local_journal, remove_listener(_));
657 EXPECT_CALL(mock_local_journal, stop_external_replay());
31f18b77 658 expect_send(mock_close_local_image_request, 0);
7c673cae 659
31f18b77 660 expect_stop_replay(mock_remote_journaler, 0);
7c673cae
FG
661 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
662 expect_shut_down(mock_remote_journaler, 0);
663
7c673cae
FG
664 C_SaferCond stop_ctx;
665 m_image_replayer->stop(&stop_ctx);
666 ASSERT_EQ(0, stop_ctx.wait());
c07f9fc5
FG
667 ASSERT_EQ(image_replayer::HEALTH_STATE_OK,
668 m_image_replayer->get_health_state());
7c673cae
FG
669}
670
671TEST_F(TestMockImageReplayer, LocalImagePrimary) {
672 create_local_image();
673 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
674
b32b8144 675 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
676 MockThreads mock_threads(m_threads);
677 expect_work_queue_repeatedly(mock_threads);
678 expect_add_event_after_repeatedly(mock_threads);
679
680 MockImageDeleter mock_image_deleter;
7c673cae 681 MockPrepareLocalImageRequest mock_prepare_local_image_request;
b32b8144 682 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
683 MockReplayStatusFormatter mock_replay_status_formatter;
684
685 expect_get_or_send_update(mock_replay_status_formatter);
686
687 InSequence seq;
d2e6a577 688 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 689 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 690 mock_local_image_ctx.name, "", 0);
b32b8144
FG
691 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
692 "remote image id", 0);
693 EXPECT_CALL(mock_remote_journaler, construct());
694 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
695 expect_shut_down(mock_remote_journaler, 0);
7c673cae 696
d2e6a577 697 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 698
7c673cae
FG
699 C_SaferCond start_ctx;
700 m_image_replayer->start(&start_ctx);
701 ASSERT_EQ(0, start_ctx.wait());
702}
703
704TEST_F(TestMockImageReplayer, LocalImageDNE) {
705 create_local_image();
706 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
707
708 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
709 MockThreads mock_threads(m_threads);
710 expect_work_queue_repeatedly(mock_threads);
711 expect_add_event_after_repeatedly(mock_threads);
712
713 MockImageDeleter mock_image_deleter;
7c673cae 714 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 715 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
716 MockBootstrapRequest mock_bootstrap_request;
717 MockReplayStatusFormatter mock_replay_status_formatter;
718
719 expect_get_or_send_update(mock_replay_status_formatter);
720
721 InSequence seq;
d2e6a577 722 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
28e407b8 723 expect_send(mock_prepare_local_image_request, "", "", "", -ENOENT);
d2e6a577
FG
724 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
725 m_remote_image_ctx->id, 0);
7c673cae
FG
726 EXPECT_CALL(mock_remote_journaler, construct());
727 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -EREMOTEIO);
728
729 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
730 expect_shut_down(mock_remote_journaler, 0);
731
d2e6a577 732 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 733
7c673cae
FG
734 C_SaferCond start_ctx;
735 m_image_replayer->start(&start_ctx);
c07f9fc5 736 ASSERT_EQ(-EREMOTEIO, start_ctx.wait());
7c673cae
FG
737}
738
739TEST_F(TestMockImageReplayer, PrepareLocalImageError) {
740 create_local_image();
741 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
742
d2e6a577
FG
743 MockThreads mock_threads(m_threads);
744 expect_work_queue_repeatedly(mock_threads);
745 expect_add_event_after_repeatedly(mock_threads);
746
747 MockImageDeleter mock_image_deleter;
7c673cae
FG
748 MockPrepareLocalImageRequest mock_prepare_local_image_request;
749 MockReplayStatusFormatter mock_replay_status_formatter;
750
751 expect_get_or_send_update(mock_replay_status_formatter);
752
753 InSequence seq;
d2e6a577 754 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 755 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 756 mock_local_image_ctx.name, "remote mirror uuid", -EINVAL);
7c673cae 757
d2e6a577
FG
758 create_image_replayer(mock_threads, mock_image_deleter);
759
760 C_SaferCond start_ctx;
761 m_image_replayer->start(&start_ctx);
762 ASSERT_EQ(-EINVAL, start_ctx.wait());
763}
764
765TEST_F(TestMockImageReplayer, GetRemoteImageIdDNE) {
766 create_local_image();
767 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
768
769 MockThreads mock_threads(m_threads);
770 expect_work_queue_repeatedly(mock_threads);
771 expect_add_event_after_repeatedly(mock_threads);
772
c07f9fc5 773 MockImageDeleter mock_image_deleter;
d2e6a577
FG
774 MockPrepareLocalImageRequest mock_prepare_local_image_request;
775 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
776 MockReplayStatusFormatter mock_replay_status_formatter;
777
778 expect_get_or_send_update(mock_replay_status_formatter);
779
780 InSequence seq;
781 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
782 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 783 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
784 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
785 "", -ENOENT);
786 expect_schedule_image_delete(mock_image_deleter, "global image id", false);
787
788 create_image_replayer(mock_threads, mock_image_deleter);
789
790 C_SaferCond start_ctx;
791 m_image_replayer->start(&start_ctx);
792 ASSERT_EQ(0, start_ctx.wait());
793}
794
795TEST_F(TestMockImageReplayer, GetRemoteImageIdNonLinkedDNE) {
796 create_local_image();
797 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
798
799 MockThreads mock_threads(m_threads);
800 expect_work_queue_repeatedly(mock_threads);
801 expect_add_event_after_repeatedly(mock_threads);
802
803 MockImageDeleter mock_image_deleter;
804 MockPrepareLocalImageRequest mock_prepare_local_image_request;
805 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
806 MockReplayStatusFormatter mock_replay_status_formatter;
807
808 expect_get_or_send_update(mock_replay_status_formatter);
809
810 InSequence seq;
811 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
812 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 813 mock_local_image_ctx.name, "some other mirror uuid", 0);
d2e6a577
FG
814 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
815 "", -ENOENT);
816
817 create_image_replayer(mock_threads, mock_image_deleter);
818
819 C_SaferCond start_ctx;
820 m_image_replayer->start(&start_ctx);
821 ASSERT_EQ(-ENOENT, start_ctx.wait());
822}
823
824TEST_F(TestMockImageReplayer, GetRemoteImageIdError) {
825 create_local_image();
826 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
827
828 MockThreads mock_threads(m_threads);
829 expect_work_queue_repeatedly(mock_threads);
830 expect_add_event_after_repeatedly(mock_threads);
831
832 MockImageDeleter mock_image_deleter;
833 MockPrepareLocalImageRequest mock_prepare_local_image_request;
834 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
835 MockReplayStatusFormatter mock_replay_status_formatter;
836
837 expect_get_or_send_update(mock_replay_status_formatter);
838
839 InSequence seq;
840 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
841 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 842 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
843 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
844 m_remote_image_ctx->id, -EINVAL);
845
846 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 847
7c673cae
FG
848 C_SaferCond start_ctx;
849 m_image_replayer->start(&start_ctx);
850 ASSERT_EQ(-EINVAL, start_ctx.wait());
851}
852
853TEST_F(TestMockImageReplayer, BootstrapError) {
854
855 create_local_image();
856 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
857
858 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
859 MockThreads mock_threads(m_threads);
860 expect_work_queue_repeatedly(mock_threads);
861 expect_add_event_after_repeatedly(mock_threads);
862
863 MockImageDeleter mock_image_deleter;
7c673cae 864 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 865 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
866 MockBootstrapRequest mock_bootstrap_request;
867 MockReplayStatusFormatter mock_replay_status_formatter;
868
869 expect_get_or_send_update(mock_replay_status_formatter);
870
871 InSequence seq;
d2e6a577 872 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 873 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 874 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
875 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
876 m_remote_image_ctx->id, 0);
7c673cae
FG
877 EXPECT_CALL(mock_remote_journaler, construct());
878 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, -EINVAL);
879
880 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
881 expect_shut_down(mock_remote_journaler, 0);
882
d2e6a577 883 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 884
7c673cae
FG
885 C_SaferCond start_ctx;
886 m_image_replayer->start(&start_ctx);
887 ASSERT_EQ(-EINVAL, start_ctx.wait());
888}
889
890TEST_F(TestMockImageReplayer, StartExternalReplayError) {
891 // START
892
893 create_local_image();
894 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
895
896 librbd::MockTestJournal mock_local_journal;
897 mock_local_image_ctx.journal = &mock_local_journal;
898
899 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
900 MockThreads mock_threads(m_threads);
901 expect_work_queue_repeatedly(mock_threads);
902 expect_add_event_after_repeatedly(mock_threads);
903
904 MockImageDeleter mock_image_deleter;
7c673cae 905 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 906 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
907 MockBootstrapRequest mock_bootstrap_request;
908 MockReplay mock_local_replay;
909 MockEventPreprocessor mock_event_preprocessor;
910 MockReplayStatusFormatter mock_replay_status_formatter;
911
912 expect_get_or_send_update(mock_replay_status_formatter);
913
914 InSequence seq;
d2e6a577 915 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 916 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 917 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
918 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
919 m_remote_image_ctx->id, 0);
7c673cae
FG
920 EXPECT_CALL(mock_remote_journaler, construct());
921 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
922
923 EXPECT_CALL(mock_local_journal, add_listener(_));
924
925 expect_init(mock_remote_journaler, 0);
926
927 EXPECT_CALL(mock_remote_journaler, add_listener(_));
928 expect_get_cached_client(mock_remote_journaler, 0);
929
930 expect_start_external_replay(mock_local_journal, nullptr, -EINVAL);
931
932 MockCloseImageRequest mock_close_local_image_request;
7c673cae 933 EXPECT_CALL(mock_local_journal, remove_listener(_));
31f18b77 934 expect_send(mock_close_local_image_request, 0);
7c673cae
FG
935
936 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
937 expect_shut_down(mock_remote_journaler, 0);
938
d2e6a577 939 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 940
7c673cae
FG
941 C_SaferCond start_ctx;
942 m_image_replayer->start(&start_ctx);
943 ASSERT_EQ(-EINVAL, start_ctx.wait());
c07f9fc5
FG
944 ASSERT_EQ(image_replayer::HEALTH_STATE_ERROR,
945 m_image_replayer->get_health_state());
7c673cae
FG
946}
947
948TEST_F(TestMockImageReplayer, StopError) {
949 // START
950
951 create_local_image();
952 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
953
954 librbd::MockTestJournal mock_local_journal;
955 mock_local_image_ctx.journal = &mock_local_journal;
956
957 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
958 MockThreads mock_threads(m_threads);
959 expect_work_queue_repeatedly(mock_threads);
960 expect_add_event_after_repeatedly(mock_threads);
961
962 MockImageDeleter mock_image_deleter;
7c673cae 963 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 964 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
965 MockBootstrapRequest mock_bootstrap_request;
966 MockReplay mock_local_replay;
967 MockEventPreprocessor mock_event_preprocessor;
968 MockReplayStatusFormatter mock_replay_status_formatter;
969
970 expect_get_or_send_update(mock_replay_status_formatter);
971
972 InSequence seq;
d2e6a577 973 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 974 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 975 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
976 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
977 m_remote_image_ctx->id, 0);
7c673cae
FG
978 EXPECT_CALL(mock_remote_journaler, construct());
979 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
980
981 EXPECT_CALL(mock_local_journal, add_listener(_));
982
983 expect_init(mock_remote_journaler, 0);
984
985 EXPECT_CALL(mock_remote_journaler, add_listener(_));
986 expect_get_cached_client(mock_remote_journaler, 0);
987
988 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
989
990 EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
991
d2e6a577 992 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 993
7c673cae
FG
994 C_SaferCond start_ctx;
995 m_image_replayer->start(&start_ctx);
996 ASSERT_EQ(0, start_ctx.wait());
997
998 // STOP (errors are ignored)
999
1000 MockCloseImageRequest mock_close_local_image_request;
1001
d2e6a577 1002 expect_cancel_waiter(mock_image_deleter);
7c673cae 1003 expect_shut_down(mock_local_replay, true, -EINVAL);
7c673cae
FG
1004 EXPECT_CALL(mock_local_journal, remove_listener(_));
1005 EXPECT_CALL(mock_local_journal, stop_external_replay());
31f18b77 1006 expect_send(mock_close_local_image_request, -EINVAL);
7c673cae 1007
31f18b77 1008 expect_stop_replay(mock_remote_journaler, -EINVAL);
7c673cae
FG
1009 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
1010 expect_shut_down(mock_remote_journaler, -EINVAL);
1011
7c673cae
FG
1012 C_SaferCond stop_ctx;
1013 m_image_replayer->stop(&stop_ctx);
1014 ASSERT_EQ(0, stop_ctx.wait());
1015}
1016
1017TEST_F(TestMockImageReplayer, Replay) {
1018 // START
1019
1020 create_local_image();
1021 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
1022
1023 librbd::MockTestJournal mock_local_journal;
1024 mock_local_image_ctx.journal = &mock_local_journal;
1025
1026 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
1027 MockThreads mock_threads(m_threads);
1028 expect_work_queue_repeatedly(mock_threads);
1029 expect_add_event_after_repeatedly(mock_threads);
1030
1031 MockImageDeleter mock_image_deleter;
7c673cae 1032 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 1033 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
1034 MockBootstrapRequest mock_bootstrap_request;
1035 MockReplay mock_local_replay;
1036 MockEventPreprocessor mock_event_preprocessor;
1037 MockReplayStatusFormatter mock_replay_status_formatter;
1038 ::journal::MockReplayEntry mock_replay_entry;
1039
1040 expect_get_or_send_update(mock_replay_status_formatter);
1041 expect_get_commit_tid_in_debug(mock_replay_entry);
1042 expect_committed(mock_remote_journaler, 2);
1043
1044 InSequence seq;
d2e6a577 1045 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 1046 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 1047 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
1048 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
1049 m_remote_image_ctx->id, 0);
7c673cae
FG
1050 EXPECT_CALL(mock_remote_journaler, construct());
1051 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
1052
1053 EXPECT_CALL(mock_local_journal, add_listener(_));
1054
1055 expect_init(mock_remote_journaler, 0);
1056
1057 EXPECT_CALL(mock_remote_journaler, add_listener(_));
1058 expect_get_cached_client(mock_remote_journaler, 0);
1059
1060 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1061
1062 EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
1063
d2e6a577 1064 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 1065
7c673cae
FG
1066 C_SaferCond start_ctx;
1067 m_image_replayer->start(&start_ctx);
1068 ASSERT_EQ(0, start_ctx.wait());
1069
1070 // REPLAY
1071
1072 cls::journal::Tag tag =
1073 {1, 0, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
1074 librbd::Journal<>::LOCAL_MIRROR_UUID,
1075 true, 0, 0})};
1076
1077 expect_try_pop_front(mock_remote_journaler, tag.tid, true);
1078
1079 // replay_flush
1080 expect_shut_down(mock_local_replay, false, 0);
1081 EXPECT_CALL(mock_local_journal, stop_external_replay());
1082 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1083 expect_get_tag(mock_remote_journaler, tag, 0);
1084 expect_allocate_tag(mock_local_journal, 0);
1085
1086 // process
1087 EXPECT_CALL(mock_replay_entry, get_data());
1088 EXPECT_CALL(mock_local_replay, decode(_, _))
1089 .WillOnce(Return(0));
1090 expect_preprocess(mock_event_preprocessor, false, 0);
1091 expect_process(mock_local_replay, 0, 0);
1092
1093 // the next event with preprocess
1094 expect_try_pop_front(mock_remote_journaler, tag.tid, true);
1095 EXPECT_CALL(mock_replay_entry, get_data());
1096 EXPECT_CALL(mock_local_replay, decode(_, _))
1097 .WillOnce(Return(0));
1098 expect_preprocess(mock_event_preprocessor, true, 0);
1099 expect_process(mock_local_replay, 0, 0);
1100
1101 // attempt to process the next event
1102 C_SaferCond replay_ctx;
1103 expect_try_pop_front_return_no_entries(mock_remote_journaler, &replay_ctx);
1104
1105 // fire
1106 m_image_replayer->handle_replay_ready();
1107 ASSERT_EQ(0, replay_ctx.wait());
1108
1109 // STOP
1110
1111 MockCloseImageRequest mock_close_local_image_request;
d2e6a577 1112 expect_cancel_waiter(mock_image_deleter);
7c673cae 1113 expect_shut_down(mock_local_replay, true, 0);
7c673cae
FG
1114 EXPECT_CALL(mock_local_journal, remove_listener(_));
1115 EXPECT_CALL(mock_local_journal, stop_external_replay());
31f18b77 1116 expect_send(mock_close_local_image_request, 0);
7c673cae 1117
31f18b77 1118 expect_stop_replay(mock_remote_journaler, 0);
7c673cae
FG
1119 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
1120 expect_shut_down(mock_remote_journaler, 0);
1121
7c673cae
FG
1122 C_SaferCond stop_ctx;
1123 m_image_replayer->stop(&stop_ctx);
1124 ASSERT_EQ(0, stop_ctx.wait());
1125}
1126
1127TEST_F(TestMockImageReplayer, DecodeError) {
1128 // START
1129
1130 create_local_image();
1131 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
1132
1133 librbd::MockTestJournal mock_local_journal;
1134 mock_local_image_ctx.journal = &mock_local_journal;
1135
1136 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
1137 MockThreads mock_threads(m_threads);
1138 expect_work_queue_repeatedly(mock_threads);
1139 expect_add_event_after_repeatedly(mock_threads);
1140
1141 MockImageDeleter mock_image_deleter;
7c673cae 1142 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 1143 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
1144 MockBootstrapRequest mock_bootstrap_request;
1145 MockReplay mock_local_replay;
1146 MockEventPreprocessor mock_event_preprocessor;
1147 MockReplayStatusFormatter mock_replay_status_formatter;
1148 ::journal::MockReplayEntry mock_replay_entry;
1149
1150 expect_get_or_send_update(mock_replay_status_formatter);
1151 expect_get_commit_tid_in_debug(mock_replay_entry);
1152
1153 InSequence seq;
d2e6a577 1154 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 1155 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 1156 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
1157 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
1158 m_remote_image_ctx->id, 0);
7c673cae
FG
1159 EXPECT_CALL(mock_remote_journaler, construct());
1160 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
1161
1162 EXPECT_CALL(mock_local_journal, add_listener(_));
1163
1164 expect_init(mock_remote_journaler, 0);
1165
1166 EXPECT_CALL(mock_remote_journaler, add_listener(_));
1167 expect_get_cached_client(mock_remote_journaler, 0);
1168
1169 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1170
1171 EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
1172
d2e6a577 1173 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 1174
7c673cae
FG
1175 C_SaferCond start_ctx;
1176 m_image_replayer->start(&start_ctx);
1177 ASSERT_EQ(0, start_ctx.wait());
1178
1179 // REPLAY
1180
1181 cls::journal::Tag tag =
1182 {1, 0, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
1183 librbd::Journal<>::LOCAL_MIRROR_UUID,
1184 true, 0, 0})};
1185
1186 expect_try_pop_front(mock_remote_journaler, tag.tid, true);
1187
1188 // replay_flush
1189 expect_shut_down(mock_local_replay, false, 0);
1190 EXPECT_CALL(mock_local_journal, stop_external_replay());
1191 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1192 expect_get_tag(mock_remote_journaler, tag, 0);
1193 expect_allocate_tag(mock_local_journal, 0);
1194
1195 // process
1196 EXPECT_CALL(mock_replay_entry, get_data());
1197 EXPECT_CALL(mock_local_replay, decode(_, _))
1198 .WillOnce(Return(-EINVAL));
1199
1200 // stop on error
7c673cae 1201 expect_shut_down(mock_local_replay, true, 0);
7c673cae
FG
1202 EXPECT_CALL(mock_local_journal, remove_listener(_));
1203 EXPECT_CALL(mock_local_journal, stop_external_replay());
1204
7c673cae
FG
1205 MockCloseImageRequest mock_close_local_image_request;
1206 C_SaferCond close_ctx;
1207 EXPECT_CALL(mock_close_local_image_request, send())
1208 .WillOnce(Invoke([&mock_close_local_image_request, &close_ctx]() {
1209 *mock_close_local_image_request.image_ctx = nullptr;
1210 mock_close_local_image_request.on_finish->complete(0);
1211 close_ctx.complete(0);
1212 }));
1213
31f18b77
FG
1214 expect_stop_replay(mock_remote_journaler, 0);
1215 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
1216 expect_shut_down(mock_remote_journaler, 0);
1217
7c673cae
FG
1218 // fire
1219 m_image_replayer->handle_replay_ready();
1220 ASSERT_EQ(0, close_ctx.wait());
1221
1222 while (!m_image_replayer->is_stopped()) {
1223 usleep(1000);
1224 }
1225}
1226
1227TEST_F(TestMockImageReplayer, DelayedReplay) {
1228
1229 // START
1230
1231 create_local_image();
1232 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
1233
1234 librbd::MockTestJournal mock_local_journal;
1235 mock_local_image_ctx.journal = &mock_local_journal;
1236
1237 journal::MockJournaler mock_remote_journaler;
d2e6a577
FG
1238 MockThreads mock_threads(m_threads);
1239 expect_work_queue_repeatedly(mock_threads);
1240 expect_add_event_after_repeatedly(mock_threads);
1241
1242 MockImageDeleter mock_image_deleter;
7c673cae 1243 MockPrepareLocalImageRequest mock_prepare_local_image_request;
d2e6a577 1244 MockPrepareRemoteImageRequest mock_prepare_remote_image_request;
7c673cae
FG
1245 MockBootstrapRequest mock_bootstrap_request;
1246 MockReplay mock_local_replay;
1247 MockEventPreprocessor mock_event_preprocessor;
1248 MockReplayStatusFormatter mock_replay_status_formatter;
1249 ::journal::MockReplayEntry mock_replay_entry;
1250
1251 expect_get_or_send_update(mock_replay_status_formatter);
1252 expect_get_commit_tid_in_debug(mock_replay_entry);
1253 expect_committed(mock_remote_journaler, 1);
1254
1255 InSequence seq;
d2e6a577 1256 expect_wait_for_scheduled_deletion(mock_image_deleter, "global image id", 0);
7c673cae 1257 expect_send(mock_prepare_local_image_request, mock_local_image_ctx.id,
28e407b8 1258 mock_local_image_ctx.name, "remote mirror uuid", 0);
d2e6a577
FG
1259 expect_send(mock_prepare_remote_image_request, "remote mirror uuid",
1260 m_remote_image_ctx->id, 0);
7c673cae
FG
1261 EXPECT_CALL(mock_remote_journaler, construct());
1262 expect_send(mock_bootstrap_request, mock_local_image_ctx, false, 0);
1263
1264 EXPECT_CALL(mock_local_journal, add_listener(_));
1265
1266 expect_init(mock_remote_journaler, 0);
1267
1268 EXPECT_CALL(mock_remote_journaler, add_listener(_));
1269 expect_get_cached_client(mock_remote_journaler, 0);
1270
1271 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1272
1273 EXPECT_CALL(mock_remote_journaler, start_live_replay(_, _));
1274
d2e6a577 1275 create_image_replayer(mock_threads, mock_image_deleter);
c07f9fc5 1276
7c673cae
FG
1277 C_SaferCond start_ctx;
1278 m_image_replayer->start(&start_ctx);
1279 ASSERT_EQ(0, start_ctx.wait());
1280
1281 // REPLAY
1282
1283 cls::journal::Tag tag =
1284 {1, 0, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
1285 librbd::Journal<>::LOCAL_MIRROR_UUID,
1286 true, 0, 0})};
1287
1288 expect_try_pop_front(mock_remote_journaler, tag.tid, true);
1289
1290 // replay_flush
1291 expect_shut_down(mock_local_replay, false, 0);
1292 EXPECT_CALL(mock_local_journal, stop_external_replay());
1293 expect_start_external_replay(mock_local_journal, &mock_local_replay, 0);
1294 expect_get_tag(mock_remote_journaler, tag, 0);
1295 expect_allocate_tag(mock_local_journal, 0);
1296
1297 // process with delay
1298 EXPECT_CALL(mock_replay_entry, get_data());
1299 librbd::journal::EventEntry event_entry(
1300 librbd::journal::AioDiscardEvent(123, 345, false), ceph_clock_now());
1301 EXPECT_CALL(mock_local_replay, decode(_, _))
1302 .WillOnce(DoAll(SetArgPointee<1>(event_entry),
1303 Return(0)));
1304 expect_preprocess(mock_event_preprocessor, false, 0);
1305 expect_process(mock_local_replay, 0, 0);
1306
1307 // attempt to process the next event
1308 C_SaferCond replay_ctx;
1309 expect_try_pop_front_return_no_entries(mock_remote_journaler, &replay_ctx);
1310
1311 // fire
1312 mock_local_image_ctx.mirroring_replay_delay = 2;
1313 m_image_replayer->handle_replay_ready();
1314 ASSERT_EQ(0, replay_ctx.wait());
1315
1316 // add a pending (delayed) entry before stop
1317 expect_try_pop_front(mock_remote_journaler, tag.tid, true);
1318 EXPECT_CALL(mock_replay_entry, get_data());
1319 C_SaferCond decode_ctx;
1320 EXPECT_CALL(mock_local_replay, decode(_, _))
1321 .WillOnce(DoAll(Invoke([&decode_ctx](bufferlist::iterator* it,
1322 librbd::journal::EventEntry *e) {
1323 decode_ctx.complete(0);
1324 }),
1325 Return(0)));
1326
1327 mock_local_image_ctx.mirroring_replay_delay = 10;
1328 m_image_replayer->handle_replay_ready();
1329 ASSERT_EQ(0, decode_ctx.wait());
1330
1331 // STOP
1332
1333 MockCloseImageRequest mock_close_local_image_request;
1334
d2e6a577 1335 expect_cancel_waiter(mock_image_deleter);
7c673cae 1336 expect_shut_down(mock_local_replay, true, 0);
7c673cae
FG
1337 EXPECT_CALL(mock_local_journal, remove_listener(_));
1338 EXPECT_CALL(mock_local_journal, stop_external_replay());
31f18b77 1339 expect_send(mock_close_local_image_request, 0);
7c673cae 1340
31f18b77 1341 expect_stop_replay(mock_remote_journaler, 0);
7c673cae
FG
1342 EXPECT_CALL(mock_remote_journaler, remove_listener(_));
1343 expect_shut_down(mock_remote_journaler, 0);
1344
7c673cae
FG
1345 C_SaferCond stop_ctx;
1346 m_image_replayer->stop(&stop_ctx);
1347 ASSERT_EQ(0, stop_ctx.wait());
1348}
1349
d2e6a577 1350
7c673cae
FG
1351} // namespace mirror
1352} // namespace rbd