]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/test_mock_ImageSync.cc
update sources to v12.2.3
[ceph.git] / ceph / src / test / rbd_mirror / test_mock_ImageSync.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 "test/rbd_mirror/test_mock_fixture.h"
5#include "include/rbd/librbd.hpp"
6#include "librbd/journal/Types.h"
7#include "librbd/journal/TypeTraits.h"
8#include "test/journal/mock/MockJournaler.h"
9#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10#include "test/librbd/mock/MockImageCtx.h"
11#include "test/librbd/mock/MockObjectMap.h"
12#include "tools/rbd_mirror/ImageSync.h"
13#include "tools/rbd_mirror/Threads.h"
14#include "tools/rbd_mirror/image_sync/ImageCopyRequest.h"
b32b8144 15#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
7c673cae
FG
16#include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h"
17#include "tools/rbd_mirror/image_sync/SyncPointCreateRequest.h"
18#include "tools/rbd_mirror/image_sync/SyncPointPruneRequest.h"
19
20namespace librbd {
21
22namespace {
23
24struct MockTestImageCtx : public librbd::MockImageCtx {
25 MockTestImageCtx(librbd::ImageCtx &image_ctx)
26 : librbd::MockImageCtx(image_ctx) {
27 }
28};
29
30} // anonymous namespace
31
32namespace journal {
33
34template <>
35struct TypeTraits<librbd::MockTestImageCtx> {
36 typedef ::journal::MockJournaler Journaler;
37};
38
39} // namespace journal
40} // namespace librbd
41
42// template definitions
43template class rbd::mirror::ImageSync<librbd::MockTestImageCtx>;
44#include "tools/rbd_mirror/ImageSync.cc"
45
46namespace rbd {
47namespace mirror {
48
31f18b77
FG
49template<>
50struct InstanceWatcher<librbd::MockTestImageCtx> {
51 MOCK_METHOD2(notify_sync_request, void(const std::string, Context *));
52 MOCK_METHOD1(cancel_sync_request, bool(const std::string &));
53 MOCK_METHOD1(notify_sync_complete, void(const std::string &));
54};
55
7c673cae
FG
56namespace image_sync {
57
58template <>
59class ImageCopyRequest<librbd::MockTestImageCtx> {
60public:
61 static ImageCopyRequest* s_instance;
62 Context *on_finish;
63
64 static ImageCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
65 librbd::MockTestImageCtx *remote_image_ctx,
66 SafeTimer *timer, Mutex *timer_lock,
67 journal::MockJournaler *journaler,
68 librbd::journal::MirrorPeerClientMeta *client_meta,
69 librbd::journal::MirrorPeerSyncPoint *sync_point,
70 Context *on_finish,
71 rbd::mirror::ProgressContext *progress_ctx = nullptr) {
72 assert(s_instance != nullptr);
73 s_instance->on_finish = on_finish;
74 return s_instance;
75 }
76
77 ImageCopyRequest() {
78 s_instance = this;
79 }
80
81 void put() {
82 }
83
84 void get() {
85 }
86
87 MOCK_METHOD0(cancel, void());
88 MOCK_METHOD0(send, void());
89};
90
b32b8144
FG
91template <>
92class MetadataCopyRequest<librbd::MockTestImageCtx> {
93public:
94 static MetadataCopyRequest* s_instance;
95 Context *on_finish;
96
97 static MetadataCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
98 librbd::MockTestImageCtx *remote_image_ctx,
99 Context *on_finish) {
100 assert(s_instance != nullptr);
101 s_instance->on_finish = on_finish;
102 return s_instance;
103 }
104
105 MetadataCopyRequest() {
106 s_instance = this;
107 }
108
109 MOCK_METHOD0(send, void());
110};
111
7c673cae
FG
112template <>
113class SnapshotCopyRequest<librbd::MockTestImageCtx> {
114public:
115 static SnapshotCopyRequest* s_instance;
116 Context *on_finish;
117
118 static SnapshotCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
119 librbd::MockTestImageCtx *remote_image_ctx,
120 SnapshotCopyRequest<librbd::ImageCtx>::SnapMap *snap_map,
121 journal::MockJournaler *journaler,
122 librbd::journal::MirrorPeerClientMeta *client_meta,
123 ContextWQ *work_queue,
124 Context *on_finish) {
125 assert(s_instance != nullptr);
126 s_instance->on_finish = on_finish;
127 return s_instance;
128 }
129
130 SnapshotCopyRequest() {
131 s_instance = this;
132 }
133
134 void put() {
135 }
136
137 void get() {
138 }
139
140 MOCK_METHOD0(send, void());
141 MOCK_METHOD0(cancel, void());
142};
143
144template <>
145class SyncPointCreateRequest<librbd::MockTestImageCtx> {
146public:
147 static SyncPointCreateRequest *s_instance;
148 Context *on_finish;
149
150 static SyncPointCreateRequest* create(librbd::MockTestImageCtx *remote_image_ctx,
151 const std::string &mirror_uuid,
152 journal::MockJournaler *journaler,
153 librbd::journal::MirrorPeerClientMeta *client_meta,
154 Context *on_finish) {
155 assert(s_instance != nullptr);
156 s_instance->on_finish = on_finish;
157 return s_instance;
158 }
159
160 SyncPointCreateRequest() {
161 s_instance = this;
162 }
163 MOCK_METHOD0(send, void());
164};
165
166template <>
167class SyncPointPruneRequest<librbd::MockTestImageCtx> {
168public:
169 static SyncPointPruneRequest *s_instance;
170 Context *on_finish;
171 bool sync_complete;
172
173 static SyncPointPruneRequest* create(librbd::MockTestImageCtx *remote_image_ctx,
174 bool sync_complete,
175 journal::MockJournaler *journaler,
176 librbd::journal::MirrorPeerClientMeta *client_meta,
177 Context *on_finish) {
178 assert(s_instance != nullptr);
179 s_instance->on_finish = on_finish;
180 s_instance->sync_complete = sync_complete;
181 return s_instance;
182 }
183
184 SyncPointPruneRequest() {
185 s_instance = this;
186 }
187 MOCK_METHOD0(send, void());
188};
189
190ImageCopyRequest<librbd::MockTestImageCtx>* ImageCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
b32b8144 191MetadataCopyRequest<librbd::MockTestImageCtx>* MetadataCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
7c673cae
FG
192SnapshotCopyRequest<librbd::MockTestImageCtx>* SnapshotCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
193SyncPointCreateRequest<librbd::MockTestImageCtx>* SyncPointCreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
194SyncPointPruneRequest<librbd::MockTestImageCtx>* SyncPointPruneRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
195
196} // namespace image_sync
197
198using ::testing::_;
199using ::testing::InSequence;
200using ::testing::Invoke;
201using ::testing::Return;
31f18b77 202using ::testing::ReturnNew;
7c673cae
FG
203using ::testing::WithArg;
204using ::testing::InvokeWithoutArgs;
205
206class TestMockImageSync : public TestMockFixture {
207public:
208 typedef ImageSync<librbd::MockTestImageCtx> MockImageSync;
31f18b77 209 typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
7c673cae 210 typedef image_sync::ImageCopyRequest<librbd::MockTestImageCtx> MockImageCopyRequest;
b32b8144 211 typedef image_sync::MetadataCopyRequest<librbd::MockTestImageCtx> MockMetadataCopyRequest;
7c673cae
FG
212 typedef image_sync::SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
213 typedef image_sync::SyncPointCreateRequest<librbd::MockTestImageCtx> MockSyncPointCreateRequest;
214 typedef image_sync::SyncPointPruneRequest<librbd::MockTestImageCtx> MockSyncPointPruneRequest;
215
216 void SetUp() override {
217 TestMockFixture::SetUp();
218
219 librbd::RBD rbd;
220 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
221 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
222
223 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
224 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
225 }
226
31f18b77
FG
227 void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
228 EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
229 ReturnNew<FunctionContext>([](int) {}));
230 }
231
232 void expect_notify_sync_request(MockInstanceWatcher &mock_instance_watcher,
233 const std::string &sync_id, int r) {
234 EXPECT_CALL(mock_instance_watcher, notify_sync_request(sync_id, _))
235 .WillOnce(Invoke([this, r](const std::string &, Context *on_sync_start) {
236 m_threads->work_queue->queue(on_sync_start, r);
237 }));
238 }
239
240 void expect_cancel_sync_request(MockInstanceWatcher &mock_instance_watcher,
241 const std::string &sync_id, bool canceled) {
242 EXPECT_CALL(mock_instance_watcher, cancel_sync_request(sync_id))
243 .WillOnce(Return(canceled));
244 }
245
246 void expect_notify_sync_complete(MockInstanceWatcher &mock_instance_watcher,
247 const std::string &sync_id) {
248 EXPECT_CALL(mock_instance_watcher, notify_sync_complete(sync_id));
249 }
250
7c673cae
FG
251 void expect_create_sync_point(librbd::MockTestImageCtx &mock_local_image_ctx,
252 MockSyncPointCreateRequest &mock_sync_point_create_request,
253 int r) {
254 EXPECT_CALL(mock_sync_point_create_request, send())
255 .WillOnce(Invoke([this, &mock_local_image_ctx, &mock_sync_point_create_request, r]() {
256 if (r == 0) {
257 mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
258 "snap1"}] = 123;
259 m_client_meta.sync_points.emplace_back(cls::rbd::UserSnapshotNamespace(),
260 "snap1",
261 boost::none);
262 }
263 m_threads->work_queue->queue(mock_sync_point_create_request.on_finish, r);
264 }));
265 }
266
267 void expect_copy_snapshots(MockSnapshotCopyRequest &mock_snapshot_copy_request, int r) {
268 EXPECT_CALL(mock_snapshot_copy_request, send())
269 .WillOnce(Invoke([this, &mock_snapshot_copy_request, r]() {
270 m_threads->work_queue->queue(mock_snapshot_copy_request.on_finish, r);
271 }));
272 }
273
274 void expect_copy_image(MockImageCopyRequest &mock_image_copy_request, int r) {
275 EXPECT_CALL(mock_image_copy_request, send())
276 .WillOnce(Invoke([this, &mock_image_copy_request, r]() {
277 m_threads->work_queue->queue(mock_image_copy_request.on_finish, r);
278 }));
279 }
280
b32b8144
FG
281 void expect_copy_metadata(MockMetadataCopyRequest &mock_metadata_copy_request,
282 int r) {
283 EXPECT_CALL(mock_metadata_copy_request, send())
284 .WillOnce(Invoke([this, &mock_metadata_copy_request, r]() {
285 m_threads->work_queue->queue(mock_metadata_copy_request.on_finish, r);
286 }));
287 }
288
7c673cae
FG
289 void expect_rollback_object_map(librbd::MockObjectMap &mock_object_map, int r) {
290 if ((m_local_image_ctx->features & RBD_FEATURE_OBJECT_MAP) != 0) {
291 EXPECT_CALL(mock_object_map, rollback(_, _))
292 .WillOnce(WithArg<1>(Invoke([this, r](Context *ctx) {
293 m_threads->work_queue->queue(ctx, r);
294 })));
295 }
296 }
297
298 void expect_create_object_map(librbd::MockTestImageCtx &mock_image_ctx,
299 librbd::MockObjectMap *mock_object_map) {
300 EXPECT_CALL(mock_image_ctx, create_object_map(CEPH_NOSNAP))
301 .WillOnce(Return(mock_object_map));
302 }
303
304 void expect_open_object_map(librbd::MockTestImageCtx &mock_image_ctx,
305 librbd::MockObjectMap &mock_object_map) {
306 EXPECT_CALL(mock_object_map, open(_))
307 .WillOnce(Invoke([this](Context *ctx) {
308 m_threads->work_queue->queue(ctx, 0);
309 }));
310 }
311
312 void expect_prune_sync_point(MockSyncPointPruneRequest &mock_sync_point_prune_request,
313 bool sync_complete, int r) {
314 EXPECT_CALL(mock_sync_point_prune_request, send())
315 .WillOnce(Invoke([this, &mock_sync_point_prune_request, sync_complete, r]() {
316 ASSERT_EQ(sync_complete, mock_sync_point_prune_request.sync_complete);
317 if (r == 0 && !m_client_meta.sync_points.empty()) {
318 if (sync_complete) {
319 m_client_meta.sync_points.pop_front();
320 } else {
321 while (m_client_meta.sync_points.size() > 1) {
322 m_client_meta.sync_points.pop_back();
323 }
324 }
325 }
326 m_threads->work_queue->queue(mock_sync_point_prune_request.on_finish, r);
327 }));
328 }
329
330 MockImageSync *create_request(librbd::MockTestImageCtx &mock_remote_image_ctx,
331 librbd::MockTestImageCtx &mock_local_image_ctx,
332 journal::MockJournaler &mock_journaler,
31f18b77 333 MockInstanceWatcher &mock_instance_watcher,
7c673cae
FG
334 Context *ctx) {
335 return new MockImageSync(&mock_local_image_ctx, &mock_remote_image_ctx,
336 m_threads->timer, &m_threads->timer_lock,
337 "mirror-uuid", &mock_journaler, &m_client_meta,
31f18b77
FG
338 m_threads->work_queue, &mock_instance_watcher,
339 ctx);
7c673cae
FG
340 }
341
342 librbd::ImageCtx *m_remote_image_ctx;
343 librbd::ImageCtx *m_local_image_ctx;
344 librbd::journal::MirrorPeerClientMeta m_client_meta;
345};
346
347TEST_F(TestMockImageSync, SimpleSync) {
348 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
349 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
350 journal::MockJournaler mock_journaler;
31f18b77 351 MockInstanceWatcher mock_instance_watcher;
7c673cae
FG
352 MockImageCopyRequest mock_image_copy_request;
353 MockSnapshotCopyRequest mock_snapshot_copy_request;
354 MockSyncPointCreateRequest mock_sync_point_create_request;
355 MockSyncPointPruneRequest mock_sync_point_prune_request;
b32b8144 356 MockMetadataCopyRequest mock_metadata_copy_request;
7c673cae 357
31f18b77
FG
358 librbd::MockExclusiveLock mock_exclusive_lock;
359 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
360
7c673cae
FG
361 librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
362 mock_local_image_ctx.object_map = mock_object_map;
363 expect_test_features(mock_local_image_ctx);
364
365 InSequence seq;
31f18b77 366 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
7c673cae
FG
367 expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
368 expect_copy_snapshots(mock_snapshot_copy_request, 0);
369 expect_copy_image(mock_image_copy_request, 0);
31f18b77 370 expect_start_op(mock_exclusive_lock);
7c673cae
FG
371 expect_rollback_object_map(*mock_object_map, 0);
372 expect_create_object_map(mock_local_image_ctx, mock_object_map);
373 expect_open_object_map(mock_local_image_ctx, *mock_object_map);
374 expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
b32b8144 375 expect_copy_metadata(mock_metadata_copy_request, 0);
31f18b77 376 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
7c673cae
FG
377
378 C_SaferCond ctx;
379 MockImageSync *request = create_request(mock_remote_image_ctx,
31f18b77
FG
380 mock_local_image_ctx, mock_journaler,
381 mock_instance_watcher, &ctx);
7c673cae
FG
382 request->send();
383 ASSERT_EQ(0, ctx.wait());
384}
385
386TEST_F(TestMockImageSync, RestartSync) {
387 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
388 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
389 journal::MockJournaler mock_journaler;
31f18b77 390 MockInstanceWatcher mock_instance_watcher;
7c673cae
FG
391 MockImageCopyRequest mock_image_copy_request;
392 MockSnapshotCopyRequest mock_snapshot_copy_request;
393 MockSyncPointCreateRequest mock_sync_point_create_request;
394 MockSyncPointPruneRequest mock_sync_point_prune_request;
b32b8144 395 MockMetadataCopyRequest mock_metadata_copy_request;
7c673cae
FG
396
397 m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none},
398 {cls::rbd::UserSnapshotNamespace(), "snap2", "snap1", boost::none}};
399 mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap1"}] = 123;
400 mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap2"}] = 234;
401
31f18b77
FG
402 librbd::MockExclusiveLock mock_exclusive_lock;
403 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
404
7c673cae
FG
405 librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
406 mock_local_image_ctx.object_map = mock_object_map;
407 expect_test_features(mock_local_image_ctx);
408
409 InSequence seq;
31f18b77 410 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
7c673cae
FG
411 expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
412 expect_copy_snapshots(mock_snapshot_copy_request, 0);
413 expect_copy_image(mock_image_copy_request, 0);
31f18b77 414 expect_start_op(mock_exclusive_lock);
7c673cae
FG
415 expect_rollback_object_map(*mock_object_map, 0);
416 expect_create_object_map(mock_local_image_ctx, mock_object_map);
417 expect_open_object_map(mock_local_image_ctx, *mock_object_map);
418 expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
b32b8144 419 expect_copy_metadata(mock_metadata_copy_request, 0);
31f18b77 420 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
7c673cae
FG
421
422 C_SaferCond ctx;
423 MockImageSync *request = create_request(mock_remote_image_ctx,
31f18b77
FG
424 mock_local_image_ctx, mock_journaler,
425 mock_instance_watcher, &ctx);
7c673cae
FG
426 request->send();
427 ASSERT_EQ(0, ctx.wait());
428}
429
31f18b77
FG
430TEST_F(TestMockImageSync, CancelNotifySyncRequest) {
431 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
432 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
433 journal::MockJournaler mock_journaler;
434 MockInstanceWatcher mock_instance_watcher;
435
436 InSequence seq;
437 Context *on_sync_start = nullptr;
438 C_SaferCond notify_sync_ctx;
439 EXPECT_CALL(mock_instance_watcher,
440 notify_sync_request(mock_local_image_ctx.id, _))
441 .WillOnce(Invoke([this, &on_sync_start, &notify_sync_ctx](
442 const std::string &, Context *ctx) {
443 on_sync_start = ctx;
444 notify_sync_ctx.complete(0);
445 }));
446 EXPECT_CALL(mock_instance_watcher,
447 cancel_sync_request(mock_local_image_ctx.id))
448 .WillOnce(Invoke([this, &on_sync_start](const std::string &) {
449 EXPECT_NE(nullptr, on_sync_start);
450 on_sync_start->complete(-ECANCELED);
451 return true;
452 }));
453
454 C_SaferCond ctx;
455 MockImageSync *request = create_request(mock_remote_image_ctx,
456 mock_local_image_ctx, mock_journaler,
457 mock_instance_watcher, &ctx);
458 request->get();
459 request->send();
460
461 // cancel the notify sync request once it starts
462 ASSERT_EQ(0, notify_sync_ctx.wait());
463 request->cancel();
464 request->put();
465
466 ASSERT_EQ(-ECANCELED, ctx.wait());
467}
468
7c673cae
FG
469TEST_F(TestMockImageSync, CancelImageCopy) {
470 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
471 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
472 journal::MockJournaler mock_journaler;
31f18b77 473 MockInstanceWatcher mock_instance_watcher;
7c673cae
FG
474 MockImageCopyRequest mock_image_copy_request;
475 MockSnapshotCopyRequest mock_snapshot_copy_request;
476 MockSyncPointCreateRequest mock_sync_point_create_request;
477 MockSyncPointPruneRequest mock_sync_point_prune_request;
478
31f18b77
FG
479 librbd::MockExclusiveLock mock_exclusive_lock;
480 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
481
7c673cae
FG
482 m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
483
484 InSequence seq;
31f18b77 485 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
7c673cae
FG
486 expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
487 expect_copy_snapshots(mock_snapshot_copy_request, 0);
488
489 C_SaferCond image_copy_ctx;
490 EXPECT_CALL(mock_image_copy_request, send())
491 .WillOnce(Invoke([&image_copy_ctx]() {
492 image_copy_ctx.complete(0);
493 }));
31f18b77
FG
494 expect_cancel_sync_request(mock_instance_watcher, mock_local_image_ctx.id,
495 false);
7c673cae 496 EXPECT_CALL(mock_image_copy_request, cancel());
31f18b77 497 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
7c673cae
FG
498
499 C_SaferCond ctx;
500 MockImageSync *request = create_request(mock_remote_image_ctx,
31f18b77
FG
501 mock_local_image_ctx, mock_journaler,
502 mock_instance_watcher, &ctx);
7c673cae
FG
503 request->get();
504 request->send();
505
506 // cancel the image copy once it starts
507 ASSERT_EQ(0, image_copy_ctx.wait());
508 request->cancel();
509 request->put();
510 m_threads->work_queue->queue(mock_image_copy_request.on_finish, 0);
511
512 ASSERT_EQ(-ECANCELED, ctx.wait());
513}
514
515TEST_F(TestMockImageSync, CancelAfterCopySnapshots) {
516 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
517 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
518 journal::MockJournaler mock_journaler;
31f18b77 519 MockInstanceWatcher mock_instance_watcher;
7c673cae
FG
520 MockSnapshotCopyRequest mock_snapshot_copy_request;
521 MockSyncPointCreateRequest mock_sync_point_create_request;
522
31f18b77
FG
523 librbd::MockExclusiveLock mock_exclusive_lock;
524 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
525
7c673cae
FG
526 librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
527 mock_local_image_ctx.object_map = mock_object_map;
528 expect_test_features(mock_local_image_ctx);
529
530 C_SaferCond ctx;
531 MockImageSync *request = create_request(mock_remote_image_ctx,
31f18b77
FG
532 mock_local_image_ctx, mock_journaler,
533 mock_instance_watcher, &ctx);
7c673cae 534 InSequence seq;
31f18b77 535 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
7c673cae
FG
536 expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
537 EXPECT_CALL(mock_snapshot_copy_request, send())
538 .WillOnce((DoAll(InvokeWithoutArgs([request]() {
539 request->cancel();
540 }),
541 Invoke([this, &mock_snapshot_copy_request]() {
542 m_threads->work_queue->queue(mock_snapshot_copy_request.on_finish, 0);
543 }))));
31f18b77
FG
544 expect_cancel_sync_request(mock_instance_watcher, mock_local_image_ctx.id,
545 false);
7c673cae 546 EXPECT_CALL(mock_snapshot_copy_request, cancel());
31f18b77 547 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
7c673cae
FG
548
549 request->send();
550 ASSERT_EQ(-ECANCELED, ctx.wait());
551}
552
553TEST_F(TestMockImageSync, CancelAfterCopyImage) {
554 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
555 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
556 journal::MockJournaler mock_journaler;
31f18b77 557 MockInstanceWatcher mock_instance_watcher;
7c673cae
FG
558 MockImageCopyRequest mock_image_copy_request;
559 MockSnapshotCopyRequest mock_snapshot_copy_request;
560 MockSyncPointCreateRequest mock_sync_point_create_request;
561 MockSyncPointPruneRequest mock_sync_point_prune_request;
562
31f18b77
FG
563 librbd::MockExclusiveLock mock_exclusive_lock;
564 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
565
7c673cae
FG
566 librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
567 mock_local_image_ctx.object_map = mock_object_map;
568 expect_test_features(mock_local_image_ctx);
569
570 C_SaferCond ctx;
571 MockImageSync *request = create_request(mock_remote_image_ctx,
31f18b77
FG
572 mock_local_image_ctx, mock_journaler,
573 mock_instance_watcher, &ctx);
7c673cae 574 InSequence seq;
31f18b77 575 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
7c673cae
FG
576 expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
577 expect_copy_snapshots(mock_snapshot_copy_request, 0);
578 EXPECT_CALL(mock_image_copy_request, send())
579 .WillOnce((DoAll(InvokeWithoutArgs([request]() {
580 request->cancel();
581 }),
582 Invoke([this, &mock_image_copy_request]() {
583 m_threads->work_queue->queue(mock_image_copy_request.on_finish, 0);
584 }))));
31f18b77
FG
585 expect_cancel_sync_request(mock_instance_watcher, mock_local_image_ctx.id,
586 false);
7c673cae 587 EXPECT_CALL(mock_image_copy_request, cancel());
31f18b77 588 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
7c673cae
FG
589
590 request->send();
591 ASSERT_EQ(-ECANCELED, ctx.wait());
592}
593
594} // namespace mirror
595} // namespace rbd