]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/mirror/test_mock_DisableRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / librbd / mirror / test_mock_DisableRequest.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/librbd/test_mock_fixture.h"
5#include "test/librbd/test_support.h"
6#include "test/librbd/mock/MockImageCtx.h"
9f95a23c 7#include "test/librbd/mock/MockImageState.h"
7c673cae
FG
8#include "test/librbd/mock/MockOperations.h"
9#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10#include "test/librados_test_stub/MockTestMemRadosClient.h"
7c673cae
FG
11#include "librbd/journal/PromoteRequest.h"
12#include "librbd/mirror/DisableRequest.h"
9f95a23c
TL
13#include "librbd/mirror/GetInfoRequest.h"
14#include "librbd/mirror/ImageRemoveRequest.h"
15#include "librbd/mirror/ImageStateUpdateRequest.h"
16#include "librbd/mirror/snapshot/PromoteRequest.h"
7c673cae
FG
17
18namespace librbd {
19
20namespace {
21
22struct MockTestImageCtx : public MockImageCtx {
11fdf7f2 23 explicit MockTestImageCtx(librbd::ImageCtx& image_ctx) : MockImageCtx(image_ctx) {
7c673cae
FG
24 }
25};
26
27} // anonymous namespace
28
9f95a23c
TL
29namespace journal {
30
7c673cae 31template <>
9f95a23c
TL
32struct PromoteRequest<librbd::MockTestImageCtx> {
33 Context *on_finish = nullptr;
34 static PromoteRequest *s_instance;
35 static PromoteRequest *create(librbd::MockTestImageCtx *, bool force,
36 Context *on_finish) {
11fdf7f2 37 ceph_assert(s_instance != nullptr);
9f95a23c
TL
38 s_instance->on_finish = on_finish;
39 return s_instance;
7c673cae
FG
40 }
41
9f95a23c 42 PromoteRequest() {
7c673cae
FG
43 s_instance = this;
44 }
45
9f95a23c 46 MOCK_METHOD0(send, void());
7c673cae
FG
47};
48
9f95a23c
TL
49PromoteRequest<librbd::MockTestImageCtx> *PromoteRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
50
51} // namespace journal
7c673cae 52
9f95a23c 53namespace mirror {
7c673cae 54template <>
9f95a23c
TL
55struct GetInfoRequest<librbd::MockTestImageCtx> {
56 cls::rbd::MirrorImage *mirror_image;
57 PromotionState *promotion_state;
58 Context *on_finish = nullptr;
59 static GetInfoRequest *s_instance;
60 static GetInfoRequest *create(librbd::MockTestImageCtx &,
61 cls::rbd::MirrorImage *mirror_image,
62 PromotionState *promotion_state,
63 std::string* primary_mirror_uuid,
64 Context *on_finish) {
11fdf7f2 65 ceph_assert(s_instance != nullptr);
9f95a23c
TL
66 s_instance->mirror_image = mirror_image;
67 s_instance->promotion_state = promotion_state;
68 s_instance->on_finish = on_finish;
69 return s_instance;
7c673cae
FG
70 }
71
9f95a23c 72 GetInfoRequest() {
7c673cae
FG
73 s_instance = this;
74 }
75
9f95a23c 76 MOCK_METHOD0(send, void());
7c673cae
FG
77};
78
9f95a23c
TL
79template <>
80struct ImageRemoveRequest<librbd::MockTestImageCtx> {
81 static ImageRemoveRequest* s_instance;
82 Context* on_finish = nullptr;
83
84 static ImageRemoveRequest* create(
85 librados::IoCtx& io_ctx,
86 const std::string& global_image_id,
87 const std::string& image_id,
88 Context* on_finish) {
89 ceph_assert(s_instance != nullptr);
90 s_instance->on_finish = on_finish;
91 return s_instance;
92 }
7c673cae 93
9f95a23c
TL
94 MOCK_METHOD0(send, void());
95
96 ImageRemoveRequest() {
97 s_instance = this;
98 }
99};
100
101template <>
102struct ImageStateUpdateRequest<librbd::MockTestImageCtx> {
103 static ImageStateUpdateRequest* s_instance;
104 Context* on_finish = nullptr;
105
106 static ImageStateUpdateRequest* create(
107 librados::IoCtx& io_ctx,
108 const std::string& image_id,
109 cls::rbd::MirrorImageState mirror_image_state,
110 const cls::rbd::MirrorImage& mirror_image,
111 Context* on_finish) {
112 ceph_assert(s_instance != nullptr);
113 s_instance->on_finish = on_finish;
114 return s_instance;
115 }
116
117 MOCK_METHOD0(send, void());
118
119 ImageStateUpdateRequest() {
120 s_instance = this;
121 }
122};
123
124GetInfoRequest<librbd::MockTestImageCtx> *GetInfoRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
125ImageRemoveRequest<librbd::MockTestImageCtx> *ImageRemoveRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
126ImageStateUpdateRequest<librbd::MockTestImageCtx> *ImageStateUpdateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
127
128namespace snapshot {
7c673cae
FG
129
130template <>
131struct PromoteRequest<librbd::MockTestImageCtx> {
132 Context *on_finish = nullptr;
133 static PromoteRequest *s_instance;
9f95a23c
TL
134 static PromoteRequest *create(librbd::MockTestImageCtx*,
135 const std::string& global_image_id,
7c673cae 136 Context *on_finish) {
11fdf7f2 137 ceph_assert(s_instance != nullptr);
7c673cae
FG
138 s_instance->on_finish = on_finish;
139 return s_instance;
140 }
141
142 PromoteRequest() {
143 s_instance = this;
144 }
145
146 MOCK_METHOD0(send, void());
147};
148
149PromoteRequest<librbd::MockTestImageCtx> *PromoteRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
150
9f95a23c
TL
151} // namespace snapshot
152} // namespace mirror
7c673cae
FG
153} // namespace librbd
154
155// template definitions
156#include "librbd/mirror/DisableRequest.cc"
157template class librbd::mirror::DisableRequest<librbd::MockTestImageCtx>;
158
9f95a23c
TL
159ACTION_P(TestFeatures, image_ctx) {
160 return ((image_ctx->features & arg0) != 0);
161}
162
7c673cae
FG
163namespace librbd {
164namespace mirror {
165
166using ::testing::_;
167using ::testing::DoAll;
168using ::testing::InSequence;
9f95a23c 169using ::testing::Invoke;
7c673cae 170using ::testing::Return;
7c673cae
FG
171using ::testing::StrEq;
172using ::testing::WithArg;
173
174class TestMockMirrorDisableRequest : public TestMockFixture {
175public:
176 typedef DisableRequest<MockTestImageCtx> MockDisableRequest;
177 typedef Journal<MockTestImageCtx> MockJournal;
9f95a23c
TL
178 typedef journal::PromoteRequest<MockTestImageCtx> MockJournalPromoteRequest;
179 typedef mirror::GetInfoRequest<MockTestImageCtx> MockGetInfoRequest;
180 typedef mirror::ImageRemoveRequest<MockTestImageCtx> MockImageRemoveRequest;
181 typedef mirror::ImageStateUpdateRequest<MockTestImageCtx> MockImageStateUpdateRequest;
182 typedef mirror::snapshot::PromoteRequest<MockTestImageCtx> MockSnapshotPromoteRequest;
183
184 void expect_get_mirror_info(MockTestImageCtx &mock_image_ctx,
185 MockGetInfoRequest &mock_get_info_request,
186 const cls::rbd::MirrorImage &mirror_image,
187 PromotionState promotion_state, int r) {
188
189 EXPECT_CALL(mock_get_info_request, send())
190 .WillOnce(
f67539c2 191 Invoke([&mock_image_ctx, &mock_get_info_request, mirror_image,
9f95a23c
TL
192 promotion_state, r]() {
193 if (r == 0) {
194 *mock_get_info_request.mirror_image = mirror_image;
195 *mock_get_info_request.promotion_state = promotion_state;
196 }
197 mock_image_ctx.op_work_queue->queue(
198 mock_get_info_request.on_finish, r);
199 }));
7c673cae
FG
200 }
201
9f95a23c
TL
202 void expect_mirror_image_state_update(
203 MockTestImageCtx &mock_image_ctx,
204 MockImageStateUpdateRequest& mock_request, int r) {
205 EXPECT_CALL(mock_request, send())
206 .WillOnce(
f67539c2 207 Invoke([&mock_image_ctx, &mock_request, r]() {
9f95a23c
TL
208 mock_image_ctx.op_work_queue->queue(mock_request.on_finish, r);
209 }));
7c673cae
FG
210 }
211
9f95a23c
TL
212 void expect_mirror_image_remove(
213 MockTestImageCtx &mock_image_ctx,
214 MockImageRemoveRequest& mock_request, int r) {
215 EXPECT_CALL(mock_request, send())
216 .WillOnce(
f67539c2 217 Invoke([&mock_image_ctx, &mock_request, r]() {
9f95a23c
TL
218 mock_image_ctx.op_work_queue->queue(mock_request.on_finish, r);
219 }));
7c673cae
FG
220 }
221
222 void expect_journal_client_list(MockTestImageCtx &mock_image_ctx,
223 const std::set<cls::journal::Client> &clients,
224 int r) {
225 bufferlist bl;
11fdf7f2
TL
226 using ceph::encode;
227 encode(clients, bl);
7c673cae
FG
228
229 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
230 exec(::journal::Journaler::header_oid(mock_image_ctx.id),
f67539c2 231 _, StrEq("journal"), StrEq("client_list"), _, _, _, _))
7c673cae
FG
232 .WillOnce(DoAll(WithArg<5>(CopyInBufferlist(bl)),
233 Return(r)));
234 }
235
236 void expect_journal_client_unregister(MockTestImageCtx &mock_image_ctx,
237 const std::string &client_id,
238 int r) {
239 bufferlist bl;
11fdf7f2
TL
240 using ceph::encode;
241 encode(client_id, bl);
7c673cae
FG
242
243 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
244 exec(::journal::Journaler::header_oid(mock_image_ctx.id),
245 _, StrEq("journal"), StrEq("client_unregister"),
f67539c2 246 ContentsEqual(bl), _, _, _))
7c673cae
FG
247 .WillOnce(Return(r));
248 }
249
250 void expect_journal_promote(MockTestImageCtx &mock_image_ctx,
9f95a23c
TL
251 MockJournalPromoteRequest &mock_promote_request,
252 int r) {
7c673cae
FG
253 EXPECT_CALL(mock_promote_request, send())
254 .WillOnce(FinishRequest(&mock_promote_request, r, &mock_image_ctx));
255 }
256
9f95a23c
TL
257 void expect_snapshot_promote(MockTestImageCtx &mock_image_ctx,
258 MockSnapshotPromoteRequest &mock_promote_request,
259 int r) {
260 EXPECT_CALL(mock_promote_request, send())
261 .WillOnce(FinishRequest(&mock_promote_request, r, &mock_image_ctx));
262 }
263
264 void expect_is_refresh_required(MockTestImageCtx &mock_image_ctx,
265 bool refresh_required) {
266 EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
267 .WillOnce(Return(refresh_required));
268 }
269
270 void expect_refresh_image(MockTestImageCtx &mock_image_ctx, int r) {
271 EXPECT_CALL(*mock_image_ctx.state, refresh(_))
272 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
273 }
274
7c673cae
FG
275 void expect_snap_remove(MockTestImageCtx &mock_image_ctx,
276 const std::string &snap_name, int r) {
91327a77 277 EXPECT_CALL(*mock_image_ctx.operations, snap_remove(_, StrEq(snap_name), _))
7c673cae
FG
278 .WillOnce(WithArg<2>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
279 }
280
281 template <typename T>
282 bufferlist encode(const T &t) {
11fdf7f2 283 using ceph::encode;
7c673cae 284 bufferlist bl;
11fdf7f2 285 encode(t, bl);
7c673cae
FG
286 return bl;
287 }
288
289};
290
291TEST_F(TestMockMirrorDisableRequest, Success) {
292 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
293
294 librbd::ImageCtx *ictx;
295 ASSERT_EQ(0, open_image(m_image_name, &ictx));
296
297 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
298
299 expect_op_work_queue(mock_image_ctx);
300 expect_snap_remove(mock_image_ctx, "snap 1", 0);
301 expect_snap_remove(mock_image_ctx, "snap 2", 0);
302
303 InSequence seq;
9f95a23c
TL
304
305 MockGetInfoRequest mock_get_info_request;
306 expect_get_mirror_info(
307 mock_image_ctx, mock_get_info_request,
308 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
309 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
310 MockImageStateUpdateRequest mock_image_state_update_request;
311 expect_mirror_image_state_update(
312 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
313 expect_journal_client_list(
314 mock_image_ctx, {
315 {"", encode(journal::ClientData{journal::ImageClientMeta{}})},
316 {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})},
317 {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{
318 "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)},
319 {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}}
320 })}
321 }, 0);
322 expect_journal_client_unregister(mock_image_ctx, "peer 1", 0);
323 expect_journal_client_unregister(mock_image_ctx, "peer 2", 0);
324 expect_journal_client_list(mock_image_ctx, {}, 0);
9f95a23c
TL
325 MockImageRemoveRequest mock_image_remove_request;
326 expect_mirror_image_remove(
327 mock_image_ctx, mock_image_remove_request, 0);
7c673cae
FG
328
329 C_SaferCond ctx;
330 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
331 req->send();
332 ASSERT_EQ(0, ctx.wait());
333}
334
335TEST_F(TestMockMirrorDisableRequest, SuccessNoRemove) {
336 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
337
338 librbd::ImageCtx *ictx;
339 ASSERT_EQ(0, open_image(m_image_name, &ictx));
340
341 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
342
343 expect_op_work_queue(mock_image_ctx);
344
345 InSequence seq;
9f95a23c
TL
346
347 MockGetInfoRequest mock_get_info_request;
348 expect_get_mirror_info(
349 mock_image_ctx, mock_get_info_request,
350 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
351 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
352 MockImageStateUpdateRequest mock_image_state_update_request;
353 expect_mirror_image_state_update(
354 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
355 expect_journal_client_list(mock_image_ctx, {}, 0);
356
357 C_SaferCond ctx;
358 auto req = new MockDisableRequest(&mock_image_ctx, false, false, &ctx);
359 req->send();
360 ASSERT_EQ(0, ctx.wait());
361}
362
363TEST_F(TestMockMirrorDisableRequest, SuccessNonPrimary) {
364 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
365
366 librbd::ImageCtx *ictx;
367 ASSERT_EQ(0, open_image(m_image_name, &ictx));
368
369 MockTestImageCtx mock_image_ctx(*ictx);
9f95a23c 370 MockJournalPromoteRequest mock_promote_request;
7c673cae
FG
371
372 expect_op_work_queue(mock_image_ctx);
373
374 InSequence seq;
9f95a23c
TL
375
376 MockGetInfoRequest mock_get_info_request;
377 expect_get_mirror_info(
378 mock_image_ctx, mock_get_info_request,
379 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
380 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0);
381 MockImageStateUpdateRequest mock_image_state_update_request;
382 expect_mirror_image_state_update(
383 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae 384 expect_journal_promote(mock_image_ctx, mock_promote_request, 0);
9f95a23c 385 expect_is_refresh_required(mock_image_ctx, false);
7c673cae 386 expect_journal_client_list(mock_image_ctx, {}, 0);
9f95a23c
TL
387 MockImageRemoveRequest mock_image_remove_request;
388 expect_mirror_image_remove(
389 mock_image_ctx, mock_image_remove_request, 0);
7c673cae
FG
390
391 C_SaferCond ctx;
392 auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx);
393 req->send();
394 ASSERT_EQ(0, ctx.wait());
395}
396
397TEST_F(TestMockMirrorDisableRequest, NonPrimaryError) {
398 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
399
400 librbd::ImageCtx *ictx;
401 ASSERT_EQ(0, open_image(m_image_name, &ictx));
402
403 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
404
405 expect_op_work_queue(mock_image_ctx);
406
407 InSequence seq;
9f95a23c
TL
408
409 MockGetInfoRequest mock_get_info_request;
410 expect_get_mirror_info(
411 mock_image_ctx, mock_get_info_request,
412 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
413 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0);
7c673cae
FG
414
415 C_SaferCond ctx;
416 auto req = new MockDisableRequest(&mock_image_ctx, false, false, &ctx);
417 req->send();
418 ASSERT_EQ(-EINVAL, ctx.wait());
419}
420
9f95a23c 421TEST_F(TestMockMirrorDisableRequest, GetMirrorInfoError) {
7c673cae
FG
422 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
423
424 librbd::ImageCtx *ictx;
425 ASSERT_EQ(0, open_image(m_image_name, &ictx));
426
427 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
428
429 expect_op_work_queue(mock_image_ctx);
430
431 InSequence seq;
7c673cae 432
9f95a23c
TL
433 MockGetInfoRequest mock_get_info_request;
434 expect_get_mirror_info(
435 mock_image_ctx, mock_get_info_request,
436 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
437 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, -EINVAL);
7c673cae
FG
438
439 C_SaferCond ctx;
440 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
441 req->send();
9f95a23c 442 ASSERT_EQ(-EINVAL, ctx.wait());
7c673cae
FG
443}
444
445TEST_F(TestMockMirrorDisableRequest, MirrorImageSetError) {
446 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
447
448 librbd::ImageCtx *ictx;
449 ASSERT_EQ(0, open_image(m_image_name, &ictx));
450
451 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
452
453 expect_op_work_queue(mock_image_ctx);
454
455 InSequence seq;
9f95a23c
TL
456
457 MockGetInfoRequest mock_get_info_request;
458 expect_get_mirror_info(
459 mock_image_ctx, mock_get_info_request,
460 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
461 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
462 MockImageStateUpdateRequest mock_image_state_update_request;
463 expect_mirror_image_state_update(
464 mock_image_ctx, mock_image_state_update_request, -ENOENT);
7c673cae
FG
465
466 C_SaferCond ctx;
467 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
468 req->send();
469 ASSERT_EQ(-ENOENT, ctx.wait());
470}
471
472TEST_F(TestMockMirrorDisableRequest, JournalPromoteError) {
7c673cae
FG
473 librbd::ImageCtx *ictx;
474 ASSERT_EQ(0, open_image(m_image_name, &ictx));
475
476 MockTestImageCtx mock_image_ctx(*ictx);
9f95a23c 477 MockJournalPromoteRequest mock_promote_request;
7c673cae
FG
478
479 expect_op_work_queue(mock_image_ctx);
480
481 InSequence seq;
9f95a23c
TL
482
483 MockGetInfoRequest mock_get_info_request;
484 expect_get_mirror_info(
485 mock_image_ctx, mock_get_info_request,
486 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
487 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0);
488 MockImageStateUpdateRequest mock_image_state_update_request;
489 expect_mirror_image_state_update(
490 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
491 expect_journal_promote(mock_image_ctx, mock_promote_request, -EPERM);
492
493 C_SaferCond ctx;
494 auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx);
495 req->send();
496 ASSERT_EQ(-EPERM, ctx.wait());
497}
498
499TEST_F(TestMockMirrorDisableRequest, JournalClientListError) {
500 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
501
502 librbd::ImageCtx *ictx;
503 ASSERT_EQ(0, open_image(m_image_name, &ictx));
504
505 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
506
507 expect_op_work_queue(mock_image_ctx);
508
509 InSequence seq;
9f95a23c
TL
510
511 MockGetInfoRequest mock_get_info_request;
512 expect_get_mirror_info(
513 mock_image_ctx, mock_get_info_request,
514 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
515 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
516 MockImageStateUpdateRequest mock_image_state_update_request;
517 expect_mirror_image_state_update(
518 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
519 expect_journal_client_list(mock_image_ctx, {}, -EBADMSG);
520
521 C_SaferCond ctx;
522 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
523 req->send();
524 ASSERT_EQ(-EBADMSG, ctx.wait());
525}
526
527TEST_F(TestMockMirrorDisableRequest, SnapRemoveError) {
528 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
529
530 librbd::ImageCtx *ictx;
531 ASSERT_EQ(0, open_image(m_image_name, &ictx));
532
533 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
534
535 expect_op_work_queue(mock_image_ctx);
536 expect_snap_remove(mock_image_ctx, "snap 1", 0);
537 expect_snap_remove(mock_image_ctx, "snap 2", -EPERM);
538
539 InSequence seq;
9f95a23c
TL
540
541 MockGetInfoRequest mock_get_info_request;
542 expect_get_mirror_info(
543 mock_image_ctx, mock_get_info_request,
544 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
545 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
546 MockImageStateUpdateRequest mock_image_state_update_request;
547 expect_mirror_image_state_update(
548 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
549 expect_journal_client_list(
550 mock_image_ctx, {
551 {"", encode(journal::ClientData{journal::ImageClientMeta{}})},
552 {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})},
553 {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{
554 "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)},
555 {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}}
556 })}
557 }, 0);
558 expect_journal_client_unregister(mock_image_ctx, "peer 1", 0);
559
560 C_SaferCond ctx;
561 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
562 req->send();
563 ASSERT_EQ(-EPERM, ctx.wait());
564}
565
566TEST_F(TestMockMirrorDisableRequest, JournalClientUnregisterError) {
567 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
568
569 librbd::ImageCtx *ictx;
570 ASSERT_EQ(0, open_image(m_image_name, &ictx));
571
572 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
573
574 expect_op_work_queue(mock_image_ctx);
575 expect_snap_remove(mock_image_ctx, "snap 1", 0);
576 expect_snap_remove(mock_image_ctx, "snap 2", 0);
577
578 InSequence seq;
9f95a23c
TL
579
580 MockGetInfoRequest mock_get_info_request;
581 expect_get_mirror_info(
582 mock_image_ctx, mock_get_info_request,
583 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
584 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
585 MockImageStateUpdateRequest mock_image_state_update_request;
586 expect_mirror_image_state_update(
587 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae
FG
588 expect_journal_client_list(
589 mock_image_ctx, {
590 {"", encode(journal::ClientData{journal::ImageClientMeta{}})},
591 {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})},
592 {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{
593 "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)},
594 {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}}
595 })}
596 }, 0);
597 expect_journal_client_unregister(mock_image_ctx, "peer 1", -EINVAL);
598 expect_journal_client_unregister(mock_image_ctx, "peer 2", 0);
599
600 C_SaferCond ctx;
601 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
602 req->send();
603 ASSERT_EQ(-EINVAL, ctx.wait());
604}
605
9f95a23c
TL
606TEST_F(TestMockMirrorDisableRequest, SnapshotPromoteError) {
607 librbd::ImageCtx *ictx;
608 ASSERT_EQ(0, open_image(m_image_name, &ictx));
609
610 MockTestImageCtx mock_image_ctx(*ictx);
611 MockSnapshotPromoteRequest mock_promote_request;
612
613 expect_op_work_queue(mock_image_ctx);
614
615 InSequence seq;
616
617 MockGetInfoRequest mock_get_info_request;
618 expect_get_mirror_info(
619 mock_image_ctx, mock_get_info_request,
620 {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, "global id",
621 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0);
622 MockImageStateUpdateRequest mock_image_state_update_request;
623 expect_mirror_image_state_update(
624 mock_image_ctx, mock_image_state_update_request, 0);
625 expect_snapshot_promote(mock_image_ctx, mock_promote_request, -EPERM);
626
627 C_SaferCond ctx;
628 auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx);
629 req->send();
630 ASSERT_EQ(-EPERM, ctx.wait());
631}
632
633TEST_F(TestMockMirrorDisableRequest, RefreshError) {
634 librbd::ImageCtx *ictx;
635 ASSERT_EQ(0, open_image(m_image_name, &ictx));
636
637 MockTestImageCtx mock_image_ctx(*ictx);
638 MockSnapshotPromoteRequest mock_promote_request;
639
640 expect_op_work_queue(mock_image_ctx);
641
642 InSequence seq;
643
644 MockGetInfoRequest mock_get_info_request;
645 expect_get_mirror_info(
646 mock_image_ctx, mock_get_info_request,
647 {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, "global id",
648 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0);
649 MockImageStateUpdateRequest mock_image_state_update_request;
650 expect_mirror_image_state_update(
651 mock_image_ctx, mock_image_state_update_request, 0);
652 expect_snapshot_promote(mock_image_ctx, mock_promote_request, 0);
653 expect_is_refresh_required(mock_image_ctx, true);
654 expect_refresh_image(mock_image_ctx, -EPERM);
655
656 C_SaferCond ctx;
657 auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx);
658 req->send();
659 ASSERT_EQ(-EPERM, ctx.wait());
660}
661
7c673cae
FG
662TEST_F(TestMockMirrorDisableRequest, MirrorImageRemoveError) {
663 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
664
665 librbd::ImageCtx *ictx;
666 ASSERT_EQ(0, open_image(m_image_name, &ictx));
667
668 MockTestImageCtx mock_image_ctx(*ictx);
7c673cae
FG
669
670 expect_op_work_queue(mock_image_ctx);
671
672 InSequence seq;
9f95a23c
TL
673
674 MockGetInfoRequest mock_get_info_request;
675 expect_get_mirror_info(
676 mock_image_ctx, mock_get_info_request,
677 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id",
678 cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0);
679 MockImageStateUpdateRequest mock_image_state_update_request;
680 expect_mirror_image_state_update(
681 mock_image_ctx, mock_image_state_update_request, 0);
7c673cae 682 expect_journal_client_list(mock_image_ctx, {}, 0);
9f95a23c
TL
683 MockImageRemoveRequest mock_image_remove_request;
684 expect_mirror_image_remove(
685 mock_image_ctx, mock_image_remove_request, -EINVAL);
7c673cae
FG
686
687 C_SaferCond ctx;
688 auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx);
689 req->send();
690 ASSERT_EQ(-EINVAL, ctx.wait());
691}
692
693} // namespace mirror
694} // namespace librbd