]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/io/test_mock_ImageRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / librbd / io / test_mock_ImageRequest.cc
CommitLineData
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"
7#include "test/librbd/mock/MockJournal.h"
8#include "test/librbd/mock/cache/MockImageCache.h"
9#include "librbd/io/ImageRequest.h"
11fdf7f2 10#include "librbd/io/ObjectDispatchSpec.h"
f67539c2 11#include "librbd/io/Utils.h"
7c673cae
FG
12
13namespace librbd {
14namespace {
15
11fdf7f2
TL
16struct MockTestImageCtx;
17
18struct MockTestJournal : public MockJournal {
19 MOCK_METHOD4(append_write_event, uint64_t(uint64_t, size_t,
20 const bufferlist &, bool));
21 MOCK_METHOD5(append_io_event_mock, uint64_t(const journal::EventEntry&,
22 uint64_t, size_t, bool, int));
23 uint64_t append_io_event(journal::EventEntry &&event_entry,
24 uint64_t offset, size_t length,
25 bool flush_entry, int filter_ret_val) {
26 // googlemock doesn't support move semantics
27 return append_io_event_mock(event_entry, offset, length, flush_entry,
28 filter_ret_val);
29 }
30
31 MOCK_METHOD2(commit_io_event, void(uint64_t, int));
32};
33
7c673cae
FG
34struct MockTestImageCtx : public MockImageCtx {
35 MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
36 }
11fdf7f2
TL
37
38 MockTestJournal* journal;
7c673cae
FG
39};
40
41} // anonymous namespace
42
43namespace util {
44
45inline ImageCtx *get_image_ctx(MockTestImageCtx *image_ctx) {
46 return image_ctx->image_ctx;
47}
48
49} // namespace util
7c673cae
FG
50} // namespace librbd
51
52#include "librbd/io/ImageRequest.cc"
53
54namespace librbd {
55namespace io {
56
f67539c2
TL
57namespace util {
58
59template<>
60void file_to_extents(
61 MockTestImageCtx *image_ctx, uint64_t offset, uint64_t length,
62 uint64_t buffer_offset,
63 striper::LightweightObjectExtents *object_extents) {
64 Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, offset, length,
65 0, buffer_offset, object_extents);
66}
67
68template <> void extent_to_file(
69 MockTestImageCtx* image_ctx, uint64_t object_no, uint64_t offset,
70 uint64_t length,
71 std::vector<std::pair<uint64_t, uint64_t> >& extents) {
72 Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
73 offset, length, extents);
74}
75
76} // namespace util
77
7c673cae
FG
78using ::testing::_;
79using ::testing::InSequence;
80using ::testing::Invoke;
81using ::testing::Return;
82using ::testing::WithArg;
11fdf7f2
TL
83using ::testing::WithoutArgs;
84using ::testing::Exactly;
7c673cae
FG
85
86struct TestMockIoImageRequest : public TestMockFixture {
87 typedef ImageRequest<librbd::MockTestImageCtx> MockImageRequest;
11fdf7f2 88 typedef ImageReadRequest<librbd::MockTestImageCtx> MockImageReadRequest;
7c673cae
FG
89 typedef ImageWriteRequest<librbd::MockTestImageCtx> MockImageWriteRequest;
90 typedef ImageDiscardRequest<librbd::MockTestImageCtx> MockImageDiscardRequest;
91 typedef ImageFlushRequest<librbd::MockTestImageCtx> MockImageFlushRequest;
92 typedef ImageWriteSameRequest<librbd::MockTestImageCtx> MockImageWriteSameRequest;
c07f9fc5 93 typedef ImageCompareAndWriteRequest<librbd::MockTestImageCtx> MockImageCompareAndWriteRequest;
f67539c2 94 typedef ImageListSnapsRequest<librbd::MockTestImageCtx> MockImageListSnapsRequest;
7c673cae 95
11fdf7f2 96 void expect_is_journal_appending(MockTestJournal &mock_journal, bool appending) {
7c673cae
FG
97 EXPECT_CALL(mock_journal, is_journal_appending())
98 .WillOnce(Return(appending));
99 }
100
11fdf7f2
TL
101 void expect_get_modify_timestamp(MockTestImageCtx &mock_image_ctx,
102 bool needs_update) {
103 if (needs_update) {
104 mock_image_ctx.mtime_update_interval = 5;
105 EXPECT_CALL(mock_image_ctx, get_modify_timestamp())
106 .WillOnce(Return(ceph_clock_now() - utime_t(10,0)));
107 } else {
108 mock_image_ctx.mtime_update_interval = 600;
109 EXPECT_CALL(mock_image_ctx, get_modify_timestamp())
110 .WillOnce(Return(ceph_clock_now()));
111 }
7c673cae
FG
112 }
113
11fdf7f2
TL
114 void expect_object_discard_request(MockTestImageCtx &mock_image_ctx,
115 uint64_t object_no, uint64_t offset,
116 uint32_t length, int r) {
117 EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, send(_))
118 .WillOnce(Invoke([&mock_image_ctx, object_no, offset, length, r]
119 (ObjectDispatchSpec* spec) {
120 auto* discard_spec = boost::get<ObjectDispatchSpec::DiscardRequest>(&spec->request);
121 ASSERT_TRUE(discard_spec != nullptr);
122 ASSERT_EQ(object_no, discard_spec->object_no);
123 ASSERT_EQ(offset, discard_spec->object_off);
124 ASSERT_EQ(length, discard_spec->object_len);
125
126 spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
127 mock_image_ctx.image_ctx->op_work_queue->queue(&spec->dispatcher_ctx, r);
7c673cae
FG
128 }));
129 }
130
11fdf7f2
TL
131 void expect_object_request_send(MockTestImageCtx &mock_image_ctx,
132 int r) {
133 EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, send(_))
134 .WillOnce(Invoke([&mock_image_ctx, r](ObjectDispatchSpec* spec) {
135 spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
136 mock_image_ctx.image_ctx->op_work_queue->queue(&spec->dispatcher_ctx, r);
137 }));
7c673cae 138 }
f67539c2
TL
139
140 void expect_object_list_snaps_request(MockTestImageCtx &mock_image_ctx,
141 uint64_t object_no,
142 const SnapshotDelta& snap_delta,
143 int r) {
144 EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, send(_))
145 .WillOnce(
146 Invoke([&mock_image_ctx, object_no, snap_delta, r]
147 (ObjectDispatchSpec* spec) {
148 auto request = boost::get<
149 librbd::io::ObjectDispatchSpec::ListSnapsRequest>(
150 &spec->request);
151 ASSERT_TRUE(request != nullptr);
152 ASSERT_EQ(object_no, request->object_no);
153
154 *request->snapshot_delta = snap_delta;
155 spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
156 mock_image_ctx.image_ctx->op_work_queue->queue(&spec->dispatcher_ctx, r);
157 }));
158 }
7c673cae
FG
159};
160
11fdf7f2
TL
161TEST_F(TestMockIoImageRequest, AioWriteModifyTimestamp) {
162 REQUIRE_FORMAT_V2();
163
164 librbd::ImageCtx *ictx;
165 ASSERT_EQ(0, open_image(m_image_name, &ictx));
166
167 MockTestImageCtx mock_image_ctx(*ictx);
168 MockTestJournal mock_journal;
169 mock_image_ctx.journal = &mock_journal;
170
171 mock_image_ctx.mtime_update_interval = 5;
172
173 utime_t dummy = ceph_clock_now();
174 dummy -= utime_t(10,0);
175
176 EXPECT_CALL(mock_image_ctx, get_modify_timestamp())
177 .Times(Exactly(3))
178 .WillOnce(Return(dummy))
179 .WillOnce(Return(dummy))
180 .WillOnce(Return(dummy + utime_t(10,0)));
181
182 EXPECT_CALL(mock_image_ctx, set_modify_timestamp(_))
183 .Times(Exactly(1));
184
185 InSequence seq;
186 expect_is_journal_appending(mock_journal, false);
187 expect_object_request_send(mock_image_ctx, 0);
188
189 C_SaferCond aio_comp_ctx_1, aio_comp_ctx_2;
190 AioCompletion *aio_comp_1 = AioCompletion::create_and_start(
191 &aio_comp_ctx_1, ictx, AIO_TYPE_WRITE);
192
193 AioCompletion *aio_comp_2 = AioCompletion::create_and_start(
194 &aio_comp_ctx_2, ictx, AIO_TYPE_WRITE);
195
196 bufferlist bl;
197 bl.append("1");
f67539c2
TL
198 MockImageWriteRequest mock_aio_image_write_1(
199 mock_image_ctx, aio_comp_1, {{0, 1}}, std::move(bl),
200 mock_image_ctx.get_data_io_context(), 0, {});
11fdf7f2 201 {
9f95a23c 202 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
203 mock_aio_image_write_1.send();
204 }
205 ASSERT_EQ(0, aio_comp_ctx_1.wait());
206
207 expect_is_journal_appending(mock_journal, false);
208 expect_object_request_send(mock_image_ctx, 0);
209
210 bl.append("1");
f67539c2
TL
211 MockImageWriteRequest mock_aio_image_write_2(
212 mock_image_ctx, aio_comp_2, {{0, 1}}, std::move(bl),
213 mock_image_ctx.get_data_io_context(), 0, {});
11fdf7f2 214 {
9f95a23c 215 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
216 mock_aio_image_write_2.send();
217 }
218 ASSERT_EQ(0, aio_comp_ctx_2.wait());
219}
220
221TEST_F(TestMockIoImageRequest, AioReadAccessTimestamp) {
222 REQUIRE_FORMAT_V2();
223
224 librbd::ImageCtx *ictx;
225 ASSERT_EQ(0, open_image(m_image_name, &ictx));
226
227 MockTestImageCtx mock_image_ctx(*ictx);
228 MockTestJournal mock_journal;
229 mock_image_ctx.journal = &mock_journal;
230
231 mock_image_ctx.atime_update_interval = 5;
232
233 utime_t dummy = ceph_clock_now();
234 dummy -= utime_t(10,0);
235
236 EXPECT_CALL(mock_image_ctx, get_access_timestamp())
237 .Times(Exactly(3))
238 .WillOnce(Return(dummy))
239 .WillOnce(Return(dummy))
240 .WillOnce(Return(dummy + utime_t(10,0)));
241
242 EXPECT_CALL(mock_image_ctx, set_access_timestamp(_))
243 .Times(Exactly(1));
244
245 InSequence seq;
246 expect_object_request_send(mock_image_ctx, 0);
247
248 C_SaferCond aio_comp_ctx_1, aio_comp_ctx_2;
249 AioCompletion *aio_comp_1 = AioCompletion::create_and_start(
250 &aio_comp_ctx_1, ictx, AIO_TYPE_READ);
251
252
253 ReadResult rr;
f67539c2
TL
254 MockImageReadRequest mock_aio_image_read_1(
255 mock_image_ctx, aio_comp_1, {{0, 1}}, std::move(rr),
256 mock_image_ctx.get_data_io_context(), 0, 0, {});
11fdf7f2 257 {
9f95a23c 258 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
259 mock_aio_image_read_1.send();
260 }
261 ASSERT_EQ(1, aio_comp_ctx_1.wait());
262
263 AioCompletion *aio_comp_2 = AioCompletion::create_and_start(
264 &aio_comp_ctx_2, ictx, AIO_TYPE_READ);
265 expect_object_request_send(mock_image_ctx, 0);
266
f67539c2
TL
267 MockImageReadRequest mock_aio_image_read_2(
268 mock_image_ctx, aio_comp_2, {{0, 1}}, std::move(rr),
269 mock_image_ctx.get_data_io_context(), 0, 0, {});
11fdf7f2 270 {
9f95a23c 271 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
272 mock_aio_image_read_2.send();
273 }
274 ASSERT_EQ(1, aio_comp_ctx_2.wait());
275}
276
277TEST_F(TestMockIoImageRequest, PartialDiscard) {
278 librbd::ImageCtx *ictx;
279 ASSERT_EQ(0, open_image(m_image_name, &ictx));
280 ictx->discard_granularity_bytes = 0;
281
282 MockTestImageCtx mock_image_ctx(*ictx);
283 mock_image_ctx.journal = nullptr;
284
285 InSequence seq;
286 expect_get_modify_timestamp(mock_image_ctx, false);
287 expect_object_discard_request(mock_image_ctx, 0, 16, 63, 0);
288 expect_object_discard_request(mock_image_ctx, 0, 84, 100, 0);
289
290 C_SaferCond aio_comp_ctx;
291 AioCompletion *aio_comp = AioCompletion::create_and_start(
292 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
293 MockImageDiscardRequest mock_aio_image_discard(
294 mock_image_ctx, aio_comp, {{16, 63}, {84, 100}},
f67539c2 295 ictx->discard_granularity_bytes, mock_image_ctx.get_data_io_context(), {});
11fdf7f2 296 {
9f95a23c 297 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
298 mock_aio_image_discard.send();
299 }
300 ASSERT_EQ(0, aio_comp_ctx.wait());
301}
302
303TEST_F(TestMockIoImageRequest, TailDiscard) {
304 librbd::ImageCtx *ictx;
305 ASSERT_EQ(0, open_image(m_image_name, &ictx));
306 ASSERT_EQ(0, resize(ictx, ictx->layout.object_size));
307 ictx->discard_granularity_bytes = 2 * ictx->layout.object_size;
308
309 MockTestImageCtx mock_image_ctx(*ictx);
310 mock_image_ctx.journal = nullptr;
311
312 InSequence seq;
313 expect_get_modify_timestamp(mock_image_ctx, false);
314 expect_object_discard_request(
315 mock_image_ctx, 0, ictx->layout.object_size - 1024, 1024, 0);
316
317 C_SaferCond aio_comp_ctx;
318 AioCompletion *aio_comp = AioCompletion::create_and_start(
319 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
320 MockImageDiscardRequest mock_aio_image_discard(
321 mock_image_ctx, aio_comp,
322 {{ictx->layout.object_size - 1024, 1024}},
f67539c2 323 ictx->discard_granularity_bytes, mock_image_ctx.get_data_io_context(), {});
11fdf7f2 324 {
9f95a23c 325 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
326 mock_aio_image_discard.send();
327 }
328 ASSERT_EQ(0, aio_comp_ctx.wait());
329}
330
331TEST_F(TestMockIoImageRequest, DiscardGranularity) {
332 librbd::ImageCtx *ictx;
333 ASSERT_EQ(0, open_image(m_image_name, &ictx));
334 ASSERT_EQ(0, resize(ictx, ictx->layout.object_size));
335 ictx->discard_granularity_bytes = 32;
336
337 MockTestImageCtx mock_image_ctx(*ictx);
338 mock_image_ctx.journal = nullptr;
339
340 InSequence seq;
341 expect_get_modify_timestamp(mock_image_ctx, false);
342 expect_object_discard_request(mock_image_ctx, 0, 32, 32, 0);
343 expect_object_discard_request(mock_image_ctx, 0, 96, 64, 0);
344 expect_object_discard_request(
345 mock_image_ctx, 0, ictx->layout.object_size - 32, 32, 0);
346
347 C_SaferCond aio_comp_ctx;
348 AioCompletion *aio_comp = AioCompletion::create_and_start(
349 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
350 MockImageDiscardRequest mock_aio_image_discard(
351 mock_image_ctx, aio_comp,
352 {{16, 63}, {96, 31}, {84, 100}, {ictx->layout.object_size - 33, 33}},
f67539c2 353 ictx->discard_granularity_bytes, mock_image_ctx.get_data_io_context(), {});
11fdf7f2 354 {
9f95a23c 355 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
11fdf7f2
TL
356 mock_aio_image_discard.send();
357 }
358 ASSERT_EQ(0, aio_comp_ctx.wait());
359}
360
7c673cae
FG
361TEST_F(TestMockIoImageRequest, AioWriteJournalAppendDisabled) {
362 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
363
364 librbd::ImageCtx *ictx;
365 ASSERT_EQ(0, open_image(m_image_name, &ictx));
366
7c673cae 367 MockTestImageCtx mock_image_ctx(*ictx);
11fdf7f2 368 MockTestJournal mock_journal;
7c673cae
FG
369 mock_image_ctx.journal = &mock_journal;
370
371 InSequence seq;
11fdf7f2 372 expect_get_modify_timestamp(mock_image_ctx, false);
7c673cae 373 expect_is_journal_appending(mock_journal, false);
11fdf7f2 374 expect_object_request_send(mock_image_ctx, 0);
7c673cae
FG
375
376 C_SaferCond aio_comp_ctx;
377 AioCompletion *aio_comp = AioCompletion::create_and_start(
378 &aio_comp_ctx, ictx, AIO_TYPE_WRITE);
379
380 bufferlist bl;
381 bl.append("1");
f67539c2
TL
382 MockImageWriteRequest mock_aio_image_write(
383 mock_image_ctx, aio_comp, {{0, 1}}, std::move(bl),
384 mock_image_ctx.get_data_io_context(), 0, {});
7c673cae 385 {
9f95a23c 386 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
7c673cae
FG
387 mock_aio_image_write.send();
388 }
389 ASSERT_EQ(0, aio_comp_ctx.wait());
390}
391
392TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) {
393 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
394
395 librbd::ImageCtx *ictx;
396 ASSERT_EQ(0, open_image(m_image_name, &ictx));
11fdf7f2 397 ictx->discard_granularity_bytes = 0;
7c673cae 398
7c673cae 399 MockTestImageCtx mock_image_ctx(*ictx);
11fdf7f2 400 MockTestJournal mock_journal;
7c673cae
FG
401 mock_image_ctx.journal = &mock_journal;
402
403 InSequence seq;
11fdf7f2 404 expect_get_modify_timestamp(mock_image_ctx, false);
7c673cae 405 expect_is_journal_appending(mock_journal, false);
11fdf7f2 406 expect_object_request_send(mock_image_ctx, 0);
7c673cae
FG
407
408 C_SaferCond aio_comp_ctx;
409 AioCompletion *aio_comp = AioCompletion::create_and_start(
410 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
11fdf7f2 411 MockImageDiscardRequest mock_aio_image_discard(
f67539c2
TL
412 mock_image_ctx, aio_comp, {{0, 1}}, ictx->discard_granularity_bytes,
413 mock_image_ctx.get_data_io_context(), {});
7c673cae 414 {
9f95a23c 415 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
7c673cae
FG
416 mock_aio_image_discard.send();
417 }
418 ASSERT_EQ(0, aio_comp_ctx.wait());
419}
420
421TEST_F(TestMockIoImageRequest, AioFlushJournalAppendDisabled) {
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);
11fdf7f2 428 MockTestJournal mock_journal;
7c673cae
FG
429 mock_image_ctx.journal = &mock_journal;
430
11fdf7f2
TL
431 expect_op_work_queue(mock_image_ctx);
432
7c673cae 433 InSequence seq;
7c673cae 434 expect_is_journal_appending(mock_journal, false);
11fdf7f2 435 expect_object_request_send(mock_image_ctx, 0);
7c673cae
FG
436
437 C_SaferCond aio_comp_ctx;
438 AioCompletion *aio_comp = AioCompletion::create_and_start(
439 &aio_comp_ctx, ictx, AIO_TYPE_FLUSH);
11fdf7f2
TL
440 MockImageFlushRequest mock_aio_image_flush(mock_image_ctx, aio_comp,
441 FLUSH_SOURCE_USER, {});
7c673cae 442 {
9f95a23c 443 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
7c673cae
FG
444 mock_aio_image_flush.send();
445 }
446 ASSERT_EQ(0, aio_comp_ctx.wait());
447}
448
449TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) {
450 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
451
452 librbd::ImageCtx *ictx;
453 ASSERT_EQ(0, open_image(m_image_name, &ictx));
454
7c673cae 455 MockTestImageCtx mock_image_ctx(*ictx);
11fdf7f2 456 MockTestJournal mock_journal;
7c673cae
FG
457 mock_image_ctx.journal = &mock_journal;
458
459 InSequence seq;
11fdf7f2 460 expect_get_modify_timestamp(mock_image_ctx, false);
7c673cae 461 expect_is_journal_appending(mock_journal, false);
11fdf7f2 462 expect_object_request_send(mock_image_ctx, 0);
7c673cae
FG
463
464 C_SaferCond aio_comp_ctx;
465 AioCompletion *aio_comp = AioCompletion::create_and_start(
466 &aio_comp_ctx, ictx, AIO_TYPE_WRITESAME);
467
468 bufferlist bl;
469 bl.append("1");
f67539c2
TL
470 MockImageWriteSameRequest mock_aio_image_writesame(
471 mock_image_ctx, aio_comp, {{0, 1}}, std::move(bl),
472 mock_image_ctx.get_data_io_context(), 0, {});
7c673cae 473 {
9f95a23c 474 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
7c673cae
FG
475 mock_aio_image_writesame.send();
476 }
477 ASSERT_EQ(0, aio_comp_ctx.wait());
478}
479
c07f9fc5
FG
480TEST_F(TestMockIoImageRequest, AioCompareAndWriteJournalAppendDisabled) {
481 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
482
483 librbd::ImageCtx *ictx;
484 ASSERT_EQ(0, open_image(m_image_name, &ictx));
485
c07f9fc5 486 MockTestImageCtx mock_image_ctx(*ictx);
11fdf7f2 487 MockTestJournal mock_journal;
c07f9fc5
FG
488 mock_image_ctx.journal = &mock_journal;
489
490 InSequence seq;
11fdf7f2 491 expect_get_modify_timestamp(mock_image_ctx, false);
c07f9fc5 492 expect_is_journal_appending(mock_journal, false);
11fdf7f2 493 expect_object_request_send(mock_image_ctx, 0);
c07f9fc5
FG
494
495 C_SaferCond aio_comp_ctx;
496 AioCompletion *aio_comp = AioCompletion::create_and_start(
497 &aio_comp_ctx, ictx, AIO_TYPE_COMPARE_AND_WRITE);
498
499 bufferlist cmp_bl;
500 cmp_bl.append("1");
501 bufferlist write_bl;
502 write_bl.append("1");
503 uint64_t mismatch_offset;
f67539c2
TL
504 MockImageCompareAndWriteRequest mock_aio_image_write(
505 mock_image_ctx, aio_comp, {{0, 1}}, std::move(cmp_bl), std::move(write_bl),
506 &mismatch_offset, mock_image_ctx.get_data_io_context(), 0, {});
c07f9fc5 507 {
9f95a23c 508 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
c07f9fc5
FG
509 mock_aio_image_write.send();
510 }
511 ASSERT_EQ(0, aio_comp_ctx.wait());
512}
513
f67539c2
TL
514TEST_F(TestMockIoImageRequest, ListSnaps) {
515 librbd::ImageCtx *ictx;
516 ASSERT_EQ(0, open_image(m_image_name, &ictx));
517
518 MockTestImageCtx mock_image_ctx(*ictx);
519 mock_image_ctx.layout.object_size = 16384;
520 mock_image_ctx.layout.stripe_unit = 4096;
521 mock_image_ctx.layout.stripe_count = 2;
522
523 InSequence seq;
524
525 SnapshotDelta object_snapshot_delta;
526 object_snapshot_delta[{5,6}].insert(
527 0, 1024, {SPARSE_EXTENT_STATE_DATA, 1024});
528 object_snapshot_delta[{5,5}].insert(
529 4096, 4096, {SPARSE_EXTENT_STATE_ZEROED, 4096});
530 expect_object_list_snaps_request(mock_image_ctx, 0, object_snapshot_delta, 0);
531 object_snapshot_delta = {};
532 object_snapshot_delta[{5,6}].insert(
533 1024, 3072, {SPARSE_EXTENT_STATE_DATA, 3072});
534 object_snapshot_delta[{5,5}].insert(
535 2048, 2048, {SPARSE_EXTENT_STATE_ZEROED, 2048});
536 expect_object_list_snaps_request(mock_image_ctx, 1, object_snapshot_delta, 0);
537
538 SnapshotDelta snapshot_delta;
539 C_SaferCond aio_comp_ctx;
540 AioCompletion *aio_comp = AioCompletion::create_and_start(
541 &aio_comp_ctx, ictx, AIO_TYPE_GENERIC);
542 MockImageListSnapsRequest mock_image_list_snaps_request(
543 mock_image_ctx, aio_comp, {{0, 16384}, {16384, 16384}}, {0, CEPH_NOSNAP},
544 0, &snapshot_delta, {});
545 {
546 std::shared_lock owner_locker{mock_image_ctx.owner_lock};
547 mock_image_list_snaps_request.send();
548 }
549 ASSERT_EQ(0, aio_comp_ctx.wait());
550
551 SnapshotDelta expected_snapshot_delta;
552 expected_snapshot_delta[{5,6}].insert(
553 0, 1024, {SPARSE_EXTENT_STATE_DATA, 1024});
554 expected_snapshot_delta[{5,6}].insert(
555 5120, 3072, {SPARSE_EXTENT_STATE_DATA, 3072});
556 expected_snapshot_delta[{5,5}].insert(
557 6144, 6144, {SPARSE_EXTENT_STATE_ZEROED, 6144});
558 ASSERT_EQ(expected_snapshot_delta, snapshot_delta);
559}
560
7c673cae
FG
561} // namespace io
562} // namespace librbd