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