]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc
Import ceph 15.2.8
[ceph.git] / ceph / src / test / librbd / cache / test_mock_ParentCacheObjectDispatch.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 "gmock/gmock.h"
8 #include "gtest/gtest.h"
9 #include "include/Context.h"
10 #include "tools/immutable_object_cache/CacheClient.h"
11 #include "test/immutable_object_cache/MockCacheDaemon.h"
12 #include "librbd/io/Utils.h"
13 #include "librbd/cache/ParentCacheObjectDispatch.h"
14 #include "test/librbd/test_mock_fixture.h"
15 #include "test/librbd/mock/MockImageCtx.h"
16
17 using namespace ceph::immutable_obj_cache;
18
19 namespace librbd {
20
21 namespace {
22
23 struct MockParentImageCacheImageCtx : public MockImageCtx {
24 MockParentImageCacheImageCtx(ImageCtx& image_ctx)
25 : MockImageCtx(image_ctx) {
26 }
27 ~MockParentImageCacheImageCtx() {}
28 };
29
30 }; // anonymous namespace
31
32 namespace cache {
33
34 template<>
35 struct TypeTraits<MockParentImageCacheImageCtx> {
36 typedef ceph::immutable_obj_cache::MockCacheClient CacheClient;
37 };
38
39 }; // namespace cache
40
41 namespace io {
42 namespace util {
43
44 namespace {
45
46 struct Mock {
47 static Mock* s_instance;
48
49 Mock() {
50 s_instance = this;
51 }
52
53 MOCK_METHOD8(read_parent,
54 void(librbd::MockParentImageCacheImageCtx *, uint64_t, uint64_t,
55 uint64_t, librados::snap_t, const ZTracer::Trace &,
56 ceph::bufferlist*, Context*));
57 };
58
59 Mock *Mock::s_instance = nullptr;
60
61 } // anonymous namespace
62
63 template<> void read_parent(
64 librbd::MockParentImageCacheImageCtx *image_ctx, uint64_t object_no,
65 uint64_t off, uint64_t len, librados::snap_t snap_id,
66 const ZTracer::Trace &trace, ceph::bufferlist* data, Context* on_finish) {
67 Mock::s_instance->read_parent(image_ctx, object_no, off, len, snap_id, trace,
68 data, on_finish);
69 }
70
71 } // namespace util
72 } // namespace io
73
74 }; // namespace librbd
75
76 #include "librbd/cache/ParentCacheObjectDispatch.cc"
77 template class librbd::cache::ParentCacheObjectDispatch<librbd::MockParentImageCacheImageCtx>;
78
79 namespace librbd {
80
81 using ::testing::_;
82 using ::testing::DoAll;
83 using ::testing::Invoke;
84 using ::testing::InSequence;
85 using ::testing::Return;
86 using ::testing::WithArg;
87 using ::testing::WithArgs;
88
89 class TestMockParentCacheObjectDispatch : public TestMockFixture {
90 public :
91 typedef cache::ParentCacheObjectDispatch<librbd::MockParentImageCacheImageCtx> MockParentImageCache;
92 typedef io::util::Mock MockUtils;
93
94 // ====== mock cache client ====
95 void expect_cache_run(MockParentImageCache& mparent_image_cache, bool ret_val) {
96 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), run());
97
98 expect.WillOnce((Invoke([ret_val]() {
99 })));
100 }
101
102 void expect_cache_session_state(MockParentImageCache& mparent_image_cache, bool ret_val) {
103 auto & expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), is_session_work());
104
105 expect.WillOnce((Invoke([ret_val]() {
106 return ret_val;
107 })));
108 }
109
110 void expect_cache_connect(MockParentImageCache& mparent_image_cache, int ret_val) {
111 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), connect());
112
113 expect.WillOnce((Invoke([ret_val]() {
114 return ret_val;
115 })));
116 }
117
118 void expect_cache_async_connect(MockParentImageCache& mparent_image_cache, int ret_val,
119 Context* on_finish) {
120 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), connect(_));
121
122 expect.WillOnce(WithArg<0>(Invoke([on_finish, ret_val](Context* ctx) {
123 ctx->complete(ret_val);
124 on_finish->complete(ret_val);
125 })));
126 }
127
128 void expect_cache_lookup_object(MockParentImageCache& mparent_image_cache,
129 const std::string &cache_path) {
130 EXPECT_CALL(*(mparent_image_cache.get_cache_client()),
131 lookup_object(_, _, _, _, _))
132 .WillOnce(WithArg<4>(Invoke([cache_path](CacheGenContextURef on_finish) {
133 auto ack = new ObjectCacheReadReplyData(RBDSC_READ_REPLY, 0, cache_path);
134 on_finish.release()->complete(ack);
135 })));
136 }
137
138 void expect_read_parent(MockUtils &mock_utils, uint64_t object_no,
139 uint64_t off, uint64_t len, librados::snap_t snap_id,
140 int r) {
141 EXPECT_CALL(mock_utils,
142 read_parent(_, object_no, off, len, snap_id, _, _, _))
143 .WillOnce(WithArg<7>(CompleteContext(r, static_cast<ContextWQ*>(nullptr))));
144 }
145
146 void expect_cache_close(MockParentImageCache& mparent_image_cache, int ret_val) {
147 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), close());
148
149 expect.WillOnce((Invoke([ret_val]() {
150 })));
151 }
152
153 void expect_cache_stop(MockParentImageCache& mparent_image_cache, int ret_val) {
154 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), stop());
155
156 expect.WillOnce((Invoke([ret_val]() {
157 })));
158 }
159
160 void expect_cache_register(MockParentImageCache& mparent_image_cache, Context* mock_handle_register, int ret_val) {
161 auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), register_client(_));
162
163 expect.WillOnce(WithArg<0>(Invoke([mock_handle_register, ret_val](Context* ctx) {
164 if(ret_val == 0) {
165 mock_handle_register->complete(true);
166 } else {
167 mock_handle_register->complete(false);
168 }
169 ctx->complete(true);
170 return ret_val;
171 })));
172 }
173
174 void expect_io_object_dispatcher_register_state(MockParentImageCache& mparent_image_cache,
175 int ret_val) {
176 auto& expect = EXPECT_CALL((*(mparent_image_cache.get_image_ctx()->io_object_dispatcher)),
177 register_object_dispatch(_));
178
179 expect.WillOnce(WithArg<0>(Invoke([ret_val, &mparent_image_cache]
180 (io::ObjectDispatchInterface* object_dispatch) {
181 ASSERT_EQ(object_dispatch, &mparent_image_cache);
182 })));
183 }
184 };
185
186 TEST_F(TestMockParentCacheObjectDispatch, test_initialization_success) {
187 librbd::ImageCtx* ictx;
188 ASSERT_EQ(0, open_image(m_image_name, &ictx));
189 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
190 mock_image_ctx.child = &mock_image_ctx;
191
192 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
193
194 expect_cache_run(*mock_parent_image_cache, 0);
195 C_SaferCond cond;
196 Context* handle_connect = new LambdaContext([&cond](int ret) {
197 ASSERT_EQ(ret, 0);
198 cond.complete(0);
199 });
200 expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect);
201 Context* ctx = new LambdaContext([](bool reg) {
202 ASSERT_EQ(reg, true);
203 });
204 expect_cache_register(*mock_parent_image_cache, ctx, 0);
205 expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
206 expect_cache_close(*mock_parent_image_cache, 0);
207 expect_cache_stop(*mock_parent_image_cache, 0);
208
209 mock_parent_image_cache->init();
210 cond.wait();
211
212 ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
213 io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
214 expect_cache_session_state(*mock_parent_image_cache, true);
215 ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(), true);
216
217 mock_parent_image_cache->get_cache_client()->close();
218 mock_parent_image_cache->get_cache_client()->stop();
219
220 delete mock_parent_image_cache;
221 }
222
223 TEST_F(TestMockParentCacheObjectDispatch, test_initialization_fail_at_connect) {
224 librbd::ImageCtx* ictx;
225 ASSERT_EQ(0, open_image(m_image_name, &ictx));
226 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
227 mock_image_ctx.child = &mock_image_ctx;
228
229 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
230
231 expect_cache_run(*mock_parent_image_cache, 0);
232 C_SaferCond cond;
233 Context* handle_connect = new LambdaContext([&cond](int ret) {
234 ASSERT_EQ(ret, -1);
235 cond.complete(0);
236 });
237 expect_cache_async_connect(*mock_parent_image_cache, -1, handle_connect);
238 expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
239 expect_cache_session_state(*mock_parent_image_cache, false);
240 expect_cache_close(*mock_parent_image_cache, 0);
241 expect_cache_stop(*mock_parent_image_cache, 0);
242
243 mock_parent_image_cache->init();
244
245 // initialization fails.
246 ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
247 io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
248 ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(), false);
249
250 mock_parent_image_cache->get_cache_client()->close();
251 mock_parent_image_cache->get_cache_client()->stop();
252
253 delete mock_parent_image_cache;
254
255 }
256
257 TEST_F(TestMockParentCacheObjectDispatch, test_initialization_fail_at_register) {
258 librbd::ImageCtx* ictx;
259 ASSERT_EQ(0, open_image(m_image_name, &ictx));
260 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
261 mock_image_ctx.child = &mock_image_ctx;
262
263 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
264
265 expect_cache_run(*mock_parent_image_cache, 0);
266 C_SaferCond cond;
267 Context* handle_connect = new LambdaContext([&cond](int ret) {
268 ASSERT_EQ(ret, 0);
269 cond.complete(0);
270 });
271 expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect);
272 Context* ctx = new LambdaContext([](bool reg) {
273 ASSERT_EQ(reg, false);
274 });
275 expect_cache_register(*mock_parent_image_cache, ctx, -1);
276 expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
277 expect_cache_close(*mock_parent_image_cache, 0);
278 expect_cache_stop(*mock_parent_image_cache, 0);
279
280 mock_parent_image_cache->init();
281 cond.wait();
282
283 ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
284 io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
285 expect_cache_session_state(*mock_parent_image_cache, true);
286 ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(), true);
287
288 mock_parent_image_cache->get_cache_client()->close();
289 mock_parent_image_cache->get_cache_client()->stop();
290
291 delete mock_parent_image_cache;
292 }
293
294 TEST_F(TestMockParentCacheObjectDispatch, test_disble_interface) {
295 librbd::ImageCtx* ictx;
296 ASSERT_EQ(0, open_image(m_image_name, &ictx));
297 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
298 mock_image_ctx.child = &mock_image_ctx;
299
300 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
301
302 std::string temp_oid("12345");
303 ceph::bufferlist temp_bl;
304 ::SnapContext *temp_snapc = nullptr;
305 io::DispatchResult* temp_dispatch_result = nullptr;
306 io::Extents temp_buffer_extents;
307 int* temp_op_flags = nullptr;
308 uint64_t* temp_journal_tid = nullptr;
309 Context** temp_on_finish = nullptr;
310 Context* temp_on_dispatched = nullptr;
311 ZTracer::Trace* temp_trace = nullptr;
312 io::LightweightBufferExtents buffer_extents;
313
314 ASSERT_EQ(mock_parent_image_cache->discard(0, 0, 0, *temp_snapc, 0, *temp_trace, temp_op_flags,
315 temp_journal_tid, temp_dispatch_result, temp_on_finish, temp_on_dispatched), false);
316 ASSERT_EQ(mock_parent_image_cache->write(0, 0, std::move(temp_bl), *temp_snapc, 0,
317 *temp_trace, temp_op_flags, temp_journal_tid, temp_dispatch_result,
318 temp_on_finish, temp_on_dispatched), false);
319 ASSERT_EQ(mock_parent_image_cache->write_same(0, 0, 0, std::move(buffer_extents),
320 std::move(temp_bl), *temp_snapc, 0, *temp_trace, temp_op_flags,
321 temp_journal_tid, temp_dispatch_result, temp_on_finish, temp_on_dispatched), false );
322 ASSERT_EQ(mock_parent_image_cache->compare_and_write(0, 0, std::move(temp_bl), std::move(temp_bl),
323 *temp_snapc, 0, *temp_trace, temp_journal_tid, temp_op_flags, temp_journal_tid,
324 temp_dispatch_result, temp_on_finish, temp_on_dispatched), false);
325 ASSERT_EQ(mock_parent_image_cache->flush(io::FLUSH_SOURCE_USER, *temp_trace, temp_journal_tid,
326 temp_dispatch_result, temp_on_finish, temp_on_dispatched), false);
327 ASSERT_EQ(mock_parent_image_cache->invalidate_cache(nullptr), false);
328 ASSERT_EQ(mock_parent_image_cache->reset_existence_cache(nullptr), false);
329
330 delete mock_parent_image_cache;
331
332 }
333
334 TEST_F(TestMockParentCacheObjectDispatch, test_read) {
335 librbd::ImageCtx* ictx;
336 ASSERT_EQ(0, open_image(m_image_name, &ictx));
337 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
338 mock_image_ctx.child = &mock_image_ctx;
339
340 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
341
342 expect_cache_run(*mock_parent_image_cache, 0);
343 C_SaferCond conn_cond;
344 Context* handle_connect = new LambdaContext([&conn_cond](int ret) {
345 ASSERT_EQ(ret, 0);
346 conn_cond.complete(0);
347 });
348 expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect);
349 Context* ctx = new LambdaContext([](bool reg) {
350 ASSERT_EQ(reg, true);
351 });
352 expect_cache_register(*mock_parent_image_cache, ctx, 0);
353 expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
354 expect_cache_close(*mock_parent_image_cache, 0);
355 expect_cache_stop(*mock_parent_image_cache, 0);
356
357 mock_parent_image_cache->init();
358 conn_cond.wait();
359
360 ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
361 io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
362 expect_cache_session_state(*mock_parent_image_cache, true);
363 ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(), true);
364
365 auto& expect = EXPECT_CALL(*(mock_parent_image_cache->get_cache_client()), is_session_work());
366 expect.WillOnce(Return(true));
367
368 expect_cache_lookup_object(*mock_parent_image_cache, "/dev/null");
369
370 C_SaferCond on_dispatched;
371 io::DispatchResult dispatch_result;
372 ceph::bufferlist read_data;
373 mock_parent_image_cache->read(0, 0, 4096, CEPH_NOSNAP, 0, {}, &read_data,
374 nullptr, nullptr, &dispatch_result, nullptr,
375 &on_dispatched);
376 ASSERT_EQ(0, on_dispatched.wait());
377
378 mock_parent_image_cache->get_cache_client()->close();
379 mock_parent_image_cache->get_cache_client()->stop();
380 delete mock_parent_image_cache;
381 }
382
383 TEST_F(TestMockParentCacheObjectDispatch, test_read_dne) {
384 librbd::ImageCtx* ictx;
385 ASSERT_EQ(0, open_image(m_image_name, &ictx));
386 MockParentImageCacheImageCtx mock_image_ctx(*ictx);
387 mock_image_ctx.child = &mock_image_ctx;
388
389 auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
390
391 expect_cache_run(*mock_parent_image_cache, 0);
392 C_SaferCond conn_cond;
393 Context* handle_connect = new LambdaContext([&conn_cond](int ret) {
394 ASSERT_EQ(ret, 0);
395 conn_cond.complete(0);
396 });
397 expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect);
398 Context* ctx = new LambdaContext([](bool reg) {
399 ASSERT_EQ(reg, true);
400 });
401 expect_cache_register(*mock_parent_image_cache, ctx, 0);
402 expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
403 expect_cache_close(*mock_parent_image_cache, 0);
404 expect_cache_stop(*mock_parent_image_cache, 0);
405
406 mock_parent_image_cache->init();
407 conn_cond.wait();
408
409 ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
410 io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
411 expect_cache_session_state(*mock_parent_image_cache, true);
412 ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(),
413 true);
414
415 EXPECT_CALL(*(mock_parent_image_cache->get_cache_client()), is_session_work())
416 .WillOnce(Return(true));
417
418 expect_cache_lookup_object(*mock_parent_image_cache, "");
419
420 MockUtils mock_utils;
421 expect_read_parent(mock_utils, 0, 0, 4096, CEPH_NOSNAP, 0);
422
423 C_SaferCond on_dispatched;
424 io::DispatchResult dispatch_result;
425 mock_parent_image_cache->read(0, 0, 4096, CEPH_NOSNAP, 0, {}, nullptr,
426 nullptr, nullptr, &dispatch_result, nullptr,
427 &on_dispatched);
428 ASSERT_EQ(0, on_dispatched.wait());
429
430 mock_parent_image_cache->get_cache_client()->close();
431 mock_parent_image_cache->get_cache_client()->stop();
432 delete mock_parent_image_cache;
433 }
434
435 } // namespace librbd