]>
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/rbd_mirror/test_mock_fixture.h" | |
5 | #include "include/rbd/librbd.hpp" | |
6 | #include "librbd/ImageState.h" | |
7 | #include "librbd/Operations.h" | |
8 | #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" | |
9 | #include "test/librados_test_stub/MockTestMemRadosClient.h" | |
10 | #include "test/librbd/mock/MockImageCtx.h" | |
11 | #include "tools/rbd_mirror/image_replayer/CreateImageRequest.h" | |
12 | #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h" | |
13 | #include "tools/rbd_mirror/image_replayer/OpenImageRequest.h" | |
14 | #include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h" | |
15 | #include "librbd/image/CreateRequest.h" | |
16 | #include "librbd/image/CloneRequest.h" | |
17 | #include "tools/rbd_mirror/Threads.h" | |
18 | ||
19 | namespace librbd { | |
20 | ||
21 | namespace { | |
22 | ||
23 | struct MockTestImageCtx : public librbd::MockImageCtx { | |
24 | MockTestImageCtx(librbd::ImageCtx &image_ctx) | |
25 | : librbd::MockImageCtx(image_ctx) { | |
26 | } | |
27 | }; | |
28 | ||
29 | } // anonymous namespace | |
30 | ||
31 | namespace image { | |
32 | ||
33 | template<> | |
34 | struct CreateRequest<librbd::MockTestImageCtx> { | |
35 | static CreateRequest *s_instance; | |
36 | Context *on_finish = nullptr; | |
37 | ||
38 | static CreateRequest *create(IoCtx &ioctx, const std::string &imgname, | |
39 | const std::string &imageid, uint64_t size, | |
40 | const librbd::ImageOptions &image_options, | |
41 | const std::string &non_primary_global_image_id, | |
42 | const std::string &primary_mirror_uuid, | |
43 | bool skip_mirror_enable, | |
44 | MockContextWQ *op_work_queue, | |
45 | Context *on_finish) { | |
46 | assert(s_instance != nullptr); | |
47 | EXPECT_FALSE(non_primary_global_image_id.empty()); | |
48 | EXPECT_FALSE(primary_mirror_uuid.empty()); | |
49 | EXPECT_FALSE(skip_mirror_enable); | |
50 | s_instance->on_finish = on_finish; | |
51 | s_instance->construct(ioctx); | |
52 | return s_instance; | |
53 | } | |
54 | ||
55 | CreateRequest() { | |
56 | s_instance = this; | |
57 | } | |
58 | ||
59 | ~CreateRequest() { | |
60 | s_instance = nullptr; | |
61 | } | |
62 | ||
63 | MOCK_METHOD0(send, void()); | |
64 | MOCK_METHOD1(construct, void(librados::IoCtx &ioctx)); | |
65 | }; | |
66 | ||
67 | CreateRequest<librbd::MockTestImageCtx>* | |
68 | CreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
69 | ||
70 | template<> | |
71 | struct CloneRequest<librbd::MockTestImageCtx> { | |
72 | static CloneRequest *s_instance; | |
73 | Context *on_finish = nullptr; | |
74 | ||
75 | static CloneRequest *create(librbd::MockTestImageCtx *p_imctx, | |
76 | IoCtx &c_ioctx, const std::string &c_name, | |
77 | const std::string &c_id, ImageOptions c_options, | |
78 | const std::string &non_primary_global_image_id, | |
79 | const std::string &primary_mirror_uuid, | |
80 | MockContextWQ *op_work_queue, Context *on_finish) { | |
81 | assert(s_instance != nullptr); | |
82 | s_instance->on_finish = on_finish; | |
83 | s_instance->construct(p_imctx); | |
84 | return s_instance; | |
85 | } | |
86 | ||
87 | CloneRequest() { | |
88 | s_instance = this; | |
89 | } | |
90 | ||
91 | ~CloneRequest() { | |
92 | s_instance = nullptr; | |
93 | } | |
94 | ||
95 | MOCK_METHOD0(send, void()); | |
96 | MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *p_imctx)); | |
97 | }; | |
98 | ||
99 | CloneRequest<librbd::MockTestImageCtx>* | |
100 | CloneRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
101 | ||
102 | } // namespace image | |
103 | } // namespace librbd | |
104 | ||
105 | namespace rbd { | |
106 | namespace mirror { | |
107 | namespace image_replayer { | |
108 | ||
109 | template<> | |
110 | struct CloseImageRequest<librbd::MockTestImageCtx> { | |
111 | static CloseImageRequest* s_instance; | |
112 | Context *on_finish = nullptr; | |
113 | ||
114 | static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx, | |
115 | Context *on_finish) { | |
116 | assert(s_instance != nullptr); | |
117 | s_instance->construct(*image_ctx); | |
118 | s_instance->on_finish = on_finish; | |
119 | return s_instance; | |
120 | } | |
121 | ||
122 | CloseImageRequest() { | |
123 | assert(s_instance == nullptr); | |
124 | s_instance = this; | |
125 | } | |
126 | ~CloseImageRequest() { | |
127 | s_instance = nullptr; | |
128 | } | |
129 | ||
130 | MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *image_ctx)); | |
131 | MOCK_METHOD0(send, void()); | |
132 | }; | |
133 | ||
134 | template<> | |
135 | struct OpenImageRequest<librbd::MockTestImageCtx> { | |
136 | static OpenImageRequest* s_instance; | |
137 | librbd::MockTestImageCtx **image_ctx = nullptr; | |
138 | Context *on_finish = nullptr; | |
139 | ||
140 | static OpenImageRequest* create(librados::IoCtx &io_ctx, | |
141 | librbd::MockTestImageCtx **image_ctx, | |
142 | const std::string &image_id, | |
143 | bool read_only, Context *on_finish) { | |
144 | assert(s_instance != nullptr); | |
145 | s_instance->image_ctx = image_ctx; | |
146 | s_instance->on_finish = on_finish; | |
147 | s_instance->construct(io_ctx, image_id); | |
148 | return s_instance; | |
149 | } | |
150 | ||
151 | OpenImageRequest() { | |
152 | assert(s_instance == nullptr); | |
153 | s_instance = this; | |
154 | } | |
155 | ~OpenImageRequest() { | |
156 | s_instance = nullptr; | |
157 | } | |
158 | ||
159 | MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx, | |
160 | const std::string &image_id)); | |
161 | MOCK_METHOD0(send, void()); | |
162 | }; | |
163 | ||
164 | CloseImageRequest<librbd::MockTestImageCtx>* | |
165 | CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
166 | OpenImageRequest<librbd::MockTestImageCtx>* | |
167 | OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; | |
168 | ||
169 | } // namespace image_replayer | |
170 | } // namespace mirror | |
171 | } // namespace rbd | |
172 | ||
173 | // template definitions | |
174 | #include "tools/rbd_mirror/image_replayer/CreateImageRequest.cc" | |
175 | template class rbd::mirror::image_replayer::CreateImageRequest<librbd::MockTestImageCtx>; | |
176 | ||
177 | namespace rbd { | |
178 | namespace mirror { | |
179 | namespace image_replayer { | |
180 | ||
181 | using ::testing::_; | |
182 | using ::testing::DoAll; | |
183 | using ::testing::InSequence; | |
184 | using ::testing::Invoke; | |
185 | using ::testing::Return; | |
186 | using ::testing::StrEq; | |
187 | using ::testing::WithArg; | |
188 | ||
189 | MATCHER_P(IsSameIoCtx, io_ctx, "") { | |
190 | return &get_mock_io_ctx(arg) == &get_mock_io_ctx(*io_ctx); | |
191 | } | |
192 | ||
193 | class TestMockImageReplayerCreateImageRequest : public TestMockFixture { | |
194 | public: | |
195 | typedef librbd::image::CreateRequest<librbd::MockTestImageCtx> MockCreateRequest; | |
196 | typedef librbd::image::CloneRequest<librbd::MockTestImageCtx> MockCloneRequest; | |
197 | typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest; | |
198 | typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest; | |
199 | typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest; | |
200 | ||
201 | void SetUp() override { | |
202 | TestMockFixture::SetUp(); | |
203 | ||
204 | librbd::RBD rbd; | |
205 | ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size)); | |
206 | ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx)); | |
207 | } | |
208 | ||
209 | int clone_image(librbd::ImageCtx *parent_image_ctx, | |
210 | const std::string &snap_name, const std::string &clone_name) { | |
211 | { | |
212 | librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_ctx->name, | |
213 | "", "", m_remote_io_ctx, | |
214 | false); | |
215 | ictx->state->open(false); | |
216 | EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(), | |
217 | snap_name.c_str())); | |
218 | EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(), | |
219 | snap_name.c_str())); | |
220 | ictx->state->close(); | |
221 | } | |
222 | ||
223 | EXPECT_EQ(0, parent_image_ctx->state->refresh()); | |
224 | ||
225 | int order = 0; | |
226 | return librbd::clone(m_remote_io_ctx, parent_image_ctx->name.c_str(), | |
227 | snap_name.c_str(), m_remote_io_ctx, | |
228 | clone_name.c_str(), parent_image_ctx->features, | |
229 | &order, 0, 0); | |
230 | } | |
231 | ||
232 | void expect_create_image(MockCreateRequest &mock_create_request, | |
233 | librados::IoCtx &ioctx, int r) { | |
234 | EXPECT_CALL(mock_create_request, construct(IsSameIoCtx(&ioctx))); | |
235 | EXPECT_CALL(mock_create_request, send()) | |
236 | .WillOnce(Invoke([this, &mock_create_request, r]() { | |
237 | m_threads->work_queue->queue(mock_create_request.on_finish, r); | |
238 | })); | |
239 | } | |
240 | ||
241 | void expect_ioctx_create(librados::IoCtx &io_ctx) { | |
242 | EXPECT_CALL(*get_mock_io_ctx(io_ctx).get_mock_rados_client(), create_ioctx(_, _)) | |
243 | .WillOnce(Return(&get_mock_io_ctx(io_ctx))); | |
244 | } | |
245 | ||
246 | void expect_get_parent_global_image_id(librados::IoCtx &io_ctx, | |
247 | const std::string &global_id, int r) { | |
248 | cls::rbd::MirrorImage mirror_image; | |
249 | mirror_image.global_image_id = global_id; | |
250 | ||
251 | bufferlist bl; | |
252 | ::encode(mirror_image, bl); | |
253 | ||
254 | EXPECT_CALL(get_mock_io_ctx(io_ctx), | |
255 | exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get"), _, _, _)) | |
256 | .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) { | |
257 | *out_bl = bl; | |
258 | })), | |
259 | Return(r))); | |
260 | } | |
261 | ||
262 | void expect_mirror_image_get_image_id(librados::IoCtx &io_ctx, | |
263 | const std::string &image_id, int r) { | |
264 | bufferlist bl; | |
265 | ::encode(image_id, bl); | |
266 | ||
267 | EXPECT_CALL(get_mock_io_ctx(io_ctx), | |
268 | exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get_image_id"), _, _, _)) | |
269 | .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) { | |
270 | *out_bl = bl; | |
271 | })), | |
272 | Return(r))); | |
273 | } | |
274 | ||
275 | void expect_open_image(MockOpenImageRequest &mock_open_image_request, | |
276 | librados::IoCtx &io_ctx, const std::string &image_id, | |
277 | librbd::MockTestImageCtx &mock_image_ctx, int r) { | |
278 | EXPECT_CALL(mock_open_image_request, construct(IsSameIoCtx(&io_ctx), image_id)); | |
279 | EXPECT_CALL(mock_open_image_request, send()) | |
280 | .WillOnce(Invoke([this, &mock_open_image_request, &mock_image_ctx, r]() { | |
281 | *mock_open_image_request.image_ctx = &mock_image_ctx; | |
282 | m_threads->work_queue->queue(mock_open_image_request.on_finish, r); | |
283 | })); | |
284 | } | |
285 | ||
286 | void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx, | |
287 | const std::string &snap_name, int r) { | |
288 | EXPECT_CALL(*mock_image_ctx.state, snap_set(_, StrEq(snap_name), _)) | |
289 | .WillOnce(WithArg<2>(Invoke([this, r](Context *on_finish) { | |
290 | m_threads->work_queue->queue(on_finish, r); | |
291 | }))); | |
292 | } | |
293 | ||
294 | void expect_clone_image(MockCloneRequest &mock_clone_request, | |
295 | librbd::MockTestImageCtx &mock_parent_imctx, | |
296 | int r) { | |
297 | EXPECT_CALL(mock_clone_request, construct(&mock_parent_imctx)); | |
298 | EXPECT_CALL(mock_clone_request, send()) | |
299 | .WillOnce(Invoke([this, &mock_clone_request, r]() { | |
300 | m_threads->work_queue->queue(mock_clone_request.on_finish, r); | |
301 | })); | |
302 | } | |
303 | ||
304 | void expect_close_image(MockCloseImageRequest &mock_close_image_request, | |
305 | librbd::MockTestImageCtx &mock_image_ctx, int r) { | |
306 | EXPECT_CALL(mock_close_image_request, construct(&mock_image_ctx)); | |
307 | EXPECT_CALL(mock_close_image_request, send()) | |
308 | .WillOnce(Invoke([this, &mock_close_image_request, r]() { | |
309 | m_threads->work_queue->queue(mock_close_image_request.on_finish, r); | |
310 | })); | |
311 | } | |
312 | ||
313 | MockCreateImageRequest *create_request(const std::string &global_image_id, | |
314 | const std::string &remote_mirror_uuid, | |
315 | const std::string &local_image_name, | |
d2e6a577 | 316 | const std::string &local_image_id, |
7c673cae | 317 | librbd::MockTestImageCtx &mock_remote_image_ctx, |
7c673cae FG |
318 | Context *on_finish) { |
319 | return new MockCreateImageRequest(m_local_io_ctx, m_threads->work_queue, | |
320 | global_image_id, remote_mirror_uuid, | |
d2e6a577 FG |
321 | local_image_name, local_image_id, |
322 | &mock_remote_image_ctx, on_finish); | |
7c673cae FG |
323 | } |
324 | ||
325 | librbd::ImageCtx *m_remote_image_ctx; | |
326 | }; | |
327 | ||
328 | TEST_F(TestMockImageReplayerCreateImageRequest, Create) { | |
329 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
330 | MockCreateRequest mock_create_request; | |
331 | ||
332 | InSequence seq; | |
333 | expect_create_image(mock_create_request, m_local_io_ctx, 0); | |
334 | ||
335 | C_SaferCond ctx; | |
7c673cae | 336 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 FG |
337 | "image name", "101241a7c4c9", |
338 | mock_remote_image_ctx, &ctx); | |
7c673cae FG |
339 | request->send(); |
340 | ASSERT_EQ(0, ctx.wait()); | |
7c673cae FG |
341 | } |
342 | ||
343 | TEST_F(TestMockImageReplayerCreateImageRequest, CreateError) { | |
344 | librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); | |
345 | MockCreateRequest mock_create_request; | |
346 | ||
347 | InSequence seq; | |
348 | expect_create_image(mock_create_request, m_local_io_ctx, -EINVAL); | |
349 | ||
350 | C_SaferCond ctx; | |
7c673cae | 351 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 FG |
352 | "image name", "101241a7c4c9", |
353 | mock_remote_image_ctx, &ctx); | |
7c673cae FG |
354 | request->send(); |
355 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
356 | } | |
357 | ||
358 | TEST_F(TestMockImageReplayerCreateImageRequest, Clone) { | |
359 | librbd::RBD rbd; | |
360 | librbd::ImageCtx *local_image_ctx; | |
361 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
362 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
363 | ||
364 | std::string clone_image_name = get_temp_image_name(); | |
365 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
366 | ||
367 | librbd::ImageCtx *remote_clone_image_ctx; | |
368 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
369 | &remote_clone_image_ctx)); | |
370 | ||
371 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
372 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
373 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
374 | MockCloneRequest mock_clone_request; | |
375 | MockOpenImageRequest mock_open_image_request; | |
376 | MockCloseImageRequest mock_close_image_request; | |
377 | ||
378 | InSequence seq; | |
379 | expect_ioctx_create(m_remote_io_ctx); | |
380 | expect_ioctx_create(m_local_io_ctx); | |
381 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
382 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
383 | ||
384 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
385 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
386 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
387 | "local parent id", mock_local_parent_image_ctx, 0); | |
388 | expect_snap_set(mock_local_parent_image_ctx, "snap", 0); | |
389 | expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); | |
390 | expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); | |
391 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); | |
392 | ||
393 | C_SaferCond ctx; | |
7c673cae | 394 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 395 | "image name", "101241a7c4c9", |
7c673cae | 396 | mock_remote_clone_image_ctx, |
d2e6a577 | 397 | &ctx); |
7c673cae FG |
398 | request->send(); |
399 | ASSERT_EQ(0, ctx.wait()); | |
7c673cae FG |
400 | } |
401 | ||
402 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) { | |
403 | std::string clone_image_name = get_temp_image_name(); | |
404 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
405 | ||
406 | librbd::ImageCtx *remote_clone_image_ctx; | |
407 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
408 | &remote_clone_image_ctx)); | |
409 | ||
410 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
411 | MockCloneRequest mock_clone_request; | |
412 | ||
413 | InSequence seq; | |
414 | expect_ioctx_create(m_remote_io_ctx); | |
415 | expect_ioctx_create(m_local_io_ctx); | |
416 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT); | |
417 | ||
418 | C_SaferCond ctx; | |
7c673cae | 419 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 420 | "image name", "101241a7c4c9", |
7c673cae | 421 | mock_remote_clone_image_ctx, |
d2e6a577 | 422 | &ctx); |
7c673cae FG |
423 | request->send(); |
424 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
425 | } | |
426 | ||
427 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetLocalParentImageIdError) { | |
428 | std::string clone_image_name = get_temp_image_name(); | |
429 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
430 | ||
431 | librbd::ImageCtx *remote_clone_image_ctx; | |
432 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
433 | &remote_clone_image_ctx)); | |
434 | ||
435 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
436 | MockCloneRequest mock_clone_request; | |
437 | ||
438 | InSequence seq; | |
439 | expect_ioctx_create(m_remote_io_ctx); | |
440 | expect_ioctx_create(m_local_io_ctx); | |
441 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
442 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT); | |
443 | ||
444 | C_SaferCond ctx; | |
7c673cae | 445 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 446 | "image name", "101241a7c4c9", |
7c673cae | 447 | mock_remote_clone_image_ctx, |
d2e6a577 | 448 | &ctx); |
7c673cae FG |
449 | request->send(); |
450 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
451 | } | |
452 | ||
453 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) { | |
454 | std::string clone_image_name = get_temp_image_name(); | |
455 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
456 | ||
457 | librbd::ImageCtx *remote_clone_image_ctx; | |
458 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
459 | &remote_clone_image_ctx)); | |
460 | ||
461 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
462 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
463 | MockCloneRequest mock_clone_request; | |
464 | MockOpenImageRequest mock_open_image_request; | |
465 | ||
466 | InSequence seq; | |
467 | expect_ioctx_create(m_remote_io_ctx); | |
468 | expect_ioctx_create(m_local_io_ctx); | |
469 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
470 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
471 | ||
472 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
473 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, -ENOENT); | |
474 | ||
475 | C_SaferCond ctx; | |
7c673cae | 476 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 477 | "image name", "101241a7c4c9", |
7c673cae | 478 | mock_remote_clone_image_ctx, |
d2e6a577 | 479 | &ctx); |
7c673cae FG |
480 | request->send(); |
481 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
482 | } | |
483 | ||
484 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenLocalParentError) { | |
485 | librbd::RBD rbd; | |
486 | librbd::ImageCtx *local_image_ctx; | |
487 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
488 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
489 | ||
490 | std::string clone_image_name = get_temp_image_name(); | |
491 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
492 | ||
493 | librbd::ImageCtx *remote_clone_image_ctx; | |
494 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
495 | &remote_clone_image_ctx)); | |
496 | ||
497 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
498 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
499 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
500 | MockCloneRequest mock_clone_request; | |
501 | MockOpenImageRequest mock_open_image_request; | |
502 | MockCloseImageRequest mock_close_image_request; | |
503 | ||
504 | InSequence seq; | |
505 | expect_ioctx_create(m_remote_io_ctx); | |
506 | expect_ioctx_create(m_local_io_ctx); | |
507 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
508 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
509 | ||
510 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
511 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
512 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
513 | "local parent id", mock_local_parent_image_ctx, -ENOENT); | |
514 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); | |
515 | ||
516 | C_SaferCond ctx; | |
7c673cae | 517 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 518 | "image name", "101241a7c4c9", |
7c673cae | 519 | mock_remote_clone_image_ctx, |
d2e6a577 | 520 | &ctx); |
7c673cae FG |
521 | request->send(); |
522 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
523 | } | |
524 | ||
525 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneSnapSetError) { | |
526 | librbd::RBD rbd; | |
527 | librbd::ImageCtx *local_image_ctx; | |
528 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
529 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
530 | ||
531 | std::string clone_image_name = get_temp_image_name(); | |
532 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
533 | ||
534 | librbd::ImageCtx *remote_clone_image_ctx; | |
535 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
536 | &remote_clone_image_ctx)); | |
537 | ||
538 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
539 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
540 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
541 | MockCloneRequest mock_clone_request; | |
542 | MockOpenImageRequest mock_open_image_request; | |
543 | MockCloseImageRequest mock_close_image_request; | |
544 | ||
545 | InSequence seq; | |
546 | expect_ioctx_create(m_remote_io_ctx); | |
547 | expect_ioctx_create(m_local_io_ctx); | |
548 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
549 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
550 | ||
551 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
552 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
553 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
554 | "local parent id", mock_local_parent_image_ctx, 0); | |
555 | expect_snap_set(mock_local_parent_image_ctx, "snap", -ENOENT); | |
556 | expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); | |
557 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); | |
558 | ||
559 | C_SaferCond ctx; | |
7c673cae | 560 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 561 | "image name", "101241a7c4c9", |
7c673cae | 562 | mock_remote_clone_image_ctx, |
d2e6a577 | 563 | &ctx); |
7c673cae FG |
564 | request->send(); |
565 | ASSERT_EQ(-ENOENT, ctx.wait()); | |
566 | } | |
567 | ||
568 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) { | |
569 | librbd::RBD rbd; | |
570 | librbd::ImageCtx *local_image_ctx; | |
571 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
572 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
573 | ||
574 | std::string clone_image_name = get_temp_image_name(); | |
575 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
576 | ||
577 | librbd::ImageCtx *remote_clone_image_ctx; | |
578 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
579 | &remote_clone_image_ctx)); | |
580 | ||
581 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
582 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
583 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
584 | MockCloneRequest mock_clone_request; | |
585 | MockOpenImageRequest mock_open_image_request; | |
586 | MockCloseImageRequest mock_close_image_request; | |
587 | ||
588 | InSequence seq; | |
589 | expect_ioctx_create(m_remote_io_ctx); | |
590 | expect_ioctx_create(m_local_io_ctx); | |
591 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
592 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
593 | ||
594 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
595 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
596 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
597 | "local parent id", mock_local_parent_image_ctx, 0); | |
598 | expect_snap_set(mock_local_parent_image_ctx, "snap", 0); | |
599 | expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, -EINVAL); | |
600 | expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); | |
601 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); | |
602 | ||
603 | C_SaferCond ctx; | |
7c673cae | 604 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 605 | "image name", "101241a7c4c9", |
7c673cae | 606 | mock_remote_clone_image_ctx, |
d2e6a577 | 607 | &ctx); |
7c673cae FG |
608 | request->send(); |
609 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
610 | } | |
611 | ||
612 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneLocalParentCloseError) { | |
613 | librbd::RBD rbd; | |
614 | librbd::ImageCtx *local_image_ctx; | |
615 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
616 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
617 | ||
618 | std::string clone_image_name = get_temp_image_name(); | |
619 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
620 | ||
621 | librbd::ImageCtx *remote_clone_image_ctx; | |
622 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
623 | &remote_clone_image_ctx)); | |
624 | ||
625 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
626 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
627 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
628 | MockCloneRequest mock_clone_request; | |
629 | MockOpenImageRequest mock_open_image_request; | |
630 | MockCloseImageRequest mock_close_image_request; | |
631 | ||
632 | InSequence seq; | |
633 | expect_ioctx_create(m_remote_io_ctx); | |
634 | expect_ioctx_create(m_local_io_ctx); | |
635 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
636 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
637 | ||
638 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
639 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
640 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
641 | "local parent id", mock_local_parent_image_ctx, 0); | |
642 | expect_snap_set(mock_local_parent_image_ctx, "snap", 0); | |
643 | expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); | |
644 | expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, -EINVAL); | |
645 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); | |
646 | ||
647 | C_SaferCond ctx; | |
7c673cae | 648 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 649 | "image name", "101241a7c4c9", |
7c673cae | 650 | mock_remote_clone_image_ctx, |
d2e6a577 | 651 | &ctx); |
7c673cae FG |
652 | request->send(); |
653 | ASSERT_EQ(0, ctx.wait()); | |
7c673cae FG |
654 | } |
655 | ||
656 | TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) { | |
657 | librbd::RBD rbd; | |
658 | librbd::ImageCtx *local_image_ctx; | |
659 | ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); | |
660 | ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); | |
661 | ||
662 | std::string clone_image_name = get_temp_image_name(); | |
663 | ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); | |
664 | ||
665 | librbd::ImageCtx *remote_clone_image_ctx; | |
666 | ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, | |
667 | &remote_clone_image_ctx)); | |
668 | ||
669 | librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); | |
670 | librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); | |
671 | librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); | |
672 | MockCloneRequest mock_clone_request; | |
673 | MockOpenImageRequest mock_open_image_request; | |
674 | MockCloseImageRequest mock_close_image_request; | |
675 | ||
676 | InSequence seq; | |
677 | expect_ioctx_create(m_remote_io_ctx); | |
678 | expect_ioctx_create(m_local_io_ctx); | |
679 | expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); | |
680 | expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); | |
681 | ||
682 | expect_open_image(mock_open_image_request, m_remote_io_ctx, | |
683 | m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); | |
684 | expect_open_image(mock_open_image_request, m_local_io_ctx, | |
685 | "local parent id", mock_local_parent_image_ctx, 0); | |
686 | expect_snap_set(mock_local_parent_image_ctx, "snap", 0); | |
687 | expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); | |
688 | expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); | |
689 | expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL); | |
690 | ||
691 | C_SaferCond ctx; | |
7c673cae | 692 | MockCreateImageRequest *request = create_request("global uuid", "remote uuid", |
d2e6a577 | 693 | "image name", "101241a7c4c9", |
7c673cae | 694 | mock_remote_clone_image_ctx, |
d2e6a577 | 695 | &ctx); |
7c673cae FG |
696 | request->send(); |
697 | ASSERT_EQ(0, ctx.wait()); | |
7c673cae FG |
698 | } |
699 | ||
700 | } // namespace image_replayer | |
701 | } // namespace mirror | |
702 | } // namespace rbd |