]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/io/test_mock_ImageRequest.cc
update sources to v12.1.0
[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
37 static ObjectRequest* create_remove(librbd::MockTestImageCtx *ictx,
38 const std::string &oid,
39 uint64_t object_no,
40 const ::SnapContext &snapc,
31f18b77 41 const ZTracer::Trace &parent_trace,
7c673cae
FG
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,
31f18b77 53 const ZTracer::Trace &parent_trace,
7c673cae
FG
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,
31f18b77
FG
65 const ::SnapContext &snapc, int op_flags,
66 const ZTracer::Trace &parent_trace,
67 Context *completion) {
7c673cae
FG
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,
31f18b77 78 const ZTracer::Trace &parent_trace,
7c673cae
FG
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,
31f18b77
FG
92 int op_flags,
93 const ZTracer::Trace &parent_trace,
94 Context *completion) {
7c673cae
FG
95 assert(s_instance != nullptr);
96 s_instance->on_finish = completion;
97 return s_instance;
98 }
99
100 ObjectRequest() {
101 assert(s_instance == nullptr);
102 s_instance = this;
103 }
104 ~ObjectRequest() override {
105 s_instance = nullptr;
106 }
107
108 MOCK_METHOD1(complete, void(int));
109 MOCK_METHOD0(send, void());
110};
111
112template <>
113struct ObjectReadRequest<librbd::MockTestImageCtx> : public ObjectRequest<librbd::MockTestImageCtx> {
114 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
115 typedef std::map<uint64_t, uint64_t> ExtentMap;
116
117 static ObjectReadRequest* s_instance;
118
119 static ObjectReadRequest* create(librbd::MockTestImageCtx *ictx,
120 const std::string &oid,
121 uint64_t objectno, uint64_t offset,
122 uint64_t len, Extents &buffer_extents,
123 librados::snap_t snap_id, bool sparse,
31f18b77
FG
124 int op_flags,
125 const ZTracer::Trace &parent_trace,
126 Context *completion) {
7c673cae
FG
127 assert(s_instance != nullptr);
128 s_instance->on_finish = completion;
129 return s_instance;
130 }
131
132 ObjectReadRequest() {
133 assert(s_instance == nullptr);
134 s_instance = this;
135 }
136 ~ObjectReadRequest() override {
137 s_instance = nullptr;
138 }
139
140 MOCK_CONST_METHOD0(get_offset, uint64_t());
141 MOCK_CONST_METHOD0(get_length, uint64_t());
142 MOCK_METHOD0(data, ceph::bufferlist &());
143 MOCK_CONST_METHOD0(get_buffer_extents, const Extents &());
144 MOCK_METHOD0(get_extent_map, ExtentMap &());
145
146};
147
148ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
149ObjectReadRequest<librbd::MockTestImageCtx>* ObjectReadRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
150
151} // namespace io
152} // namespace librbd
153
154#include "librbd/io/ImageRequest.cc"
155
156namespace librbd {
157namespace io {
158
159using ::testing::_;
160using ::testing::InSequence;
161using ::testing::Invoke;
162using ::testing::Return;
163using ::testing::WithArg;
164
165struct TestMockIoImageRequest : public TestMockFixture {
166 typedef ImageRequest<librbd::MockTestImageCtx> MockImageRequest;
167 typedef ImageWriteRequest<librbd::MockTestImageCtx> MockImageWriteRequest;
168 typedef ImageDiscardRequest<librbd::MockTestImageCtx> MockImageDiscardRequest;
169 typedef ImageFlushRequest<librbd::MockTestImageCtx> MockImageFlushRequest;
170 typedef ImageWriteSameRequest<librbd::MockTestImageCtx> MockImageWriteSameRequest;
171 typedef ObjectRequest<librbd::MockTestImageCtx> MockObjectRequest;
172 typedef ObjectReadRequest<librbd::MockTestImageCtx> MockObjectReadRequest;
173
174 void expect_is_journal_appending(MockJournal &mock_journal, bool appending) {
175 EXPECT_CALL(mock_journal, is_journal_appending())
176 .WillOnce(Return(appending));
177 }
178
179 void expect_write_to_cache(MockImageCtx &mock_image_ctx,
180 const object_t &object,
181 uint64_t offset, uint64_t length,
182 uint64_t journal_tid, int r) {
183 EXPECT_CALL(mock_image_ctx, write_to_cache(object, _, length, offset, _, _,
31f18b77 184 journal_tid, _))
7c673cae
FG
185 .WillOnce(WithArg<4>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
186 }
187
188 void expect_object_request_send(MockImageCtx &mock_image_ctx,
189 MockObjectRequest &mock_object_request,
190 int r) {
191 EXPECT_CALL(mock_object_request, send())
192 .WillOnce(Invoke([&mock_image_ctx, &mock_object_request, r]() {
193 mock_image_ctx.image_ctx->op_work_queue->queue(
194 mock_object_request.on_finish, r);
195 }));
196 }
197
198 void expect_user_flushed(MockImageCtx &mock_image_ctx) {
199 EXPECT_CALL(mock_image_ctx, user_flushed());
200 }
201
202 void expect_flush(MockImageCtx &mock_image_ctx, int r) {
203 EXPECT_CALL(mock_image_ctx, flush(_))
204 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
205 }
206};
207
208TEST_F(TestMockIoImageRequest, AioWriteJournalAppendDisabled) {
209 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
210
211 librbd::ImageCtx *ictx;
212 ASSERT_EQ(0, open_image(m_image_name, &ictx));
213
214 MockObjectRequest mock_aio_object_request;
215 MockTestImageCtx mock_image_ctx(*ictx);
216 MockJournal mock_journal;
217 mock_image_ctx.journal = &mock_journal;
218
219 InSequence seq;
220 expect_is_journal_appending(mock_journal, false);
31f18b77
FG
221 if (mock_image_ctx.image_ctx->cache) {
222 expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
223 0, 1, 0, 0);
224 } else {
225 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
226 }
7c673cae
FG
227
228 C_SaferCond aio_comp_ctx;
229 AioCompletion *aio_comp = AioCompletion::create_and_start(
230 &aio_comp_ctx, ictx, AIO_TYPE_WRITE);
231
232 bufferlist bl;
233 bl.append("1");
234 MockImageWriteRequest mock_aio_image_write(mock_image_ctx, aio_comp,
31f18b77 235 {{0, 1}}, std::move(bl), 0, {});
7c673cae
FG
236 {
237 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
238 mock_aio_image_write.send();
239 }
240 ASSERT_EQ(0, aio_comp_ctx.wait());
241}
242
243TEST_F(TestMockIoImageRequest, AioDiscardJournalAppendDisabled) {
244 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
245
246 librbd::ImageCtx *ictx;
247 ASSERT_EQ(0, open_image(m_image_name, &ictx));
248
249 MockObjectRequest mock_aio_object_request;
250 MockTestImageCtx mock_image_ctx(*ictx);
251 MockJournal mock_journal;
252 mock_image_ctx.journal = &mock_journal;
253
254 InSequence seq;
255 expect_is_journal_appending(mock_journal, false);
256 if (!ictx->skip_partial_discard) {
257 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
258 }
259
260 C_SaferCond aio_comp_ctx;
261 AioCompletion *aio_comp = AioCompletion::create_and_start(
262 &aio_comp_ctx, ictx, AIO_TYPE_DISCARD);
263 MockImageDiscardRequest mock_aio_image_discard(mock_image_ctx, aio_comp,
31f18b77
FG
264 0, 1,
265 ictx->skip_partial_discard,
266 {});
7c673cae
FG
267 {
268 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
269 mock_aio_image_discard.send();
270 }
271 ASSERT_EQ(0, aio_comp_ctx.wait());
272}
273
274TEST_F(TestMockIoImageRequest, AioFlushJournalAppendDisabled) {
275 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
276
277 librbd::ImageCtx *ictx;
278 ASSERT_EQ(0, open_image(m_image_name, &ictx));
279
280 MockTestImageCtx mock_image_ctx(*ictx);
281 MockJournal mock_journal;
282 mock_image_ctx.journal = &mock_journal;
283
284 InSequence seq;
285 expect_user_flushed(mock_image_ctx);
286 expect_is_journal_appending(mock_journal, false);
287 expect_flush(mock_image_ctx, 0);
288
289 C_SaferCond aio_comp_ctx;
290 AioCompletion *aio_comp = AioCompletion::create_and_start(
291 &aio_comp_ctx, ictx, AIO_TYPE_FLUSH);
31f18b77 292 MockImageFlushRequest mock_aio_image_flush(mock_image_ctx, aio_comp, {});
7c673cae
FG
293 {
294 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
295 mock_aio_image_flush.send();
296 }
297 ASSERT_EQ(0, aio_comp_ctx.wait());
298}
299
300TEST_F(TestMockIoImageRequest, AioWriteSameJournalAppendDisabled) {
301 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
302
303 librbd::ImageCtx *ictx;
304 ASSERT_EQ(0, open_image(m_image_name, &ictx));
305
306 MockObjectRequest mock_aio_object_request;
307 MockTestImageCtx mock_image_ctx(*ictx);
308 MockJournal mock_journal;
309 mock_image_ctx.journal = &mock_journal;
310
311 InSequence seq;
312 expect_is_journal_appending(mock_journal, false);
31f18b77
FG
313 if (mock_image_ctx.image_ctx->cache) {
314 expect_write_to_cache(mock_image_ctx, ictx->get_object_name(0),
315 0, 1, 0, 0);
316 } else {
317 expect_object_request_send(mock_image_ctx, mock_aio_object_request, 0);
318 }
319
7c673cae
FG
320
321 C_SaferCond aio_comp_ctx;
322 AioCompletion *aio_comp = AioCompletion::create_and_start(
323 &aio_comp_ctx, ictx, AIO_TYPE_WRITESAME);
324
325 bufferlist bl;
326 bl.append("1");
327 MockImageWriteSameRequest mock_aio_image_writesame(mock_image_ctx, aio_comp,
31f18b77
FG
328 0, 1, std::move(bl), 0,
329 {});
7c673cae
FG
330 {
331 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
332 mock_aio_image_writesame.send();
333 }
334 ASSERT_EQ(0, aio_comp_ctx.wait());
335}
336
337} // namespace io
338} // namespace librbd