1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "cls/rbd/cls_rbd_types.h"
6 #include "librbd/journal/TypeTraits.h"
7 #include "librbd/mirror/GetInfoRequest.h"
8 #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
9 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
10 #include "tools/rbd_mirror/image_replayer/StateBuilder.h"
11 #include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
12 #include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h"
13 #include "test/journal/mock/MockJournaler.h"
14 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
15 #include "test/librbd/mock/MockImageCtx.h"
16 #include "test/librbd/mock/MockJournal.h"
22 struct MockTestImageCtx
: public librbd::MockImageCtx
{
23 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
24 : librbd::MockImageCtx(image_ctx
) {
28 } // anonymous namespace
33 struct GetInfoRequest
<librbd::MockTestImageCtx
> {
34 static GetInfoRequest
* s_instance
;
35 cls::rbd::MirrorImage
*mirror_image
;
36 PromotionState
*promotion_state
;
37 std::string
*primary_mirror_uuid
;
38 Context
*on_finish
= nullptr;
40 static GetInfoRequest
* create(librados::IoCtx
& io_ctx
,
41 librbd::asio::ContextWQ
* context_wq
,
42 const std::string
& image_id
,
43 cls::rbd::MirrorImage
*mirror_image
,
44 PromotionState
*promotion_state
,
45 std::string
* primary_mirror_uuid
,
47 ceph_assert(s_instance
!= nullptr);
48 s_instance
->mirror_image
= mirror_image
;
49 s_instance
->promotion_state
= promotion_state
;
50 s_instance
->primary_mirror_uuid
= primary_mirror_uuid
;
51 s_instance
->on_finish
= on_finish
;
56 ceph_assert(s_instance
== nullptr);
63 MOCK_METHOD0(send
, void());
66 GetInfoRequest
<librbd::MockTestImageCtx
>* GetInfoRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
73 namespace image_replayer
{
76 struct GetMirrorImageIdRequest
<librbd::MockTestImageCtx
> {
77 static GetMirrorImageIdRequest
* s_instance
;
78 std::string
* image_id
= nullptr;
79 Context
* on_finish
= nullptr;
81 static GetMirrorImageIdRequest
* create(librados::IoCtx
& io_ctx
,
82 const std::string
& global_image_id
,
83 std::string
* image_id
,
85 ceph_assert(s_instance
!= nullptr);
86 s_instance
->image_id
= image_id
;
87 s_instance
->on_finish
= on_finish
;
91 GetMirrorImageIdRequest() {
95 MOCK_METHOD0(send
, void());
99 struct StateBuilder
<librbd::MockTestImageCtx
> {
100 virtual ~StateBuilder() {}
102 std::string local_image_id
;
103 librbd::mirror::PromotionState local_promotion_state
;
106 GetMirrorImageIdRequest
<librbd::MockTestImageCtx
>* GetMirrorImageIdRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
111 struct StateBuilder
<librbd::MockTestImageCtx
>
112 : public image_replayer::StateBuilder
<librbd::MockTestImageCtx
> {
113 static StateBuilder
* s_instance
;
115 cls::rbd::MirrorImageMode mirror_image_mode
=
116 cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
;
118 std::string local_primary_mirror_uuid
;
120 static StateBuilder
* create(const std::string
&) {
121 ceph_assert(s_instance
!= nullptr);
130 StateBuilder
<librbd::MockTestImageCtx
>* StateBuilder
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
132 } // namespace journal
137 struct StateBuilder
<librbd::MockTestImageCtx
>
138 : public image_replayer::StateBuilder
<librbd::MockTestImageCtx
> {
139 static StateBuilder
* s_instance
;
141 cls::rbd::MirrorImageMode mirror_image_mode
=
142 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
;
144 static StateBuilder
* create(const std::string
&) {
145 ceph_assert(s_instance
!= nullptr);
154 StateBuilder
<librbd::MockTestImageCtx
>* StateBuilder
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
156 } // namespace snapshot
157 } // namespace image_replayer
158 } // namespace mirror
161 // template definitions
162 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc"
166 namespace image_replayer
{
169 using ::testing::DoAll
;
170 using ::testing::InSequence
;
171 using ::testing::Invoke
;
172 using ::testing::Return
;
173 using ::testing::StrEq
;
174 using ::testing::WithArg
;
175 using ::testing::WithArgs
;
177 class TestMockImageReplayerPrepareLocalImageRequest
: public TestMockFixture
{
179 typedef PrepareLocalImageRequest
<librbd::MockTestImageCtx
> MockPrepareLocalImageRequest
;
180 typedef GetMirrorImageIdRequest
<librbd::MockTestImageCtx
> MockGetMirrorImageIdRequest
;
181 typedef StateBuilder
<librbd::MockTestImageCtx
> MockStateBuilder
;
182 typedef journal::StateBuilder
<librbd::MockTestImageCtx
> MockJournalStateBuilder
;
183 typedef snapshot::StateBuilder
<librbd::MockTestImageCtx
> MockSnapshotStateBuilder
;
184 typedef librbd::mirror::GetInfoRequest
<librbd::MockTestImageCtx
> MockGetMirrorInfoRequest
;
186 void expect_get_mirror_image_id(MockGetMirrorImageIdRequest
& mock_get_mirror_image_id_request
,
187 const std::string
& image_id
, int r
) {
188 EXPECT_CALL(mock_get_mirror_image_id_request
, send())
189 .WillOnce(Invoke([&mock_get_mirror_image_id_request
, image_id
, r
]() {
190 *mock_get_mirror_image_id_request
.image_id
= image_id
;
191 mock_get_mirror_image_id_request
.on_finish
->complete(r
);
195 void expect_dir_get_name(librados::IoCtx
&io_ctx
,
196 const std::string
&image_name
, int r
) {
198 encode(image_name
, bl
);
200 EXPECT_CALL(get_mock_io_ctx(io_ctx
),
201 exec(RBD_DIRECTORY
, _
, StrEq("rbd"), StrEq("dir_get_name"), _
,
203 .WillOnce(DoAll(WithArg
<5>(Invoke([bl
](bufferlist
*out_bl
) {
209 void expect_get_mirror_info(
210 MockGetMirrorInfoRequest
&mock_get_mirror_info_request
,
211 const cls::rbd::MirrorImage
&mirror_image
,
212 librbd::mirror::PromotionState promotion_state
,
213 const std::string
& primary_mirror_uuid
, int r
) {
214 EXPECT_CALL(mock_get_mirror_info_request
, send())
215 .WillOnce(Invoke([this, &mock_get_mirror_info_request
, mirror_image
,
216 promotion_state
, primary_mirror_uuid
, r
]() {
217 *mock_get_mirror_info_request
.mirror_image
= mirror_image
;
218 *mock_get_mirror_info_request
.promotion_state
= promotion_state
;
219 *mock_get_mirror_info_request
.primary_mirror_uuid
=
221 m_threads
->work_queue
->queue(
222 mock_get_mirror_info_request
.on_finish
, r
);
227 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, SuccessJournal
) {
229 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
230 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "local image id",
232 expect_dir_get_name(m_local_io_ctx
, "local image name", 0);
234 MockGetMirrorInfoRequest mock_get_mirror_info_request
;
235 expect_get_mirror_info(mock_get_mirror_info_request
,
236 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
,
238 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
},
239 librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
240 "remote mirror uuid", 0);
242 MockJournalStateBuilder mock_journal_state_builder
;
243 MockStateBuilder
* mock_state_builder
= nullptr;
244 std::string local_image_name
;
246 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
250 m_threads
->work_queue
,
254 ASSERT_EQ(0, ctx
.wait());
255 ASSERT_TRUE(mock_state_builder
!= nullptr);
256 ASSERT_EQ(std::string("local image name"), local_image_name
);
257 ASSERT_EQ(std::string("local image id"),
258 mock_journal_state_builder
.local_image_id
);
259 ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
,
260 mock_journal_state_builder
.mirror_image_mode
);
261 ASSERT_EQ(librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
262 mock_journal_state_builder
.local_promotion_state
);
263 ASSERT_EQ(std::string("remote mirror uuid"),
264 mock_journal_state_builder
.local_primary_mirror_uuid
);
267 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, SuccessSnapshot
) {
269 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
270 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "local image id",
272 expect_dir_get_name(m_local_io_ctx
, "local image name", 0);
274 MockGetMirrorInfoRequest mock_get_mirror_info_request
;
275 expect_get_mirror_info(mock_get_mirror_info_request
,
276 {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
,
278 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
},
279 librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
280 "remote mirror uuid", 0);
282 MockSnapshotStateBuilder mock_journal_state_builder
;
283 MockStateBuilder
* mock_state_builder
= nullptr;
284 std::string local_image_name
;
286 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
290 m_threads
->work_queue
,
294 ASSERT_EQ(0, ctx
.wait());
295 ASSERT_TRUE(mock_state_builder
!= nullptr);
296 ASSERT_EQ(std::string("local image name"), local_image_name
);
297 ASSERT_EQ(std::string("local image id"),
298 mock_journal_state_builder
.local_image_id
);
299 ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
,
300 mock_journal_state_builder
.mirror_image_mode
);
301 ASSERT_EQ(librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
302 mock_journal_state_builder
.local_promotion_state
);
305 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, MirrorImageIdError
) {
307 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
308 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "", -EINVAL
);
310 MockStateBuilder
* mock_state_builder
= nullptr;
311 std::string local_image_name
;
313 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
317 m_threads
->work_queue
,
321 ASSERT_EQ(-EINVAL
, ctx
.wait());
324 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, DirGetNameDNE
) {
326 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
327 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "local image id",
329 expect_dir_get_name(m_local_io_ctx
, "", -ENOENT
);
331 MockGetMirrorInfoRequest mock_get_mirror_info_request
;
332 expect_get_mirror_info(mock_get_mirror_info_request
,
333 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
,
335 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
},
336 librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
337 "remote mirror uuid", 0);
339 MockJournalStateBuilder mock_journal_state_builder
;
340 MockStateBuilder
* mock_state_builder
= nullptr;
341 std::string local_image_name
;
343 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
347 m_threads
->work_queue
,
351 ASSERT_EQ(0, ctx
.wait());
354 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, DirGetNameError
) {
356 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
357 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "local image id",
359 expect_dir_get_name(m_local_io_ctx
, "", -EPERM
);
361 MockStateBuilder
* mock_state_builder
= nullptr;
362 std::string local_image_name
;
364 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
368 m_threads
->work_queue
,
372 ASSERT_EQ(-EPERM
, ctx
.wait());
375 TEST_F(TestMockImageReplayerPrepareLocalImageRequest
, MirrorImageInfoError
) {
377 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request
;
378 expect_get_mirror_image_id(mock_get_mirror_image_id_request
, "local image id",
380 expect_dir_get_name(m_local_io_ctx
, "local image name", 0);
382 MockGetMirrorInfoRequest mock_get_mirror_info_request
;
383 expect_get_mirror_info(mock_get_mirror_info_request
,
384 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
,
386 cls::rbd::MIRROR_IMAGE_STATE_ENABLED
},
387 librbd::mirror::PROMOTION_STATE_NON_PRIMARY
,
388 "remote mirror uuid", -EINVAL
);
390 MockStateBuilder
* mock_state_builder
= nullptr;
391 std::string local_image_name
;
393 auto req
= MockPrepareLocalImageRequest::create(m_local_io_ctx
,
397 m_threads
->work_queue
,
400 ASSERT_EQ(-EINVAL
, ctx
.wait());
403 } // namespace image_replayer
404 } // namespace mirror