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 "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"
15 #include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
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"
24 struct MockTestImageCtx
: public librbd::MockImageCtx
{
25 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
26 : librbd::MockImageCtx(image_ctx
) {
30 } // anonymous namespace
35 struct TypeTraits
<librbd::MockTestImageCtx
> {
36 typedef ::journal::MockJournaler Journaler
;
39 } // namespace journal
42 // template definitions
43 template class rbd::mirror::ImageSync
<librbd::MockTestImageCtx
>;
44 #include "tools/rbd_mirror/ImageSync.cc"
50 struct 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
&));
56 namespace image_sync
{
59 class ImageCopyRequest
<librbd::MockTestImageCtx
> {
61 static ImageCopyRequest
* s_instance
;
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
,
71 rbd::mirror::ProgressContext
*progress_ctx
= nullptr) {
72 assert(s_instance
!= nullptr);
73 s_instance
->on_finish
= on_finish
;
87 MOCK_METHOD0(cancel
, void());
88 MOCK_METHOD0(send
, void());
92 class MetadataCopyRequest
<librbd::MockTestImageCtx
> {
94 static MetadataCopyRequest
* s_instance
;
97 static MetadataCopyRequest
* create(librbd::MockTestImageCtx
*local_image_ctx
,
98 librbd::MockTestImageCtx
*remote_image_ctx
,
100 assert(s_instance
!= nullptr);
101 s_instance
->on_finish
= on_finish
;
105 MetadataCopyRequest() {
109 MOCK_METHOD0(send
, void());
113 class SnapshotCopyRequest
<librbd::MockTestImageCtx
> {
115 static SnapshotCopyRequest
* s_instance
;
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
;
130 SnapshotCopyRequest() {
140 MOCK_METHOD0(send
, void());
141 MOCK_METHOD0(cancel
, void());
145 class SyncPointCreateRequest
<librbd::MockTestImageCtx
> {
147 static SyncPointCreateRequest
*s_instance
;
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
;
160 SyncPointCreateRequest() {
163 MOCK_METHOD0(send
, void());
167 class SyncPointPruneRequest
<librbd::MockTestImageCtx
> {
169 static SyncPointPruneRequest
*s_instance
;
173 static SyncPointPruneRequest
* create(librbd::MockTestImageCtx
*remote_image_ctx
,
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
;
184 SyncPointPruneRequest() {
187 MOCK_METHOD0(send
, void());
190 ImageCopyRequest
<librbd::MockTestImageCtx
>* ImageCopyRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
191 MetadataCopyRequest
<librbd::MockTestImageCtx
>* MetadataCopyRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
192 SnapshotCopyRequest
<librbd::MockTestImageCtx
>* SnapshotCopyRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
193 SyncPointCreateRequest
<librbd::MockTestImageCtx
>* SyncPointCreateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
194 SyncPointPruneRequest
<librbd::MockTestImageCtx
>* SyncPointPruneRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
196 } // namespace image_sync
199 using ::testing::InSequence
;
200 using ::testing::Invoke
;
201 using ::testing::Return
;
202 using ::testing::ReturnNew
;
203 using ::testing::WithArg
;
204 using ::testing::InvokeWithoutArgs
;
206 class TestMockImageSync
: public TestMockFixture
{
208 typedef ImageSync
<librbd::MockTestImageCtx
> MockImageSync
;
209 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
210 typedef image_sync::ImageCopyRequest
<librbd::MockTestImageCtx
> MockImageCopyRequest
;
211 typedef image_sync::MetadataCopyRequest
<librbd::MockTestImageCtx
> MockMetadataCopyRequest
;
212 typedef image_sync::SnapshotCopyRequest
<librbd::MockTestImageCtx
> MockSnapshotCopyRequest
;
213 typedef image_sync::SyncPointCreateRequest
<librbd::MockTestImageCtx
> MockSyncPointCreateRequest
;
214 typedef image_sync::SyncPointPruneRequest
<librbd::MockTestImageCtx
> MockSyncPointPruneRequest
;
216 void SetUp() override
{
217 TestMockFixture::SetUp();
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
));
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
));
227 void expect_start_op(librbd::MockExclusiveLock
&mock_exclusive_lock
) {
228 EXPECT_CALL(mock_exclusive_lock
, start_op(_
)).WillOnce(
229 ReturnNew
<FunctionContext
>([](int) {}));
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
);
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
));
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
));
251 void expect_create_sync_point(librbd::MockTestImageCtx
&mock_local_image_ctx
,
252 MockSyncPointCreateRequest
&mock_sync_point_create_request
,
254 EXPECT_CALL(mock_sync_point_create_request
, send())
255 .WillOnce(Invoke([this, &mock_local_image_ctx
, &mock_sync_point_create_request
, r
]() {
257 mock_local_image_ctx
.snap_ids
[{cls::rbd::UserSnapshotNamespace(),
259 m_client_meta
.sync_points
.emplace_back(cls::rbd::UserSnapshotNamespace(),
263 m_threads
->work_queue
->queue(mock_sync_point_create_request
.on_finish
, r
);
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
);
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
);
281 void expect_copy_metadata(MockMetadataCopyRequest
&mock_metadata_copy_request
,
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
);
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
);
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
));
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);
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()) {
319 m_client_meta
.sync_points
.pop_front();
321 while (m_client_meta
.sync_points
.size() > 1) {
322 m_client_meta
.sync_points
.pop_back();
326 m_threads
->work_queue
->queue(mock_sync_point_prune_request
.on_finish
, r
);
330 MockImageSync
*create_request(librbd::MockTestImageCtx
&mock_remote_image_ctx
,
331 librbd::MockTestImageCtx
&mock_local_image_ctx
,
332 journal::MockJournaler
&mock_journaler
,
333 MockInstanceWatcher
&mock_instance_watcher
,
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
,
338 m_threads
->work_queue
, &mock_instance_watcher
,
342 librbd::ImageCtx
*m_remote_image_ctx
;
343 librbd::ImageCtx
*m_local_image_ctx
;
344 librbd::journal::MirrorPeerClientMeta m_client_meta
;
347 TEST_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
;
351 MockInstanceWatcher mock_instance_watcher
;
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
;
356 MockMetadataCopyRequest mock_metadata_copy_request
;
358 librbd::MockExclusiveLock mock_exclusive_lock
;
359 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
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
);
366 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
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);
370 expect_start_op(mock_exclusive_lock
);
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);
375 expect_copy_metadata(mock_metadata_copy_request
, 0);
376 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
379 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
380 mock_local_image_ctx
, mock_journaler
,
381 mock_instance_watcher
, &ctx
);
383 ASSERT_EQ(0, ctx
.wait());
386 TEST_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
;
390 MockInstanceWatcher mock_instance_watcher
;
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
;
395 MockMetadataCopyRequest mock_metadata_copy_request
;
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;
402 librbd::MockExclusiveLock mock_exclusive_lock
;
403 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
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
);
410 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
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);
414 expect_start_op(mock_exclusive_lock
);
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);
419 expect_copy_metadata(mock_metadata_copy_request
, 0);
420 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
423 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
424 mock_local_image_ctx
, mock_journaler
,
425 mock_instance_watcher
, &ctx
);
427 ASSERT_EQ(0, ctx
.wait());
430 TEST_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
;
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
, ¬ify_sync_ctx
](
442 const std::string
&, Context
*ctx
) {
444 notify_sync_ctx
.complete(0);
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
);
455 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
456 mock_local_image_ctx
, mock_journaler
,
457 mock_instance_watcher
, &ctx
);
461 // cancel the notify sync request once it starts
462 ASSERT_EQ(0, notify_sync_ctx
.wait());
466 ASSERT_EQ(-ECANCELED
, ctx
.wait());
469 TEST_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
;
473 MockInstanceWatcher mock_instance_watcher
;
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
;
479 librbd::MockExclusiveLock mock_exclusive_lock
;
480 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
482 m_client_meta
.sync_points
= {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none
}};
485 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
486 expect_prune_sync_point(mock_sync_point_prune_request
, false, 0);
487 expect_copy_snapshots(mock_snapshot_copy_request
, 0);
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);
494 expect_cancel_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
496 EXPECT_CALL(mock_image_copy_request
, cancel());
497 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
500 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
501 mock_local_image_ctx
, mock_journaler
,
502 mock_instance_watcher
, &ctx
);
506 // cancel the image copy once it starts
507 ASSERT_EQ(0, image_copy_ctx
.wait());
510 m_threads
->work_queue
->queue(mock_image_copy_request
.on_finish
, 0);
512 ASSERT_EQ(-ECANCELED
, ctx
.wait());
515 TEST_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
;
519 MockInstanceWatcher mock_instance_watcher
;
520 MockSnapshotCopyRequest mock_snapshot_copy_request
;
521 MockSyncPointCreateRequest mock_sync_point_create_request
;
523 librbd::MockExclusiveLock mock_exclusive_lock
;
524 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
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
);
531 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
532 mock_local_image_ctx
, mock_journaler
,
533 mock_instance_watcher
, &ctx
);
535 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
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
]() {
541 Invoke([this, &mock_snapshot_copy_request
]() {
542 m_threads
->work_queue
->queue(mock_snapshot_copy_request
.on_finish
, 0);
544 expect_cancel_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
546 EXPECT_CALL(mock_snapshot_copy_request
, cancel());
547 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
550 ASSERT_EQ(-ECANCELED
, ctx
.wait());
553 TEST_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
;
557 MockInstanceWatcher mock_instance_watcher
;
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
;
563 librbd::MockExclusiveLock mock_exclusive_lock
;
564 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
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
);
571 MockImageSync
*request
= create_request(mock_remote_image_ctx
,
572 mock_local_image_ctx
, mock_journaler
,
573 mock_instance_watcher
, &ctx
);
575 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
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
]() {
582 Invoke([this, &mock_image_copy_request
]() {
583 m_threads
->work_queue
->queue(mock_image_copy_request
.on_finish
, 0);
585 expect_cancel_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
587 EXPECT_CALL(mock_image_copy_request
, cancel());
588 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
591 ASSERT_EQ(-ECANCELED
, ctx
.wait());
594 } // namespace mirror