1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7 #include "test/librbd/mock/MockImageState.h"
8 #include "test/librbd/mock/MockOperations.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "test/librados_test_stub/MockTestMemRadosClient.h"
11 #include "librbd/journal/PromoteRequest.h"
12 #include "librbd/mirror/DisableRequest.h"
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"
22 struct MockTestImageCtx
: public MockImageCtx
{
23 explicit MockTestImageCtx(librbd::ImageCtx
& image_ctx
) : MockImageCtx(image_ctx
) {
27 } // anonymous namespace
32 struct PromoteRequest
<librbd::MockTestImageCtx
> {
33 Context
*on_finish
= nullptr;
34 static PromoteRequest
*s_instance
;
35 static PromoteRequest
*create(librbd::MockTestImageCtx
*, bool force
,
37 ceph_assert(s_instance
!= nullptr);
38 s_instance
->on_finish
= on_finish
;
46 MOCK_METHOD0(send
, void());
49 PromoteRequest
<librbd::MockTestImageCtx
> *PromoteRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
51 } // namespace journal
55 struct 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
,
65 ceph_assert(s_instance
!= nullptr);
66 s_instance
->mirror_image
= mirror_image
;
67 s_instance
->promotion_state
= promotion_state
;
68 s_instance
->on_finish
= on_finish
;
76 MOCK_METHOD0(send
, void());
80 struct ImageRemoveRequest
<librbd::MockTestImageCtx
> {
81 static ImageRemoveRequest
* s_instance
;
82 Context
* on_finish
= nullptr;
84 static ImageRemoveRequest
* create(
85 librados::IoCtx
& io_ctx
,
86 const std::string
& global_image_id
,
87 const std::string
& image_id
,
89 ceph_assert(s_instance
!= nullptr);
90 s_instance
->on_finish
= on_finish
;
94 MOCK_METHOD0(send
, void());
96 ImageRemoveRequest() {
102 struct ImageStateUpdateRequest
<librbd::MockTestImageCtx
> {
103 static ImageStateUpdateRequest
* s_instance
;
104 Context
* on_finish
= nullptr;
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
;
117 MOCK_METHOD0(send
, void());
119 ImageStateUpdateRequest() {
124 GetInfoRequest
<librbd::MockTestImageCtx
> *GetInfoRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
125 ImageRemoveRequest
<librbd::MockTestImageCtx
> *ImageRemoveRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
126 ImageStateUpdateRequest
<librbd::MockTestImageCtx
> *ImageStateUpdateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
131 struct PromoteRequest
<librbd::MockTestImageCtx
> {
132 Context
*on_finish
= nullptr;
133 static PromoteRequest
*s_instance
;
134 static PromoteRequest
*create(librbd::MockTestImageCtx
*,
135 const std::string
& global_image_id
,
136 Context
*on_finish
) {
137 ceph_assert(s_instance
!= nullptr);
138 s_instance
->on_finish
= on_finish
;
146 MOCK_METHOD0(send
, void());
149 PromoteRequest
<librbd::MockTestImageCtx
> *PromoteRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
151 } // namespace snapshot
152 } // namespace mirror
153 } // namespace librbd
155 // template definitions
156 #include "librbd/mirror/DisableRequest.cc"
157 template class librbd::mirror::DisableRequest
<librbd::MockTestImageCtx
>;
159 ACTION_P(TestFeatures
, image_ctx
) {
160 return ((image_ctx
->features
& arg0
) != 0);
167 using ::testing::DoAll
;
168 using ::testing::InSequence
;
169 using ::testing::Invoke
;
170 using ::testing::Return
;
171 using ::testing::StrEq
;
172 using ::testing::WithArg
;
174 class TestMockMirrorDisableRequest
: public TestMockFixture
{
176 typedef DisableRequest
<MockTestImageCtx
> MockDisableRequest
;
177 typedef Journal
<MockTestImageCtx
> MockJournal
;
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
;
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
) {
189 EXPECT_CALL(mock_get_info_request
, send())
191 Invoke([this, &mock_image_ctx
, &mock_get_info_request
, mirror_image
,
192 promotion_state
, r
]() {
194 *mock_get_info_request
.mirror_image
= mirror_image
;
195 *mock_get_info_request
.promotion_state
= promotion_state
;
197 mock_image_ctx
.op_work_queue
->queue(
198 mock_get_info_request
.on_finish
, r
);
202 void expect_mirror_image_state_update(
203 MockTestImageCtx
&mock_image_ctx
,
204 MockImageStateUpdateRequest
& mock_request
, int r
) {
205 EXPECT_CALL(mock_request
, send())
207 Invoke([this, &mock_image_ctx
, &mock_request
, r
]() {
208 mock_image_ctx
.op_work_queue
->queue(mock_request
.on_finish
, r
);
212 void expect_mirror_image_remove(
213 MockTestImageCtx
&mock_image_ctx
,
214 MockImageRemoveRequest
& mock_request
, int r
) {
215 EXPECT_CALL(mock_request
, send())
217 Invoke([this, &mock_image_ctx
, &mock_request
, r
]() {
218 mock_image_ctx
.op_work_queue
->queue(mock_request
.on_finish
, r
);
222 void expect_journal_client_list(MockTestImageCtx
&mock_image_ctx
,
223 const std::set
<cls::journal::Client
> &clients
,
229 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
230 exec(::journal::Journaler::header_oid(mock_image_ctx
.id
),
231 _
, StrEq("journal"), StrEq("client_list"), _
, _
, _
))
232 .WillOnce(DoAll(WithArg
<5>(CopyInBufferlist(bl
)),
236 void expect_journal_client_unregister(MockTestImageCtx
&mock_image_ctx
,
237 const std::string
&client_id
,
241 encode(client_id
, bl
);
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"),
246 ContentsEqual(bl
), _
, _
))
247 .WillOnce(Return(r
));
250 void expect_journal_promote(MockTestImageCtx
&mock_image_ctx
,
251 MockJournalPromoteRequest
&mock_promote_request
,
253 EXPECT_CALL(mock_promote_request
, send())
254 .WillOnce(FinishRequest(&mock_promote_request
, r
, &mock_image_ctx
));
257 void expect_snapshot_promote(MockTestImageCtx
&mock_image_ctx
,
258 MockSnapshotPromoteRequest
&mock_promote_request
,
260 EXPECT_CALL(mock_promote_request
, send())
261 .WillOnce(FinishRequest(&mock_promote_request
, r
, &mock_image_ctx
));
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
));
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
));
275 void expect_snap_remove(MockTestImageCtx
&mock_image_ctx
,
276 const std::string
&snap_name
, int r
) {
277 EXPECT_CALL(*mock_image_ctx
.operations
, snap_remove(_
, StrEq(snap_name
), _
))
278 .WillOnce(WithArg
<2>(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
281 template <typename T
>
282 bufferlist
encode(const T
&t
) {
291 TEST_F(TestMockMirrorDisableRequest
, Success
) {
292 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
294 librbd::ImageCtx
*ictx
;
295 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
297 MockTestImageCtx
mock_image_ctx(*ictx
);
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);
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);
313 expect_journal_client_list(
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)}}}
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);
325 MockImageRemoveRequest mock_image_remove_request
;
326 expect_mirror_image_remove(
327 mock_image_ctx
, mock_image_remove_request
, 0);
330 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
332 ASSERT_EQ(0, ctx
.wait());
335 TEST_F(TestMockMirrorDisableRequest
, SuccessNoRemove
) {
336 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
338 librbd::ImageCtx
*ictx
;
339 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
341 MockTestImageCtx
mock_image_ctx(*ictx
);
343 expect_op_work_queue(mock_image_ctx
);
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);
355 expect_journal_client_list(mock_image_ctx
, {}, 0);
358 auto req
= new MockDisableRequest(&mock_image_ctx
, false, false, &ctx
);
360 ASSERT_EQ(0, ctx
.wait());
363 TEST_F(TestMockMirrorDisableRequest
, SuccessNonPrimary
) {
364 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
366 librbd::ImageCtx
*ictx
;
367 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
369 MockTestImageCtx
mock_image_ctx(*ictx
);
370 MockJournalPromoteRequest mock_promote_request
;
372 expect_op_work_queue(mock_image_ctx
);
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);
384 expect_journal_promote(mock_image_ctx
, mock_promote_request
, 0);
385 expect_is_refresh_required(mock_image_ctx
, false);
386 expect_journal_client_list(mock_image_ctx
, {}, 0);
387 MockImageRemoveRequest mock_image_remove_request
;
388 expect_mirror_image_remove(
389 mock_image_ctx
, mock_image_remove_request
, 0);
392 auto req
= new MockDisableRequest(&mock_image_ctx
, true, true, &ctx
);
394 ASSERT_EQ(0, ctx
.wait());
397 TEST_F(TestMockMirrorDisableRequest
, NonPrimaryError
) {
398 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
400 librbd::ImageCtx
*ictx
;
401 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
403 MockTestImageCtx
mock_image_ctx(*ictx
);
405 expect_op_work_queue(mock_image_ctx
);
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);
416 auto req
= new MockDisableRequest(&mock_image_ctx
, false, false, &ctx
);
418 ASSERT_EQ(-EINVAL
, ctx
.wait());
421 TEST_F(TestMockMirrorDisableRequest
, GetMirrorInfoError
) {
422 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
424 librbd::ImageCtx
*ictx
;
425 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
427 MockTestImageCtx
mock_image_ctx(*ictx
);
429 expect_op_work_queue(mock_image_ctx
);
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
);
440 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
442 ASSERT_EQ(-EINVAL
, ctx
.wait());
445 TEST_F(TestMockMirrorDisableRequest
, MirrorImageSetError
) {
446 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
448 librbd::ImageCtx
*ictx
;
449 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
451 MockTestImageCtx
mock_image_ctx(*ictx
);
453 expect_op_work_queue(mock_image_ctx
);
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
);
467 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
469 ASSERT_EQ(-ENOENT
, ctx
.wait());
472 TEST_F(TestMockMirrorDisableRequest
, JournalPromoteError
) {
473 librbd::ImageCtx
*ictx
;
474 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
476 MockTestImageCtx
mock_image_ctx(*ictx
);
477 MockJournalPromoteRequest mock_promote_request
;
479 expect_op_work_queue(mock_image_ctx
);
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);
491 expect_journal_promote(mock_image_ctx
, mock_promote_request
, -EPERM
);
494 auto req
= new MockDisableRequest(&mock_image_ctx
, true, true, &ctx
);
496 ASSERT_EQ(-EPERM
, ctx
.wait());
499 TEST_F(TestMockMirrorDisableRequest
, JournalClientListError
) {
500 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
502 librbd::ImageCtx
*ictx
;
503 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
505 MockTestImageCtx
mock_image_ctx(*ictx
);
507 expect_op_work_queue(mock_image_ctx
);
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);
519 expect_journal_client_list(mock_image_ctx
, {}, -EBADMSG
);
522 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
524 ASSERT_EQ(-EBADMSG
, ctx
.wait());
527 TEST_F(TestMockMirrorDisableRequest
, SnapRemoveError
) {
528 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
530 librbd::ImageCtx
*ictx
;
531 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
533 MockTestImageCtx
mock_image_ctx(*ictx
);
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
);
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);
549 expect_journal_client_list(
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)}}}
558 expect_journal_client_unregister(mock_image_ctx
, "peer 1", 0);
561 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
563 ASSERT_EQ(-EPERM
, ctx
.wait());
566 TEST_F(TestMockMirrorDisableRequest
, JournalClientUnregisterError
) {
567 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
569 librbd::ImageCtx
*ictx
;
570 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
572 MockTestImageCtx
mock_image_ctx(*ictx
);
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);
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);
588 expect_journal_client_list(
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)}}}
597 expect_journal_client_unregister(mock_image_ctx
, "peer 1", -EINVAL
);
598 expect_journal_client_unregister(mock_image_ctx
, "peer 2", 0);
601 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
603 ASSERT_EQ(-EINVAL
, ctx
.wait());
606 TEST_F(TestMockMirrorDisableRequest
, SnapshotPromoteError
) {
607 librbd::ImageCtx
*ictx
;
608 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
610 MockTestImageCtx
mock_image_ctx(*ictx
);
611 MockSnapshotPromoteRequest mock_promote_request
;
613 expect_op_work_queue(mock_image_ctx
);
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
);
628 auto req
= new MockDisableRequest(&mock_image_ctx
, true, true, &ctx
);
630 ASSERT_EQ(-EPERM
, ctx
.wait());
633 TEST_F(TestMockMirrorDisableRequest
, RefreshError
) {
634 librbd::ImageCtx
*ictx
;
635 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
637 MockTestImageCtx
mock_image_ctx(*ictx
);
638 MockSnapshotPromoteRequest mock_promote_request
;
640 expect_op_work_queue(mock_image_ctx
);
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
);
657 auto req
= new MockDisableRequest(&mock_image_ctx
, true, true, &ctx
);
659 ASSERT_EQ(-EPERM
, ctx
.wait());
662 TEST_F(TestMockMirrorDisableRequest
, MirrorImageRemoveError
) {
663 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
665 librbd::ImageCtx
*ictx
;
666 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
668 MockTestImageCtx
mock_image_ctx(*ictx
);
670 expect_op_work_queue(mock_image_ctx
);
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);
682 expect_journal_client_list(mock_image_ctx
, {}, 0);
683 MockImageRemoveRequest mock_image_remove_request
;
684 expect_mirror_image_remove(
685 mock_image_ctx
, mock_image_remove_request
, -EINVAL
);
688 auto req
= new MockDisableRequest(&mock_image_ctx
, false, true, &ctx
);
690 ASSERT_EQ(-EINVAL
, ctx
.wait());
693 } // namespace mirror
694 } // namespace librbd