]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / rbd_mirror / image_sync / test_mock_SnapshotCopyRequest.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "test/rbd_mirror/test_mock_fixture.h"
5#include "include/rbd/librbd.hpp"
6#include "librbd/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
17namespace librbd {
18
19namespace {
20
21struct MockTestImageCtx : public librbd::MockImageCtx {
22 MockTestImageCtx(librbd::ImageCtx &image_ctx)
23 : librbd::MockImageCtx(image_ctx) {
24 }
25};
26
27} // anonymous namespace
28
29namespace journal {
30
31template <>
32struct TypeTraits<librbd::MockTestImageCtx> {
33 typedef ::journal::MockJournaler Journaler;
34};
35
36} // namespace journal
37} // namespace librbd
38
39namespace rbd {
40namespace mirror {
41namespace image_sync {
42
43template <>
44struct 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
67SnapshotCreateRequest<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"
75template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::MockTestImageCtx>;
76
77namespace rbd {
78namespace mirror {
79namespace image_sync {
80
81using ::testing::_;
82using ::testing::DoAll;
83using ::testing::DoDefault;
84using ::testing::InSequence;
85using ::testing::Invoke;
86using ::testing::InvokeWithoutArgs;
87using ::testing::Return;
31f18b77 88using ::testing::ReturnNew;
7c673cae
FG
89using ::testing::SetArgPointee;
90using ::testing::StrEq;
91using ::testing::WithArg;
92
93class TestMockImageSyncSnapshotCopyRequest : public TestMockFixture {
94public:
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
31f18b77
FG
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
7c673cae
FG
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
230TEST_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
31f18b77
FG
235 librbd::MockExclusiveLock mock_exclusive_lock;
236 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
237
7c673cae
FG
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
252TEST_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
31f18b77
FG
257 librbd::MockExclusiveLock mock_exclusive_lock;
258 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
259
7c673cae
FG
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
271TEST_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
31f18b77
FG
276 librbd::MockExclusiveLock mock_exclusive_lock;
277 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
278
7c673cae
FG
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
294TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
308 librbd::MockExclusiveLock mock_exclusive_lock;
309 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
310
7c673cae
FG
311 InSequence seq;
312 expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
31f18b77 313 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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);
31f18b77 316 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
333TEST_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
31f18b77
FG
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"}];
7c673cae
FG
346 InSequence seq;
347 expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
31f18b77 348 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
359TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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;
31f18b77 379 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
392TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
406 librbd::MockExclusiveLock mock_exclusive_lock;
407 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
408
7c673cae
FG
409 InSequence seq;
410 expect_snap_is_unprotected(mock_local_image_ctx,
31f18b77
FG
411 m_local_image_ctx->snap_ids[
412 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
413 true, 0);
7c673cae 414 expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
31f18b77 415 expect_start_op(mock_exclusive_lock);
7c673cae
FG
416 expect_snap_remove(mock_local_image_ctx, "snap1", 0);
417 expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
31f18b77 418 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
434TEST_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
31f18b77
FG
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"}];
7c673cae
FG
446 InSequence seq;
447 expect_snap_is_unprotected(mock_local_image_ctx,
31f18b77
FG
448 m_local_image_ctx->snap_ids[
449 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
450 true, 0);
7c673cae 451 expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
31f18b77 452 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
463TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
477 librbd::MockExclusiveLock mock_exclusive_lock;
478 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
479
7c673cae
FG
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);
31f18b77 483 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
501TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
515 librbd::MockExclusiveLock mock_exclusive_lock;
516 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
517
7c673cae
FG
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);
31f18b77 521 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
532TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
546 librbd::MockExclusiveLock mock_exclusive_lock;
547 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
548
7c673cae
FG
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);
31f18b77 556 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
570TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
584 librbd::MockExclusiveLock mock_exclusive_lock;
585 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
586
7c673cae
FG
587 InSequence seq;
588 expect_snap_is_unprotected(mock_local_image_ctx,
31f18b77
FG
589 m_local_image_ctx->snap_ids[
590 {cls::rbd::UserSnapshotNamespace(), "snap1"}],
591 false, 0);
592 expect_start_op(mock_exclusive_lock);
7c673cae
FG
593 expect_snap_unprotect(mock_local_image_ctx, "snap1", 0);
594 expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
31f18b77 595 expect_start_op(mock_exclusive_lock);
7c673cae
FG
596 expect_snap_remove(mock_local_image_ctx, "snap1", 0);
597 expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
31f18b77 598 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
614TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateProtect) {
615 ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
616
31f18b77
FG
617 uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
618 {cls::rbd::UserSnapshotNamespace(), "snap1"}];
7c673cae
FG
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
31f18b77
FG
625 librbd::MockExclusiveLock mock_exclusive_lock;
626 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
627
7c673cae
FG
628 InSequence seq;
629 expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
31f18b77 630 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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);
31f18b77 634 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
649TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
663 librbd::MockExclusiveLock mock_exclusive_lock;
664 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
665
7c673cae
FG
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);
31f18b77 672 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
687TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
701 librbd::MockExclusiveLock mock_exclusive_lock;
702 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
703
7c673cae
FG
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);
31f18b77 710 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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
721TEST_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
31f18b77
FG
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"}];
7c673cae
FG
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
31f18b77
FG
735 librbd::MockExclusiveLock mock_exclusive_lock;
736 mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
737
7c673cae
FG
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);
31f18b77 748 expect_start_op(mock_exclusive_lock);
7c673cae
FG
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