Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / rbd_mirror / image_sync / test_mock_SnapshotCopyRequest.cc
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/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"
16
17 namespace librbd {
18
19 namespace {
20
21 struct MockTestImageCtx : public librbd::MockImageCtx {
22   MockTestImageCtx(librbd::ImageCtx &image_ctx)
23     : librbd::MockImageCtx(image_ctx) {
24   }
25 };
26
27 } // anonymous namespace
28
29 namespace journal {
30
31 template <>
32 struct TypeTraits<librbd::MockTestImageCtx> {
33   typedef ::journal::MockJournaler Journaler;
34 };
35
36 } // namespace journal
37 } // namespace librbd
38
39 namespace rbd {
40 namespace mirror {
41 namespace image_sync {
42
43 template <>
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,
49                                        uint64_t size,
50                                        const librbd::ParentSpec &parent_spec,
51                                        uint64_t parent_overlap,
52                                        Context *on_finish) {
53     assert(s_instance != nullptr);
54     s_instance->on_finish = on_finish;
55     return s_instance;
56   }
57
58   Context *on_finish = nullptr;
59
60   SnapshotCreateRequest() {
61     s_instance = this;
62   }
63
64   MOCK_METHOD0(send, void());
65 };
66
67 SnapshotCreateRequest<librbd::MockTestImageCtx>* SnapshotCreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
68
69 } // namespace image_sync
70 } // namespace mirror
71 } // namespace rbd
72
73 // template definitions
74 #include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc"
75 template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::MockTestImageCtx>;
76
77 namespace rbd {
78 namespace mirror {
79 namespace image_sync {
80
81 using ::testing::_;
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;
92
93 class TestMockImageSyncSnapshotCopyRequest : public TestMockFixture {
94 public:
95   typedef SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
96   typedef SnapshotCreateRequest<librbd::MockTestImageCtx> MockSnapshotCreateRequest;
97
98   void SetUp() override {
99     TestMockFixture::SetUp();
100
101     librbd::RBD rbd;
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));
104
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));
107   }
108
109   void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
110     EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
111       ReturnNew<FunctionContext>([](int) {}));
112   }
113
114   void expect_get_snap_namespace(librbd::MockTestImageCtx &mock_image_ctx,
115                                  uint64_t snap_id) {
116     EXPECT_CALL(mock_image_ctx, get_snap_namespace(snap_id, _))
117       .WillOnce(DoAll(SetArgPointee<1>(cls::rbd::UserSnapshotNamespace()),
118                       Return(0)));
119   }
120
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);
127                       }),
128                       Invoke([this, &mock_snapshot_create_request, r]() {
129                         m_threads->work_queue->queue(mock_snapshot_create_request.on_finish, r);
130                       })));
131   }
132
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);
138                             })));
139   }
140
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);
146                             })));
147   }
148
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);
154                             })));
155   }
156
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),
161                                   Return(r)));
162   }
163
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),
168                                   Return(r)));
169   }
170
171   void expect_update_client(journal::MockJournaler &mock_journaler, int r) {
172     EXPECT_CALL(mock_journaler, update_client(_, _))
173                   .WillOnce(WithArg<1>(CompleteContext(r)));
174   }
175
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;
180   }
181
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);
190   }
191
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(),
195                                                snap_name.c_str());
196     if (r < 0) {
197       return r;
198     }
199
200     if (protect) {
201       r = image_ctx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
202                                               snap_name.c_str());
203       if (r < 0) {
204         return r;
205       }
206     }
207
208     r = image_ctx->state->refresh();
209     if (r < 0) {
210       return r;
211     }
212     return 0;
213   }
214
215   void validate_snap_seqs(const librbd::journal::MirrorPeerClientMeta::SnapSeqs &snap_seqs) {
216     ASSERT_EQ(snap_seqs, m_client_meta.snap_seqs);
217   }
218
219   void validate_snap_map(const MockSnapshotCopyRequest::SnapMap &snap_map) {
220     ASSERT_EQ(snap_map, m_snap_map);
221   }
222
223   librbd::ImageCtx *m_remote_image_ctx;
224   librbd::ImageCtx *m_local_image_ctx;
225
226   MockSnapshotCopyRequest::SnapMap m_snap_map;
227   librbd::journal::MirrorPeerClientMeta m_client_meta;
228 };
229
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;
234
235   librbd::MockExclusiveLock mock_exclusive_lock;
236   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
237
238   InSequence seq;
239   expect_update_client(mock_journaler, 0);
240
241   C_SaferCond ctx;
242   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
243                                                     mock_local_image_ctx,
244                                                     mock_journaler, &ctx);
245   request->send();
246   ASSERT_EQ(0, ctx.wait());
247
248   validate_snap_map({});
249   validate_snap_seqs({});
250 }
251
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;
256
257   librbd::MockExclusiveLock mock_exclusive_lock;
258   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
259
260   InSequence seq;
261   expect_update_client(mock_journaler, -EINVAL);
262
263   C_SaferCond ctx;
264   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
265                                                     mock_local_image_ctx,
266                                                     mock_journaler, &ctx);
267   request->send();
268   ASSERT_EQ(-EINVAL, ctx.wait());
269 }
270
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;
275
276   librbd::MockExclusiveLock mock_exclusive_lock;
277   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
278
279   C_SaferCond ctx;
280   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
281                                                     mock_local_image_ctx,
282                                                     mock_journaler, &ctx);
283   InSequence seq;
284   EXPECT_CALL(mock_journaler, update_client(_, _))
285     .WillOnce(DoAll(InvokeWithoutArgs([request]() {
286             request->cancel();
287           }),
288         WithArg<1>(CompleteContext(0))));
289
290   request->send();
291   ASSERT_EQ(-ECANCELED, ctx.wait());
292 }
293
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"));
297
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"}];
302
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;
307
308   librbd::MockExclusiveLock mock_exclusive_lock;
309   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
310
311   InSequence seq;
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);
321
322   C_SaferCond ctx;
323   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
324                                                     mock_local_image_ctx,
325                                                     mock_journaler, &ctx);
326   request->send();
327   ASSERT_EQ(0, ctx.wait());
328
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}});
331 }
332
333 TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateError) {
334   ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
335
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;
340
341   librbd::MockExclusiveLock mock_exclusive_lock;
342   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
343
344   uint64_t remote_snap_id1 = mock_remote_image_ctx.snap_ids[
345     {cls::rbd::UserSnapshotNamespace(), "snap1"}];
346   InSequence seq;
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);
350
351   C_SaferCond ctx;
352   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
353                                                     mock_local_image_ctx,
354                                                     mock_journaler, &ctx);
355   request->send();
356   ASSERT_EQ(-EINVAL, ctx.wait());
357 }
358
359 TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateCancel) {
360   ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
361
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;
366
367   librbd::MockExclusiveLock mock_exclusive_lock;
368   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
369
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);
373
374   C_SaferCond ctx;
375   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
376                                                     mock_local_image_ctx,
377                                                     mock_journaler, &ctx);
378   InSequence seq;
379   expect_start_op(mock_exclusive_lock);
380   EXPECT_CALL(mock_snapshot_create_request, send())
381     .WillOnce(DoAll(InvokeWithoutArgs([request]() {
382             request->cancel();
383           }),
384         Invoke([this, &mock_snapshot_create_request]() {
385             m_threads->work_queue->queue(mock_snapshot_create_request.on_finish, 0);
386           })));
387
388   request->send();
389   ASSERT_EQ(-ECANCELED, ctx.wait());
390 }
391
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"));
395
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"}];
400
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;
405
406   librbd::MockExclusiveLock mock_exclusive_lock;
407   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
408
409   InSequence seq;
410   expect_snap_is_unprotected(mock_local_image_ctx,
411                              m_local_image_ctx->snap_ids[
412                                {cls::rbd::UserSnapshotNamespace(), "snap1"}],
413                              true, 0);
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);
422
423   C_SaferCond ctx;
424   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
425                                                     mock_local_image_ctx,
426                                                     mock_journaler, &ctx);
427   request->send();
428   ASSERT_EQ(0, ctx.wait());
429
430   validate_snap_map({{remote_snap_id1, {12}}});
431   validate_snap_seqs({{remote_snap_id1, 12}});
432 }
433
434 TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapRemoveError) {
435   ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1"));
436
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;
440
441   librbd::MockExclusiveLock mock_exclusive_lock;
442   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
443
444   uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
445     {cls::rbd::UserSnapshotNamespace(), "snap1"}];
446   InSequence seq;
447   expect_snap_is_unprotected(mock_local_image_ctx,
448                              m_local_image_ctx->snap_ids[
449                                {cls::rbd::UserSnapshotNamespace(), "snap1"}],
450                              true, 0);
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);
454
455   C_SaferCond ctx;
456   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
457                                                     mock_local_image_ctx,
458                                                     mock_journaler, &ctx);
459   request->send();
460   ASSERT_EQ(-EINVAL, ctx.wait());
461 }
462
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));
466
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;
472
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;
476
477   librbd::MockExclusiveLock mock_exclusive_lock;
478   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
479
480   InSequence seq;
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);
489
490   C_SaferCond ctx;
491   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
492                                                     mock_local_image_ctx,
493                                                     mock_journaler, &ctx);
494   request->send();
495   ASSERT_EQ(0, ctx.wait());
496
497   validate_snap_map({{remote_snap_id1, {local_snap_id1}}});
498   validate_snap_seqs({{remote_snap_id1, local_snap_id1}});
499 }
500
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));
504
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;
510
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;
514
515   librbd::MockExclusiveLock mock_exclusive_lock;
516   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
517
518   InSequence seq;
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);
523
524   C_SaferCond ctx;
525   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
526                                                     mock_local_image_ctx,
527                                                     mock_journaler, &ctx);
528   request->send();
529   ASSERT_EQ(-EBUSY, ctx.wait());
530 }
531
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));
535
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;
541
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;
545
546   librbd::MockExclusiveLock mock_exclusive_lock;
547   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
548
549   C_SaferCond ctx;
550   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
551                                                     mock_local_image_ctx,
552                                                     mock_journaler, &ctx);
553   InSequence seq;
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]() {
560             request->cancel();
561           }),
562         WithArg<2>(Invoke([this](Context *ctx) {
563             m_threads->work_queue->queue(ctx, 0);
564             }))));
565
566   request->send();
567   ASSERT_EQ(-ECANCELED, ctx.wait());
568 }
569
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));
573
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"}];
578
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;
583
584   librbd::MockExclusiveLock mock_exclusive_lock;
585   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
586
587   InSequence seq;
588   expect_snap_is_unprotected(mock_local_image_ctx,
589                              m_local_image_ctx->snap_ids[
590                                {cls::rbd::UserSnapshotNamespace(), "snap1"}],
591                              false, 0);
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);
602
603   C_SaferCond ctx;
604   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
605                                                     mock_local_image_ctx,
606                                                     mock_journaler, &ctx);
607   request->send();
608   ASSERT_EQ(0, ctx.wait());
609
610   validate_snap_map({{remote_snap_id1, {12}}});
611   validate_snap_seqs({{remote_snap_id1, 12}});
612 }
613
614 TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateProtect) {
615   ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
616
617   uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
618     {cls::rbd::UserSnapshotNamespace(), "snap1"}];
619
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;
624
625   librbd::MockExclusiveLock mock_exclusive_lock;
626   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
627
628   InSequence seq;
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);
637
638   C_SaferCond ctx;
639   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
640                                                     mock_local_image_ctx,
641                                                     mock_journaler, &ctx);
642   request->send();
643   ASSERT_EQ(0, ctx.wait());
644
645   validate_snap_map({{remote_snap_id1, {12}}});
646   validate_snap_seqs({{remote_snap_id1, 12}});
647 }
648
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));
652
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;
658
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;
662
663   librbd::MockExclusiveLock mock_exclusive_lock;
664   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
665
666   InSequence seq;
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);
675
676   C_SaferCond ctx;
677   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
678                                                     mock_local_image_ctx,
679                                                     mock_journaler, &ctx);
680   request->send();
681   ASSERT_EQ(0, ctx.wait());
682
683   validate_snap_map({{remote_snap_id1, {local_snap_id1}}});
684   validate_snap_seqs({{remote_snap_id1, local_snap_id1}});
685 }
686
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));
690
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;
696
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;
700
701   librbd::MockExclusiveLock mock_exclusive_lock;
702   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
703
704   InSequence seq;
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);
712
713   C_SaferCond ctx;
714   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
715                                                     mock_local_image_ctx,
716                                                     mock_journaler, &ctx);
717   request->send();
718   ASSERT_EQ(-EINVAL, ctx.wait());
719 }
720
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));
724
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;
730
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;
734
735   librbd::MockExclusiveLock mock_exclusive_lock;
736   mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
737
738   C_SaferCond ctx;
739   MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
740                                                     mock_local_image_ctx,
741                                                     mock_journaler, &ctx);
742   InSequence seq;
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]() {
752             request->cancel();
753           }),
754         WithArg<2>(Invoke([this](Context *ctx) {
755               m_threads->work_queue->queue(ctx, 0);
756             }))));
757
758   request->send();
759   ASSERT_EQ(-ECANCELED, ctx.wait());
760 }
761
762 } // namespace image_sync
763 } // namespace mirror
764 } // namespace rbd