]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/io/test_mock_ImageRequest.cc
update sources to v12.1.2
[ceph.git] / ceph / src / test / librbd / io / test_mock_ImageRequest.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/MockJournal.h"
8 #include "test/librbd/mock/cache/MockImageCache.h"
9 #include "librbd/io/ImageRequest.h"
10 #include "librbd/io/ObjectRequest.h"
11
12 namespace librbd {
13 namespace {
14
15 struct MockTestImageCtx : public MockImageCtx {
16 MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
17 }
18 };
19
20 } // anonymous namespace
21
22 namespace util {
23
24 inline ImageCtx *get_image_ctx(MockTestImageCtx *image_ctx) {
25 return image_ctx->image_ctx;
26 }
27
28 } // namespace util
29
30 namespace io {
31
32 template <>
33 struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle {
34 static ObjectRequest* s_instance;
35 Context *on_finish = nullptr;
36
37 static ObjectRequest* create_remove(librbd::MockTestImageCtx *ictx,
38 const std::string &oid,
39 uint64_t object_no,
40 const ::SnapContext &snapc,
41 const ZTracer::Trace &parent_trace,
42 Context *completion) {
43 assert(s_instance != nullptr);
44 s_instance->on_finish = completion;
45 return s_instance;
46 }
47
48 static ObjectRequest* create_truncate(librbd::MockTestImageCtx *ictx,
49 const std::string &oid,
50 uint64_t object_no,
51 uint64_t object_off,
52 const ::SnapContext &snapc,
53 const ZTracer::Trace &parent_trace,
54 Context *completion) {
55 assert(s_instance != nullptr);
56 s_instance->on_finish = completion;
57 return s_instance;
58 }
59
60 static ObjectRequest* create_write(librbd::MockTestImageCtx *ictx,
61 const std::string &oid,
62 uint64_t object_no,
63 uint64_t object_off,
64 const ceph::bufferlist &data,
65 const ::SnapContext &snapc, int op_flags,
66 const ZTracer::Trace &parent_trace,
67 Context *completion) {
68 assert(s_instance != nullptr);
69 s_instance->on_finish = completion;
70 return s_instance;
71 }
72
73 static ObjectRequest* create_zero(librbd::MockTestImageCtx *ictx,
74 const std::string &oid,
75 uint64_t object_no, uint64_t object_off,
76 uint64_t object_len,
77 const ::SnapContext &snapc,
78 const ZTracer::Trace &parent_trace,
79 Context *completion) {
80 assert(s_instance != nullptr);
81 s_instance->on_finish = completion;
82 return s_instance;
83 }
84
85 static ObjectRequest* create_writesame(librbd::MockTestImageCtx *ictx,
86 const std::string &oid,
87 uint64_t object_no,
88 uint64_t object_off,
89 uint64_t object_len,
90 const ceph::bufferlist &data,
91 const ::SnapContext &snapc,
92 int op_flags,
93 const ZTracer::Trace &parent_trace,
94 Context *completion) {
95 assert(s_instance != nullptr);
96 s_instance->on_finish = completion;
97 return s_instance;
98 }
99
100 static ObjectRequest* create_compare_and_write(librbd::MockTestImageCtx *ictx,
101 const std::string &oid,
102 uint64_t object_no,
103 uint64_t object_off,
104 const ceph::bufferlist &cmp_data,
105 const ceph::bufferlist &write_data,
106 const ::SnapContext &snapc,
107 uint64_t *mismatch_offset,
108 int op_flags,
109 const ZTracer::Trace &parent_trace,
110 Context *completion) {
111 assert(s_instance != nullptr);
112 s_instance->on_finish = completion;
113 return s_instance;
114 }
115
116 ObjectRequest() {
117 assert(s_instance == nullptr);
118 s_instance = this;
119 }
120 ~ObjectRequest() override {
121 s_instance = nullptr;
122 }
123
124 MOCK_METHOD1(complete, void(int));
125 MOCK_METHOD0(send, void());
126 };
127
128 template <>
129 struct ObjectReadRequest<librbd::MockTestImageCtx> : public ObjectRequest<librbd::MockTestImageCtx> {
130 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
131 typedef std::map<uint64_t, uint64_t> ExtentMap;
132
133 static ObjectReadRequest* s_instance;
134
135 static ObjectReadRequest* create(librbd::MockTestImageCtx *ictx,
136 const std::string &oid,
137 uint64_t objectno, uint64_t offset,
138 uint64_t len, Extents &buffer_extents,
139 librados::snap_t snap_id, bool sparse,
140 int op_flags,
141 const ZTracer::Trace &parent_trace,
142 Context *completion) {
143 assert(s_instance != nullptr);
144 s_instance->on_finish = completion;
145 return s_instance;
146 }
147
148 ObjectReadRequest() {
149 assert(s_instance == nullptr);
150 s_instance = this;
151 }
152 ~ObjectReadRequest() override {
153 s_instance = nullptr;
154 }
155
156 MOCK_CONST_METHOD0(get_offset, uint64_t());
157 MOCK_CONST_METHOD0(get_length, uint64_t());
158 MOCK_METHOD0(data, ceph::bufferlist &());
159 MOCK_CONST_METHOD0(get_buffer_extents, const Extents &());
160 MOCK_METHOD0(get_extent_map, ExtentMap &());
161
162 };
163
164 ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
165 ObjectReadRequest<librbd::MockTestImageCtx>* ObjectReadRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
166
167 } // namespace io
168 } // namespace librbd
169
170 #include "librbd/io/ImageRequest.cc"
171
172 namespace librbd {
173 namespace io {
174
175 using ::testing::_;
176 using ::testing::InSequence;
177 using ::testing::Invoke;
178 using ::testing::Return;
179 using ::testing::WithArg;
180
181 struct TestMockIoImageRequest : public TestMockFixture {
182 typedef ImageRequest<librbd::MockTestImageCtx> MockImageRequest;
183 typedef ImageWriteRequest<librbd::MockTestImageCtx> MockImageWriteRequest;
184 typedef ImageDiscardRequest<librbd::MockTestImageCtx> MockImageDiscardRequest;
185 typedef ImageFlushRequest<librbd::MockTestImageCtx> MockImageFlushRequest;
186 typedef ImageWriteSameRequest<librbd::MockTestImageCtx> MockImageWriteSameRequest;
187 typedef ImageCompareAndWriteRequest<librbd::MockTestImageCtx> MockImageCompareAndWriteRequest;
188 typedef ObjectRequest<librbd::MockTestImageCtx> MockObjectRequest;
189 typedef ObjectReadRequest<librbd::MockTestImageCtx> MockObjectReadRequest;
190
191 void expect_is_journal_appending(MockJournal &mock_journal, bool appending) {
192 EXPECT_CALL(mock_journal, is_journal_appending())
193 .WillOnce(Return(appending));
194 }
195
196 void expect_write_to_cache(MockImageCtx &mock_image_ctx,
197 const object_t &object,
198 uint64_t offset, uint64_t length,
199 uint64_t journal_tid, int r) {
200 EXPECT_CALL(mock_image_ctx, write_to_cache(object, _, length, offset, _, _,
201 journal_tid, _))
202 .WillOnce(WithArg<4>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
203 }
204
205 void expect_object_request_send(MockImageCtx &mock_image_ctx,
206 MockObjectRequest &mock_object_request,
207 int r) {
208 EXPECT_CALL(mock_object_request, send())
209 .WillOnce(Invoke([&mock_image_ctx, &mock_object_request, r]() {
210 mock_image_ctx.image_ctx->op_work_queue->queue(
211 mock_object_request.on_finish, r);
212 }));
213 }
214
215 void expect_user_flushed(MockImageCtx &mock_image_ctx) {
216 EXPECT_CALL(mock_image_ctx, user_flushed());
217 }
218
219 void expect_flush(MockImageCtx &mock_image_ctx, int r) {
220 EXPECT_CALL(mock_image_ctx, flush(_))
221 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
222 }
223 };
224
225 TEST_F(TestMockIoImageRequest, AioWriteJournalAppendDisabled) {
226 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
227
228 librbd::ImageCtx *ictx;
229 ASSERT_EQ(0, open_image(m_image_name, &ictx));
230
231 MockObjectRequest mock_aio_object_request;
232 MockTestImageCtx mock_image_ctx(*ictx);
233 MockJournal mock_journal;
234 mock_image_ctx.journal = &mock_journal;
235
236 InSequence seq;
237 expect_is_journal_appending(mock_journal, false);
238 if (mock_image_ctx.image_ctx->cache) {
239 expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
240 0, 1, 0, 0);
241 } else {
242 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
243 }
244
245 C_SaferCond aio_comp_ctx;
246 AioCompletion *aio_comp = AioCompletion::create_and_start(
247 &aio_comp_ctx, ictx, AIO_TYPE_WRITE);
248
249 bufferlist bl;
250 bl.append("1");
251 MockImageWriteRequest mock_aio_image_write(mock_image_ctx, aio_comp,
252 {{0, 1}}, std::move(bl), 0, {});
253 {
254 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
255 mock_aio_image_write.send();
256 }
257 ASSERT_EQ(0, aio_comp_ctx.wait());
258 }
259
260 TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) {
261 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
262
263 librbd::ImageCtx *ictx;
264 ASSERT_EQ(0, open_image(m_image_name, &ictx));
265
266 MockObjectRequest mock_aio_object_request;
267 MockTestImageCtx mock_image_ctx(*ictx);
268 MockJournal mock_journal;
269 mock_image_ctx.journal = &mock_journal;
270
271 InSequence seq;
272 expect_is_journal_appending(mock_journal, false);
273 if (!ictx->skip_partial_discard) {
274 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
275 }
276
277 C_SaferCond aio_comp_ctx;
278 AioCompletion *aio_comp = AioCompletion::create_and_start(
279 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
280 MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp,
281 0, 1,
282 ictx->skip_partial_discard,
283 {});
284 {
285 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
286 mock_aio_image_discard.send();
287 }
288 ASSERT_EQ(0, aio_comp_ctx.wait());
289 }
290
291 TEST_F(TestMockIoImageRequest, AioFlushJournalAppendDisabled) {
292 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
293
294 librbd::ImageCtx *ictx;
295 ASSERT_EQ(0, open_image(m_image_name, &ictx));
296
297 MockTestImageCtx mock_image_ctx(*ictx);
298 MockJournal mock_journal;
299 mock_image_ctx.journal = &mock_journal;
300
301 InSequence seq;
302 expect_user_flushed(mock_image_ctx);
303 expect_is_journal_appending(mock_journal, false);
304 expect_flush(mock_image_ctx, 0);
305
306 C_SaferCond aio_comp_ctx;
307 AioCompletion *aio_comp = AioCompletion::create_and_start(
308 &aio_comp_ctx, ictx, AIO_TYPE_FLUSH);
309 MockImageFlushRequest mock_aio_image_flush(mock_image_ctx, aio_comp, {});
310 {
311 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
312 mock_aio_image_flush.send();
313 }
314 ASSERT_EQ(0, aio_comp_ctx.wait());
315 }
316
317 TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) {
318 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
319
320 librbd::ImageCtx *ictx;
321 ASSERT_EQ(0, open_image(m_image_name, &ictx));
322
323 MockObjectRequest mock_aio_object_request;
324 MockTestImageCtx mock_image_ctx(*ictx);
325 MockJournal mock_journal;
326 mock_image_ctx.journal = &mock_journal;
327
328 InSequence seq;
329 expect_is_journal_appending(mock_journal, false);
330 if (mock_image_ctx.image_ctx->cache) {
331 expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
332 0, 1, 0, 0);
333 } else {
334 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
335 }
336
337
338 C_SaferCond aio_comp_ctx;
339 AioCompletion *aio_comp = AioCompletion::create_and_start(
340 &aio_comp_ctx, ictx, AIO_TYPE_WRITESAME);
341
342 bufferlist bl;
343 bl.append("1");
344 MockImageWriteSameRequest mock_aio_image_writesame(mock_image_ctx, aio_comp,
345 0, 1, std::move(bl), 0,
346 {});
347 {
348 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
349 mock_aio_image_writesame.send();
350 }
351 ASSERT_EQ(0, aio_comp_ctx.wait());
352 }
353
354 TEST_F(TestMockIoImageRequest, AioCompareAndWriteJournalAppendDisabled) {
355 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
356
357 librbd::ImageCtx *ictx;
358 ASSERT_EQ(0, open_image(m_image_name, &ictx));
359
360 MockObjectRequest mock_aio_object_request;
361 MockTestImageCtx mock_image_ctx(*ictx);
362 MockJournal mock_journal;
363 mock_image_ctx.journal = &mock_journal;
364
365 InSequence seq;
366 expect_is_journal_appending(mock_journal, false);
367 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
368
369 C_SaferCond aio_comp_ctx;
370 AioCompletion *aio_comp = AioCompletion::create_and_start(
371 &aio_comp_ctx, ictx, AIO_TYPE_COMPARE_AND_WRITE);
372
373 bufferlist cmp_bl;
374 cmp_bl.append("1");
375 bufferlist write_bl;
376 write_bl.append("1");
377 uint64_t mismatch_offset;
378 MockImageCompareAndWriteRequest mock_aio_image_write(mock_image_ctx, aio_comp,
379 {{0, 1}}, std::move(cmp_bl),
380 std::move(write_bl),
381 &mismatch_offset,
382 0, {});
383 {
384 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
385 mock_aio_image_write.send();
386 }
387 ASSERT_EQ(0, aio_comp_ctx.wait());
388 }
389
390 } // namespace io
391 } // namespace librbd