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/MockOperations.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "librbd/mirror/snapshot/CreateNonPrimaryRequest.h"
11 #include "librbd/mirror/snapshot/Utils.h"
12 #include "librbd/mirror/snapshot/WriteImageStateRequest.h"
18 struct MockTestImageCtx
: public MockImageCtx
{
19 explicit MockTestImageCtx(librbd::ImageCtx
& image_ctx
) : MockImageCtx(image_ctx
) {
23 } // anonymous namespace
32 static Mock
* s_instance
;
38 MOCK_METHOD1(can_create_non_primary_snapshot
,
39 bool(librbd::MockTestImageCtx
*));
42 Mock
*Mock::s_instance
= nullptr;
44 } // anonymous namespace
46 template<> bool can_create_non_primary_snapshot(
47 librbd::MockTestImageCtx
*image_ctx
) {
48 return Mock::s_instance
->can_create_non_primary_snapshot(image_ctx
);
54 struct WriteImageStateRequest
<MockTestImageCtx
> {
55 uint64_t snap_id
= CEPH_NOSNAP
;
56 ImageState image_state
;
57 Context
* on_finish
= nullptr;
58 static WriteImageStateRequest
* s_instance
;
59 static WriteImageStateRequest
*create(MockTestImageCtx
*image_ctx
,
61 const ImageState
&image_state
,
63 ceph_assert(s_instance
!= nullptr);
64 s_instance
->snap_id
= snap_id
;
65 s_instance
->image_state
= image_state
;
66 s_instance
->on_finish
= on_finish
;
70 MOCK_METHOD0(send
, void());
72 WriteImageStateRequest() {
77 WriteImageStateRequest
<MockTestImageCtx
>* WriteImageStateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
79 } // namespace snapshot
83 // template definitions
84 #include "librbd/mirror/snapshot/CreateNonPrimaryRequest.cc"
85 template class librbd::mirror::snapshot::CreateNonPrimaryRequest
<librbd::MockTestImageCtx
>;
92 using ::testing::DoAll
;
93 using ::testing::InSequence
;
94 using ::testing::Invoke
;
95 using ::testing::Return
;
96 using ::testing::StrEq
;
97 using ::testing::WithArg
;
99 class TestMockMirrorSnapshotCreateNonPrimaryRequest
: public TestMockFixture
{
101 typedef CreateNonPrimaryRequest
<MockTestImageCtx
> MockCreateNonPrimaryRequest
;
102 typedef WriteImageStateRequest
<MockTestImageCtx
> MockWriteImageStateRequest
;
103 typedef util::Mock MockUtils
;
105 void expect_clone_md_ctx(MockTestImageCtx
&mock_image_ctx
) {
106 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
), clone())
107 .WillOnce(Invoke([&mock_image_ctx
]() {
108 get_mock_io_ctx(mock_image_ctx
.md_ctx
).get();
109 return &get_mock_io_ctx(mock_image_ctx
.md_ctx
);
113 void expect_refresh_image(MockTestImageCtx
&mock_image_ctx
,
114 bool refresh_required
, int r
) {
115 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
116 .WillOnce(Return(refresh_required
));
117 if (refresh_required
) {
118 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
119 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
123 void expect_get_mirror_image(MockTestImageCtx
&mock_image_ctx
,
124 const cls::rbd::MirrorImage
&mirror_image
,
128 encode(mirror_image
, bl
);
130 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
131 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_image_get"),
133 .WillOnce(DoAll(WithArg
<5>(CopyInBufferlist(bl
)),
137 void expect_can_create_non_primary_snapshot(MockUtils
&mock_utils
,
139 EXPECT_CALL(mock_utils
, can_create_non_primary_snapshot(_
))
140 .WillOnce(Return(result
));
143 void expect_get_mirror_peers(MockTestImageCtx
&mock_image_ctx
,
144 const std::vector
<cls::rbd::MirrorPeer
> &peers
,
150 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
151 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_peer_list"),
153 .WillOnce(DoAll(WithArg
<5>(CopyInBufferlist(bl
)),
157 void expect_create_snapshot(MockTestImageCtx
&mock_image_ctx
, int r
) {
158 EXPECT_CALL(*mock_image_ctx
.operations
, snap_create(_
, _
, _
))
159 .WillOnce(WithArg
<2>(CompleteContext(
160 r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
163 void expect_write_image_state(
164 MockTestImageCtx
&mock_image_ctx
,
165 MockWriteImageStateRequest
&mock_write_image_state_request
, int r
) {
166 EXPECT_CALL(mock_image_ctx
, get_snap_id(_
, _
))
167 .WillOnce(Return(123));
168 EXPECT_CALL(mock_write_image_state_request
, send())
169 .WillOnce(Invoke([&mock_image_ctx
, &mock_write_image_state_request
, r
]() {
170 mock_image_ctx
.image_ctx
->op_work_queue
->queue(
171 mock_write_image_state_request
.on_finish
, r
);
176 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, Success
) {
179 librbd::ImageCtx
*ictx
;
180 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
182 MockTestImageCtx
mock_image_ctx(*ictx
);
186 expect_refresh_image(mock_image_ctx
, true, 0);
187 expect_get_mirror_image(
188 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
189 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
190 MockUtils mock_utils
;
191 expect_can_create_non_primary_snapshot(mock_utils
, true);
192 expect_create_snapshot(mock_image_ctx
, 0);
193 MockWriteImageStateRequest mock_write_image_state_request
;
194 expect_write_image_state(mock_image_ctx
, mock_write_image_state_request
, 0);
197 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
198 "mirror_uuid", 123, {{1, 2}}, {},
201 ASSERT_EQ(0, ctx
.wait());
204 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, SuccessDemoted
) {
207 librbd::ImageCtx
*ictx
;
208 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
210 MockTestImageCtx
mock_image_ctx(*ictx
);
214 expect_clone_md_ctx(mock_image_ctx
);
215 expect_refresh_image(mock_image_ctx
, true, 0);
216 expect_get_mirror_image(
217 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
218 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
219 MockUtils mock_utils
;
220 expect_can_create_non_primary_snapshot(mock_utils
, true);
221 expect_get_mirror_peers(mock_image_ctx
,
222 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
223 "mirror", "mirror uuid"}}, 0);
224 expect_create_snapshot(mock_image_ctx
, 0);
225 MockWriteImageStateRequest mock_write_image_state_request
;
226 expect_write_image_state(mock_image_ctx
, mock_write_image_state_request
, 0);
229 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, true,
230 "mirror_uuid", 123, {{1, 2}}, {},
233 ASSERT_EQ(0, ctx
.wait());
236 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, RefreshError
) {
239 librbd::ImageCtx
*ictx
;
240 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
242 MockTestImageCtx
mock_image_ctx(*ictx
);
246 expect_refresh_image(mock_image_ctx
, true, -EINVAL
);
249 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
250 "mirror_uuid", 123, {{1, 2}}, {},
253 ASSERT_EQ(-EINVAL
, ctx
.wait());
256 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, GetMirrorImageError
) {
259 librbd::ImageCtx
*ictx
;
260 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
262 MockTestImageCtx
mock_image_ctx(*ictx
);
266 expect_refresh_image(mock_image_ctx
, false, 0);
267 expect_get_mirror_image(
268 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
269 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, -EINVAL
);
272 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
273 "mirror_uuid", 123, {{1, 2}}, {},
276 ASSERT_EQ(-EINVAL
, ctx
.wait());
279 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, CanNotError
) {
282 librbd::ImageCtx
*ictx
;
283 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
285 MockTestImageCtx
mock_image_ctx(*ictx
);
289 expect_refresh_image(mock_image_ctx
, false, 0);
290 expect_get_mirror_image(
291 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
292 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
293 MockUtils mock_utils
;
294 expect_can_create_non_primary_snapshot(mock_utils
, false);
297 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
298 "mirror_uuid", 123, {{1, 2}}, {},
301 ASSERT_EQ(-EINVAL
, ctx
.wait());
304 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, GetMirrorPeersError
) {
307 librbd::ImageCtx
*ictx
;
308 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
310 MockTestImageCtx
mock_image_ctx(*ictx
);
314 expect_clone_md_ctx(mock_image_ctx
);
315 expect_refresh_image(mock_image_ctx
, true, 0);
316 expect_get_mirror_image(
317 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
318 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
319 MockUtils mock_utils
;
320 expect_can_create_non_primary_snapshot(mock_utils
, true);
321 expect_get_mirror_peers(mock_image_ctx
, {}, -EPERM
);
324 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, true,
325 "mirror_uuid", 123, {{1, 2}}, {},
328 ASSERT_EQ(-EPERM
, ctx
.wait());
331 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, CreateSnapshotError
) {
334 librbd::ImageCtx
*ictx
;
335 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
337 MockTestImageCtx
mock_image_ctx(*ictx
);
341 expect_refresh_image(mock_image_ctx
, true, 0);
342 expect_get_mirror_image(
343 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
344 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
345 MockUtils mock_utils
;
346 expect_can_create_non_primary_snapshot(mock_utils
, true);
347 expect_create_snapshot(mock_image_ctx
, -EINVAL
);
350 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
351 "mirror_uuid", 123, {{1, 2}}, {},
354 ASSERT_EQ(-EINVAL
, ctx
.wait());
357 TEST_F(TestMockMirrorSnapshotCreateNonPrimaryRequest
, WriteImageStateError
) {
360 librbd::ImageCtx
*ictx
;
361 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
363 MockTestImageCtx
mock_image_ctx(*ictx
);
367 expect_refresh_image(mock_image_ctx
, true, 0);
368 expect_get_mirror_image(
369 mock_image_ctx
, {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
, "gid",
370 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
}, 0);
371 MockUtils mock_utils
;
372 expect_can_create_non_primary_snapshot(mock_utils
, true);
373 expect_create_snapshot(mock_image_ctx
, 0);
374 MockWriteImageStateRequest mock_write_image_state_request
;
375 expect_write_image_state(mock_image_ctx
, mock_write_image_state_request
,
379 auto req
= new MockCreateNonPrimaryRequest(&mock_image_ctx
, false,
380 "mirror_uuid", 123, {{1, 2}}, {},
383 ASSERT_EQ(-EINVAL
, ctx
.wait());
386 } // namespace snapshot
387 } // namespace mirror
388 } // namespace librbd