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