]>
Commit | Line | Data |
---|---|---|
d2e6a577 FG |
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" | |
9f95a23c | 7 | #include "librbd/mirror/GetInfoRequest.h" |
b32b8144 | 8 | #include "tools/rbd_mirror/Threads.h" |
d2e6a577 FG |
9 | #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h" |
10 | #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h" | |
9f95a23c TL |
11 | #include "tools/rbd_mirror/image_replayer/StateBuilder.h" |
12 | #include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h" | |
13 | #include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h" | |
b32b8144 | 14 | #include "test/journal/mock/MockJournaler.h" |
d2e6a577 FG |
15 | #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" |
16 | #include "test/librbd/mock/MockImageCtx.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 | |
b32b8144 FG |
29 | |
30 | namespace journal { | |
31 | ||
32 | template <> | |
33 | struct TypeTraits<MockTestImageCtx> { | |
34 | typedef ::journal::MockJournalerProxy Journaler; | |
35 | }; | |
36 | ||
37 | } // namespace journal | |
9f95a23c TL |
38 | |
39 | namespace mirror { | |
40 | ||
41 | template<> | |
42 | struct GetInfoRequest<librbd::MockTestImageCtx> { | |
43 | static GetInfoRequest* s_instance; | |
44 | cls::rbd::MirrorImage *mirror_image; | |
45 | PromotionState *promotion_state; | |
46 | std::string *primary_mirror_uuid; | |
47 | Context *on_finish = nullptr; | |
48 | ||
49 | static GetInfoRequest* create(librados::IoCtx& io_ctx, | |
f67539c2 | 50 | librbd::asio::ContextWQ* context_wq, |
9f95a23c TL |
51 | const std::string& image_id, |
52 | cls::rbd::MirrorImage *mirror_image, | |
53 | PromotionState *promotion_state, | |
54 | std::string* primary_mirror_uuid, | |
55 | Context *on_finish) { | |
56 | ceph_assert(s_instance != nullptr); | |
57 | s_instance->mirror_image = mirror_image; | |
58 | s_instance->promotion_state = promotion_state; | |
59 | s_instance->primary_mirror_uuid = primary_mirror_uuid; | |
60 | s_instance->on_finish = on_finish; | |
61 | return s_instance; | |
62 | } | |
63 | ||
64 | GetInfoRequest() { | |
65 | ceph_assert(s_instance == nullptr); | |
66 | s_instance = this; | |
67 | } | |
68 | ~GetInfoRequest() { | |
69 | s_instance = nullptr; | |
70 | } | |
71 | ||
72 | MOCK_METHOD0(send, void()); | |
73 | }; | |
74 | ||
75 | GetInfoRequest<librbd::MockTestImageCtx>* GetInfoRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
76 | ||
77 | } // namespace mirror | |
d2e6a577 FG |
78 | } // namespace librbd |
79 | ||
80 | namespace rbd { | |
81 | namespace mirror { | |
b32b8144 FG |
82 | |
83 | template <> | |
84 | struct Threads<librbd::MockTestImageCtx> { | |
9f95a23c | 85 | ceph::mutex &timer_lock; |
b32b8144 | 86 | SafeTimer *timer; |
f67539c2 | 87 | librbd::asio::ContextWQ *work_queue; |
b32b8144 FG |
88 | |
89 | Threads(Threads<librbd::ImageCtx> *threads) | |
90 | : timer_lock(threads->timer_lock), timer(threads->timer), | |
91 | work_queue(threads->work_queue) { | |
92 | } | |
93 | }; | |
94 | ||
d2e6a577 FG |
95 | namespace image_replayer { |
96 | ||
97 | template <> | |
98 | struct GetMirrorImageIdRequest<librbd::MockTestImageCtx> { | |
99 | static GetMirrorImageIdRequest* s_instance; | |
100 | std::string* image_id = nullptr; | |
101 | Context* on_finish = nullptr; | |
102 | ||
103 | static GetMirrorImageIdRequest* create(librados::IoCtx& io_ctx, | |
104 | const std::string& global_image_id, | |
105 | std::string* image_id, | |
106 | Context* on_finish) { | |
11fdf7f2 | 107 | ceph_assert(s_instance != nullptr); |
d2e6a577 FG |
108 | s_instance->image_id = image_id; |
109 | s_instance->on_finish = on_finish; | |
110 | return s_instance; | |
111 | } | |
112 | ||
113 | GetMirrorImageIdRequest() { | |
114 | s_instance = this; | |
115 | } | |
116 | ||
117 | MOCK_METHOD0(send, void()); | |
118 | }; | |
119 | ||
9f95a23c TL |
120 | template<> |
121 | struct StateBuilder<librbd::MockTestImageCtx> { | |
122 | std::string local_image_id; | |
123 | librbd::mirror::PromotionState local_promotion_state = | |
124 | librbd::mirror::PROMOTION_STATE_NON_PRIMARY; | |
125 | std::string remote_image_id; | |
126 | std::string remote_mirror_uuid; | |
127 | librbd::mirror::PromotionState remote_promotion_state; | |
128 | ||
129 | virtual ~StateBuilder() {} | |
130 | ||
131 | MOCK_CONST_METHOD0(get_mirror_image_mode, cls::rbd::MirrorImageMode()); | |
132 | }; | |
133 | ||
d2e6a577 FG |
134 | GetMirrorImageIdRequest<librbd::MockTestImageCtx>* GetMirrorImageIdRequest<librbd::MockTestImageCtx>::s_instance = nullptr; |
135 | ||
9f95a23c TL |
136 | namespace journal { |
137 | ||
138 | template<> | |
139 | struct StateBuilder<librbd::MockTestImageCtx> | |
140 | : public image_replayer::StateBuilder<librbd::MockTestImageCtx> { | |
141 | static StateBuilder* s_instance; | |
142 | ||
143 | cls::rbd::MirrorImageMode mirror_image_mode = | |
144 | cls::rbd::MIRROR_IMAGE_MODE_JOURNAL; | |
145 | ||
146 | ::journal::MockJournalerProxy* remote_journaler = nullptr; | |
147 | cls::journal::ClientState remote_client_state; | |
148 | librbd::journal::MirrorPeerClientMeta remote_client_meta; | |
149 | ||
150 | static StateBuilder* create(const std::string&) { | |
151 | ceph_assert(s_instance != nullptr); | |
152 | return s_instance; | |
153 | } | |
154 | ||
155 | StateBuilder() { | |
156 | s_instance = this; | |
157 | } | |
158 | }; | |
159 | ||
160 | StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr; | |
161 | ||
162 | } // namespace journal | |
163 | ||
164 | namespace snapshot { | |
165 | ||
166 | template<> | |
167 | struct StateBuilder<librbd::MockTestImageCtx> | |
168 | : public image_replayer::StateBuilder<librbd::MockTestImageCtx> { | |
169 | static StateBuilder* s_instance; | |
170 | ||
171 | cls::rbd::MirrorImageMode mirror_image_mode = | |
172 | cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT; | |
173 | ||
174 | std::string remote_mirror_peer_uuid; | |
175 | ||
176 | static StateBuilder* create(const std::string&) { | |
177 | ceph_assert(s_instance != nullptr); | |
178 | return s_instance; | |
179 | } | |
180 | ||
181 | StateBuilder() { | |
182 | s_instance = this; | |
183 | } | |
184 | }; | |
185 | ||
186 | StateBuilder<librbd::MockTestImageCtx>* StateBuilder<librbd::MockTestImageCtx>::s_instance = nullptr; | |
187 | ||
188 | } // namespace snapshot | |
d2e6a577 FG |
189 | } // namespace image_replayer |
190 | } // namespace mirror | |
191 | } // namespace rbd | |
192 | ||
193 | // template definitions | |
194 | #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc" | |
195 | ||
196 | namespace rbd { | |
197 | namespace mirror { | |
198 | namespace image_replayer { | |
199 | ||
200 | using ::testing::_; | |
201 | using ::testing::DoAll; | |
202 | using ::testing::InSequence; | |
203 | using ::testing::Invoke; | |
204 | using ::testing::Return; | |
205 | using ::testing::StrEq; | |
206 | using ::testing::WithArg; | |
207 | ||
208 | class TestMockImageReplayerPrepareRemoteImageRequest : public TestMockFixture { | |
209 | public: | |
b32b8144 | 210 | typedef Threads<librbd::MockTestImageCtx> MockThreads; |
d2e6a577 FG |
211 | typedef PrepareRemoteImageRequest<librbd::MockTestImageCtx> MockPrepareRemoteImageRequest; |
212 | typedef GetMirrorImageIdRequest<librbd::MockTestImageCtx> MockGetMirrorImageIdRequest; | |
9f95a23c TL |
213 | typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder; |
214 | typedef journal::StateBuilder<librbd::MockTestImageCtx> MockJournalStateBuilder; | |
215 | typedef snapshot::StateBuilder<librbd::MockTestImageCtx> MockSnapshotStateBuilder; | |
216 | typedef librbd::mirror::GetInfoRequest<librbd::MockTestImageCtx> MockGetMirrorInfoRequest; | |
217 | ||
218 | void expect_get_mirror_image_mode(MockStateBuilder& mock_state_builder, | |
219 | cls::rbd::MirrorImageMode mirror_image_mode) { | |
220 | EXPECT_CALL(mock_state_builder, get_mirror_image_mode()) | |
221 | .WillOnce(Return(mirror_image_mode)); | |
222 | } | |
d2e6a577 FG |
223 | |
224 | void expect_get_mirror_image_id(MockGetMirrorImageIdRequest& mock_get_mirror_image_id_request, | |
225 | const std::string& image_id, int r) { | |
226 | EXPECT_CALL(mock_get_mirror_image_id_request, send()) | |
227 | .WillOnce(Invoke([&mock_get_mirror_image_id_request, image_id, r]() { | |
228 | *mock_get_mirror_image_id_request.image_id = image_id; | |
229 | mock_get_mirror_image_id_request.on_finish->complete(r); | |
230 | })); | |
231 | } | |
232 | ||
9f95a23c TL |
233 | void expect_get_mirror_info( |
234 | MockGetMirrorInfoRequest &mock_get_mirror_info_request, | |
235 | const cls::rbd::MirrorImage &mirror_image, | |
236 | librbd::mirror::PromotionState promotion_state, | |
237 | const std::string& primary_mirror_uuid, int r) { | |
238 | EXPECT_CALL(mock_get_mirror_info_request, send()) | |
239 | .WillOnce(Invoke([this, &mock_get_mirror_info_request, mirror_image, | |
240 | promotion_state, primary_mirror_uuid, r]() { | |
241 | *mock_get_mirror_info_request.mirror_image = mirror_image; | |
242 | *mock_get_mirror_info_request.promotion_state = promotion_state; | |
243 | *mock_get_mirror_info_request.primary_mirror_uuid = | |
244 | primary_mirror_uuid; | |
245 | m_threads->work_queue->queue( | |
246 | mock_get_mirror_info_request.on_finish, r); | |
247 | })); | |
d2e6a577 | 248 | } |
b32b8144 FG |
249 | |
250 | void expect_journaler_get_client(::journal::MockJournaler &mock_journaler, | |
251 | const std::string &client_id, | |
252 | cls::journal::Client &client, int r) { | |
253 | EXPECT_CALL(mock_journaler, get_client(StrEq(client_id), _, _)) | |
254 | .WillOnce(DoAll(WithArg<1>(Invoke([client](cls::journal::Client *out_client) { | |
255 | *out_client = client; | |
256 | })), | |
257 | WithArg<2>(Invoke([this, r](Context *on_finish) { | |
258 | m_threads->work_queue->queue(on_finish, r); | |
259 | })))); | |
260 | } | |
261 | ||
262 | void expect_journaler_register_client(::journal::MockJournaler &mock_journaler, | |
263 | const librbd::journal::ClientData &client_data, | |
264 | int r) { | |
265 | bufferlist bl; | |
11fdf7f2 | 266 | encode(client_data, bl); |
b32b8144 FG |
267 | |
268 | EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _)) | |
269 | .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) { | |
270 | m_threads->work_queue->queue(on_finish, r); | |
271 | }))); | |
272 | } | |
d2e6a577 FG |
273 | }; |
274 | ||
9f95a23c TL |
275 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessJournal) { |
276 | ::journal::MockJournaler mock_remote_journaler; | |
b32b8144 FG |
277 | MockThreads mock_threads(m_threads); |
278 | ||
d2e6a577 | 279 | InSequence seq; |
d2e6a577 FG |
280 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
281 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
282 | "remote image id", 0); | |
283 | ||
9f95a23c TL |
284 | MockGetMirrorInfoRequest mock_get_mirror_info_request; |
285 | expect_get_mirror_info(mock_get_mirror_info_request, | |
286 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
287 | "global image id", | |
288 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
289 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
290 | "remote mirror uuid", 0); | |
291 | ||
b32b8144 FG |
292 | EXPECT_CALL(mock_remote_journaler, construct()); |
293 | ||
294 | librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta; | |
295 | mirror_peer_client_meta.image_id = "local image id"; | |
296 | mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING; | |
297 | librbd::journal::ClientData client_data{mirror_peer_client_meta}; | |
298 | cls::journal::Client client; | |
299 | client.state = cls::journal::CLIENT_STATE_DISCONNECTED; | |
11fdf7f2 | 300 | encode(client_data, client.data); |
b32b8144 FG |
301 | expect_journaler_get_client(mock_remote_journaler, "local mirror uuid", |
302 | client, 0); | |
303 | ||
9f95a23c TL |
304 | MockJournalStateBuilder mock_journal_state_builder; |
305 | MockStateBuilder* mock_state_builder = nullptr; | |
306 | C_SaferCond ctx; | |
307 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
308 | m_local_io_ctx, | |
309 | m_remote_io_ctx, | |
310 | "global image id", | |
311 | "local mirror uuid", | |
312 | {"remote mirror uuid", ""}, | |
313 | nullptr, | |
314 | &mock_state_builder, | |
315 | &ctx); | |
316 | req->send(); | |
317 | ||
318 | ASSERT_EQ(0, ctx.wait()); | |
319 | ASSERT_TRUE(mock_state_builder != nullptr); | |
320 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
321 | mock_journal_state_builder.mirror_image_mode); | |
322 | ASSERT_EQ(std::string("remote mirror uuid"), | |
323 | mock_journal_state_builder.remote_mirror_uuid); | |
324 | ASSERT_EQ(std::string("remote image id"), | |
325 | mock_journal_state_builder.remote_image_id); | |
326 | ASSERT_EQ(librbd::mirror::PROMOTION_STATE_PRIMARY, | |
327 | mock_journal_state_builder.remote_promotion_state); | |
328 | ASSERT_TRUE(mock_journal_state_builder.remote_journaler != nullptr); | |
329 | ASSERT_EQ(cls::journal::CLIENT_STATE_DISCONNECTED, | |
330 | mock_journal_state_builder.remote_client_state); | |
331 | } | |
332 | ||
333 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessSnapshot) { | |
9f95a23c TL |
334 | MockThreads mock_threads(m_threads); |
335 | ||
336 | InSequence seq; | |
337 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
338 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
339 | "remote image id", 0); | |
340 | ||
341 | MockGetMirrorInfoRequest mock_get_mirror_info_request; | |
342 | expect_get_mirror_info(mock_get_mirror_info_request, | |
343 | {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
344 | "global image id", | |
345 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
346 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
347 | "remote mirror uuid", 0); | |
348 | ||
349 | MockSnapshotStateBuilder mock_snapshot_state_builder; | |
350 | MockStateBuilder* mock_state_builder = nullptr; | |
d2e6a577 | 351 | C_SaferCond ctx; |
b32b8144 | 352 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, |
9f95a23c | 353 | m_local_io_ctx, |
b32b8144 | 354 | m_remote_io_ctx, |
d2e6a577 | 355 | "global image id", |
b32b8144 | 356 | "local mirror uuid", |
9f95a23c TL |
357 | {"remote mirror uuid", |
358 | "remote mirror peer uuid"}, | |
359 | nullptr, | |
360 | &mock_state_builder, | |
d2e6a577 FG |
361 | &ctx); |
362 | req->send(); | |
363 | ||
364 | ASSERT_EQ(0, ctx.wait()); | |
9f95a23c TL |
365 | ASSERT_TRUE(mock_state_builder != nullptr); |
366 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
367 | mock_snapshot_state_builder.mirror_image_mode); | |
368 | ASSERT_EQ(std::string("remote mirror uuid"), | |
369 | mock_snapshot_state_builder.remote_mirror_uuid); | |
370 | ASSERT_EQ(std::string("remote mirror peer uuid"), | |
371 | mock_snapshot_state_builder.remote_mirror_peer_uuid); | |
372 | ASSERT_EQ(std::string("remote image id"), | |
373 | mock_snapshot_state_builder.remote_image_id); | |
374 | ASSERT_EQ(librbd::mirror::PROMOTION_STATE_PRIMARY, | |
375 | mock_snapshot_state_builder.remote_promotion_state); | |
b32b8144 FG |
376 | } |
377 | ||
378 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) { | |
9f95a23c | 379 | ::journal::MockJournaler mock_remote_journaler; |
b32b8144 FG |
380 | MockThreads mock_threads(m_threads); |
381 | ||
382 | InSequence seq; | |
b32b8144 FG |
383 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
384 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
385 | "remote image id", 0); | |
386 | ||
9f95a23c TL |
387 | MockGetMirrorInfoRequest mock_get_mirror_info_request; |
388 | expect_get_mirror_info(mock_get_mirror_info_request, | |
389 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
390 | "global image id", | |
391 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
392 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
393 | "remote mirror uuid", 0); | |
394 | ||
395 | MockJournalStateBuilder mock_journal_state_builder; | |
396 | expect_get_mirror_image_mode(mock_journal_state_builder, | |
397 | cls::rbd::MIRROR_IMAGE_MODE_JOURNAL); | |
398 | ||
b32b8144 FG |
399 | EXPECT_CALL(mock_remote_journaler, construct()); |
400 | ||
401 | cls::journal::Client client; | |
402 | expect_journaler_get_client(mock_remote_journaler, "local mirror uuid", | |
403 | client, -ENOENT); | |
404 | ||
405 | librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta; | |
406 | mirror_peer_client_meta.image_id = "local image id"; | |
407 | mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING; | |
408 | librbd::journal::ClientData client_data{mirror_peer_client_meta}; | |
409 | expect_journaler_register_client(mock_remote_journaler, client_data, 0); | |
410 | ||
9f95a23c TL |
411 | mock_journal_state_builder.local_image_id = "local image id"; |
412 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
b32b8144 FG |
413 | C_SaferCond ctx; |
414 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
9f95a23c | 415 | m_local_io_ctx, |
b32b8144 FG |
416 | m_remote_io_ctx, |
417 | "global image id", | |
418 | "local mirror uuid", | |
9f95a23c TL |
419 | {"remote mirror uuid", ""}, |
420 | nullptr, | |
421 | &mock_state_builder, | |
b32b8144 FG |
422 | &ctx); |
423 | req->send(); | |
424 | ||
425 | ASSERT_EQ(0, ctx.wait()); | |
9f95a23c TL |
426 | ASSERT_TRUE(mock_state_builder != nullptr); |
427 | ASSERT_EQ(std::string("remote image id"), | |
428 | mock_journal_state_builder.remote_image_id); | |
429 | ASSERT_EQ(librbd::mirror::PROMOTION_STATE_PRIMARY, | |
430 | mock_journal_state_builder.remote_promotion_state); | |
431 | ASSERT_TRUE(mock_journal_state_builder.remote_journaler != nullptr); | |
432 | ASSERT_EQ(cls::journal::CLIENT_STATE_CONNECTED, | |
433 | mock_journal_state_builder.remote_client_state); | |
d2e6a577 FG |
434 | } |
435 | ||
20effc67 | 436 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetMirrorImageIdError) { |
b32b8144 FG |
437 | MockThreads mock_threads(m_threads); |
438 | ||
d2e6a577 | 439 | InSequence seq; |
9f95a23c TL |
440 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
441 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -EINVAL); | |
d2e6a577 | 442 | |
9f95a23c TL |
443 | MockJournalStateBuilder mock_journal_state_builder; |
444 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
d2e6a577 | 445 | C_SaferCond ctx; |
b32b8144 | 446 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, |
9f95a23c | 447 | m_local_io_ctx, |
b32b8144 | 448 | m_remote_io_ctx, |
d2e6a577 | 449 | "global image id", |
b32b8144 | 450 | "local mirror uuid", |
9f95a23c TL |
451 | {"remote mirror uuid", ""}, |
452 | nullptr, | |
453 | &mock_state_builder, | |
d2e6a577 FG |
454 | &ctx); |
455 | req->send(); | |
456 | ||
457 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
9f95a23c | 458 | ASSERT_TRUE(mock_journal_state_builder.remote_journaler == nullptr); |
d2e6a577 FG |
459 | } |
460 | ||
9f95a23c | 461 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetMirrorInfoError) { |
b32b8144 FG |
462 | MockThreads mock_threads(m_threads); |
463 | ||
d2e6a577 | 464 | InSequence seq; |
d2e6a577 | 465 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
9f95a23c TL |
466 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, |
467 | "remote image id", 0); | |
d2e6a577 | 468 | |
9f95a23c TL |
469 | MockGetMirrorInfoRequest mock_get_mirror_info_request; |
470 | expect_get_mirror_info(mock_get_mirror_info_request, | |
471 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
472 | "global image id", | |
473 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
474 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
475 | "remote mirror uuid", -EINVAL); | |
476 | ||
477 | MockJournalStateBuilder mock_journal_state_builder; | |
478 | MockStateBuilder* mock_state_builder = nullptr; | |
d2e6a577 | 479 | C_SaferCond ctx; |
b32b8144 | 480 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, |
9f95a23c | 481 | m_local_io_ctx, |
b32b8144 | 482 | m_remote_io_ctx, |
d2e6a577 | 483 | "global image id", |
b32b8144 | 484 | "local mirror uuid", |
9f95a23c TL |
485 | {"remote mirror uuid", ""}, |
486 | nullptr, | |
487 | &mock_state_builder, | |
d2e6a577 FG |
488 | &ctx); |
489 | req->send(); | |
490 | ||
491 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
9f95a23c | 492 | ASSERT_TRUE(mock_state_builder == nullptr); |
b32b8144 FG |
493 | } |
494 | ||
495 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) { | |
9f95a23c | 496 | ::journal::MockJournaler mock_remote_journaler; |
b32b8144 FG |
497 | MockThreads mock_threads(m_threads); |
498 | ||
499 | InSequence seq; | |
b32b8144 FG |
500 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
501 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
502 | "remote image id", 0); | |
503 | ||
9f95a23c TL |
504 | MockGetMirrorInfoRequest mock_get_mirror_info_request; |
505 | expect_get_mirror_info(mock_get_mirror_info_request, | |
506 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
507 | "global image id", | |
508 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
509 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
510 | "remote mirror uuid", 0); | |
511 | ||
b32b8144 FG |
512 | EXPECT_CALL(mock_remote_journaler, construct()); |
513 | ||
514 | cls::journal::Client client; | |
515 | expect_journaler_get_client(mock_remote_journaler, "local mirror uuid", | |
516 | client, -EINVAL); | |
517 | ||
9f95a23c TL |
518 | MockJournalStateBuilder mock_journal_state_builder; |
519 | MockStateBuilder* mock_state_builder = nullptr; | |
b32b8144 FG |
520 | C_SaferCond ctx; |
521 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
9f95a23c | 522 | m_local_io_ctx, |
b32b8144 FG |
523 | m_remote_io_ctx, |
524 | "global image id", | |
525 | "local mirror uuid", | |
9f95a23c TL |
526 | {"remote mirror uuid", ""}, |
527 | nullptr, | |
528 | &mock_state_builder, | |
b32b8144 FG |
529 | &ctx); |
530 | req->send(); | |
531 | ||
532 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
9f95a23c | 533 | ASSERT_TRUE(mock_state_builder == nullptr); |
b32b8144 FG |
534 | } |
535 | ||
536 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) { | |
9f95a23c | 537 | ::journal::MockJournaler mock_remote_journaler; |
b32b8144 FG |
538 | MockThreads mock_threads(m_threads); |
539 | ||
540 | InSequence seq; | |
b32b8144 FG |
541 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; |
542 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
543 | "remote image id", 0); | |
544 | ||
9f95a23c TL |
545 | MockGetMirrorInfoRequest mock_get_mirror_info_request; |
546 | expect_get_mirror_info(mock_get_mirror_info_request, | |
547 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
548 | "global image id", | |
549 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
550 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
551 | "remote mirror uuid", 0); | |
552 | ||
553 | MockJournalStateBuilder mock_journal_state_builder; | |
554 | expect_get_mirror_image_mode(mock_journal_state_builder, | |
555 | cls::rbd::MIRROR_IMAGE_MODE_JOURNAL); | |
556 | ||
b32b8144 FG |
557 | EXPECT_CALL(mock_remote_journaler, construct()); |
558 | ||
559 | cls::journal::Client client; | |
560 | expect_journaler_get_client(mock_remote_journaler, "local mirror uuid", | |
561 | client, -ENOENT); | |
562 | ||
563 | librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta; | |
564 | mirror_peer_client_meta.image_id = "local image id"; | |
565 | mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING; | |
566 | librbd::journal::ClientData client_data{mirror_peer_client_meta}; | |
567 | expect_journaler_register_client(mock_remote_journaler, client_data, -EINVAL); | |
568 | ||
9f95a23c TL |
569 | mock_journal_state_builder.local_image_id = "local image id"; |
570 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
b32b8144 FG |
571 | C_SaferCond ctx; |
572 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
9f95a23c | 573 | m_local_io_ctx, |
b32b8144 FG |
574 | m_remote_io_ctx, |
575 | "global image id", | |
576 | "local mirror uuid", | |
9f95a23c TL |
577 | {"remote mirror uuid", ""}, |
578 | nullptr, | |
579 | &mock_state_builder, | |
b32b8144 FG |
580 | &ctx); |
581 | req->send(); | |
582 | ||
583 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
d2e6a577 FG |
584 | } |
585 | ||
20effc67 TL |
586 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdDNEJournal) { |
587 | MockThreads mock_threads(m_threads); | |
588 | ||
589 | InSequence seq; | |
590 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
591 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -ENOENT); | |
592 | ||
593 | MockJournalStateBuilder mock_journal_state_builder; | |
594 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
595 | C_SaferCond ctx; | |
596 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
597 | m_local_io_ctx, | |
598 | m_remote_io_ctx, | |
599 | "global image id", | |
600 | "local mirror uuid", | |
601 | {"remote mirror uuid", ""}, | |
602 | nullptr, | |
603 | &mock_state_builder, | |
604 | &ctx); | |
605 | req->send(); | |
606 | ||
607 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
608 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
609 | mock_journal_state_builder.mirror_image_mode); | |
610 | ASSERT_EQ("remote mirror uuid", | |
611 | mock_journal_state_builder.remote_mirror_uuid); | |
612 | ASSERT_EQ("", mock_journal_state_builder.remote_image_id); | |
613 | } | |
614 | ||
615 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdDNESnapshot) { | |
616 | MockThreads mock_threads(m_threads); | |
617 | ||
618 | InSequence seq; | |
619 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
620 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, "", -ENOENT); | |
621 | ||
622 | MockSnapshotStateBuilder mock_snapshot_state_builder; | |
623 | MockStateBuilder* mock_state_builder = &mock_snapshot_state_builder; | |
624 | C_SaferCond ctx; | |
625 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
626 | m_local_io_ctx, | |
627 | m_remote_io_ctx, | |
628 | "global image id", | |
629 | "local mirror uuid", | |
630 | {"remote mirror uuid", | |
631 | "remote mirror peer uuid"}, | |
632 | nullptr, | |
633 | &mock_state_builder, | |
634 | &ctx); | |
635 | req->send(); | |
636 | ||
637 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
638 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
639 | mock_snapshot_state_builder.mirror_image_mode); | |
640 | ASSERT_EQ("remote mirror uuid", | |
641 | mock_snapshot_state_builder.remote_mirror_uuid); | |
642 | ASSERT_EQ("remote mirror peer uuid", | |
643 | mock_snapshot_state_builder.remote_mirror_peer_uuid); | |
644 | ASSERT_EQ("", mock_snapshot_state_builder.remote_image_id); | |
645 | } | |
646 | ||
647 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorInfoDNEJournal) { | |
648 | MockThreads mock_threads(m_threads); | |
649 | ||
650 | InSequence seq; | |
651 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
652 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
653 | "remote image id", 0); | |
654 | ||
655 | MockGetMirrorInfoRequest mock_get_mirror_info_request; | |
656 | expect_get_mirror_info(mock_get_mirror_info_request, | |
657 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
658 | "global image id", | |
659 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
660 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
661 | "remote mirror uuid", -ENOENT); | |
662 | ||
663 | MockJournalStateBuilder mock_journal_state_builder; | |
664 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
665 | C_SaferCond ctx; | |
666 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
667 | m_local_io_ctx, | |
668 | m_remote_io_ctx, | |
669 | "global image id", | |
670 | "local mirror uuid", | |
671 | {"remote mirror uuid", ""}, | |
672 | nullptr, | |
673 | &mock_state_builder, | |
674 | &ctx); | |
675 | req->send(); | |
676 | ||
677 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
678 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
679 | mock_journal_state_builder.mirror_image_mode); | |
680 | ASSERT_EQ("remote mirror uuid", | |
681 | mock_journal_state_builder.remote_mirror_uuid); | |
682 | ASSERT_EQ("", mock_journal_state_builder.remote_image_id); | |
683 | } | |
684 | ||
685 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorInfoDNESnapshot) { | |
686 | MockThreads mock_threads(m_threads); | |
687 | ||
688 | InSequence seq; | |
689 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
690 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
691 | "remote image id", 0); | |
692 | ||
693 | MockGetMirrorInfoRequest mock_get_mirror_info_request; | |
694 | expect_get_mirror_info(mock_get_mirror_info_request, | |
695 | {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
696 | "global image id", | |
697 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, | |
698 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
699 | "remote mirror uuid", -ENOENT); | |
700 | ||
701 | MockSnapshotStateBuilder mock_snapshot_state_builder; | |
702 | MockStateBuilder* mock_state_builder = &mock_snapshot_state_builder; | |
703 | C_SaferCond ctx; | |
704 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
705 | m_local_io_ctx, | |
706 | m_remote_io_ctx, | |
707 | "global image id", | |
708 | "local mirror uuid", | |
709 | {"remote mirror uuid", | |
710 | "remote mirror peer uuid"}, | |
711 | nullptr, | |
712 | &mock_state_builder, | |
713 | &ctx); | |
714 | req->send(); | |
715 | ||
716 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
717 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
718 | mock_snapshot_state_builder.mirror_image_mode); | |
719 | ASSERT_EQ("remote mirror uuid", | |
720 | mock_snapshot_state_builder.remote_mirror_uuid); | |
721 | ASSERT_EQ("remote mirror peer uuid", | |
722 | mock_snapshot_state_builder.remote_mirror_peer_uuid); | |
723 | ASSERT_EQ("", mock_snapshot_state_builder.remote_image_id); | |
724 | } | |
725 | ||
726 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorInfoDisablingJournal) { | |
727 | MockThreads mock_threads(m_threads); | |
728 | ||
729 | InSequence seq; | |
730 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
731 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
732 | "remote image id", 0); | |
733 | ||
734 | MockGetMirrorInfoRequest mock_get_mirror_info_request; | |
735 | expect_get_mirror_info(mock_get_mirror_info_request, | |
736 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
737 | "global image id", | |
738 | cls::rbd::MIRROR_IMAGE_STATE_DISABLING}, | |
739 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
740 | "remote mirror uuid", 0); | |
741 | ||
742 | MockJournalStateBuilder mock_journal_state_builder; | |
743 | expect_get_mirror_image_mode(mock_journal_state_builder, | |
744 | cls::rbd::MIRROR_IMAGE_MODE_JOURNAL); | |
745 | MockStateBuilder* mock_state_builder = &mock_journal_state_builder; | |
746 | C_SaferCond ctx; | |
747 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
748 | m_local_io_ctx, | |
749 | m_remote_io_ctx, | |
750 | "global image id", | |
751 | "local mirror uuid", | |
752 | {"remote mirror uuid", ""}, | |
753 | nullptr, | |
754 | &mock_state_builder, | |
755 | &ctx); | |
756 | req->send(); | |
757 | ||
758 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
759 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, | |
760 | mock_journal_state_builder.mirror_image_mode); | |
761 | ASSERT_EQ("remote mirror uuid", | |
762 | mock_journal_state_builder.remote_mirror_uuid); | |
763 | ASSERT_EQ("", mock_journal_state_builder.remote_image_id); | |
764 | } | |
765 | ||
766 | TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorInfoDisablingSnapshot) { | |
767 | MockThreads mock_threads(m_threads); | |
768 | ||
769 | InSequence seq; | |
770 | MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; | |
771 | expect_get_mirror_image_id(mock_get_mirror_image_id_request, | |
772 | "remote image id", 0); | |
773 | ||
774 | MockGetMirrorInfoRequest mock_get_mirror_info_request; | |
775 | expect_get_mirror_info(mock_get_mirror_info_request, | |
776 | {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
777 | "global image id", | |
778 | cls::rbd::MIRROR_IMAGE_STATE_DISABLING}, | |
779 | librbd::mirror::PROMOTION_STATE_PRIMARY, | |
780 | "remote mirror uuid", 0); | |
781 | ||
782 | MockSnapshotStateBuilder mock_snapshot_state_builder; | |
783 | expect_get_mirror_image_mode(mock_snapshot_state_builder, | |
784 | cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT); | |
785 | MockStateBuilder* mock_state_builder = &mock_snapshot_state_builder; | |
786 | C_SaferCond ctx; | |
787 | auto req = MockPrepareRemoteImageRequest::create(&mock_threads, | |
788 | m_local_io_ctx, | |
789 | m_remote_io_ctx, | |
790 | "global image id", | |
791 | "local mirror uuid", | |
792 | {"remote mirror uuid", | |
793 | "remote mirror peer uuid"}, | |
794 | nullptr, | |
795 | &mock_state_builder, | |
796 | &ctx); | |
797 | req->send(); | |
798 | ||
799 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
800 | ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, | |
801 | mock_snapshot_state_builder.mirror_image_mode); | |
802 | ASSERT_EQ("remote mirror uuid", | |
803 | mock_snapshot_state_builder.remote_mirror_uuid); | |
804 | ASSERT_EQ("remote mirror peer uuid", | |
805 | mock_snapshot_state_builder.remote_mirror_peer_uuid); | |
806 | ASSERT_EQ("", mock_snapshot_state_builder.remote_image_id); | |
807 | } | |
808 | ||
d2e6a577 FG |
809 | } // namespace image_replayer |
810 | } // namespace mirror | |
811 | } // namespace rbd |