]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/image/test_mock_CloneRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / librbd / image / test_mock_CloneRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7 #include "test/librbd/mock/MockContextWQ.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "librbd/ImageState.h"
11 #include "librbd/Operations.h"
12 #include "librbd/image/TypeTraits.h"
13 #include "librbd/image/AttachChildRequest.h"
14 #include "librbd/image/AttachParentRequest.h"
15 #include "librbd/image/CreateRequest.h"
16 #include "librbd/image/RemoveRequest.h"
17 #include "librbd/mirror/EnableRequest.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20
21 namespace librbd {
22 namespace {
23
24 struct MockTestImageCtx : public MockImageCtx {
25 static MockTestImageCtx* s_instance;
26 static MockTestImageCtx* create(const std::string &image_name,
27 const std::string &image_id,
28 const char *snap, librados::IoCtx& p,
29 bool read_only) {
30 ceph_assert(s_instance != nullptr);
31 return s_instance;
32 }
33 static MockTestImageCtx* create(const std::string &image_name,
34 const std::string &image_id,
35 librados::snap_t snap_id, IoCtx& p,
36 bool read_only) {
37 ceph_assert(s_instance != nullptr);
38 return s_instance;
39 }
40
41 MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
42 s_instance = this;
43 }
44 };
45
46 MockTestImageCtx* MockTestImageCtx::s_instance = nullptr;
47
48 } // anonymous namespace
49
50 namespace image {
51
52 template <>
53 struct AttachChildRequest<MockTestImageCtx> {
54 uint32_t clone_format;
55 Context* on_finish = nullptr;
56 static AttachChildRequest* s_instance;
57 static AttachChildRequest* create(MockTestImageCtx *,
58 MockTestImageCtx *,
59 const librados::snap_t &,
60 MockTestImageCtx *,
61 const librados::snap_t &,
62 uint32_t clone_format,
63 Context *on_finish) {
64 ceph_assert(s_instance != nullptr);
65 s_instance->clone_format = clone_format;
66 s_instance->on_finish = on_finish;
67 return s_instance;
68 }
69
70 MOCK_METHOD0(send, void());
71
72 AttachChildRequest() {
73 s_instance = this;
74 }
75 };
76
77 AttachChildRequest<MockTestImageCtx>* AttachChildRequest<MockTestImageCtx>::s_instance = nullptr;
78
79 template <>
80 struct AttachParentRequest<MockTestImageCtx> {
81 Context* on_finish = nullptr;
82 static AttachParentRequest* s_instance;
83 static AttachParentRequest* create(MockTestImageCtx&,
84 const cls::rbd::ParentImageSpec& pspec,
85 uint64_t parent_overlap, bool reattach,
86 Context *on_finish) {
87 ceph_assert(s_instance != nullptr);
88 s_instance->on_finish = on_finish;
89 return s_instance;
90 }
91
92 MOCK_METHOD0(send, void());
93
94 AttachParentRequest() {
95 s_instance = this;
96 }
97 };
98
99 AttachParentRequest<MockTestImageCtx>* AttachParentRequest<MockTestImageCtx>::s_instance = nullptr;
100
101 template <>
102 struct CreateRequest<MockTestImageCtx> {
103 Context* on_finish = nullptr;
104 static CreateRequest* s_instance;
105 static CreateRequest* create(const ConfigProxy& config, IoCtx &ioctx,
106 const std::string &image_name,
107 const std::string &image_id, uint64_t size,
108 const ImageOptions &image_options,
109 const std::string &non_primary_global_image_id,
110 const std::string &primary_mirror_uuid,
111 bool skip_mirror_enable,
112 ContextWQ *op_work_queue,
113 Context *on_finish) {
114 ceph_assert(s_instance != nullptr);
115 s_instance->on_finish = on_finish;
116 return s_instance;
117 }
118
119 MOCK_METHOD0(send, void());
120
121 CreateRequest() {
122 s_instance = this;
123 }
124 };
125
126 CreateRequest<MockTestImageCtx>* CreateRequest<MockTestImageCtx>::s_instance = nullptr;
127
128 template <>
129 struct RemoveRequest<MockTestImageCtx> {
130 Context* on_finish = nullptr;
131 static RemoveRequest* s_instance;
132 static RemoveRequest* create(librados::IoCtx &ioctx,
133 const std::string &image_name,
134 const std::string &image_id,
135 bool force, bool from_trash_remove,
136 ProgressContext &prog_ctx,
137 ContextWQ *op_work_queue,
138 Context *on_finish) {
139 ceph_assert(s_instance != nullptr);
140 s_instance->on_finish = on_finish;
141 return s_instance;
142 }
143
144 MOCK_METHOD0(send, void());
145
146 RemoveRequest() {
147 s_instance = this;
148 }
149 };
150
151 RemoveRequest<MockTestImageCtx>* RemoveRequest<MockTestImageCtx>::s_instance = nullptr;
152
153 } // namespace image
154
155 namespace mirror {
156
157 template <>
158 struct EnableRequest<MockTestImageCtx> {
159 Context* on_finish = nullptr;
160 static EnableRequest* s_instance;
161 static EnableRequest* create(librados::IoCtx &io_ctx,
162 const std::string &image_id,
163 const std::string &non_primary_global_image_id,
164 MockContextWQ *op_work_queue,
165 Context *on_finish) {
166 ceph_assert(s_instance != nullptr);
167 s_instance->on_finish = on_finish;
168 return s_instance;
169 }
170
171 MOCK_METHOD0(send, void());
172
173 EnableRequest() {
174 s_instance = this;
175 }
176 };
177
178 EnableRequest<MockTestImageCtx>* EnableRequest<MockTestImageCtx>::s_instance = nullptr;
179
180 } // namespace mirror
181 } // namespace librbd
182
183 // template definitions
184 #include "librbd/image/CloneRequest.cc"
185
186 namespace librbd {
187 namespace image {
188
189 using ::testing::_;
190 using ::testing::Invoke;
191 using ::testing::InSequence;
192 using ::testing::Return;
193 using ::testing::StrEq;
194 using ::testing::WithArg;
195
196 class TestMockImageCloneRequest : public TestMockFixture {
197 public:
198 typedef CloneRequest<MockTestImageCtx> MockCloneRequest;
199 typedef AttachChildRequest<MockTestImageCtx> MockAttachChildRequest;
200 typedef AttachParentRequest<MockTestImageCtx> MockAttachParentRequest;
201 typedef CreateRequest<MockTestImageCtx> MockCreateRequest;
202 typedef RemoveRequest<MockTestImageCtx> MockRemoveRequest;
203 typedef mirror::EnableRequest<MockTestImageCtx> MockMirrorEnableRequest;
204
205 void SetUp() override {
206 TestMockFixture::SetUp();
207
208 ASSERT_EQ(0, _rados.conf_set("rbd_default_clone_format", "2"));
209
210 ASSERT_EQ(0, open_image(m_image_name, &image_ctx));
211 ASSERT_EQ(0, image_ctx->operations->snap_create(
212 cls::rbd::UserSnapshotNamespace{}, "snap"));
213 if (is_feature_enabled(RBD_FEATURE_LAYERING)) {
214 ASSERT_EQ(0, image_ctx->operations->snap_protect(
215 cls::rbd::UserSnapshotNamespace{}, "snap"));
216
217 uint64_t snap_id = image_ctx->snap_ids[
218 {cls::rbd::UserSnapshotNamespace{}, "snap"}];
219 ASSERT_NE(CEPH_NOSNAP, snap_id);
220
221 C_SaferCond ctx;
222 image_ctx->state->snap_set(snap_id, &ctx);
223 ASSERT_EQ(0, ctx.wait());
224 }
225 }
226
227 void expect_get_min_compat_client(int8_t min_compat_client, int r) {
228 auto mock_rados_client = get_mock_io_ctx(m_ioctx).get_mock_rados_client();
229 EXPECT_CALL(*mock_rados_client, get_min_compatible_client(_, _))
230 .WillOnce(Invoke([min_compat_client, r](int8_t* min, int8_t* required_min) {
231 *min = min_compat_client;
232 *required_min = min_compat_client;
233 return r;
234 }));
235 }
236
237 void expect_get_image_size(MockTestImageCtx &mock_image_ctx, uint64_t snap_id,
238 uint64_t size) {
239 EXPECT_CALL(mock_image_ctx, get_image_size(snap_id))
240 .WillOnce(Return(size));
241 }
242
243 void expect_is_snap_protected(MockImageCtx &mock_image_ctx, bool is_protected,
244 int r) {
245 EXPECT_CALL(mock_image_ctx, is_snap_protected(_, _))
246 .WillOnce(WithArg<1>(Invoke([is_protected, r](bool* is_prot) {
247 *is_prot = is_protected;
248 return r;
249 })));
250 }
251
252 void expect_create(MockCreateRequest& mock_create_request, int r) {
253 EXPECT_CALL(mock_create_request, send())
254 .WillOnce(Invoke([this, &mock_create_request, r]() {
255 image_ctx->op_work_queue->queue(mock_create_request.on_finish, r);
256 }));
257 }
258
259 void expect_open(MockImageCtx &mock_image_ctx, int r) {
260 EXPECT_CALL(*mock_image_ctx.state, open(true, _))
261 .WillOnce(WithArg<1>(Invoke([this, r](Context* ctx) {
262 image_ctx->op_work_queue->queue(ctx, r);
263 })));
264 if (r < 0) {
265 EXPECT_CALL(mock_image_ctx, destroy());
266 }
267 }
268
269 void expect_attach_parent(MockAttachParentRequest& mock_request, int r) {
270 EXPECT_CALL(mock_request, send())
271 .WillOnce(Invoke([this, &mock_request, r]() {
272 image_ctx->op_work_queue->queue(mock_request.on_finish, r);
273 }));
274 }
275
276 void expect_attach_child(MockAttachChildRequest& mock_request,
277 uint32_t clone_format, int r) {
278 EXPECT_CALL(mock_request, send())
279 .WillOnce(Invoke([this, &mock_request, clone_format, r]() {
280 EXPECT_EQ(mock_request.clone_format, clone_format);
281 image_ctx->op_work_queue->queue(mock_request.on_finish, r);
282 }));
283 }
284
285 void expect_metadata_list(MockTestImageCtx &mock_image_ctx,
286 const std::map<std::string, bufferlist>& metadata,
287 int r) {
288 bufferlist out_bl;
289 encode(metadata, out_bl);
290
291 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
292 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("metadata_list"), _, _, _))
293 .WillOnce(WithArg<5>(Invoke([out_bl, r](bufferlist *out) {
294 *out = out_bl;
295 return r;
296 })));
297 }
298
299 void expect_metadata_set(librados::IoCtx& io_ctx,
300 MockTestImageCtx& mock_image_ctx,
301 const std::map<std::string, bufferlist>& metadata,
302 int r) {
303 bufferlist in_bl;
304 encode(metadata, in_bl);
305
306 EXPECT_CALL(get_mock_io_ctx(io_ctx),
307 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("metadata_set"),
308 ContentsEqual(in_bl), _, _))
309 .WillOnce(Return(r));
310 }
311
312 void expect_test_features(MockTestImageCtx &mock_image_ctx,
313 uint64_t features, bool enabled) {
314 EXPECT_CALL(mock_image_ctx, test_features(features))
315 .WillOnce(Return(enabled));
316 }
317
318 void expect_mirror_mode_get(MockTestImageCtx &mock_image_ctx,
319 cls::rbd::MirrorMode mirror_mode, int r) {
320 bufferlist out_bl;
321 encode(static_cast<uint32_t>(mirror_mode), out_bl);
322
323 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
324 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_mode_get"),
325 _, _, _))
326 .WillOnce(WithArg<5>(Invoke([out_bl, r](bufferlist* out) {
327 *out = out_bl;
328 return r;
329 })));
330 }
331
332 void expect_mirror_enable(MockMirrorEnableRequest& mock_mirror_enable_request,
333 int r) {
334 EXPECT_CALL(mock_mirror_enable_request, send())
335 .WillOnce(Invoke([this, &mock_mirror_enable_request, r]() {
336 image_ctx->op_work_queue->queue(mock_mirror_enable_request.on_finish, r);
337 }));
338 }
339
340 void expect_close(MockImageCtx &mock_image_ctx, int r) {
341 EXPECT_CALL(*mock_image_ctx.state, close(_))
342 .WillOnce(Invoke([this, r](Context* ctx) {
343 image_ctx->op_work_queue->queue(ctx, r);
344 }));
345 EXPECT_CALL(mock_image_ctx, destroy());
346 }
347
348 void expect_remove(MockRemoveRequest& mock_remove_request, int r) {
349 EXPECT_CALL(mock_remove_request, send())
350 .WillOnce(Invoke([this, &mock_remove_request, r]() {
351 image_ctx->op_work_queue->queue(mock_remove_request.on_finish, r);
352 }));
353 }
354
355 librbd::ImageCtx *image_ctx;
356 };
357
358 TEST_F(TestMockImageCloneRequest, SuccessV1) {
359 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
360 ASSERT_EQ(0, _rados.conf_set("rbd_default_clone_format", "1"));
361
362 MockTestImageCtx mock_image_ctx(*image_ctx);
363 expect_op_work_queue(mock_image_ctx);
364
365 InSequence seq;
366 expect_open(mock_image_ctx, 0);
367
368 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
369 expect_is_snap_protected(mock_image_ctx, true, 0);
370
371 MockCreateRequest mock_create_request;
372 expect_create(mock_create_request, 0);
373
374 expect_open(mock_image_ctx, 0);
375
376 MockAttachParentRequest mock_attach_parent_request;
377 expect_attach_parent(mock_attach_parent_request, 0);
378
379 MockAttachChildRequest mock_attach_child_request;
380 expect_attach_child(mock_attach_child_request, 1, 0);
381
382 expect_metadata_list(mock_image_ctx, {{"key", {}}}, 0);
383 expect_metadata_set(m_ioctx, mock_image_ctx, {{"key", {}}}, 0);
384
385 MockMirrorEnableRequest mock_mirror_enable_request;
386 if (is_feature_enabled(RBD_FEATURE_JOURNALING)) {
387 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
388 expect_mirror_mode_get(mock_image_ctx, cls::rbd::MIRROR_MODE_POOL, 0);
389
390 expect_mirror_enable(mock_mirror_enable_request, 0);
391 } else {
392 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, false);
393 }
394
395 expect_close(mock_image_ctx, 0);
396 expect_close(mock_image_ctx, 0);
397
398 C_SaferCond ctx;
399 ImageOptions clone_opts;
400 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
401 m_ioctx, "clone name", "clone id", clone_opts,
402 "", "", image_ctx->op_work_queue, &ctx);
403 req->send();
404 ASSERT_EQ(0, ctx.wait());
405 }
406
407 TEST_F(TestMockImageCloneRequest, SuccessV2) {
408 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
409 ASSERT_EQ(0, _rados.conf_set("rbd_default_clone_format", "2"));
410
411 MockTestImageCtx mock_image_ctx(*image_ctx);
412 expect_op_work_queue(mock_image_ctx);
413
414 InSequence seq;
415 expect_open(mock_image_ctx, 0);
416
417 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
418 expect_is_snap_protected(mock_image_ctx, true, 0);
419
420 MockCreateRequest mock_create_request;
421 expect_create(mock_create_request, 0);
422
423 expect_open(mock_image_ctx, 0);
424
425 MockAttachParentRequest mock_attach_parent_request;
426 expect_attach_parent(mock_attach_parent_request, 0);
427
428 MockAttachChildRequest mock_attach_child_request;
429 expect_attach_child(mock_attach_child_request, 2, 0);
430
431 expect_metadata_list(mock_image_ctx, {{"key", {}}}, 0);
432 expect_metadata_set(m_ioctx, mock_image_ctx, {{"key", {}}}, 0);
433
434 MockMirrorEnableRequest mock_mirror_enable_request;
435 if (is_feature_enabled(RBD_FEATURE_JOURNALING)) {
436 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
437 expect_mirror_mode_get(mock_image_ctx, cls::rbd::MIRROR_MODE_POOL, 0);
438
439 expect_mirror_enable(mock_mirror_enable_request, 0);
440 } else {
441 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, false);
442 }
443
444 expect_close(mock_image_ctx, 0);
445 expect_close(mock_image_ctx, 0);
446
447 C_SaferCond ctx;
448 ImageOptions clone_opts;
449 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
450 m_ioctx, "clone name", "clone id", clone_opts,
451 "", "", image_ctx->op_work_queue, &ctx);
452 req->send();
453 ASSERT_EQ(0, ctx.wait());
454 }
455
456 TEST_F(TestMockImageCloneRequest, SuccessAuto) {
457 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
458 ASSERT_EQ(0, _rados.conf_set("rbd_default_clone_format", "auto"));
459
460 MockTestImageCtx mock_image_ctx(*image_ctx);
461 expect_op_work_queue(mock_image_ctx);
462
463 InSequence seq;
464 expect_open(mock_image_ctx, 0);
465
466 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
467 expect_is_snap_protected(mock_image_ctx, true, 0);
468
469 MockCreateRequest mock_create_request;
470 expect_create(mock_create_request, 0);
471
472 expect_open(mock_image_ctx, 0);
473
474 MockAttachParentRequest mock_attach_parent_request;
475 expect_attach_parent(mock_attach_parent_request, 0);
476
477 MockAttachChildRequest mock_attach_child_request;
478 expect_attach_child(mock_attach_child_request, 2, 0);
479
480 expect_metadata_list(mock_image_ctx, {{"key", {}}}, 0);
481 expect_metadata_set(m_ioctx, mock_image_ctx, {{"key", {}}}, 0);
482
483 MockMirrorEnableRequest mock_mirror_enable_request;
484 if (is_feature_enabled(RBD_FEATURE_JOURNALING)) {
485 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
486 expect_mirror_mode_get(mock_image_ctx, cls::rbd::MIRROR_MODE_POOL, 0);
487
488 expect_mirror_enable(mock_mirror_enable_request, 0);
489 } else {
490 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, false);
491 }
492
493 expect_close(mock_image_ctx, 0);
494 expect_close(mock_image_ctx, 0);
495
496 C_SaferCond ctx;
497 ImageOptions clone_opts;
498 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
499 m_ioctx, "clone name", "clone id", clone_opts,
500 "", "", image_ctx->op_work_queue, &ctx);
501 req->send();
502 ASSERT_EQ(0, ctx.wait());
503 }
504
505 TEST_F(TestMockImageCloneRequest, OpenParentError) {
506 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
507
508 MockTestImageCtx mock_image_ctx(*image_ctx);
509 expect_op_work_queue(mock_image_ctx);
510
511 InSequence seq;
512 expect_open(mock_image_ctx, -EINVAL);
513
514 C_SaferCond ctx;
515 ImageOptions clone_opts;
516 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
517 m_ioctx, "clone name", "clone id", clone_opts,
518 "", "", image_ctx->op_work_queue, &ctx);
519 req->send();
520 ASSERT_EQ(-EINVAL, ctx.wait());
521 }
522
523 TEST_F(TestMockImageCloneRequest, CreateError) {
524 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
525
526 MockTestImageCtx mock_image_ctx(*image_ctx);
527 expect_op_work_queue(mock_image_ctx);
528
529 InSequence seq;
530 expect_open(mock_image_ctx, 0);
531
532 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
533 expect_is_snap_protected(mock_image_ctx, true, 0);
534
535 MockCreateRequest mock_create_request;
536 expect_create(mock_create_request, -EINVAL);
537
538 expect_close(mock_image_ctx, 0);
539
540 C_SaferCond ctx;
541 ImageOptions clone_opts;
542 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
543 m_ioctx, "clone name", "clone id", clone_opts,
544 "", "", image_ctx->op_work_queue, &ctx);
545 req->send();
546 ASSERT_EQ(-EINVAL, ctx.wait());
547 }
548
549 TEST_F(TestMockImageCloneRequest, OpenError) {
550 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
551
552 MockTestImageCtx mock_image_ctx(*image_ctx);
553 expect_op_work_queue(mock_image_ctx);
554
555 InSequence seq;
556 expect_open(mock_image_ctx, 0);
557
558 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
559 expect_is_snap_protected(mock_image_ctx, true, 0);
560
561 MockCreateRequest mock_create_request;
562 expect_create(mock_create_request, 0);
563
564 expect_open(mock_image_ctx, -EINVAL);
565
566 MockRemoveRequest mock_remove_request;
567 expect_remove(mock_remove_request, 0);
568
569 expect_close(mock_image_ctx, 0);
570
571 C_SaferCond ctx;
572 ImageOptions clone_opts;
573 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
574 m_ioctx, "clone name", "clone id", clone_opts,
575 "", "", image_ctx->op_work_queue, &ctx);
576 req->send();
577 ASSERT_EQ(-EINVAL, ctx.wait());
578 }
579
580 TEST_F(TestMockImageCloneRequest, AttachParentError) {
581 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
582
583 MockTestImageCtx mock_image_ctx(*image_ctx);
584 expect_op_work_queue(mock_image_ctx);
585
586 InSequence seq;
587 expect_open(mock_image_ctx, 0);
588
589 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
590 expect_is_snap_protected(mock_image_ctx, true, 0);
591
592 MockCreateRequest mock_create_request;
593 expect_create(mock_create_request, 0);
594
595 expect_open(mock_image_ctx, 0);
596
597 MockAttachParentRequest mock_attach_parent_request;
598 expect_attach_parent(mock_attach_parent_request, -EINVAL);
599
600 expect_close(mock_image_ctx, 0);
601
602 MockRemoveRequest mock_remove_request;
603 expect_remove(mock_remove_request, 0);
604
605 expect_close(mock_image_ctx, 0);
606
607 C_SaferCond ctx;
608 ImageOptions clone_opts;
609 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
610 m_ioctx, "clone name", "clone id", clone_opts,
611 "", "", image_ctx->op_work_queue, &ctx);
612 req->send();
613 ASSERT_EQ(-EINVAL, ctx.wait());
614 }
615
616 TEST_F(TestMockImageCloneRequest, AttachChildError) {
617 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
618
619 MockTestImageCtx mock_image_ctx(*image_ctx);
620 expect_op_work_queue(mock_image_ctx);
621
622 InSequence seq;
623 expect_open(mock_image_ctx, 0);
624
625 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
626 expect_is_snap_protected(mock_image_ctx, true, 0);
627
628 MockCreateRequest mock_create_request;
629 expect_create(mock_create_request, 0);
630
631 expect_open(mock_image_ctx, 0);
632
633 MockAttachParentRequest mock_attach_parent_request;
634 expect_attach_parent(mock_attach_parent_request, 0);
635
636 MockAttachChildRequest mock_attach_child_request;
637 expect_attach_child(mock_attach_child_request, 2, -EINVAL);
638
639 expect_close(mock_image_ctx, 0);
640
641 MockRemoveRequest mock_remove_request;
642 expect_remove(mock_remove_request, 0);
643
644 expect_close(mock_image_ctx, 0);
645
646 C_SaferCond ctx;
647 ImageOptions clone_opts;
648 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
649 m_ioctx, "clone name", "clone id", clone_opts,
650 "", "", image_ctx->op_work_queue, &ctx);
651 req->send();
652 ASSERT_EQ(-EINVAL, ctx.wait());
653 }
654
655 TEST_F(TestMockImageCloneRequest, MetadataListError) {
656 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
657
658 MockTestImageCtx mock_image_ctx(*image_ctx);
659 expect_op_work_queue(mock_image_ctx);
660
661 InSequence seq;
662 expect_open(mock_image_ctx, 0);
663
664 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
665 expect_is_snap_protected(mock_image_ctx, true, 0);
666
667 MockCreateRequest mock_create_request;
668 expect_create(mock_create_request, 0);
669
670 expect_open(mock_image_ctx, 0);
671
672 MockAttachParentRequest mock_attach_parent_request;
673 expect_attach_parent(mock_attach_parent_request, 0);
674
675 MockAttachChildRequest mock_attach_child_request;
676 expect_attach_child(mock_attach_child_request, 2, 0);
677
678 expect_metadata_list(mock_image_ctx, {{"key", {}}}, -EINVAL);
679
680 expect_close(mock_image_ctx, 0);
681
682 MockRemoveRequest mock_remove_request;
683 expect_remove(mock_remove_request, 0);
684
685 expect_close(mock_image_ctx, 0);
686
687 C_SaferCond ctx;
688 ImageOptions clone_opts;
689 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
690 m_ioctx, "clone name", "clone id", clone_opts,
691 "", "", image_ctx->op_work_queue, &ctx);
692 req->send();
693 ASSERT_EQ(-EINVAL, ctx.wait());
694 }
695
696 TEST_F(TestMockImageCloneRequest, MetadataSetError) {
697 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
698
699 MockTestImageCtx mock_image_ctx(*image_ctx);
700 expect_op_work_queue(mock_image_ctx);
701
702 InSequence seq;
703 expect_open(mock_image_ctx, 0);
704
705 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
706 expect_is_snap_protected(mock_image_ctx, true, 0);
707
708 MockCreateRequest mock_create_request;
709 expect_create(mock_create_request, 0);
710
711 expect_open(mock_image_ctx, 0);
712
713 MockAttachParentRequest mock_attach_parent_request;
714 expect_attach_parent(mock_attach_parent_request, 0);
715
716 MockAttachChildRequest mock_attach_child_request;
717 expect_attach_child(mock_attach_child_request, 2, 0);
718
719 expect_metadata_list(mock_image_ctx, {{"key", {}}}, 0);
720 expect_metadata_set(m_ioctx, mock_image_ctx, {{"key", {}}}, -EINVAL);
721
722 expect_close(mock_image_ctx, 0);
723
724 MockRemoveRequest mock_remove_request;
725 expect_remove(mock_remove_request, 0);
726
727 expect_close(mock_image_ctx, 0);
728
729 C_SaferCond ctx;
730 ImageOptions clone_opts;
731 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
732 m_ioctx, "clone name", "clone id", clone_opts,
733 "", "", image_ctx->op_work_queue, &ctx);
734 req->send();
735 ASSERT_EQ(-EINVAL, ctx.wait());
736 }
737
738 TEST_F(TestMockImageCloneRequest, GetMirrorModeError) {
739 REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_JOURNALING);
740
741 MockTestImageCtx mock_image_ctx(*image_ctx);
742 expect_op_work_queue(mock_image_ctx);
743
744 InSequence seq;
745 expect_open(mock_image_ctx, 0);
746
747 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
748 expect_is_snap_protected(mock_image_ctx, true, 0);
749
750 MockCreateRequest mock_create_request;
751 expect_create(mock_create_request, 0);
752
753 expect_open(mock_image_ctx, 0);
754
755 MockAttachParentRequest mock_attach_parent_request;
756 expect_attach_parent(mock_attach_parent_request, 0);
757
758 MockAttachChildRequest mock_attach_child_request;
759 expect_attach_child(mock_attach_child_request, 2, 0);
760
761 expect_metadata_list(mock_image_ctx, {}, 0);
762
763 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
764 expect_mirror_mode_get(mock_image_ctx, cls::rbd::MIRROR_MODE_POOL, -EINVAL);
765
766 expect_close(mock_image_ctx, 0);
767
768 MockRemoveRequest mock_remove_request;
769 expect_remove(mock_remove_request, 0);
770
771 expect_close(mock_image_ctx, 0);
772
773 C_SaferCond ctx;
774 ImageOptions clone_opts;
775 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
776 m_ioctx, "clone name", "clone id", clone_opts,
777 "", "", image_ctx->op_work_queue, &ctx);
778 req->send();
779 ASSERT_EQ(-EINVAL, ctx.wait());
780 }
781
782 TEST_F(TestMockImageCloneRequest, MirrorEnableError) {
783 REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_JOURNALING);
784
785 MockTestImageCtx mock_image_ctx(*image_ctx);
786 expect_op_work_queue(mock_image_ctx);
787
788 InSequence seq;
789 expect_open(mock_image_ctx, 0);
790
791 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
792 expect_is_snap_protected(mock_image_ctx, true, 0);
793
794 MockCreateRequest mock_create_request;
795 expect_create(mock_create_request, 0);
796
797 expect_open(mock_image_ctx, 0);
798
799 MockAttachParentRequest mock_attach_parent_request;
800 expect_attach_parent(mock_attach_parent_request, 0);
801
802 MockAttachChildRequest mock_attach_child_request;
803 expect_attach_child(mock_attach_child_request, 2, 0);
804
805 expect_metadata_list(mock_image_ctx, {}, 0);
806
807 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, true);
808 expect_mirror_mode_get(mock_image_ctx, cls::rbd::MIRROR_MODE_POOL, 0);
809
810 MockMirrorEnableRequest mock_mirror_enable_request;
811 expect_mirror_enable(mock_mirror_enable_request, -EINVAL);
812
813 expect_close(mock_image_ctx, 0);
814
815 MockRemoveRequest mock_remove_request;
816 expect_remove(mock_remove_request, 0);
817
818 expect_close(mock_image_ctx, 0);
819
820 C_SaferCond ctx;
821 ImageOptions clone_opts;
822 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
823 m_ioctx, "clone name", "clone id", clone_opts,
824 "", "", image_ctx->op_work_queue, &ctx);
825 req->send();
826 ASSERT_EQ(-EINVAL, ctx.wait());
827 }
828
829 TEST_F(TestMockImageCloneRequest, CloseError) {
830 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
831
832 MockTestImageCtx mock_image_ctx(*image_ctx);
833 expect_op_work_queue(mock_image_ctx);
834
835 InSequence seq;
836 expect_open(mock_image_ctx, 0);
837
838 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
839 expect_is_snap_protected(mock_image_ctx, true, 0);
840
841 MockCreateRequest mock_create_request;
842 expect_create(mock_create_request, 0);
843
844 expect_open(mock_image_ctx, 0);
845
846 MockAttachParentRequest mock_attach_parent_request;
847 expect_attach_parent(mock_attach_parent_request, 0);
848
849 MockAttachChildRequest mock_attach_child_request;
850 expect_attach_child(mock_attach_child_request, 2, 0);
851
852 expect_metadata_list(mock_image_ctx, {}, 0);
853 expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING, false);
854
855 expect_close(mock_image_ctx, -EINVAL);
856
857 MockRemoveRequest mock_remove_request;
858 expect_remove(mock_remove_request, 0);
859
860 expect_close(mock_image_ctx, 0);
861
862 C_SaferCond ctx;
863 ImageOptions clone_opts;
864 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
865 m_ioctx, "clone name", "clone id", clone_opts,
866 "", "", image_ctx->op_work_queue, &ctx);
867 req->send();
868 ASSERT_EQ(-EINVAL, ctx.wait());
869 }
870
871 TEST_F(TestMockImageCloneRequest, RemoveError) {
872 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
873
874 MockTestImageCtx mock_image_ctx(*image_ctx);
875 expect_op_work_queue(mock_image_ctx);
876
877 InSequence seq;
878 expect_open(mock_image_ctx, 0);
879
880 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
881 expect_is_snap_protected(mock_image_ctx, true, 0);
882
883 MockCreateRequest mock_create_request;
884 expect_create(mock_create_request, 0);
885
886 expect_open(mock_image_ctx, -EINVAL);
887
888 MockRemoveRequest mock_remove_request;
889 expect_remove(mock_remove_request, -EPERM);
890
891 expect_close(mock_image_ctx, 0);
892
893 C_SaferCond ctx;
894 ImageOptions clone_opts;
895 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
896 m_ioctx, "clone name", "clone id", clone_opts,
897 "", "", image_ctx->op_work_queue, &ctx);
898 req->send();
899 ASSERT_EQ(-EINVAL, ctx.wait());
900 }
901
902 TEST_F(TestMockImageCloneRequest, CloseParentError) {
903 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
904
905 MockTestImageCtx mock_image_ctx(*image_ctx);
906 expect_op_work_queue(mock_image_ctx);
907
908 InSequence seq;
909 expect_open(mock_image_ctx, 0);
910
911 expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123);
912 expect_is_snap_protected(mock_image_ctx, true, 0);
913
914 MockCreateRequest mock_create_request;
915 expect_create(mock_create_request, 0);
916
917 expect_open(mock_image_ctx, -EINVAL);
918
919 MockRemoveRequest mock_remove_request;
920 expect_remove(mock_remove_request, 0);
921
922 expect_close(mock_image_ctx, -EPERM);
923
924 C_SaferCond ctx;
925 ImageOptions clone_opts;
926 auto req = new MockCloneRequest(m_cct->_conf, m_ioctx, "parent id", "", 123,
927 m_ioctx, "clone name", "clone id", clone_opts,
928 "", "", image_ctx->op_work_queue, &ctx);
929 req->send();
930 ASSERT_EQ(-EINVAL, ctx.wait());
931 }
932
933 } // namespace image
934 } // namespace librbd