1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/test_mock_fixture.h"
5 #include "include/rbd/librbd.hpp"
6 #include "librbd/ImageCtx.h"
7 #include "librbd/ImageState.h"
8 #include "librbd/internal.h"
9 #include "librbd/Operations.h"
10 #include "librbd/deep_copy/Handler.h"
11 #include "librbd/deep_copy/ImageCopyRequest.h"
12 #include "librbd/deep_copy/ObjectCopyRequest.h"
13 #include "librbd/image/CloseRequest.h"
14 #include "librbd/image/OpenRequest.h"
15 #include "librbd/object_map/DiffRequest.h"
16 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
17 #include "test/librbd/mock/MockImageCtx.h"
18 #include "test/librbd/test_support.h"
19 #include <boost/scope_exit.hpp>
25 struct MockTestImageCtx
: public librbd::MockImageCtx
{
26 static MockTestImageCtx
* s_instance
;
27 static MockTestImageCtx
* create(const std::string
&image_name
,
28 const std::string
&image_id
,
29 librados::snap_t snap_id
, librados::IoCtx
& p
,
31 ceph_assert(s_instance
!= nullptr);
35 explicit MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
36 : librbd::MockImageCtx(image_ctx
) {
40 MOCK_METHOD0(destroy
, void());
43 MockTestImageCtx
* MockTestImageCtx::s_instance
= nullptr;
45 } // anonymous namespace
50 struct ObjectCopyRequest
<librbd::MockTestImageCtx
> {
51 static ObjectCopyRequest
* s_instance
;
52 static ObjectCopyRequest
* create(
53 librbd::MockTestImageCtx
*src_image_ctx
,
54 librbd::MockTestImageCtx
*dst_image_ctx
,
55 librados::snap_t src_snap_id_start
,
56 librados::snap_t dst_snap_id_start
,
57 const SnapMap
&snap_map
,
58 uint64_t object_number
, bool flatten
, Handler
* handler
,
60 ceph_assert(s_instance
!= nullptr);
61 std::lock_guard locker
{s_instance
->lock
};
62 s_instance
->snap_map
= &snap_map
;
63 s_instance
->object_contexts
[object_number
] = on_finish
;
64 s_instance
->cond
.notify_all();
68 MOCK_METHOD0(send
, void());
70 ceph::mutex lock
= ceph::make_mutex("lock");
71 ceph::condition_variable cond
;
73 const SnapMap
*snap_map
= nullptr;
74 std::map
<uint64_t, Context
*> object_contexts
;
81 ObjectCopyRequest
<librbd::MockTestImageCtx
>* ObjectCopyRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
83 } // namespace deep_copy
88 struct CloseRequest
<MockTestImageCtx
> {
89 Context
* on_finish
= nullptr;
90 static CloseRequest
* s_instance
;
91 static CloseRequest
* create(MockTestImageCtx
*image_ctx
, Context
*on_finish
) {
92 ceph_assert(s_instance
!= nullptr);
93 s_instance
->on_finish
= on_finish
;
97 MOCK_METHOD0(send
, void());
104 CloseRequest
<MockTestImageCtx
>* CloseRequest
<MockTestImageCtx
>::s_instance
= nullptr;
107 struct OpenRequest
<MockTestImageCtx
> {
108 Context
* on_finish
= nullptr;
109 static OpenRequest
* s_instance
;
110 static OpenRequest
* create(MockTestImageCtx
*image_ctx
,
111 bool skip_open_parent
, Context
*on_finish
) {
112 ceph_assert(s_instance
!= nullptr);
113 s_instance
->on_finish
= on_finish
;
117 MOCK_METHOD0(send
, void());
124 OpenRequest
<MockTestImageCtx
>* OpenRequest
<MockTestImageCtx
>::s_instance
= nullptr;
128 namespace object_map
{
131 struct DiffRequest
<MockTestImageCtx
> {
132 BitVector
<2>* object_diff_state
= nullptr;
133 Context
* on_finish
= nullptr;
134 static DiffRequest
* s_instance
;
135 static DiffRequest
* create(MockTestImageCtx
*image_ctx
,
136 uint64_t snap_id_start
, uint64_t snap_id_end
,
137 BitVector
<2>* object_diff_state
,
138 Context
* on_finish
) {
139 ceph_assert(s_instance
!= nullptr);
140 s_instance
->object_diff_state
= object_diff_state
;
141 s_instance
->on_finish
= on_finish
;
149 MOCK_METHOD0(send
, void());
152 DiffRequest
<MockTestImageCtx
>* DiffRequest
<MockTestImageCtx
>::s_instance
= nullptr;
154 } // namespace object_map
155 } // namespace librbd
157 // template definitions
158 #include "librbd/deep_copy/ImageCopyRequest.cc"
159 template class librbd::deep_copy::ImageCopyRequest
<librbd::MockTestImageCtx
>;
162 namespace deep_copy
{
165 using ::testing::InSequence
;
166 using ::testing::Invoke
;
167 using ::testing::Return
;
169 class TestMockDeepCopyImageCopyRequest
: public TestMockFixture
{
171 typedef ImageCopyRequest
<librbd::MockTestImageCtx
> MockImageCopyRequest
;
172 typedef ObjectCopyRequest
<librbd::MockTestImageCtx
> MockObjectCopyRequest
;
173 typedef object_map::DiffRequest
<librbd::MockTestImageCtx
> MockDiffRequest
;
175 librbd::ImageCtx
*m_src_image_ctx
;
176 librbd::ImageCtx
*m_dst_image_ctx
;
177 ThreadPool
*m_thread_pool
;
178 ContextWQ
*m_work_queue
;
179 librbd::SnapSeqs m_snap_seqs
;
182 void SetUp() override
{
183 TestMockFixture::SetUp();
185 ASSERT_EQ(0, open_image(m_image_name
, &m_src_image_ctx
));
188 std::string dst_image_name
= get_temp_image_name();
189 ASSERT_EQ(0, create_image_pp(rbd
, m_ioctx
, dst_image_name
, m_image_size
));
190 ASSERT_EQ(0, open_image(dst_image_name
, &m_dst_image_ctx
));
192 librbd::ImageCtx::get_thread_pool_instance(m_src_image_ctx
->cct
,
193 &m_thread_pool
, &m_work_queue
);
196 void expect_get_image_size(librbd::MockTestImageCtx
&mock_image_ctx
,
198 EXPECT_CALL(mock_image_ctx
, get_image_size(_
))
199 .WillOnce(Return(size
)).RetiresOnSaturation();
202 void expect_diff_send(MockDiffRequest
& mock_request
,
203 const BitVector
<2>& diff_state
, int r
) {
204 EXPECT_CALL(mock_request
, send())
205 .WillOnce(Invoke([this, &mock_request
, diff_state
, r
]() {
207 *mock_request
.object_diff_state
= diff_state
;
209 m_work_queue
->queue(mock_request
.on_finish
, r
);
213 void expect_object_copy_send(MockObjectCopyRequest
&mock_object_copy_request
) {
214 EXPECT_CALL(mock_object_copy_request
, send());
217 bool complete_object_copy(MockObjectCopyRequest
&mock_object_copy_request
,
218 uint64_t object_num
, Context
**object_ctx
, int r
) {
219 std::unique_lock locker
{mock_object_copy_request
.lock
};
220 while (mock_object_copy_request
.object_contexts
.count(object_num
) == 0) {
221 if (mock_object_copy_request
.cond
.wait_for(locker
, 10s
) ==
222 std::cv_status::timeout
) {
227 if (object_ctx
!= nullptr) {
228 *object_ctx
= mock_object_copy_request
.object_contexts
[object_num
];
230 m_work_queue
->queue(mock_object_copy_request
.object_contexts
[object_num
],
236 SnapMap
wait_for_snap_map(MockObjectCopyRequest
&mock_object_copy_request
) {
237 std::unique_lock locker
{mock_object_copy_request
.lock
};
238 while (mock_object_copy_request
.snap_map
== nullptr) {
239 if (mock_object_copy_request
.cond
.wait_for(locker
, 10s
) ==
240 std::cv_status::timeout
) {
244 return *mock_object_copy_request
.snap_map
;
247 int create_snap(librbd::ImageCtx
*image_ctx
, const char* snap_name
,
248 librados::snap_t
*snap_id
) {
249 int r
= image_ctx
->operations
->snap_create(
250 cls::rbd::UserSnapshotNamespace(), snap_name
);
255 r
= image_ctx
->state
->refresh();
260 if (image_ctx
->snap_ids
.count({cls::rbd::UserSnapshotNamespace(),
265 if (snap_id
!= nullptr) {
266 *snap_id
= image_ctx
->snap_ids
[{cls::rbd::UserSnapshotNamespace(),
272 int create_snap(const char* snap_name
,
273 librados::snap_t
*src_snap_id_
= nullptr) {
274 librados::snap_t src_snap_id
;
275 int r
= create_snap(m_src_image_ctx
, snap_name
, &src_snap_id
);
280 if (src_snap_id_
!= nullptr) {
281 *src_snap_id_
= src_snap_id
;
284 librados::snap_t dst_snap_id
;
285 r
= create_snap(m_dst_image_ctx
, snap_name
, &dst_snap_id
);
290 // collection of all existing snaps in dst image
291 SnapIds
dst_snap_ids({dst_snap_id
});
292 if (!m_snap_map
.empty()) {
293 dst_snap_ids
.insert(dst_snap_ids
.end(),
294 m_snap_map
.rbegin()->second
.begin(),
295 m_snap_map
.rbegin()->second
.end());
297 m_snap_map
[src_snap_id
] = dst_snap_ids
;
298 m_snap_seqs
[src_snap_id
] = dst_snap_id
;
303 TEST_F(TestMockDeepCopyImageCopyRequest
, SimpleImage
) {
304 librados::snap_t snap_id_end
;
305 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
307 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
308 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
309 MockObjectCopyRequest mock_object_copy_request
;
312 MockDiffRequest mock_diff_request
;
313 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
314 expect_get_image_size(mock_src_image_ctx
, 1 << m_src_image_ctx
->order
);
315 expect_get_image_size(mock_src_image_ctx
, 0);
316 expect_object_copy_send(mock_object_copy_request
);
318 librbd::deep_copy::NoOpHandler no_op
;
320 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
322 0, snap_id_end
, 0, false, boost::none
,
323 m_snap_seqs
, &no_op
, &ctx
);
326 ASSERT_EQ(m_snap_map
, wait_for_snap_map(mock_object_copy_request
));
327 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 0, nullptr, 0));
328 ASSERT_EQ(0, ctx
.wait());
331 TEST_F(TestMockDeepCopyImageCopyRequest
, FastDiff
) {
332 librados::snap_t snap_id_end
;
333 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
335 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
336 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
340 MockDiffRequest mock_diff_request
;
341 BitVector
<2> diff_state
;
342 diff_state
.resize(1);
343 expect_diff_send(mock_diff_request
, diff_state
, 0);
345 expect_get_image_size(mock_src_image_ctx
, 1 << m_src_image_ctx
->order
);
346 expect_get_image_size(mock_src_image_ctx
, 0);
348 librbd::deep_copy::NoOpHandler no_op
;
350 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
352 0, snap_id_end
, 0, false, boost::none
,
353 m_snap_seqs
, &no_op
, &ctx
);
356 ASSERT_EQ(0, ctx
.wait());
359 TEST_F(TestMockDeepCopyImageCopyRequest
, OutOfOrder
) {
360 std::string max_ops_str
;
361 ASSERT_EQ(0, _rados
.conf_get("rbd_concurrent_management_ops", max_ops_str
));
362 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops", "10"));
363 BOOST_SCOPE_EXIT( (max_ops_str
) ) {
364 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops",
365 max_ops_str
.c_str()));
366 } BOOST_SCOPE_EXIT_END
;
368 librados::snap_t snap_id_end
;
369 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
371 uint64_t object_count
= 55;
373 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
374 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
375 MockObjectCopyRequest mock_object_copy_request
;
377 MockDiffRequest mock_diff_request
;
378 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
379 expect_get_image_size(mock_src_image_ctx
,
380 object_count
* (1 << m_src_image_ctx
->order
));
381 expect_get_image_size(mock_src_image_ctx
, 0);
383 EXPECT_CALL(mock_object_copy_request
, send()).Times(object_count
);
385 class Handler
: public librbd::deep_copy::NoOpHandler
{
387 uint64_t object_count
;
388 librbd::deep_copy::ObjectNumber expected_object_number
;
390 Handler(uint64_t object_count
)
391 : object_count(object_count
) {
394 int update_progress(uint64_t object_no
, uint64_t end_object_no
) override
{
395 EXPECT_LE(object_no
, object_count
);
396 EXPECT_EQ(end_object_no
, object_count
);
397 if (!expected_object_number
) {
398 expected_object_number
= 0;
400 expected_object_number
= *expected_object_number
+ 1;
402 EXPECT_EQ(*expected_object_number
, object_no
- 1);
406 } handler(object_count
);
409 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
411 0, snap_id_end
, 0, false, boost::none
,
412 m_snap_seqs
, &handler
, &ctx
);
415 std::map
<uint64_t, Context
*> copy_contexts
;
416 ASSERT_EQ(m_snap_map
, wait_for_snap_map(mock_object_copy_request
));
417 for (uint64_t i
= 0; i
< object_count
; ++i
) {
419 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, i
,
420 ©_contexts
[i
], 0));
422 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, i
, nullptr,
427 for (auto& pair
: copy_contexts
) {
428 pair
.second
->complete(0);
431 ASSERT_EQ(0, ctx
.wait());
434 TEST_F(TestMockDeepCopyImageCopyRequest
, SnapshotSubset
) {
435 librados::snap_t snap_id_start
;
436 librados::snap_t snap_id_end
;
437 ASSERT_EQ(0, create_snap("snap1"));
438 ASSERT_EQ(0, create_snap("snap2", &snap_id_start
));
439 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
441 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
442 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
443 MockObjectCopyRequest mock_object_copy_request
;
446 MockDiffRequest mock_diff_request
;
447 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
448 expect_get_image_size(mock_src_image_ctx
, 1 << m_src_image_ctx
->order
);
449 expect_get_image_size(mock_src_image_ctx
, 0);
450 expect_get_image_size(mock_src_image_ctx
, 0);
451 expect_get_image_size(mock_src_image_ctx
, 0);
452 expect_object_copy_send(mock_object_copy_request
);
454 librbd::deep_copy::NoOpHandler no_op
;
456 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
458 snap_id_start
, snap_id_end
, 0, false,
459 boost::none
, m_snap_seqs
, &no_op
,
463 SnapMap
snap_map(m_snap_map
);
464 snap_map
.erase(snap_map
.begin());
465 ASSERT_EQ(snap_map
, wait_for_snap_map(mock_object_copy_request
));
467 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 0, nullptr, 0));
468 ASSERT_EQ(0, ctx
.wait());
471 TEST_F(TestMockDeepCopyImageCopyRequest
, RestartPartialSync
) {
472 librados::snap_t snap_id_end
;
473 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
475 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
476 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
477 MockObjectCopyRequest mock_object_copy_request
;
480 MockDiffRequest mock_diff_request
;
481 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
482 expect_get_image_size(mock_src_image_ctx
, 2 * (1 << m_src_image_ctx
->order
));
483 expect_get_image_size(mock_src_image_ctx
, 0);
484 expect_object_copy_send(mock_object_copy_request
);
486 librbd::deep_copy::NoOpHandler no_op
;
488 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
490 0, snap_id_end
, 0, false,
491 librbd::deep_copy::ObjectNumber
{0U},
492 m_snap_seqs
, &no_op
, &ctx
);
495 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 1, nullptr, 0));
496 ASSERT_EQ(0, ctx
.wait());
499 TEST_F(TestMockDeepCopyImageCopyRequest
, Cancel
) {
500 std::string max_ops_str
;
501 ASSERT_EQ(0, _rados
.conf_get("rbd_concurrent_management_ops", max_ops_str
));
502 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops", "1"));
503 BOOST_SCOPE_EXIT( (max_ops_str
) ) {
504 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops",
505 max_ops_str
.c_str()));
506 } BOOST_SCOPE_EXIT_END
;
508 librados::snap_t snap_id_end
;
509 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
511 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
512 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
513 MockObjectCopyRequest mock_object_copy_request
;
516 MockDiffRequest mock_diff_request
;
517 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
518 expect_get_image_size(mock_src_image_ctx
, 1 << m_src_image_ctx
->order
);
519 expect_get_image_size(mock_src_image_ctx
, 0);
520 expect_object_copy_send(mock_object_copy_request
);
522 librbd::deep_copy::NoOpHandler no_op
;
524 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
526 0, snap_id_end
, 0, false, boost::none
,
527 m_snap_seqs
, &no_op
, &ctx
);
530 ASSERT_EQ(m_snap_map
, wait_for_snap_map(mock_object_copy_request
));
533 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 0, nullptr, 0));
534 ASSERT_EQ(-ECANCELED
, ctx
.wait());
537 TEST_F(TestMockDeepCopyImageCopyRequest
, Cancel_Inflight_Sync
) {
538 std::string max_ops_str
;
539 ASSERT_EQ(0, _rados
.conf_get("rbd_concurrent_management_ops", max_ops_str
));
540 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops", "3"));
541 BOOST_SCOPE_EXIT( (max_ops_str
) ) {
542 ASSERT_EQ(0, _rados
.conf_set("rbd_concurrent_management_ops",
543 max_ops_str
.c_str()));
544 } BOOST_SCOPE_EXIT_END
;
546 librados::snap_t snap_id_end
;
547 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
549 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
550 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
551 MockObjectCopyRequest mock_object_copy_request
;
554 MockDiffRequest mock_diff_request
;
555 expect_diff_send(mock_diff_request
, {}, -EINVAL
);
556 expect_get_image_size(mock_src_image_ctx
, 6 * (1 << m_src_image_ctx
->order
));
557 expect_get_image_size(mock_src_image_ctx
, m_image_size
);
559 EXPECT_CALL(mock_object_copy_request
, send()).Times(6);
561 struct Handler
: public librbd::deep_copy::NoOpHandler
{
562 librbd::deep_copy::ObjectNumber object_number
;
564 int update_progress(uint64_t object_no
, uint64_t end_object_no
) override
{
565 object_number
= object_number
? *object_number
+ 1 : 0;
571 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
573 0, snap_id_end
, 0, false, boost::none
,
574 m_snap_seqs
, &handler
, &ctx
);
577 ASSERT_EQ(m_snap_map
, wait_for_snap_map(mock_object_copy_request
));
579 Context
*cancel_ctx
= nullptr;
580 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 0, nullptr, 0));
581 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 1, nullptr, 0));
582 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 2, nullptr, 0));
583 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 3, &cancel_ctx
,
585 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 4, nullptr, 0));
586 ASSERT_TRUE(complete_object_copy(mock_object_copy_request
, 5, nullptr, 0));
589 cancel_ctx
->complete(0);
591 ASSERT_EQ(-ECANCELED
, ctx
.wait());
592 ASSERT_EQ(5u, handler
.object_number
.get());
595 TEST_F(TestMockDeepCopyImageCopyRequest
, MissingSnap
) {
596 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
597 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
599 librbd::deep_copy::NoOpHandler no_op
;
601 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
603 0, 123, 0, false, boost::none
,
604 m_snap_seqs
, &no_op
, &ctx
);
606 ASSERT_EQ(-EINVAL
, ctx
.wait());
609 TEST_F(TestMockDeepCopyImageCopyRequest
, MissingFromSnap
) {
610 librados::snap_t snap_id_end
;
611 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
613 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
614 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
616 librbd::deep_copy::NoOpHandler no_op
;
618 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
620 123, snap_id_end
, 0, false,
621 boost::none
, m_snap_seqs
, &no_op
,
624 ASSERT_EQ(-EINVAL
, ctx
.wait());
627 TEST_F(TestMockDeepCopyImageCopyRequest
, EmptySnapMap
) {
628 librados::snap_t snap_id_start
;
629 librados::snap_t snap_id_end
;
630 ASSERT_EQ(0, create_snap("snap1", &snap_id_start
));
631 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
633 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
634 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
636 librbd::deep_copy::NoOpHandler no_op
;
638 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
640 snap_id_start
, snap_id_end
, 0, false,
641 boost::none
, {{0, 0}}, &no_op
, &ctx
);
643 ASSERT_EQ(-EINVAL
, ctx
.wait());
646 TEST_F(TestMockDeepCopyImageCopyRequest
, EmptySnapSeqs
) {
647 librados::snap_t snap_id_start
;
648 librados::snap_t snap_id_end
;
649 ASSERT_EQ(0, create_snap("snap1", &snap_id_start
));
650 ASSERT_EQ(0, create_snap("copy", &snap_id_end
));
652 librbd::MockTestImageCtx
mock_src_image_ctx(*m_src_image_ctx
);
653 librbd::MockTestImageCtx
mock_dst_image_ctx(*m_dst_image_ctx
);
655 librbd::deep_copy::NoOpHandler no_op
;
657 auto request
= new MockImageCopyRequest(&mock_src_image_ctx
,
659 snap_id_start
, snap_id_end
, 0, false,
660 boost::none
, {}, &no_op
, &ctx
);
662 ASSERT_EQ(-EINVAL
, ctx
.wait());
665 } // namespace deep_copy
666 } // namespace librbd