]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/image/test_mock_RemoveRequest.cc
update sources to 12.2.8
[ceph.git] / ceph / src / test / librbd / image / test_mock_RemoveRequest.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/MockContextWQ.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "librbd/ImageState.h"
11 #include "librbd/internal.h"
12 #include "librbd/journal/RemoveRequest.h"
13 #include "librbd/Operations.h"
14 #include "librbd/operation/TrimRequest.h"
15 #include "librbd/image/TypeTraits.h"
16 #include "librbd/image/RemoveRequest.h"
17 #include "librbd/image/RefreshParentRequest.h"
18 #include "librbd/mirror/DisableRequest.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <arpa/inet.h>
22 #include <list>
23 #include <boost/scope_exit.hpp>
24
25 namespace librbd {
26 namespace image {
27 template <>
28 struct TypeTraits<MockImageCtx> {
29 typedef librbd::MockContextWQ ContextWQ;
30 };
31 }
32
33 namespace operation {
34
35 template <>
36 class TrimRequest<MockImageCtx> {
37 public:
38 static TrimRequest *s_instance;
39 static TrimRequest *create(MockImageCtx &image_ctx, Context *on_finish,
40 uint64_t original_size, uint64_t new_size,
41 ProgressContext &prog_ctx) {
42 assert(s_instance != nullptr);
43 s_instance->on_finish = on_finish;
44 return s_instance;
45 }
46
47 Context *on_finish = nullptr;
48
49 TrimRequest() {
50 s_instance = this;
51 }
52
53 MOCK_METHOD0(send, void());
54 };
55
56 } // namespace operation
57
58 namespace journal {
59 template <>
60 class RemoveRequest<MockImageCtx> {
61 private:
62 typedef ::librbd::image::TypeTraits<MockImageCtx> TypeTraits;
63 typedef typename TypeTraits::ContextWQ ContextWQ;
64 public:
65 static RemoveRequest *s_instance;
66 static RemoveRequest *create(IoCtx &ioctx, const std::string &imageid,
67 const std::string &client_id,
68 ContextWQ *op_work_queue, Context *on_finish) {
69 assert(s_instance != nullptr);
70 s_instance->on_finish = on_finish;
71 return s_instance;
72 }
73
74 Context *on_finish = nullptr;
75
76 RemoveRequest() {
77 s_instance = this;
78 }
79
80 MOCK_METHOD0(send, void());
81 };
82 RemoveRequest<MockImageCtx> *RemoveRequest<MockImageCtx>::s_instance = nullptr;
83 } // namespace journal
84
85 namespace mirror {
86
87 template<>
88 class DisableRequest<MockImageCtx> {
89 public:
90 static DisableRequest *s_instance;
91 Context *on_finish = nullptr;
92
93 static DisableRequest *create(MockImageCtx *image_ctx, bool force,
94 bool remove, Context *on_finish) {
95 assert(s_instance != nullptr);
96 s_instance->on_finish = on_finish;
97 return s_instance;
98 }
99
100 DisableRequest() {
101 s_instance = this;
102 }
103
104 MOCK_METHOD0(send, void());
105 };
106
107 DisableRequest<MockImageCtx> *DisableRequest<MockImageCtx>::s_instance;
108
109 } // namespace mirror
110 } // namespace librbd
111
112 // template definitions
113 #include "librbd/image/RemoveRequest.cc"
114 template class librbd::image::RemoveRequest<librbd::MockImageCtx>;
115
116 ACTION_P(TestFeatures, image_ctx) {
117 return ((image_ctx->features & arg0) != 0);
118 }
119
120 ACTION_P(ShutDownExclusiveLock, image_ctx) {
121 // shutting down exclusive lock will close object map and journal
122 image_ctx->exclusive_lock = nullptr;
123 image_ctx->object_map = nullptr;
124 image_ctx->journal = nullptr;
125 }
126
127 namespace librbd {
128 namespace image {
129
130 using ::testing::_;
131 using ::testing::DoAll;
132 using ::testing::DoDefault;
133 using ::testing::Invoke;
134 using ::testing::InSequence;
135 using ::testing::Return;
136 using ::testing::WithArg;
137 using ::testing::SetArgPointee;
138 using ::testing::StrEq;
139
140 class TestMockImageRemoveRequest : public TestMockFixture {
141 public:
142 typedef ::librbd::image::TypeTraits<MockImageCtx> TypeTraits;
143 typedef typename TypeTraits::ContextWQ ContextWQ;
144 typedef RemoveRequest<MockImageCtx> MockRemoveRequest;
145 typedef librbd::operation::TrimRequest<MockImageCtx> MockTrimRequest;
146 typedef librbd::journal::RemoveRequest<MockImageCtx> MockJournalRemoveRequest;
147 typedef librbd::mirror::DisableRequest<MockImageCtx> MockMirrorDisableRequest;
148
149 librbd::ImageCtx *m_test_imctx = NULL;
150 MockImageCtx *m_mock_imctx = NULL;
151
152
153 void TestImageRemoveSetUp() {
154 ASSERT_EQ(0, open_image(m_image_name, &m_test_imctx));
155 m_mock_imctx = new MockImageCtx(*m_test_imctx);
156 librbd::MockImageCtx::s_instance = m_mock_imctx;
157 }
158 void TestImageRemoveTearDown() {
159 librbd::MockImageCtx::s_instance = NULL;
160 delete m_mock_imctx;
161 }
162
163 void expect_state_open(MockImageCtx &mock_image_ctx, int r) {
164 EXPECT_CALL(*mock_image_ctx.state, open(_, _))
165 .WillOnce(Invoke([r](bool open_parent, Context *on_ready) {
166 on_ready->complete(r);
167 }));
168 if (r < 0) {
169 EXPECT_CALL(mock_image_ctx, destroy());
170 }
171 }
172
173 void expect_state_close(MockImageCtx &mock_image_ctx) {
174 EXPECT_CALL(*mock_image_ctx.state, close(_))
175 .WillOnce(Invoke([](Context *on_ready) {
176 on_ready->complete(0);
177 }));
178 EXPECT_CALL(mock_image_ctx, destroy());
179 }
180
181 void expect_wq_queue(ContextWQ &wq, int r) {
182 EXPECT_CALL(wq, queue(_, r))
183 .WillRepeatedly(Invoke([](Context *on_ready, int r) {
184 on_ready->complete(r);
185 }));
186 }
187
188 void expect_get_group(MockImageCtx &mock_image_ctx, int r) {
189 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
190 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
191 StrEq("image_get_group"), _, _, _));
192 if (r < 0) {
193 expect.WillOnce(Return(r));
194 } else {
195 expect.WillOnce(DoDefault());
196 }
197 }
198
199 void expect_trim(MockImageCtx &mock_image_ctx,
200 MockTrimRequest &mock_trim_request, int r) {
201 EXPECT_CALL(mock_trim_request, send())
202 .WillOnce(FinishRequest(&mock_trim_request, r, &mock_image_ctx));
203 }
204
205 void expect_journal_remove(MockImageCtx &mock_image_ctx,
206 MockJournalRemoveRequest &mock_journal_remove_request, int r) {
207 EXPECT_CALL(mock_journal_remove_request, send())
208 .WillOnce(FinishRequest(&mock_journal_remove_request, r, &mock_image_ctx));
209 }
210
211 void expect_mirror_disable(MockImageCtx &mock_image_ctx,
212 MockMirrorDisableRequest &mock_mirror_disable_request, int r) {
213 EXPECT_CALL(mock_mirror_disable_request, send())
214 .WillOnce(FinishRequest(&mock_mirror_disable_request, r, &mock_image_ctx));
215 }
216
217 void expect_remove_child(MockImageCtx &mock_image_ctx, int r) {
218 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
219 exec(RBD_CHILDREN, _, StrEq("rbd"), StrEq("remove_child"), _,
220 _, _))
221 .WillOnce(Return(r));
222 }
223
224 void expect_remove_mirror_image(librados::IoCtx &ioctx, int r) {
225 EXPECT_CALL(get_mock_io_ctx(ioctx),
226 exec(StrEq("rbd_mirroring"), _, StrEq("rbd"), StrEq("mirror_image_remove"),
227 _, _, _))
228 .WillOnce(Return(r));
229 }
230
231 void expect_mirror_image_get(MockImageCtx &mock_image_ctx, int r) {
232 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
233 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get"),
234 _, _, _))
235 .WillOnce(Return(r));
236 }
237
238 void expect_dir_remove_image(librados::IoCtx &ioctx, int r) {
239 EXPECT_CALL(get_mock_io_ctx(ioctx),
240 exec(RBD_DIRECTORY, _, StrEq("rbd"), StrEq("dir_remove_image"),
241 _, _, _))
242 .WillOnce(Return(r));
243 }
244
245 void expect_test_features(MockImageCtx &mock_image_ctx) {
246 if (m_mock_imctx->exclusive_lock != nullptr) {
247 EXPECT_CALL(mock_image_ctx, test_features(_))
248 .WillRepeatedly(TestFeatures(&mock_image_ctx));
249 }
250 }
251
252 void expect_set_journal_policy(MockImageCtx &mock_image_ctx) {
253 if (m_test_imctx->test_features(RBD_FEATURE_JOURNALING)) {
254 EXPECT_CALL(mock_image_ctx, set_journal_policy(_))
255 .WillOnce(Invoke([](journal::Policy* policy) {
256 ASSERT_TRUE(policy->journal_disabled());
257 delete policy;
258 }));
259 }
260 }
261
262 void expect_shut_down_exclusive_lock(MockImageCtx &mock_image_ctx,
263 MockExclusiveLock &mock_exclusive_lock,
264 int r) {
265 if (m_mock_imctx->exclusive_lock != nullptr) {
266 EXPECT_CALL(mock_exclusive_lock, shut_down(_))
267 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx),
268 CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
269 }
270 }
271
272 };
273
274 TEST_F(TestMockImageRemoveRequest, SuccessV1) {
275 REQUIRE_FORMAT_V1();
276 TestImageRemoveSetUp();
277
278 C_SaferCond ctx;
279 librbd::NoOpProgressContext no_op;
280 ContextWQ op_work_queue;
281 MockTrimRequest mock_trim_request;
282 MockJournalRemoveRequest mock_journal_remove_request;
283
284 InSequence seq;
285 expect_state_open(*m_mock_imctx, 0);
286 expect_get_group(*m_mock_imctx, 0);
287 expect_trim(*m_mock_imctx, mock_trim_request, 0);
288 expect_op_work_queue(*m_mock_imctx);
289 expect_state_close(*m_mock_imctx);
290 expect_wq_queue(op_work_queue, 0);
291
292 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
293 true, false, no_op, &op_work_queue, &ctx);
294 req->send();
295
296 ASSERT_EQ(0, ctx.wait());
297
298 TestImageRemoveTearDown();
299 }
300
301 TEST_F(TestMockImageRemoveRequest, OpenFailV1) {
302 REQUIRE_FORMAT_V1();
303 TestImageRemoveSetUp();
304
305 C_SaferCond ctx;
306 librbd::NoOpProgressContext no_op;
307 ContextWQ op_work_queue;
308 MockTrimRequest mock_trim_request;
309
310 InSequence seq;
311 expect_state_open(*m_mock_imctx, -ENOENT);
312 expect_wq_queue(op_work_queue, 0);
313
314 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
315 true, false, no_op, &op_work_queue, &ctx);
316 req->send();
317
318 ASSERT_EQ(0, ctx.wait());
319
320 TestImageRemoveTearDown();
321 }
322
323 TEST_F(TestMockImageRemoveRequest, SuccessV2) {
324 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
325 TestImageRemoveSetUp();
326
327 MockExclusiveLock *mock_exclusive_lock = nullptr;
328 if (m_test_imctx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
329 mock_exclusive_lock = new MockExclusiveLock();
330 m_mock_imctx->exclusive_lock = mock_exclusive_lock;
331 }
332
333 C_SaferCond ctx;
334 librbd::NoOpProgressContext no_op;
335 ContextWQ op_work_queue;
336 MockTrimRequest mock_trim_request;
337 MockJournalRemoveRequest mock_journal_remove_request;
338 MockMirrorDisableRequest mock_mirror_disable_request;
339
340 InSequence seq;
341 expect_state_open(*m_mock_imctx, 0);
342
343 expect_test_features(*m_mock_imctx);
344 expect_set_journal_policy(*m_mock_imctx);
345 expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, 0);
346
347 expect_mirror_image_get(*m_mock_imctx, 0);
348 expect_get_group(*m_mock_imctx, 0);
349 expect_trim(*m_mock_imctx, mock_trim_request, 0);
350 expect_op_work_queue(*m_mock_imctx);
351 expect_remove_child(*m_mock_imctx, 0);
352 expect_mirror_disable(*m_mock_imctx, mock_mirror_disable_request, 0);
353 expect_state_close(*m_mock_imctx);
354 expect_wq_queue(op_work_queue, 0);
355 expect_journal_remove(*m_mock_imctx, mock_journal_remove_request, 0);
356 expect_remove_mirror_image(m_ioctx, 0);
357 expect_dir_remove_image(m_ioctx, 0);
358
359 MockRemoveRequest *req = MockRemoveRequest::create(
360 m_ioctx, m_image_name, "", true, false, no_op, &op_work_queue, &ctx);
361 req->send();
362
363 ASSERT_EQ(0, ctx.wait());
364
365 TestImageRemoveTearDown();
366 }
367
368 TEST_F(TestMockImageRemoveRequest, NotExistsV2) {
369 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
370 TestImageRemoveSetUp();
371
372 MockExclusiveLock *mock_exclusive_lock = nullptr;
373 if (m_test_imctx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
374 mock_exclusive_lock = new MockExclusiveLock();
375 m_mock_imctx->exclusive_lock = mock_exclusive_lock;
376 }
377
378 C_SaferCond ctx;
379 librbd::NoOpProgressContext no_op;
380 ContextWQ op_work_queue;
381 MockTrimRequest mock_trim_request;
382 MockJournalRemoveRequest mock_journal_remove_request;
383 MockMirrorDisableRequest mock_mirror_disable_request;
384
385 InSequence seq;
386 expect_state_open(*m_mock_imctx, 0);
387
388 expect_test_features(*m_mock_imctx);
389 expect_set_journal_policy(*m_mock_imctx);
390 expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, 0);
391
392 expect_mirror_image_get(*m_mock_imctx, 0);
393 expect_get_group(*m_mock_imctx, 0);
394 expect_trim(*m_mock_imctx, mock_trim_request, 0);
395 expect_op_work_queue(*m_mock_imctx);
396 expect_remove_child(*m_mock_imctx, 0);
397 expect_mirror_disable(*m_mock_imctx, mock_mirror_disable_request, 0);
398 expect_state_close(*m_mock_imctx);
399 expect_wq_queue(op_work_queue, 0);
400 expect_journal_remove(*m_mock_imctx, mock_journal_remove_request, 0);
401 expect_remove_mirror_image(m_ioctx, 0);
402 expect_dir_remove_image(m_ioctx, -ENOENT);
403
404 MockRemoveRequest *req = MockRemoveRequest::create(
405 m_ioctx, m_image_name, "", true, false, no_op, &op_work_queue, &ctx);
406 req->send();
407 ASSERT_EQ(-ENOENT, ctx.wait());
408
409 TestImageRemoveTearDown();
410 }
411
412 } // namespace image
413 } // namespace librbd