]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / test_mock_PrepareLocalImageRequest.cc
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/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"
17
18 namespace librbd {
19
20 namespace {
21
22 struct MockTestImageCtx : public librbd::MockImageCtx {
23 MockTestImageCtx(librbd::ImageCtx &image_ctx)
24 : librbd::MockImageCtx(image_ctx) {
25 }
26 };
27
28 } // anonymous namespace
29
30 namespace mirror {
31
32 template<>
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;
39
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,
46 Context *on_finish) {
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;
52 return s_instance;
53 }
54
55 GetInfoRequest() {
56 ceph_assert(s_instance == nullptr);
57 s_instance = this;
58 }
59 ~GetInfoRequest() {
60 s_instance = nullptr;
61 }
62
63 MOCK_METHOD0(send, void());
64 };
65
66 GetInfoRequest<librbd::MockTestImageCtx>* GetInfoRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
67
68 } // namespace mirror
69 } // namespace librbd
70
71 namespace rbd {
72 namespace mirror {
73 namespace image_replayer {
74
75 template <>
76 struct GetMirrorImageIdRequest<librbd::MockTestImageCtx> {
77 static GetMirrorImageIdRequest* s_instance;
78 std::string* image_id = nullptr;
79 Context* on_finish = nullptr;
80
81 static GetMirrorImageIdRequest* create(librados::IoCtx& io_ctx,
82 const std::string& global_image_id,
83 std::string* image_id,
84 Context* on_finish) {
85 ceph_assert(s_instance != nullptr);
86 s_instance->image_id = image_id;
87 s_instance->on_finish = on_finish;
88 return s_instance;
89 }
90
91 GetMirrorImageIdRequest() {
92 s_instance = this;
93 }
94
95 MOCK_METHOD0(send, void());
96 };
97
98 template<>
99 struct StateBuilder<librbd::MockTestImageCtx> {
100 virtual ~StateBuilder() {}
101
102 std::string local_image_id;
103 librbd::mirror::PromotionState local_promotion_state;
104 };
105
106 GetMirrorImageIdRequest<librbd::MockTestImageCtx>* GetMirrorImageIdRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
107
108 namespace journal {
109
110 template<>
111 struct StateBuilder<librbd::MockTestImageCtx>
112 : public image_replayer::StateBuilder<librbd::MockTestImageCtx> {
113 static StateBuilder* s_instance;
114
115 cls::rbd::MirrorImageMode mirror_image_mode =
116 cls::rbd::MIRROR_IMAGE_MODE_JOURNAL;
117
118 std::string local_primary_mirror_uuid;
119
120 static StateBuilder* create(const std::string&) {
121 ceph_assert(s_instance != nullptr);
122 return s_instance;
123 }
124
125 StateBuilder() {
126 s_instance = this;
127 }
128 };
129
130 StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
131
132 } // namespace journal
133
134 namespace snapshot {
135
136 template<>
137 struct StateBuilder<librbd::MockTestImageCtx>
138 : public image_replayer::StateBuilder<librbd::MockTestImageCtx> {
139 static StateBuilder* s_instance;
140
141 cls::rbd::MirrorImageMode mirror_image_mode =
142 cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT;
143
144 static StateBuilder* create(const std::string&) {
145 ceph_assert(s_instance != nullptr);
146 return s_instance;
147 }
148
149 StateBuilder() {
150 s_instance = this;
151 }
152 };
153
154 StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr;
155
156 } // namespace snapshot
157 } // namespace image_replayer
158 } // namespace mirror
159 } // namespace rbd
160
161 // template definitions
162 #include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc"
163
164 namespace rbd {
165 namespace mirror {
166 namespace image_replayer {
167
168 using ::testing::_;
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;
176
177 class TestMockImageReplayerPrepareLocalImageRequest : public TestMockFixture {
178 public:
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;
185
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);
192 }));
193 }
194
195 void expect_dir_get_name(librados::IoCtx &io_ctx,
196 const std::string &image_name, int r) {
197 bufferlist bl;
198 encode(image_name, bl);
199
200 EXPECT_CALL(get_mock_io_ctx(io_ctx),
201 exec(RBD_DIRECTORY, _, StrEq("rbd"), StrEq("dir_get_name"), _,
202 _, _, _))
203 .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
204 *out_bl = bl;
205 })),
206 Return(r)));
207 }
208
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 =
220 primary_mirror_uuid;
221 m_threads->work_queue->queue(
222 mock_get_mirror_info_request.on_finish, r);
223 }));
224 }
225 };
226
227 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, SuccessJournal) {
228 InSequence seq;
229 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
230 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
231 0);
232 expect_dir_get_name(m_local_io_ctx, "local image name", 0);
233
234 MockGetMirrorInfoRequest mock_get_mirror_info_request;
235 expect_get_mirror_info(mock_get_mirror_info_request,
236 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
237 "global image id",
238 cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
239 librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
240 "remote mirror uuid", 0);
241
242 MockJournalStateBuilder mock_journal_state_builder;
243 MockStateBuilder* mock_state_builder = nullptr;
244 std::string local_image_name;
245 C_SaferCond ctx;
246 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
247 "global image id",
248 &local_image_name,
249 &mock_state_builder,
250 m_threads->work_queue,
251 &ctx);
252 req->send();
253
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);
265 }
266
267 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, SuccessSnapshot) {
268 InSequence seq;
269 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
270 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
271 0);
272 expect_dir_get_name(m_local_io_ctx, "local image name", 0);
273
274 MockGetMirrorInfoRequest mock_get_mirror_info_request;
275 expect_get_mirror_info(mock_get_mirror_info_request,
276 {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT,
277 "global image id",
278 cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
279 librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
280 "remote mirror uuid", 0);
281
282 MockSnapshotStateBuilder mock_journal_state_builder;
283 MockStateBuilder* mock_state_builder = nullptr;
284 std::string local_image_name;
285 C_SaferCond ctx;
286 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
287 "global image id",
288 &local_image_name,
289 &mock_state_builder,
290 m_threads->work_queue,
291 &ctx);
292 req->send();
293
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);
303 }
304
305 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageIdError) {
306 InSequence seq;
307 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
308 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -EINVAL);
309
310 MockStateBuilder* mock_state_builder = nullptr;
311 std::string local_image_name;
312 C_SaferCond ctx;
313 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
314 "global image id",
315 &local_image_name,
316 &mock_state_builder,
317 m_threads->work_queue,
318 &ctx);
319 req->send();
320
321 ASSERT_EQ(-EINVAL, ctx.wait());
322 }
323
324 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, DirGetNameDNE) {
325 InSequence seq;
326 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
327 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
328 0);
329 expect_dir_get_name(m_local_io_ctx, "", -ENOENT);
330
331 MockGetMirrorInfoRequest mock_get_mirror_info_request;
332 expect_get_mirror_info(mock_get_mirror_info_request,
333 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
334 "global image id",
335 cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
336 librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
337 "remote mirror uuid", 0);
338
339 MockJournalStateBuilder mock_journal_state_builder;
340 MockStateBuilder* mock_state_builder = nullptr;
341 std::string local_image_name;
342 C_SaferCond ctx;
343 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
344 "global image id",
345 &local_image_name,
346 &mock_state_builder,
347 m_threads->work_queue,
348 &ctx);
349 req->send();
350
351 ASSERT_EQ(0, ctx.wait());
352 }
353
354 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, DirGetNameError) {
355 InSequence seq;
356 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
357 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
358 0);
359 expect_dir_get_name(m_local_io_ctx, "", -EPERM);
360
361 MockStateBuilder* mock_state_builder = nullptr;
362 std::string local_image_name;
363 C_SaferCond ctx;
364 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
365 "global image id",
366 &local_image_name,
367 &mock_state_builder,
368 m_threads->work_queue,
369 &ctx);
370 req->send();
371
372 ASSERT_EQ(-EPERM, ctx.wait());
373 }
374
375 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageInfoError) {
376 InSequence seq;
377 MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
378 expect_get_mirror_image_id(mock_get_mirror_image_id_request, "local image id",
379 0);
380 expect_dir_get_name(m_local_io_ctx, "local image name", 0);
381
382 MockGetMirrorInfoRequest mock_get_mirror_info_request;
383 expect_get_mirror_info(mock_get_mirror_info_request,
384 {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
385 "global image id",
386 cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
387 librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
388 "remote mirror uuid", -EINVAL);
389
390 MockStateBuilder* mock_state_builder = nullptr;
391 std::string local_image_name;
392 C_SaferCond ctx;
393 auto req = MockPrepareLocalImageRequest::create(m_local_io_ctx,
394 "global image id",
395 &local_image_name,
396 &mock_state_builder,
397 m_threads->work_queue,
398 &ctx);
399 req->send();
400 ASSERT_EQ(-EINVAL, ctx.wait());
401 }
402
403 } // namespace image_replayer
404 } // namespace mirror
405 } // namespace rbd