]>
Commit | Line | Data |
---|---|---|
7c673cae 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/librbd/test_mock_fixture.h" | |
5 | #include "test/librbd/test_support.h" | |
6 | #include "test/librbd/mock/MockImageCtx.h" | |
9f95a23c | 7 | #include "test/librbd/mock/MockImageState.h" |
7c673cae FG |
8 | #include "test/librbd/mock/MockOperations.h" |
9 | #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" | |
10 | #include "test/librados_test_stub/MockTestMemRadosClient.h" | |
7c673cae FG |
11 | #include "librbd/journal/PromoteRequest.h" |
12 | #include "librbd/mirror/DisableRequest.h" | |
9f95a23c TL |
13 | #include "librbd/mirror/GetInfoRequest.h" |
14 | #include "librbd/mirror/ImageRemoveRequest.h" | |
15 | #include "librbd/mirror/ImageStateUpdateRequest.h" | |
16 | #include "librbd/mirror/snapshot/PromoteRequest.h" | |
7c673cae FG |
17 | |
18 | namespace librbd { | |
19 | ||
20 | namespace { | |
21 | ||
22 | struct MockTestImageCtx : public MockImageCtx { | |
11fdf7f2 | 23 | explicit MockTestImageCtx(librbd::ImageCtx& image_ctx) : MockImageCtx(image_ctx) { |
7c673cae FG |
24 | } |
25 | }; | |
26 | ||
27 | } // anonymous namespace | |
28 | ||
9f95a23c TL |
29 | namespace journal { |
30 | ||
7c673cae | 31 | template <> |
9f95a23c TL |
32 | struct PromoteRequest<librbd::MockTestImageCtx> { |
33 | Context *on_finish = nullptr; | |
34 | static PromoteRequest *s_instance; | |
35 | static PromoteRequest *create(librbd::MockTestImageCtx *, bool force, | |
36 | Context *on_finish) { | |
11fdf7f2 | 37 | ceph_assert(s_instance != nullptr); |
9f95a23c TL |
38 | s_instance->on_finish = on_finish; |
39 | return s_instance; | |
7c673cae FG |
40 | } |
41 | ||
9f95a23c | 42 | PromoteRequest() { |
7c673cae FG |
43 | s_instance = this; |
44 | } | |
45 | ||
9f95a23c | 46 | MOCK_METHOD0(send, void()); |
7c673cae FG |
47 | }; |
48 | ||
9f95a23c TL |
49 | PromoteRequest<librbd::MockTestImageCtx> *PromoteRequest<librbd::MockTestImageCtx>::s_instance = nullptr; |
50 | ||
51 | } // namespace journal | |
7c673cae | 52 | |
9f95a23c | 53 | namespace mirror { |
7c673cae | 54 | template <> |
9f95a23c TL |
55 | struct GetInfoRequest<librbd::MockTestImageCtx> { |
56 | cls::rbd::MirrorImage *mirror_image; | |
57 | PromotionState *promotion_state; | |
58 | Context *on_finish = nullptr; | |
59 | static GetInfoRequest *s_instance; | |
60 | static GetInfoRequest *create(librbd::MockTestImageCtx &, | |
61 | cls::rbd::MirrorImage *mirror_image, | |
62 | PromotionState *promotion_state, | |
63 | std::string* primary_mirror_uuid, | |
64 | Context *on_finish) { | |
11fdf7f2 | 65 | ceph_assert(s_instance != nullptr); |
9f95a23c TL |
66 | s_instance->mirror_image = mirror_image; |
67 | s_instance->promotion_state = promotion_state; | |
68 | s_instance->on_finish = on_finish; | |
69 | return s_instance; | |
7c673cae FG |
70 | } |
71 | ||
9f95a23c | 72 | GetInfoRequest() { |
7c673cae FG |
73 | s_instance = this; |
74 | } | |
75 | ||
9f95a23c | 76 | MOCK_METHOD0(send, void()); |
7c673cae FG |
77 | }; |
78 | ||
9f95a23c TL |
79 | template <> |
80 | struct ImageRemoveRequest<librbd::MockTestImageCtx> { | |
81 | static ImageRemoveRequest* s_instance; | |
82 | Context* on_finish = nullptr; | |
83 | ||
84 | static ImageRemoveRequest* create( | |
85 | librados::IoCtx& io_ctx, | |
86 | const std::string& global_image_id, | |
87 | const std::string& image_id, | |
88 | Context* on_finish) { | |
89 | ceph_assert(s_instance != nullptr); | |
90 | s_instance->on_finish = on_finish; | |
91 | return s_instance; | |
92 | } | |
7c673cae | 93 | |
9f95a23c TL |
94 | MOCK_METHOD0(send, void()); |
95 | ||
96 | ImageRemoveRequest() { | |
97 | s_instance = this; | |
98 | } | |
99 | }; | |
100 | ||
101 | template <> | |
102 | struct ImageStateUpdateRequest<librbd::MockTestImageCtx> { | |
103 | static ImageStateUpdateRequest* s_instance; | |
104 | Context* on_finish = nullptr; | |
105 | ||
106 | static ImageStateUpdateRequest* create( | |
107 | librados::IoCtx& io_ctx, | |
108 | const std::string& image_id, | |
109 | cls::rbd::MirrorImageState mirror_image_state, | |
110 | const cls::rbd::MirrorImage& mirror_image, | |
111 | Context* on_finish) { | |
112 | ceph_assert(s_instance != nullptr); | |
113 | s_instance->on_finish = on_finish; | |
114 | return s_instance; | |
115 | } | |
116 | ||
117 | MOCK_METHOD0(send, void()); | |
118 | ||
119 | ImageStateUpdateRequest() { | |
120 | s_instance = this; | |
121 | } | |
122 | }; | |
123 | ||
124 | GetInfoRequest<librbd::MockTestImageCtx> *GetInfoRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
125 | ImageRemoveRequest<librbd::MockTestImageCtx> *ImageRemoveRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
126 | ImageStateUpdateRequest<librbd::MockTestImageCtx> *ImageStateUpdateRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
127 | ||
128 | namespace snapshot { | |
7c673cae FG |
129 | |
130 | template <> | |
131 | struct PromoteRequest<librbd::MockTestImageCtx> { | |
132 | Context *on_finish = nullptr; | |
133 | static PromoteRequest *s_instance; | |
9f95a23c TL |
134 | static PromoteRequest *create(librbd::MockTestImageCtx*, |
135 | const std::string& global_image_id, | |
7c673cae | 136 | Context *on_finish) { |
11fdf7f2 | 137 | ceph_assert(s_instance != nullptr); |
7c673cae FG |
138 | s_instance->on_finish = on_finish; |
139 | return s_instance; | |
140 | } | |
141 | ||
142 | PromoteRequest() { | |
143 | s_instance = this; | |
144 | } | |
145 | ||
146 | MOCK_METHOD0(send, void()); | |
147 | }; | |
148 | ||
149 | PromoteRequest<librbd::MockTestImageCtx> *PromoteRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
150 | ||
9f95a23c TL |
151 | } // namespace snapshot |
152 | } // namespace mirror | |
7c673cae FG |
153 | } // namespace librbd |
154 | ||
155 | // template definitions | |
156 | #include "librbd/mirror/DisableRequest.cc" | |
157 | template class librbd::mirror::DisableRequest<librbd::MockTestImageCtx>; | |
158 | ||
9f95a23c TL |
159 | ACTION_P(TestFeatures, image_ctx) { |
160 | return ((image_ctx->features & arg0) != 0); | |
161 | } | |
162 | ||
7c673cae FG |
163 | namespace librbd { |
164 | namespace mirror { | |
165 | ||
166 | using ::testing::_; | |
167 | using ::testing::DoAll; | |
168 | using ::testing::InSequence; | |
9f95a23c | 169 | using ::testing::Invoke; |
7c673cae | 170 | using ::testing::Return; |
7c673cae FG |
171 | using ::testing::StrEq; |
172 | using ::testing::WithArg; | |
173 | ||
174 | class TestMockMirrorDisableRequest : public TestMockFixture { | |
175 | public: | |
176 | typedef DisableRequest<MockTestImageCtx> MockDisableRequest; | |
177 | typedef Journal<MockTestImageCtx> MockJournal; | |
9f95a23c TL |
178 | typedef journal::PromoteRequest<MockTestImageCtx> MockJournalPromoteRequest; |
179 | typedef mirror::GetInfoRequest<MockTestImageCtx> MockGetInfoRequest; | |
180 | typedef mirror::ImageRemoveRequest<MockTestImageCtx> MockImageRemoveRequest; | |
181 | typedef mirror::ImageStateUpdateRequest<MockTestImageCtx> MockImageStateUpdateRequest; | |
182 | typedef mirror::snapshot::PromoteRequest<MockTestImageCtx> MockSnapshotPromoteRequest; | |
183 | ||
184 | void expect_get_mirror_info(MockTestImageCtx &mock_image_ctx, | |
185 | MockGetInfoRequest &mock_get_info_request, | |
186 | const cls::rbd::MirrorImage &mirror_image, | |
187 | PromotionState promotion_state, int r) { | |
188 | ||
189 | EXPECT_CALL(mock_get_info_request, send()) | |
190 | .WillOnce( | |
f67539c2 | 191 | Invoke([&mock_image_ctx, &mock_get_info_request, mirror_image, |
9f95a23c TL |
192 | promotion_state, r]() { |
193 | if (r == 0) { | |
194 | *mock_get_info_request.mirror_image = mirror_image; | |
195 | *mock_get_info_request.promotion_state = promotion_state; | |
196 | } | |
197 | mock_image_ctx.op_work_queue->queue( | |
198 | mock_get_info_request.on_finish, r); | |
199 | })); | |
7c673cae FG |
200 | } |
201 | ||
9f95a23c TL |
202 | void expect_mirror_image_state_update( |
203 | MockTestImageCtx &mock_image_ctx, | |
204 | MockImageStateUpdateRequest& mock_request, int r) { | |
205 | EXPECT_CALL(mock_request, send()) | |
206 | .WillOnce( | |
f67539c2 | 207 | Invoke([&mock_image_ctx, &mock_request, r]() { |
9f95a23c TL |
208 | mock_image_ctx.op_work_queue->queue(mock_request.on_finish, r); |
209 | })); | |
7c673cae FG |
210 | } |
211 | ||
9f95a23c TL |
212 | void expect_mirror_image_remove( |
213 | MockTestImageCtx &mock_image_ctx, | |
214 | MockImageRemoveRequest& mock_request, int r) { | |
215 | EXPECT_CALL(mock_request, send()) | |
216 | .WillOnce( | |
f67539c2 | 217 | Invoke([&mock_image_ctx, &mock_request, r]() { |
9f95a23c TL |
218 | mock_image_ctx.op_work_queue->queue(mock_request.on_finish, r); |
219 | })); | |
7c673cae FG |
220 | } |
221 | ||
222 | void expect_journal_client_list(MockTestImageCtx &mock_image_ctx, | |
223 | const std::set<cls::journal::Client> &clients, | |
224 | int r) { | |
225 | bufferlist bl; | |
11fdf7f2 TL |
226 | using ceph::encode; |
227 | encode(clients, bl); | |
7c673cae FG |
228 | |
229 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
230 | exec(::journal::Journaler::header_oid(mock_image_ctx.id), | |
f67539c2 | 231 | _, StrEq("journal"), StrEq("client_list"), _, _, _, _)) |
7c673cae FG |
232 | .WillOnce(DoAll(WithArg<5>(CopyInBufferlist(bl)), |
233 | Return(r))); | |
234 | } | |
235 | ||
236 | void expect_journal_client_unregister(MockTestImageCtx &mock_image_ctx, | |
237 | const std::string &client_id, | |
238 | int r) { | |
239 | bufferlist bl; | |
11fdf7f2 TL |
240 | using ceph::encode; |
241 | encode(client_id, bl); | |
7c673cae FG |
242 | |
243 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
244 | exec(::journal::Journaler::header_oid(mock_image_ctx.id), | |
245 | _, StrEq("journal"), StrEq("client_unregister"), | |
f67539c2 | 246 | ContentsEqual(bl), _, _, _)) |
7c673cae FG |
247 | .WillOnce(Return(r)); |
248 | } | |
249 | ||
250 | void expect_journal_promote(MockTestImageCtx &mock_image_ctx, | |
9f95a23c TL |
251 | MockJournalPromoteRequest &mock_promote_request, |
252 | int r) { | |
7c673cae FG |
253 | EXPECT_CALL(mock_promote_request, send()) |
254 | .WillOnce(FinishRequest(&mock_promote_request, r, &mock_image_ctx)); | |
255 | } | |
256 | ||
9f95a23c TL |
257 | void expect_snapshot_promote(MockTestImageCtx &mock_image_ctx, |
258 | MockSnapshotPromoteRequest &mock_promote_request, | |
259 | int r) { | |
260 | EXPECT_CALL(mock_promote_request, send()) | |
261 | .WillOnce(FinishRequest(&mock_promote_request, r, &mock_image_ctx)); | |
262 | } | |
263 | ||
264 | void expect_is_refresh_required(MockTestImageCtx &mock_image_ctx, | |
265 | bool refresh_required) { | |
266 | EXPECT_CALL(*mock_image_ctx.state, is_refresh_required()) | |
267 | .WillOnce(Return(refresh_required)); | |
268 | } | |
269 | ||
270 | void expect_refresh_image(MockTestImageCtx &mock_image_ctx, int r) { | |
271 | EXPECT_CALL(*mock_image_ctx.state, refresh(_)) | |
272 | .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)); | |
273 | } | |
274 | ||
7c673cae FG |
275 | void expect_snap_remove(MockTestImageCtx &mock_image_ctx, |
276 | const std::string &snap_name, int r) { | |
91327a77 | 277 | EXPECT_CALL(*mock_image_ctx.operations, snap_remove(_, StrEq(snap_name), _)) |
7c673cae FG |
278 | .WillOnce(WithArg<2>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue))); |
279 | } | |
280 | ||
281 | template <typename T> | |
282 | bufferlist encode(const T &t) { | |
11fdf7f2 | 283 | using ceph::encode; |
7c673cae | 284 | bufferlist bl; |
11fdf7f2 | 285 | encode(t, bl); |
7c673cae FG |
286 | return bl; |
287 | } | |
288 | ||
289 | }; | |
290 | ||
291 | TEST_F(TestMockMirrorDisableRequest, Success) { | |
292 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
293 | ||
294 | librbd::ImageCtx *ictx; | |
295 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
296 | ||
297 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
298 | |
299 | expect_op_work_queue(mock_image_ctx); | |
300 | expect_snap_remove(mock_image_ctx, "snap 1", 0); | |
301 | expect_snap_remove(mock_image_ctx, "snap 2", 0); | |
302 | ||
303 | InSequence seq; | |
9f95a23c TL |
304 | |
305 | MockGetInfoRequest mock_get_info_request; | |
306 | expect_get_mirror_info( | |
307 | mock_image_ctx, mock_get_info_request, | |
308 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
309 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
310 | MockImageStateUpdateRequest mock_image_state_update_request; | |
311 | expect_mirror_image_state_update( | |
312 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
313 | expect_journal_client_list( |
314 | mock_image_ctx, { | |
315 | {"", encode(journal::ClientData{journal::ImageClientMeta{}})}, | |
316 | {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})}, | |
317 | {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{ | |
318 | "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)}, | |
319 | {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}} | |
320 | })} | |
321 | }, 0); | |
322 | expect_journal_client_unregister(mock_image_ctx, "peer 1", 0); | |
323 | expect_journal_client_unregister(mock_image_ctx, "peer 2", 0); | |
324 | expect_journal_client_list(mock_image_ctx, {}, 0); | |
9f95a23c TL |
325 | MockImageRemoveRequest mock_image_remove_request; |
326 | expect_mirror_image_remove( | |
327 | mock_image_ctx, mock_image_remove_request, 0); | |
7c673cae FG |
328 | |
329 | C_SaferCond ctx; | |
330 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
331 | req->send(); | |
332 | ASSERT_EQ(0, ctx.wait()); | |
333 | } | |
334 | ||
335 | TEST_F(TestMockMirrorDisableRequest, SuccessNoRemove) { | |
336 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
337 | ||
338 | librbd::ImageCtx *ictx; | |
339 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
340 | ||
341 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
342 | |
343 | expect_op_work_queue(mock_image_ctx); | |
344 | ||
345 | InSequence seq; | |
9f95a23c TL |
346 | |
347 | MockGetInfoRequest mock_get_info_request; | |
348 | expect_get_mirror_info( | |
349 | mock_image_ctx, mock_get_info_request, | |
350 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
351 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
352 | MockImageStateUpdateRequest mock_image_state_update_request; | |
353 | expect_mirror_image_state_update( | |
354 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
355 | expect_journal_client_list(mock_image_ctx, {}, 0); |
356 | ||
357 | C_SaferCond ctx; | |
358 | auto req = new MockDisableRequest(&mock_image_ctx, false, false, &ctx); | |
359 | req->send(); | |
360 | ASSERT_EQ(0, ctx.wait()); | |
361 | } | |
362 | ||
363 | TEST_F(TestMockMirrorDisableRequest, SuccessNonPrimary) { | |
364 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
365 | ||
366 | librbd::ImageCtx *ictx; | |
367 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
368 | ||
369 | MockTestImageCtx mock_image_ctx(*ictx); | |
9f95a23c | 370 | MockJournalPromoteRequest mock_promote_request; |
7c673cae FG |
371 | |
372 | expect_op_work_queue(mock_image_ctx); | |
373 | ||
374 | InSequence seq; | |
9f95a23c TL |
375 | |
376 | MockGetInfoRequest mock_get_info_request; | |
377 | expect_get_mirror_info( | |
378 | mock_image_ctx, mock_get_info_request, | |
379 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
380 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0); | |
381 | MockImageStateUpdateRequest mock_image_state_update_request; | |
382 | expect_mirror_image_state_update( | |
383 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae | 384 | expect_journal_promote(mock_image_ctx, mock_promote_request, 0); |
9f95a23c | 385 | expect_is_refresh_required(mock_image_ctx, false); |
7c673cae | 386 | expect_journal_client_list(mock_image_ctx, {}, 0); |
9f95a23c TL |
387 | MockImageRemoveRequest mock_image_remove_request; |
388 | expect_mirror_image_remove( | |
389 | mock_image_ctx, mock_image_remove_request, 0); | |
7c673cae FG |
390 | |
391 | C_SaferCond ctx; | |
392 | auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx); | |
393 | req->send(); | |
394 | ASSERT_EQ(0, ctx.wait()); | |
395 | } | |
396 | ||
397 | TEST_F(TestMockMirrorDisableRequest, NonPrimaryError) { | |
398 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
399 | ||
400 | librbd::ImageCtx *ictx; | |
401 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
402 | ||
403 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
404 | |
405 | expect_op_work_queue(mock_image_ctx); | |
406 | ||
407 | InSequence seq; | |
9f95a23c TL |
408 | |
409 | MockGetInfoRequest mock_get_info_request; | |
410 | expect_get_mirror_info( | |
411 | mock_image_ctx, mock_get_info_request, | |
412 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
413 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0); | |
7c673cae FG |
414 | |
415 | C_SaferCond ctx; | |
416 | auto req = new MockDisableRequest(&mock_image_ctx, false, false, &ctx); | |
417 | req->send(); | |
418 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
419 | } | |
420 | ||
9f95a23c | 421 | TEST_F(TestMockMirrorDisableRequest, GetMirrorInfoError) { |
7c673cae FG |
422 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); |
423 | ||
424 | librbd::ImageCtx *ictx; | |
425 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
426 | ||
427 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
428 | |
429 | expect_op_work_queue(mock_image_ctx); | |
430 | ||
431 | InSequence seq; | |
7c673cae | 432 | |
9f95a23c TL |
433 | MockGetInfoRequest mock_get_info_request; |
434 | expect_get_mirror_info( | |
435 | mock_image_ctx, mock_get_info_request, | |
436 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
437 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, -EINVAL); | |
7c673cae FG |
438 | |
439 | C_SaferCond ctx; | |
440 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
441 | req->send(); | |
9f95a23c | 442 | ASSERT_EQ(-EINVAL, ctx.wait()); |
7c673cae FG |
443 | } |
444 | ||
445 | TEST_F(TestMockMirrorDisableRequest, MirrorImageSetError) { | |
446 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
447 | ||
448 | librbd::ImageCtx *ictx; | |
449 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
450 | ||
451 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
452 | |
453 | expect_op_work_queue(mock_image_ctx); | |
454 | ||
455 | InSequence seq; | |
9f95a23c TL |
456 | |
457 | MockGetInfoRequest mock_get_info_request; | |
458 | expect_get_mirror_info( | |
459 | mock_image_ctx, mock_get_info_request, | |
460 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
461 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
462 | MockImageStateUpdateRequest mock_image_state_update_request; | |
463 | expect_mirror_image_state_update( | |
464 | mock_image_ctx, mock_image_state_update_request, -ENOENT); | |
7c673cae FG |
465 | |
466 | C_SaferCond ctx; | |
467 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
468 | req->send(); | |
469 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
470 | } | |
471 | ||
472 | TEST_F(TestMockMirrorDisableRequest, JournalPromoteError) { | |
7c673cae FG |
473 | librbd::ImageCtx *ictx; |
474 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
475 | ||
476 | MockTestImageCtx mock_image_ctx(*ictx); | |
9f95a23c | 477 | MockJournalPromoteRequest mock_promote_request; |
7c673cae FG |
478 | |
479 | expect_op_work_queue(mock_image_ctx); | |
480 | ||
481 | InSequence seq; | |
9f95a23c TL |
482 | |
483 | MockGetInfoRequest mock_get_info_request; | |
484 | expect_get_mirror_info( | |
485 | mock_image_ctx, mock_get_info_request, | |
486 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
487 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0); | |
488 | MockImageStateUpdateRequest mock_image_state_update_request; | |
489 | expect_mirror_image_state_update( | |
490 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
491 | expect_journal_promote(mock_image_ctx, mock_promote_request, -EPERM); |
492 | ||
493 | C_SaferCond ctx; | |
494 | auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx); | |
495 | req->send(); | |
496 | ASSERT_EQ(-EPERM, ctx.wait()); | |
497 | } | |
498 | ||
499 | TEST_F(TestMockMirrorDisableRequest, JournalClientListError) { | |
500 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
501 | ||
502 | librbd::ImageCtx *ictx; | |
503 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
504 | ||
505 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
506 | |
507 | expect_op_work_queue(mock_image_ctx); | |
508 | ||
509 | InSequence seq; | |
9f95a23c TL |
510 | |
511 | MockGetInfoRequest mock_get_info_request; | |
512 | expect_get_mirror_info( | |
513 | mock_image_ctx, mock_get_info_request, | |
514 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
515 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
516 | MockImageStateUpdateRequest mock_image_state_update_request; | |
517 | expect_mirror_image_state_update( | |
518 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
519 | expect_journal_client_list(mock_image_ctx, {}, -EBADMSG); |
520 | ||
521 | C_SaferCond ctx; | |
522 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
523 | req->send(); | |
524 | ASSERT_EQ(-EBADMSG, ctx.wait()); | |
525 | } | |
526 | ||
527 | TEST_F(TestMockMirrorDisableRequest, SnapRemoveError) { | |
528 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
529 | ||
530 | librbd::ImageCtx *ictx; | |
531 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
532 | ||
533 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
534 | |
535 | expect_op_work_queue(mock_image_ctx); | |
536 | expect_snap_remove(mock_image_ctx, "snap 1", 0); | |
537 | expect_snap_remove(mock_image_ctx, "snap 2", -EPERM); | |
538 | ||
539 | InSequence seq; | |
9f95a23c TL |
540 | |
541 | MockGetInfoRequest mock_get_info_request; | |
542 | expect_get_mirror_info( | |
543 | mock_image_ctx, mock_get_info_request, | |
544 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
545 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
546 | MockImageStateUpdateRequest mock_image_state_update_request; | |
547 | expect_mirror_image_state_update( | |
548 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
549 | expect_journal_client_list( |
550 | mock_image_ctx, { | |
551 | {"", encode(journal::ClientData{journal::ImageClientMeta{}})}, | |
552 | {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})}, | |
553 | {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{ | |
554 | "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)}, | |
555 | {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}} | |
556 | })} | |
557 | }, 0); | |
558 | expect_journal_client_unregister(mock_image_ctx, "peer 1", 0); | |
559 | ||
560 | C_SaferCond ctx; | |
561 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
562 | req->send(); | |
563 | ASSERT_EQ(-EPERM, ctx.wait()); | |
564 | } | |
565 | ||
566 | TEST_F(TestMockMirrorDisableRequest, JournalClientUnregisterError) { | |
567 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
568 | ||
569 | librbd::ImageCtx *ictx; | |
570 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
571 | ||
572 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
573 | |
574 | expect_op_work_queue(mock_image_ctx); | |
575 | expect_snap_remove(mock_image_ctx, "snap 1", 0); | |
576 | expect_snap_remove(mock_image_ctx, "snap 2", 0); | |
577 | ||
578 | InSequence seq; | |
9f95a23c TL |
579 | |
580 | MockGetInfoRequest mock_get_info_request; | |
581 | expect_get_mirror_info( | |
582 | mock_image_ctx, mock_get_info_request, | |
583 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
584 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
585 | MockImageStateUpdateRequest mock_image_state_update_request; | |
586 | expect_mirror_image_state_update( | |
587 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae FG |
588 | expect_journal_client_list( |
589 | mock_image_ctx, { | |
590 | {"", encode(journal::ClientData{journal::ImageClientMeta{}})}, | |
591 | {"peer 1", encode(journal::ClientData{journal::MirrorPeerClientMeta{}})}, | |
592 | {"peer 2", encode(journal::ClientData{journal::MirrorPeerClientMeta{ | |
593 | "remote image id", {{cls::rbd::UserSnapshotNamespace(), "snap 1", boost::optional<uint64_t>(0)}, | |
594 | {cls::rbd::UserSnapshotNamespace(), "snap 2", boost::optional<uint64_t>(0)}}} | |
595 | })} | |
596 | }, 0); | |
597 | expect_journal_client_unregister(mock_image_ctx, "peer 1", -EINVAL); | |
598 | expect_journal_client_unregister(mock_image_ctx, "peer 2", 0); | |
599 | ||
600 | C_SaferCond ctx; | |
601 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
602 | req->send(); | |
603 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
604 | } | |
605 | ||
9f95a23c TL |
606 | TEST_F(TestMockMirrorDisableRequest, SnapshotPromoteError) { |
607 | librbd::ImageCtx *ictx; | |
608 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
609 | ||
610 | MockTestImageCtx mock_image_ctx(*ictx); | |
611 | MockSnapshotPromoteRequest mock_promote_request; | |
612 | ||
613 | expect_op_work_queue(mock_image_ctx); | |
614 | ||
615 | InSequence seq; | |
616 | ||
617 | MockGetInfoRequest mock_get_info_request; | |
618 | expect_get_mirror_info( | |
619 | mock_image_ctx, mock_get_info_request, | |
620 | {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, "global id", | |
621 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0); | |
622 | MockImageStateUpdateRequest mock_image_state_update_request; | |
623 | expect_mirror_image_state_update( | |
624 | mock_image_ctx, mock_image_state_update_request, 0); | |
625 | expect_snapshot_promote(mock_image_ctx, mock_promote_request, -EPERM); | |
626 | ||
627 | C_SaferCond ctx; | |
628 | auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx); | |
629 | req->send(); | |
630 | ASSERT_EQ(-EPERM, ctx.wait()); | |
631 | } | |
632 | ||
633 | TEST_F(TestMockMirrorDisableRequest, RefreshError) { | |
634 | librbd::ImageCtx *ictx; | |
635 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
636 | ||
637 | MockTestImageCtx mock_image_ctx(*ictx); | |
638 | MockSnapshotPromoteRequest mock_promote_request; | |
639 | ||
640 | expect_op_work_queue(mock_image_ctx); | |
641 | ||
642 | InSequence seq; | |
643 | ||
644 | MockGetInfoRequest mock_get_info_request; | |
645 | expect_get_mirror_info( | |
646 | mock_image_ctx, mock_get_info_request, | |
647 | {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, "global id", | |
648 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_NON_PRIMARY, 0); | |
649 | MockImageStateUpdateRequest mock_image_state_update_request; | |
650 | expect_mirror_image_state_update( | |
651 | mock_image_ctx, mock_image_state_update_request, 0); | |
652 | expect_snapshot_promote(mock_image_ctx, mock_promote_request, 0); | |
653 | expect_is_refresh_required(mock_image_ctx, true); | |
654 | expect_refresh_image(mock_image_ctx, -EPERM); | |
655 | ||
656 | C_SaferCond ctx; | |
657 | auto req = new MockDisableRequest(&mock_image_ctx, true, true, &ctx); | |
658 | req->send(); | |
659 | ASSERT_EQ(-EPERM, ctx.wait()); | |
660 | } | |
661 | ||
7c673cae FG |
662 | TEST_F(TestMockMirrorDisableRequest, MirrorImageRemoveError) { |
663 | REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); | |
664 | ||
665 | librbd::ImageCtx *ictx; | |
666 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
667 | ||
668 | MockTestImageCtx mock_image_ctx(*ictx); | |
7c673cae FG |
669 | |
670 | expect_op_work_queue(mock_image_ctx); | |
671 | ||
672 | InSequence seq; | |
9f95a23c TL |
673 | |
674 | MockGetInfoRequest mock_get_info_request; | |
675 | expect_get_mirror_info( | |
676 | mock_image_ctx, mock_get_info_request, | |
677 | {cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "global id", | |
678 | cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, PROMOTION_STATE_PRIMARY, 0); | |
679 | MockImageStateUpdateRequest mock_image_state_update_request; | |
680 | expect_mirror_image_state_update( | |
681 | mock_image_ctx, mock_image_state_update_request, 0); | |
7c673cae | 682 | expect_journal_client_list(mock_image_ctx, {}, 0); |
9f95a23c TL |
683 | MockImageRemoveRequest mock_image_remove_request; |
684 | expect_mirror_image_remove( | |
685 | mock_image_ctx, mock_image_remove_request, -EINVAL); | |
7c673cae FG |
686 | |
687 | C_SaferCond ctx; | |
688 | auto req = new MockDisableRequest(&mock_image_ctx, false, true, &ctx); | |
689 | req->send(); | |
690 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
691 | } | |
692 | ||
693 | } // namespace mirror | |
694 | } // namespace librbd |