Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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