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/MockContextWQ.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "librbd/ImageState.h"
11 #include "librbd/Operations.h"
12 #include "librbd/image/TypeTraits.h"
13 #include "librbd/image/AttachChildRequest.h"
14 #include "librbd/image/AttachParentRequest.h"
15 #include "librbd/image/CreateRequest.h"
16 #include "librbd/image/RemoveRequest.h"
17 #include "librbd/mirror/EnableRequest.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
24 struct MockTestImageCtx
: public MockImageCtx
{
25 static MockTestImageCtx
* s_instance
;
26 static MockTestImageCtx
* create(const std::string
&image_name
,
27 const std::string
&image_id
,
28 const char *snap
, librados::IoCtx
& p
,
30 ceph_assert(s_instance
!= nullptr);
33 static MockTestImageCtx
* create(const std::string
&image_name
,
34 const std::string
&image_id
,
35 librados::snap_t snap_id
, IoCtx
& p
,
37 ceph_assert(s_instance
!= nullptr);
41 MockTestImageCtx(ImageCtx
&image_ctx
) : MockImageCtx(image_ctx
) {
46 MockTestImageCtx
* MockTestImageCtx::s_instance
= nullptr;
48 } // anonymous namespace
53 struct AttachChildRequest
<MockTestImageCtx
> {
54 uint32_t clone_format
;
55 Context
* on_finish
= nullptr;
56 static AttachChildRequest
* s_instance
;
57 static AttachChildRequest
* create(MockTestImageCtx
*,
59 const librados::snap_t
&,
61 const librados::snap_t
&,
62 uint32_t clone_format
,
64 ceph_assert(s_instance
!= nullptr);
65 s_instance
->clone_format
= clone_format
;
66 s_instance
->on_finish
= on_finish
;
70 MOCK_METHOD0(send
, void());
72 AttachChildRequest() {
77 AttachChildRequest
<MockTestImageCtx
>* AttachChildRequest
<MockTestImageCtx
>::s_instance
= nullptr;
80 struct AttachParentRequest
<MockTestImageCtx
> {
81 Context
* on_finish
= nullptr;
82 static AttachParentRequest
* s_instance
;
83 static AttachParentRequest
* create(MockTestImageCtx
&,
84 const cls::rbd::ParentImageSpec
& pspec
,
85 uint64_t parent_overlap
, bool reattach
,
87 ceph_assert(s_instance
!= nullptr);
88 s_instance
->on_finish
= on_finish
;
92 MOCK_METHOD0(send
, void());
94 AttachParentRequest() {
99 AttachParentRequest
<MockTestImageCtx
>* AttachParentRequest
<MockTestImageCtx
>::s_instance
= nullptr;
102 struct CreateRequest
<MockTestImageCtx
> {
103 Context
* on_finish
= nullptr;
104 static CreateRequest
* s_instance
;
105 static CreateRequest
* create(const ConfigProxy
& config
, IoCtx
&ioctx
,
106 const std::string
&image_name
,
107 const std::string
&image_id
, uint64_t size
,
108 const ImageOptions
&image_options
,
109 const std::string
&non_primary_global_image_id
,
110 const std::string
&primary_mirror_uuid
,
111 bool skip_mirror_enable
,
112 ContextWQ
*op_work_queue
,
113 Context
*on_finish
) {
114 ceph_assert(s_instance
!= nullptr);
115 s_instance
->on_finish
= on_finish
;
119 MOCK_METHOD0(send
, void());
126 CreateRequest
<MockTestImageCtx
>* CreateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
129 struct RemoveRequest
<MockTestImageCtx
> {
130 Context
* on_finish
= nullptr;
131 static RemoveRequest
* s_instance
;
132 static RemoveRequest
* create(librados::IoCtx
&ioctx
,
133 const std::string
&image_name
,
134 const std::string
&image_id
,
135 bool force
, bool from_trash_remove
,
136 ProgressContext
&prog_ctx
,
137 ContextWQ
*op_work_queue
,
138 Context
*on_finish
) {
139 ceph_assert(s_instance
!= nullptr);
140 s_instance
->on_finish
= on_finish
;
144 MOCK_METHOD0(send
, void());
151 RemoveRequest
<MockTestImageCtx
>* RemoveRequest
<MockTestImageCtx
>::s_instance
= nullptr;
158 struct EnableRequest
<MockTestImageCtx
> {
159 Context
* on_finish
= nullptr;
160 static EnableRequest
* s_instance
;
161 static EnableRequest
* create(librados::IoCtx
&io_ctx
,
162 const std::string
&image_id
,
163 const std::string
&non_primary_global_image_id
,
164 MockContextWQ
*op_work_queue
,
165 Context
*on_finish
) {
166 ceph_assert(s_instance
!= nullptr);
167 s_instance
->on_finish
= on_finish
;
171 MOCK_METHOD0(send
, void());
178 EnableRequest
<MockTestImageCtx
>* EnableRequest
<MockTestImageCtx
>::s_instance
= nullptr;
180 } // namespace mirror
181 } // namespace librbd
183 // template definitions
184 #include "librbd/image/CloneRequest.cc"
190 using ::testing::Invoke
;
191 using ::testing::InSequence
;
192 using ::testing::Return
;
193 using ::testing::StrEq
;
194 using ::testing::WithArg
;
196 class TestMockImageCloneRequest
: public TestMockFixture
{
198 typedef CloneRequest
<MockTestImageCtx
> MockCloneRequest
;
199 typedef AttachChildRequest
<MockTestImageCtx
> MockAttachChildRequest
;
200 typedef AttachParentRequest
<MockTestImageCtx
> MockAttachParentRequest
;
201 typedef CreateRequest
<MockTestImageCtx
> MockCreateRequest
;
202 typedef RemoveRequest
<MockTestImageCtx
> MockRemoveRequest
;
203 typedef mirror::EnableRequest
<MockTestImageCtx
> MockMirrorEnableRequest
;
205 void SetUp() override
{
206 TestMockFixture::SetUp();
208 ASSERT_EQ(0, _rados
.conf_set("rbd_default_clone_format", "2"));
210 ASSERT_EQ(0, open_image(m_image_name
, &image_ctx
));
211 ASSERT_EQ(0, image_ctx
->operations
->snap_create(
212 cls::rbd::UserSnapshotNamespace
{}, "snap"));
213 if (is_feature_enabled(RBD_FEATURE_LAYERING
)) {
214 ASSERT_EQ(0, image_ctx
->operations
->snap_protect(
215 cls::rbd::UserSnapshotNamespace
{}, "snap"));
217 uint64_t snap_id
= image_ctx
->snap_ids
[
218 {cls::rbd::UserSnapshotNamespace
{}, "snap"}];
219 ASSERT_NE(CEPH_NOSNAP
, snap_id
);
222 image_ctx
->state
->snap_set(snap_id
, &ctx
);
223 ASSERT_EQ(0, ctx
.wait());
227 void expect_get_min_compat_client(int8_t min_compat_client
, int r
) {
228 auto mock_rados_client
= get_mock_io_ctx(m_ioctx
).get_mock_rados_client();
229 EXPECT_CALL(*mock_rados_client
, get_min_compatible_client(_
, _
))
230 .WillOnce(Invoke([min_compat_client
, r
](int8_t* min
, int8_t* required_min
) {
231 *min
= min_compat_client
;
232 *required_min
= min_compat_client
;
237 void expect_get_image_size(MockTestImageCtx
&mock_image_ctx
, uint64_t snap_id
,
239 EXPECT_CALL(mock_image_ctx
, get_image_size(snap_id
))
240 .WillOnce(Return(size
));
243 void expect_is_snap_protected(MockImageCtx
&mock_image_ctx
, bool is_protected
,
245 EXPECT_CALL(mock_image_ctx
, is_snap_protected(_
, _
))
246 .WillOnce(WithArg
<1>(Invoke([is_protected
, r
](bool* is_prot
) {
247 *is_prot
= is_protected
;
252 void expect_create(MockCreateRequest
& mock_create_request
, int r
) {
253 EXPECT_CALL(mock_create_request
, send())
254 .WillOnce(Invoke([this, &mock_create_request
, r
]() {
255 image_ctx
->op_work_queue
->queue(mock_create_request
.on_finish
, r
);
259 void expect_open(MockImageCtx
&mock_image_ctx
, int r
) {
260 EXPECT_CALL(*mock_image_ctx
.state
, open(true, _
))
261 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
262 image_ctx
->op_work_queue
->queue(ctx
, r
);
265 EXPECT_CALL(mock_image_ctx
, destroy());
269 void expect_attach_parent(MockAttachParentRequest
& mock_request
, int r
) {
270 EXPECT_CALL(mock_request
, send())
271 .WillOnce(Invoke([this, &mock_request
, r
]() {
272 image_ctx
->op_work_queue
->queue(mock_request
.on_finish
, r
);
276 void expect_attach_child(MockAttachChildRequest
& mock_request
,
277 uint32_t clone_format
, int r
) {
278 EXPECT_CALL(mock_request
, send())
279 .WillOnce(Invoke([this, &mock_request
, clone_format
, r
]() {
280 EXPECT_EQ(mock_request
.clone_format
, clone_format
);
281 image_ctx
->op_work_queue
->queue(mock_request
.on_finish
, r
);
285 void expect_metadata_list(MockTestImageCtx
&mock_image_ctx
,
286 const std::map
<std::string
, bufferlist
>& metadata
,
289 encode(metadata
, out_bl
);
291 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
292 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("metadata_list"), _
, _
, _
))
293 .WillOnce(WithArg
<5>(Invoke([out_bl
, r
](bufferlist
*out
) {
299 void expect_metadata_set(librados::IoCtx
& io_ctx
,
300 MockTestImageCtx
& mock_image_ctx
,
301 const std::map
<std::string
, bufferlist
>& metadata
,
304 encode(metadata
, in_bl
);
306 EXPECT_CALL(get_mock_io_ctx(io_ctx
),
307 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("metadata_set"),
308 ContentsEqual(in_bl
), _
, _
))
309 .WillOnce(Return(r
));
312 void expect_test_features(MockTestImageCtx
&mock_image_ctx
,
313 uint64_t features
, bool enabled
) {
314 EXPECT_CALL(mock_image_ctx
, test_features(features
))
315 .WillOnce(Return(enabled
));
318 void expect_mirror_mode_get(MockTestImageCtx
&mock_image_ctx
,
319 cls::rbd::MirrorMode mirror_mode
, int r
) {
321 encode(static_cast<uint32_t>(mirror_mode
), out_bl
);
323 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
324 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_mode_get"),
326 .WillOnce(WithArg
<5>(Invoke([out_bl
, r
](bufferlist
* out
) {
332 void expect_mirror_enable(MockMirrorEnableRequest
& mock_mirror_enable_request
,
334 EXPECT_CALL(mock_mirror_enable_request
, send())
335 .WillOnce(Invoke([this, &mock_mirror_enable_request
, r
]() {
336 image_ctx
->op_work_queue
->queue(mock_mirror_enable_request
.on_finish
, r
);
340 void expect_close(MockImageCtx
&mock_image_ctx
, int r
) {
341 EXPECT_CALL(*mock_image_ctx
.state
, close(_
))
342 .WillOnce(Invoke([this, r
](Context
* ctx
) {
343 image_ctx
->op_work_queue
->queue(ctx
, r
);
345 EXPECT_CALL(mock_image_ctx
, destroy());
348 void expect_remove(MockRemoveRequest
& mock_remove_request
, int r
) {
349 EXPECT_CALL(mock_remove_request
, send())
350 .WillOnce(Invoke([this, &mock_remove_request
, r
]() {
351 image_ctx
->op_work_queue
->queue(mock_remove_request
.on_finish
, r
);
355 librbd::ImageCtx
*image_ctx
;
358 TEST_F(TestMockImageCloneRequest
, SuccessV1
) {
359 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
360 ASSERT_EQ(0, _rados
.conf_set("rbd_default_clone_format", "1"));
362 MockTestImageCtx
mock_image_ctx(*image_ctx
);
363 expect_op_work_queue(mock_image_ctx
);
366 expect_open(mock_image_ctx
, 0);
368 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
369 expect_is_snap_protected(mock_image_ctx
, true, 0);
371 MockCreateRequest mock_create_request
;
372 expect_create(mock_create_request
, 0);
374 expect_open(mock_image_ctx
, 0);
376 MockAttachParentRequest mock_attach_parent_request
;
377 expect_attach_parent(mock_attach_parent_request
, 0);
379 MockAttachChildRequest mock_attach_child_request
;
380 expect_attach_child(mock_attach_child_request
, 1, 0);
382 expect_metadata_list(mock_image_ctx
, {{"key", {}}}, 0);
383 expect_metadata_set(m_ioctx
, mock_image_ctx
, {{"key", {}}}, 0);
385 MockMirrorEnableRequest mock_mirror_enable_request
;
386 if (is_feature_enabled(RBD_FEATURE_JOURNALING
)) {
387 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, true);
388 expect_mirror_mode_get(mock_image_ctx
, cls::rbd::MIRROR_MODE_POOL
, 0);
390 expect_mirror_enable(mock_mirror_enable_request
, 0);
392 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, false);
395 expect_close(mock_image_ctx
, 0);
396 expect_close(mock_image_ctx
, 0);
399 ImageOptions clone_opts
;
400 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
401 m_ioctx
, "clone name", "clone id", clone_opts
,
402 "", "", image_ctx
->op_work_queue
, &ctx
);
404 ASSERT_EQ(0, ctx
.wait());
407 TEST_F(TestMockImageCloneRequest
, SuccessV2
) {
408 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
409 ASSERT_EQ(0, _rados
.conf_set("rbd_default_clone_format", "2"));
411 MockTestImageCtx
mock_image_ctx(*image_ctx
);
412 expect_op_work_queue(mock_image_ctx
);
415 expect_open(mock_image_ctx
, 0);
417 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
418 expect_is_snap_protected(mock_image_ctx
, true, 0);
420 MockCreateRequest mock_create_request
;
421 expect_create(mock_create_request
, 0);
423 expect_open(mock_image_ctx
, 0);
425 MockAttachParentRequest mock_attach_parent_request
;
426 expect_attach_parent(mock_attach_parent_request
, 0);
428 MockAttachChildRequest mock_attach_child_request
;
429 expect_attach_child(mock_attach_child_request
, 2, 0);
431 expect_metadata_list(mock_image_ctx
, {{"key", {}}}, 0);
432 expect_metadata_set(m_ioctx
, mock_image_ctx
, {{"key", {}}}, 0);
434 MockMirrorEnableRequest mock_mirror_enable_request
;
435 if (is_feature_enabled(RBD_FEATURE_JOURNALING
)) {
436 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, true);
437 expect_mirror_mode_get(mock_image_ctx
, cls::rbd::MIRROR_MODE_POOL
, 0);
439 expect_mirror_enable(mock_mirror_enable_request
, 0);
441 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, false);
444 expect_close(mock_image_ctx
, 0);
445 expect_close(mock_image_ctx
, 0);
448 ImageOptions clone_opts
;
449 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
450 m_ioctx
, "clone name", "clone id", clone_opts
,
451 "", "", image_ctx
->op_work_queue
, &ctx
);
453 ASSERT_EQ(0, ctx
.wait());
456 TEST_F(TestMockImageCloneRequest
, SuccessAuto
) {
457 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
458 ASSERT_EQ(0, _rados
.conf_set("rbd_default_clone_format", "auto"));
460 MockTestImageCtx
mock_image_ctx(*image_ctx
);
461 expect_op_work_queue(mock_image_ctx
);
464 expect_open(mock_image_ctx
, 0);
466 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
467 expect_is_snap_protected(mock_image_ctx
, true, 0);
469 MockCreateRequest mock_create_request
;
470 expect_create(mock_create_request
, 0);
472 expect_open(mock_image_ctx
, 0);
474 MockAttachParentRequest mock_attach_parent_request
;
475 expect_attach_parent(mock_attach_parent_request
, 0);
477 MockAttachChildRequest mock_attach_child_request
;
478 expect_attach_child(mock_attach_child_request
, 2, 0);
480 expect_metadata_list(mock_image_ctx
, {{"key", {}}}, 0);
481 expect_metadata_set(m_ioctx
, mock_image_ctx
, {{"key", {}}}, 0);
483 MockMirrorEnableRequest mock_mirror_enable_request
;
484 if (is_feature_enabled(RBD_FEATURE_JOURNALING
)) {
485 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, true);
486 expect_mirror_mode_get(mock_image_ctx
, cls::rbd::MIRROR_MODE_POOL
, 0);
488 expect_mirror_enable(mock_mirror_enable_request
, 0);
490 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, false);
493 expect_close(mock_image_ctx
, 0);
494 expect_close(mock_image_ctx
, 0);
497 ImageOptions clone_opts
;
498 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
499 m_ioctx
, "clone name", "clone id", clone_opts
,
500 "", "", image_ctx
->op_work_queue
, &ctx
);
502 ASSERT_EQ(0, ctx
.wait());
505 TEST_F(TestMockImageCloneRequest
, OpenParentError
) {
506 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
508 MockTestImageCtx
mock_image_ctx(*image_ctx
);
509 expect_op_work_queue(mock_image_ctx
);
512 expect_open(mock_image_ctx
, -EINVAL
);
515 ImageOptions clone_opts
;
516 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
517 m_ioctx
, "clone name", "clone id", clone_opts
,
518 "", "", image_ctx
->op_work_queue
, &ctx
);
520 ASSERT_EQ(-EINVAL
, ctx
.wait());
523 TEST_F(TestMockImageCloneRequest
, CreateError
) {
524 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
526 MockTestImageCtx
mock_image_ctx(*image_ctx
);
527 expect_op_work_queue(mock_image_ctx
);
530 expect_open(mock_image_ctx
, 0);
532 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
533 expect_is_snap_protected(mock_image_ctx
, true, 0);
535 MockCreateRequest mock_create_request
;
536 expect_create(mock_create_request
, -EINVAL
);
538 expect_close(mock_image_ctx
, 0);
541 ImageOptions clone_opts
;
542 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
543 m_ioctx
, "clone name", "clone id", clone_opts
,
544 "", "", image_ctx
->op_work_queue
, &ctx
);
546 ASSERT_EQ(-EINVAL
, ctx
.wait());
549 TEST_F(TestMockImageCloneRequest
, OpenError
) {
550 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
552 MockTestImageCtx
mock_image_ctx(*image_ctx
);
553 expect_op_work_queue(mock_image_ctx
);
556 expect_open(mock_image_ctx
, 0);
558 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
559 expect_is_snap_protected(mock_image_ctx
, true, 0);
561 MockCreateRequest mock_create_request
;
562 expect_create(mock_create_request
, 0);
564 expect_open(mock_image_ctx
, -EINVAL
);
566 MockRemoveRequest mock_remove_request
;
567 expect_remove(mock_remove_request
, 0);
569 expect_close(mock_image_ctx
, 0);
572 ImageOptions clone_opts
;
573 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
574 m_ioctx
, "clone name", "clone id", clone_opts
,
575 "", "", image_ctx
->op_work_queue
, &ctx
);
577 ASSERT_EQ(-EINVAL
, ctx
.wait());
580 TEST_F(TestMockImageCloneRequest
, AttachParentError
) {
581 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
583 MockTestImageCtx
mock_image_ctx(*image_ctx
);
584 expect_op_work_queue(mock_image_ctx
);
587 expect_open(mock_image_ctx
, 0);
589 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
590 expect_is_snap_protected(mock_image_ctx
, true, 0);
592 MockCreateRequest mock_create_request
;
593 expect_create(mock_create_request
, 0);
595 expect_open(mock_image_ctx
, 0);
597 MockAttachParentRequest mock_attach_parent_request
;
598 expect_attach_parent(mock_attach_parent_request
, -EINVAL
);
600 expect_close(mock_image_ctx
, 0);
602 MockRemoveRequest mock_remove_request
;
603 expect_remove(mock_remove_request
, 0);
605 expect_close(mock_image_ctx
, 0);
608 ImageOptions clone_opts
;
609 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
610 m_ioctx
, "clone name", "clone id", clone_opts
,
611 "", "", image_ctx
->op_work_queue
, &ctx
);
613 ASSERT_EQ(-EINVAL
, ctx
.wait());
616 TEST_F(TestMockImageCloneRequest
, AttachChildError
) {
617 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
619 MockTestImageCtx
mock_image_ctx(*image_ctx
);
620 expect_op_work_queue(mock_image_ctx
);
623 expect_open(mock_image_ctx
, 0);
625 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
626 expect_is_snap_protected(mock_image_ctx
, true, 0);
628 MockCreateRequest mock_create_request
;
629 expect_create(mock_create_request
, 0);
631 expect_open(mock_image_ctx
, 0);
633 MockAttachParentRequest mock_attach_parent_request
;
634 expect_attach_parent(mock_attach_parent_request
, 0);
636 MockAttachChildRequest mock_attach_child_request
;
637 expect_attach_child(mock_attach_child_request
, 2, -EINVAL
);
639 expect_close(mock_image_ctx
, 0);
641 MockRemoveRequest mock_remove_request
;
642 expect_remove(mock_remove_request
, 0);
644 expect_close(mock_image_ctx
, 0);
647 ImageOptions clone_opts
;
648 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
649 m_ioctx
, "clone name", "clone id", clone_opts
,
650 "", "", image_ctx
->op_work_queue
, &ctx
);
652 ASSERT_EQ(-EINVAL
, ctx
.wait());
655 TEST_F(TestMockImageCloneRequest
, MetadataListError
) {
656 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
658 MockTestImageCtx
mock_image_ctx(*image_ctx
);
659 expect_op_work_queue(mock_image_ctx
);
662 expect_open(mock_image_ctx
, 0);
664 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
665 expect_is_snap_protected(mock_image_ctx
, true, 0);
667 MockCreateRequest mock_create_request
;
668 expect_create(mock_create_request
, 0);
670 expect_open(mock_image_ctx
, 0);
672 MockAttachParentRequest mock_attach_parent_request
;
673 expect_attach_parent(mock_attach_parent_request
, 0);
675 MockAttachChildRequest mock_attach_child_request
;
676 expect_attach_child(mock_attach_child_request
, 2, 0);
678 expect_metadata_list(mock_image_ctx
, {{"key", {}}}, -EINVAL
);
680 expect_close(mock_image_ctx
, 0);
682 MockRemoveRequest mock_remove_request
;
683 expect_remove(mock_remove_request
, 0);
685 expect_close(mock_image_ctx
, 0);
688 ImageOptions clone_opts
;
689 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
690 m_ioctx
, "clone name", "clone id", clone_opts
,
691 "", "", image_ctx
->op_work_queue
, &ctx
);
693 ASSERT_EQ(-EINVAL
, ctx
.wait());
696 TEST_F(TestMockImageCloneRequest
, MetadataSetError
) {
697 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
699 MockTestImageCtx
mock_image_ctx(*image_ctx
);
700 expect_op_work_queue(mock_image_ctx
);
703 expect_open(mock_image_ctx
, 0);
705 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
706 expect_is_snap_protected(mock_image_ctx
, true, 0);
708 MockCreateRequest mock_create_request
;
709 expect_create(mock_create_request
, 0);
711 expect_open(mock_image_ctx
, 0);
713 MockAttachParentRequest mock_attach_parent_request
;
714 expect_attach_parent(mock_attach_parent_request
, 0);
716 MockAttachChildRequest mock_attach_child_request
;
717 expect_attach_child(mock_attach_child_request
, 2, 0);
719 expect_metadata_list(mock_image_ctx
, {{"key", {}}}, 0);
720 expect_metadata_set(m_ioctx
, mock_image_ctx
, {{"key", {}}}, -EINVAL
);
722 expect_close(mock_image_ctx
, 0);
724 MockRemoveRequest mock_remove_request
;
725 expect_remove(mock_remove_request
, 0);
727 expect_close(mock_image_ctx
, 0);
730 ImageOptions clone_opts
;
731 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
732 m_ioctx
, "clone name", "clone id", clone_opts
,
733 "", "", image_ctx
->op_work_queue
, &ctx
);
735 ASSERT_EQ(-EINVAL
, ctx
.wait());
738 TEST_F(TestMockImageCloneRequest
, GetMirrorModeError
) {
739 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_JOURNALING
);
741 MockTestImageCtx
mock_image_ctx(*image_ctx
);
742 expect_op_work_queue(mock_image_ctx
);
745 expect_open(mock_image_ctx
, 0);
747 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
748 expect_is_snap_protected(mock_image_ctx
, true, 0);
750 MockCreateRequest mock_create_request
;
751 expect_create(mock_create_request
, 0);
753 expect_open(mock_image_ctx
, 0);
755 MockAttachParentRequest mock_attach_parent_request
;
756 expect_attach_parent(mock_attach_parent_request
, 0);
758 MockAttachChildRequest mock_attach_child_request
;
759 expect_attach_child(mock_attach_child_request
, 2, 0);
761 expect_metadata_list(mock_image_ctx
, {}, 0);
763 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, true);
764 expect_mirror_mode_get(mock_image_ctx
, cls::rbd::MIRROR_MODE_POOL
, -EINVAL
);
766 expect_close(mock_image_ctx
, 0);
768 MockRemoveRequest mock_remove_request
;
769 expect_remove(mock_remove_request
, 0);
771 expect_close(mock_image_ctx
, 0);
774 ImageOptions clone_opts
;
775 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
776 m_ioctx
, "clone name", "clone id", clone_opts
,
777 "", "", image_ctx
->op_work_queue
, &ctx
);
779 ASSERT_EQ(-EINVAL
, ctx
.wait());
782 TEST_F(TestMockImageCloneRequest
, MirrorEnableError
) {
783 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
| RBD_FEATURE_JOURNALING
);
785 MockTestImageCtx
mock_image_ctx(*image_ctx
);
786 expect_op_work_queue(mock_image_ctx
);
789 expect_open(mock_image_ctx
, 0);
791 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
792 expect_is_snap_protected(mock_image_ctx
, true, 0);
794 MockCreateRequest mock_create_request
;
795 expect_create(mock_create_request
, 0);
797 expect_open(mock_image_ctx
, 0);
799 MockAttachParentRequest mock_attach_parent_request
;
800 expect_attach_parent(mock_attach_parent_request
, 0);
802 MockAttachChildRequest mock_attach_child_request
;
803 expect_attach_child(mock_attach_child_request
, 2, 0);
805 expect_metadata_list(mock_image_ctx
, {}, 0);
807 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, true);
808 expect_mirror_mode_get(mock_image_ctx
, cls::rbd::MIRROR_MODE_POOL
, 0);
810 MockMirrorEnableRequest mock_mirror_enable_request
;
811 expect_mirror_enable(mock_mirror_enable_request
, -EINVAL
);
813 expect_close(mock_image_ctx
, 0);
815 MockRemoveRequest mock_remove_request
;
816 expect_remove(mock_remove_request
, 0);
818 expect_close(mock_image_ctx
, 0);
821 ImageOptions clone_opts
;
822 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
823 m_ioctx
, "clone name", "clone id", clone_opts
,
824 "", "", image_ctx
->op_work_queue
, &ctx
);
826 ASSERT_EQ(-EINVAL
, ctx
.wait());
829 TEST_F(TestMockImageCloneRequest
, CloseError
) {
830 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
832 MockTestImageCtx
mock_image_ctx(*image_ctx
);
833 expect_op_work_queue(mock_image_ctx
);
836 expect_open(mock_image_ctx
, 0);
838 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
839 expect_is_snap_protected(mock_image_ctx
, true, 0);
841 MockCreateRequest mock_create_request
;
842 expect_create(mock_create_request
, 0);
844 expect_open(mock_image_ctx
, 0);
846 MockAttachParentRequest mock_attach_parent_request
;
847 expect_attach_parent(mock_attach_parent_request
, 0);
849 MockAttachChildRequest mock_attach_child_request
;
850 expect_attach_child(mock_attach_child_request
, 2, 0);
852 expect_metadata_list(mock_image_ctx
, {}, 0);
853 expect_test_features(mock_image_ctx
, RBD_FEATURE_JOURNALING
, false);
855 expect_close(mock_image_ctx
, -EINVAL
);
857 MockRemoveRequest mock_remove_request
;
858 expect_remove(mock_remove_request
, 0);
860 expect_close(mock_image_ctx
, 0);
863 ImageOptions clone_opts
;
864 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
865 m_ioctx
, "clone name", "clone id", clone_opts
,
866 "", "", image_ctx
->op_work_queue
, &ctx
);
868 ASSERT_EQ(-EINVAL
, ctx
.wait());
871 TEST_F(TestMockImageCloneRequest
, RemoveError
) {
872 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
874 MockTestImageCtx
mock_image_ctx(*image_ctx
);
875 expect_op_work_queue(mock_image_ctx
);
878 expect_open(mock_image_ctx
, 0);
880 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
881 expect_is_snap_protected(mock_image_ctx
, true, 0);
883 MockCreateRequest mock_create_request
;
884 expect_create(mock_create_request
, 0);
886 expect_open(mock_image_ctx
, -EINVAL
);
888 MockRemoveRequest mock_remove_request
;
889 expect_remove(mock_remove_request
, -EPERM
);
891 expect_close(mock_image_ctx
, 0);
894 ImageOptions clone_opts
;
895 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
896 m_ioctx
, "clone name", "clone id", clone_opts
,
897 "", "", image_ctx
->op_work_queue
, &ctx
);
899 ASSERT_EQ(-EINVAL
, ctx
.wait());
902 TEST_F(TestMockImageCloneRequest
, CloseParentError
) {
903 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
905 MockTestImageCtx
mock_image_ctx(*image_ctx
);
906 expect_op_work_queue(mock_image_ctx
);
909 expect_open(mock_image_ctx
, 0);
911 expect_get_image_size(mock_image_ctx
, mock_image_ctx
.snaps
.front(), 123);
912 expect_is_snap_protected(mock_image_ctx
, true, 0);
914 MockCreateRequest mock_create_request
;
915 expect_create(mock_create_request
, 0);
917 expect_open(mock_image_ctx
, -EINVAL
);
919 MockRemoveRequest mock_remove_request
;
920 expect_remove(mock_remove_request
, 0);
922 expect_close(mock_image_ctx
, -EPERM
);
925 ImageOptions clone_opts
;
926 auto req
= new MockCloneRequest(m_cct
->_conf
, m_ioctx
, "parent id", "", 123,
927 m_ioctx
, "clone name", "clone id", clone_opts
,
928 "", "", image_ctx
->op_work_queue
, &ctx
);
930 ASSERT_EQ(-EINVAL
, ctx
.wait());
934 } // namespace librbd