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/ImageCtx.h"
7 #include "librbd/ImageState.h"
8 #include "librbd/Operations.h"
9 #include "librbd/journal/TypeTraits.h"
10 #include "test/journal/mock/MockJournaler.h"
11 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
12 #include "test/librbd/mock/MockImageCtx.h"
13 #include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h"
14 #include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h"
15 #include "tools/rbd_mirror/Threads.h"
21 struct MockTestImageCtx
: public librbd::MockImageCtx
{
22 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
23 : librbd::MockImageCtx(image_ctx
) {
27 } // anonymous namespace
32 struct TypeTraits
<librbd::MockTestImageCtx
> {
33 typedef ::journal::MockJournaler Journaler
;
36 } // namespace journal
41 namespace image_sync
{
44 struct SnapshotCreateRequest
<librbd::MockTestImageCtx
> {
45 static SnapshotCreateRequest
* s_instance
;
46 static SnapshotCreateRequest
* create(librbd::MockTestImageCtx
* image_ctx
,
47 const std::string
&snap_name
,
48 const cls::rbd::SnapshotNamespace
&snap_namespace
,
50 const librbd::ParentSpec
&parent_spec
,
51 uint64_t parent_overlap
,
53 assert(s_instance
!= nullptr);
54 s_instance
->on_finish
= on_finish
;
58 Context
*on_finish
= nullptr;
60 SnapshotCreateRequest() {
64 MOCK_METHOD0(send
, void());
67 SnapshotCreateRequest
<librbd::MockTestImageCtx
>* SnapshotCreateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
69 } // namespace image_sync
73 // template definitions
74 #include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc"
75 template class rbd::mirror::image_sync::SnapshotCopyRequest
<librbd::MockTestImageCtx
>;
79 namespace image_sync
{
82 using ::testing::DoAll
;
83 using ::testing::DoDefault
;
84 using ::testing::InSequence
;
85 using ::testing::Invoke
;
86 using ::testing::InvokeWithoutArgs
;
87 using ::testing::Return
;
88 using ::testing::ReturnNew
;
89 using ::testing::SetArgPointee
;
90 using ::testing::StrEq
;
91 using ::testing::WithArg
;
93 class TestMockImageSyncSnapshotCopyRequest
: public TestMockFixture
{
95 typedef SnapshotCopyRequest
<librbd::MockTestImageCtx
> MockSnapshotCopyRequest
;
96 typedef SnapshotCreateRequest
<librbd::MockTestImageCtx
> MockSnapshotCreateRequest
;
98 void SetUp() override
{
99 TestMockFixture::SetUp();
102 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
103 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
105 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
106 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
109 void expect_start_op(librbd::MockExclusiveLock
&mock_exclusive_lock
) {
110 EXPECT_CALL(mock_exclusive_lock
, start_op(_
)).WillOnce(
111 ReturnNew
<FunctionContext
>([](int) {}));
114 void expect_get_snap_namespace(librbd::MockTestImageCtx
&mock_image_ctx
,
116 EXPECT_CALL(mock_image_ctx
, get_snap_namespace(snap_id
, _
))
117 .WillOnce(DoAll(SetArgPointee
<1>(cls::rbd::UserSnapshotNamespace()),
121 void expect_snap_create(librbd::MockTestImageCtx
&mock_image_ctx
,
122 MockSnapshotCreateRequest
&mock_snapshot_create_request
,
123 const std::string
&snap_name
, uint64_t snap_id
, int r
) {
124 EXPECT_CALL(mock_snapshot_create_request
, send())
125 .WillOnce(DoAll(Invoke([&mock_image_ctx
, snap_id
, snap_name
]() {
126 inject_snap(mock_image_ctx
, snap_id
, snap_name
);
128 Invoke([this, &mock_snapshot_create_request
, r
]() {
129 m_threads
->work_queue
->queue(mock_snapshot_create_request
.on_finish
, r
);
133 void expect_snap_remove(librbd::MockTestImageCtx
&mock_image_ctx
,
134 const std::string
&snap_name
, int r
) {
135 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_remove(_
, StrEq(snap_name
), _
))
136 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
*ctx
) {
137 m_threads
->work_queue
->queue(ctx
, r
);
141 void expect_snap_protect(librbd::MockTestImageCtx
&mock_image_ctx
,
142 const std::string
&snap_name
, int r
) {
143 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_protect(_
, StrEq(snap_name
), _
))
144 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
*ctx
) {
145 m_threads
->work_queue
->queue(ctx
, r
);
149 void expect_snap_unprotect(librbd::MockTestImageCtx
&mock_image_ctx
,
150 const std::string
&snap_name
, int r
) {
151 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_unprotect(_
, StrEq(snap_name
), _
))
152 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
*ctx
) {
153 m_threads
->work_queue
->queue(ctx
, r
);
157 void expect_snap_is_protected(librbd::MockTestImageCtx
&mock_image_ctx
,
158 uint64_t snap_id
, bool is_protected
, int r
) {
159 EXPECT_CALL(mock_image_ctx
, is_snap_protected(snap_id
, _
))
160 .WillOnce(DoAll(SetArgPointee
<1>(is_protected
),
164 void expect_snap_is_unprotected(librbd::MockTestImageCtx
&mock_image_ctx
,
165 uint64_t snap_id
, bool is_unprotected
, int r
) {
166 EXPECT_CALL(mock_image_ctx
, is_snap_unprotected(snap_id
, _
))
167 .WillOnce(DoAll(SetArgPointee
<1>(is_unprotected
),
171 void expect_update_client(journal::MockJournaler
&mock_journaler
, int r
) {
172 EXPECT_CALL(mock_journaler
, update_client(_
, _
))
173 .WillOnce(WithArg
<1>(CompleteContext(r
)));
176 static void inject_snap(librbd::MockTestImageCtx
&mock_image_ctx
,
177 uint64_t snap_id
, const std::string
&snap_name
) {
178 mock_image_ctx
.snap_ids
[{cls::rbd::UserSnapshotNamespace(),
179 snap_name
}] = snap_id
;
182 MockSnapshotCopyRequest
*create_request(librbd::MockTestImageCtx
&mock_remote_image_ctx
,
183 librbd::MockTestImageCtx
&mock_local_image_ctx
,
184 journal::MockJournaler
&mock_journaler
,
185 Context
*on_finish
) {
186 return new MockSnapshotCopyRequest(&mock_local_image_ctx
,
187 &mock_remote_image_ctx
, &m_snap_map
,
188 &mock_journaler
, &m_client_meta
,
189 m_threads
->work_queue
, on_finish
);
192 int create_snap(librbd::ImageCtx
*image_ctx
, const std::string
&snap_name
,
193 bool protect
= false) {
194 int r
= image_ctx
->operations
->snap_create(cls::rbd::UserSnapshotNamespace(),
201 r
= image_ctx
->operations
->snap_protect(cls::rbd::UserSnapshotNamespace(),
208 r
= image_ctx
->state
->refresh();
215 void validate_snap_seqs(const librbd::journal::MirrorPeerClientMeta::SnapSeqs
&snap_seqs
) {
216 ASSERT_EQ(snap_seqs
, m_client_meta
.snap_seqs
);
219 void validate_snap_map(const MockSnapshotCopyRequest::SnapMap
&snap_map
) {
220 ASSERT_EQ(snap_map
, m_snap_map
);
223 librbd::ImageCtx
*m_remote_image_ctx
;
224 librbd::ImageCtx
*m_local_image_ctx
;
226 MockSnapshotCopyRequest::SnapMap m_snap_map
;
227 librbd::journal::MirrorPeerClientMeta m_client_meta
;
230 TEST_F(TestMockImageSyncSnapshotCopyRequest
, Empty
) {
231 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
232 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
233 journal::MockJournaler mock_journaler
;
235 librbd::MockExclusiveLock mock_exclusive_lock
;
236 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
239 expect_update_client(mock_journaler
, 0);
242 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
243 mock_local_image_ctx
,
244 mock_journaler
, &ctx
);
246 ASSERT_EQ(0, ctx
.wait());
248 validate_snap_map({});
249 validate_snap_seqs({});
252 TEST_F(TestMockImageSyncSnapshotCopyRequest
, UpdateClientError
) {
253 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
254 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
255 journal::MockJournaler mock_journaler
;
257 librbd::MockExclusiveLock mock_exclusive_lock
;
258 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
261 expect_update_client(mock_journaler
, -EINVAL
);
264 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
265 mock_local_image_ctx
,
266 mock_journaler
, &ctx
);
268 ASSERT_EQ(-EINVAL
, ctx
.wait());
271 TEST_F(TestMockImageSyncSnapshotCopyRequest
, UpdateClientCancel
) {
272 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
273 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
274 journal::MockJournaler mock_journaler
;
276 librbd::MockExclusiveLock mock_exclusive_lock
;
277 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
280 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
281 mock_local_image_ctx
,
282 mock_journaler
, &ctx
);
284 EXPECT_CALL(mock_journaler
, update_client(_
, _
))
285 .WillOnce(DoAll(InvokeWithoutArgs([request
]() {
288 WithArg
<1>(CompleteContext(0))));
291 ASSERT_EQ(-ECANCELED
, ctx
.wait());
294 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapCreate
) {
295 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1"));
296 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap2"));
298 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
299 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
300 uint64_t remote_snap_id2
= m_remote_image_ctx
->snap_ids
[
301 {cls::rbd::UserSnapshotNamespace(), "snap2"}];
303 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
304 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
305 MockSnapshotCreateRequest mock_snapshot_create_request
;
306 journal::MockJournaler mock_journaler
;
308 librbd::MockExclusiveLock mock_exclusive_lock
;
309 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
312 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
313 expect_start_op(mock_exclusive_lock
);
314 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap1", 12, 0);
315 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id2
);
316 expect_start_op(mock_exclusive_lock
);
317 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap2", 14, 0);
318 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, false, 0);
319 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id2
, false, 0);
320 expect_update_client(mock_journaler
, 0);
323 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
324 mock_local_image_ctx
,
325 mock_journaler
, &ctx
);
327 ASSERT_EQ(0, ctx
.wait());
329 validate_snap_map({{remote_snap_id1
, {12}}, {remote_snap_id2
, {14, 12}}});
330 validate_snap_seqs({{remote_snap_id1
, 12}, {remote_snap_id2
, 14}});
333 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapCreateError
) {
334 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1"));
336 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
337 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
338 MockSnapshotCreateRequest mock_snapshot_create_request
;
339 journal::MockJournaler mock_journaler
;
341 librbd::MockExclusiveLock mock_exclusive_lock
;
342 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
344 uint64_t remote_snap_id1
= mock_remote_image_ctx
.snap_ids
[
345 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
347 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
348 expect_start_op(mock_exclusive_lock
);
349 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap1", 12, -EINVAL
);
352 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
353 mock_local_image_ctx
,
354 mock_journaler
, &ctx
);
356 ASSERT_EQ(-EINVAL
, ctx
.wait());
359 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapCreateCancel
) {
360 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1"));
362 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
363 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
364 MockSnapshotCreateRequest mock_snapshot_create_request
;
365 journal::MockJournaler mock_journaler
;
367 librbd::MockExclusiveLock mock_exclusive_lock
;
368 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
370 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
371 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
372 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
375 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
376 mock_local_image_ctx
,
377 mock_journaler
, &ctx
);
379 expect_start_op(mock_exclusive_lock
);
380 EXPECT_CALL(mock_snapshot_create_request
, send())
381 .WillOnce(DoAll(InvokeWithoutArgs([request
]() {
384 Invoke([this, &mock_snapshot_create_request
]() {
385 m_threads
->work_queue
->queue(mock_snapshot_create_request
.on_finish
, 0);
389 ASSERT_EQ(-ECANCELED
, ctx
.wait());
392 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapRemoveAndCreate
) {
393 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1"));
394 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1"));
396 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
397 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
398 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
399 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
401 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
402 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
403 MockSnapshotCreateRequest mock_snapshot_create_request
;
404 journal::MockJournaler mock_journaler
;
406 librbd::MockExclusiveLock mock_exclusive_lock
;
407 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
410 expect_snap_is_unprotected(mock_local_image_ctx
,
411 m_local_image_ctx
->snap_ids
[
412 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
414 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
415 expect_start_op(mock_exclusive_lock
);
416 expect_snap_remove(mock_local_image_ctx
, "snap1", 0);
417 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
418 expect_start_op(mock_exclusive_lock
);
419 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap1", 12, 0);
420 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, false, 0);
421 expect_update_client(mock_journaler
, 0);
424 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
425 mock_local_image_ctx
,
426 mock_journaler
, &ctx
);
428 ASSERT_EQ(0, ctx
.wait());
430 validate_snap_map({{remote_snap_id1
, {12}}});
431 validate_snap_seqs({{remote_snap_id1
, 12}});
434 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapRemoveError
) {
435 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1"));
437 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
438 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
439 journal::MockJournaler mock_journaler
;
441 librbd::MockExclusiveLock mock_exclusive_lock
;
442 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
444 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
445 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
447 expect_snap_is_unprotected(mock_local_image_ctx
,
448 m_local_image_ctx
->snap_ids
[
449 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
451 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
452 expect_start_op(mock_exclusive_lock
);
453 expect_snap_remove(mock_local_image_ctx
, "snap1", -EINVAL
);
456 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
457 mock_local_image_ctx
,
458 mock_journaler
, &ctx
);
460 ASSERT_EQ(-EINVAL
, ctx
.wait());
463 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapUnprotect
) {
464 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
465 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
467 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
468 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
469 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
470 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
471 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
473 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
474 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
475 journal::MockJournaler mock_journaler
;
477 librbd::MockExclusiveLock mock_exclusive_lock
;
478 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
481 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, false, 0);
482 expect_snap_is_unprotected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
483 expect_start_op(mock_exclusive_lock
);
484 expect_snap_unprotect(mock_local_image_ctx
, "snap1", 0);
485 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
486 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
487 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, false, 0);
488 expect_update_client(mock_journaler
, 0);
491 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
492 mock_local_image_ctx
,
493 mock_journaler
, &ctx
);
495 ASSERT_EQ(0, ctx
.wait());
497 validate_snap_map({{remote_snap_id1
, {local_snap_id1
}}});
498 validate_snap_seqs({{remote_snap_id1
, local_snap_id1
}});
501 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapUnprotectError
) {
502 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
503 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
505 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
506 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
507 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
508 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
509 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
511 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
512 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
513 journal::MockJournaler mock_journaler
;
515 librbd::MockExclusiveLock mock_exclusive_lock
;
516 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
519 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, false, 0);
520 expect_snap_is_unprotected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
521 expect_start_op(mock_exclusive_lock
);
522 expect_snap_unprotect(mock_local_image_ctx
, "snap1", -EBUSY
);
525 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
526 mock_local_image_ctx
,
527 mock_journaler
, &ctx
);
529 ASSERT_EQ(-EBUSY
, ctx
.wait());
532 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapUnprotectCancel
) {
533 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
534 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
536 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
537 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
538 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
539 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
540 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
542 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
543 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
544 journal::MockJournaler mock_journaler
;
546 librbd::MockExclusiveLock mock_exclusive_lock
;
547 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
550 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
551 mock_local_image_ctx
,
552 mock_journaler
, &ctx
);
554 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, false, 0);
555 expect_snap_is_unprotected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
556 expect_start_op(mock_exclusive_lock
);
557 EXPECT_CALL(*mock_local_image_ctx
.operations
,
558 execute_snap_unprotect(_
, StrEq("snap1"), _
))
559 .WillOnce(DoAll(InvokeWithoutArgs([request
]() {
562 WithArg
<2>(Invoke([this](Context
*ctx
) {
563 m_threads
->work_queue
->queue(ctx
, 0);
567 ASSERT_EQ(-ECANCELED
, ctx
.wait());
570 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapUnprotectRemove
) {
571 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
572 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
574 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
575 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
576 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
577 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
579 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
580 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
581 MockSnapshotCreateRequest mock_snapshot_create_request
;
582 journal::MockJournaler mock_journaler
;
584 librbd::MockExclusiveLock mock_exclusive_lock
;
585 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
588 expect_snap_is_unprotected(mock_local_image_ctx
,
589 m_local_image_ctx
->snap_ids
[
590 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
592 expect_start_op(mock_exclusive_lock
);
593 expect_snap_unprotect(mock_local_image_ctx
, "snap1", 0);
594 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
595 expect_start_op(mock_exclusive_lock
);
596 expect_snap_remove(mock_local_image_ctx
, "snap1", 0);
597 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
598 expect_start_op(mock_exclusive_lock
);
599 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap1", 12, 0);
600 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, false, 0);
601 expect_update_client(mock_journaler
, 0);
604 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
605 mock_local_image_ctx
,
606 mock_journaler
, &ctx
);
608 ASSERT_EQ(0, ctx
.wait());
610 validate_snap_map({{remote_snap_id1
, {12}}});
611 validate_snap_seqs({{remote_snap_id1
, 12}});
614 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapCreateProtect
) {
615 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
617 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
618 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
620 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
621 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
622 MockSnapshotCreateRequest mock_snapshot_create_request
;
623 journal::MockJournaler mock_journaler
;
625 librbd::MockExclusiveLock mock_exclusive_lock
;
626 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
629 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
630 expect_start_op(mock_exclusive_lock
);
631 expect_snap_create(mock_local_image_ctx
, mock_snapshot_create_request
, "snap1", 12, 0);
632 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
633 expect_snap_is_protected(mock_local_image_ctx
, 12, false, 0);
634 expect_start_op(mock_exclusive_lock
);
635 expect_snap_protect(mock_local_image_ctx
, "snap1", 0);
636 expect_update_client(mock_journaler
, 0);
639 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
640 mock_local_image_ctx
,
641 mock_journaler
, &ctx
);
643 ASSERT_EQ(0, ctx
.wait());
645 validate_snap_map({{remote_snap_id1
, {12}}});
646 validate_snap_seqs({{remote_snap_id1
, 12}});
649 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapProtect
) {
650 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
651 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
653 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
654 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
655 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
656 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
657 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
659 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
660 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
661 journal::MockJournaler mock_journaler
;
663 librbd::MockExclusiveLock mock_exclusive_lock
;
664 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
667 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, true, 0);
668 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
669 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
670 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
671 expect_snap_is_protected(mock_local_image_ctx
, local_snap_id1
, false, 0);
672 expect_start_op(mock_exclusive_lock
);
673 expect_snap_protect(mock_local_image_ctx
, "snap1", 0);
674 expect_update_client(mock_journaler
, 0);
677 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
678 mock_local_image_ctx
,
679 mock_journaler
, &ctx
);
681 ASSERT_EQ(0, ctx
.wait());
683 validate_snap_map({{remote_snap_id1
, {local_snap_id1
}}});
684 validate_snap_seqs({{remote_snap_id1
, local_snap_id1
}});
687 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapProtectError
) {
688 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
689 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
691 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
692 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
693 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
694 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
695 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
697 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
698 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
699 journal::MockJournaler mock_journaler
;
701 librbd::MockExclusiveLock mock_exclusive_lock
;
702 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
705 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, true, 0);
706 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
707 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
708 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
709 expect_snap_is_protected(mock_local_image_ctx
, local_snap_id1
, false, 0);
710 expect_start_op(mock_exclusive_lock
);
711 expect_snap_protect(mock_local_image_ctx
, "snap1", -EINVAL
);
714 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
715 mock_local_image_ctx
,
716 mock_journaler
, &ctx
);
718 ASSERT_EQ(-EINVAL
, ctx
.wait());
721 TEST_F(TestMockImageSyncSnapshotCopyRequest
, SnapProtectCancel
) {
722 ASSERT_EQ(0, create_snap(m_remote_image_ctx
, "snap1", true));
723 ASSERT_EQ(0, create_snap(m_local_image_ctx
, "snap1", true));
725 uint64_t remote_snap_id1
= m_remote_image_ctx
->snap_ids
[
726 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
727 uint64_t local_snap_id1
= m_local_image_ctx
->snap_ids
[
728 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
729 m_client_meta
.snap_seqs
[remote_snap_id1
] = local_snap_id1
;
731 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
732 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
733 journal::MockJournaler mock_journaler
;
735 librbd::MockExclusiveLock mock_exclusive_lock
;
736 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
739 MockSnapshotCopyRequest
*request
= create_request(mock_remote_image_ctx
,
740 mock_local_image_ctx
,
741 mock_journaler
, &ctx
);
743 expect_snap_is_unprotected(mock_local_image_ctx
, local_snap_id1
, true, 0);
744 expect_get_snap_namespace(mock_local_image_ctx
, local_snap_id1
);
745 expect_get_snap_namespace(mock_remote_image_ctx
, remote_snap_id1
);
746 expect_snap_is_protected(mock_remote_image_ctx
, remote_snap_id1
, true, 0);
747 expect_snap_is_protected(mock_local_image_ctx
, local_snap_id1
, false, 0);
748 expect_start_op(mock_exclusive_lock
);
749 EXPECT_CALL(*mock_local_image_ctx
.operations
,
750 execute_snap_protect(_
, StrEq("snap1"), _
))
751 .WillOnce(DoAll(InvokeWithoutArgs([request
]() {
754 WithArg
<2>(Invoke([this](Context
*ctx
) {
755 m_threads
->work_queue
->queue(ctx
, 0);
759 ASSERT_EQ(-ECANCELED
, ctx
.wait());
762 } // namespace image_sync
763 } // namespace mirror