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