]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/image/test_mock_RemoveRequest.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / librbd / image / test_mock_RemoveRequest.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/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
25namespace librbd {
26namespace image {
27template <>
28struct TypeTraits<MockImageCtx> {
29 typedef librbd::MockContextWQ ContextWQ;
30};
31}
32
33namespace operation {
34
35template <>
36class TrimRequest<MockImageCtx> {
37public:
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
58namespace journal {
59template <>
60class RemoveRequest<MockImageCtx> {
61private:
62 typedef ::librbd::image::TypeTraits<MockImageCtx> TypeTraits;
63 typedef typename TypeTraits::ContextWQ ContextWQ;
64public:
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};
82RemoveRequest<MockImageCtx> *RemoveRequest<MockImageCtx>::s_instance = nullptr;
83} // namespace journal
84
85namespace mirror {
86
87template<>
88class DisableRequest<MockImageCtx> {
89public:
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
107DisableRequest<MockImageCtx> *DisableRequest<MockImageCtx>::s_instance;
108
109} // namespace mirror
110} // namespace librbd
111
112// template definitions
113#include "librbd/image/RemoveRequest.cc"
114template class librbd::image::RemoveRequest<librbd::MockImageCtx>;
115
116namespace librbd {
117namespace image {
118
119using ::testing::_;
120using ::testing::DoAll;
121using ::testing::DoDefault;
122using ::testing::Invoke;
123using ::testing::InSequence;
124using ::testing::Return;
125using ::testing::WithArg;
126using ::testing::SetArgPointee;
127using ::testing::StrEq;
128
129class TestMockImageRemoveRequest : public TestMockFixture {
130public:
131 typedef ::librbd::image::TypeTraits<MockImageCtx> TypeTraits;
132 typedef typename TypeTraits::ContextWQ ContextWQ;
133 typedef RemoveRequest<MockImageCtx> MockRemoveRequest;
134 typedef librbd::operation::TrimRequest<MockImageCtx> MockTrimRequest;
135 typedef librbd::journal::RemoveRequest<MockImageCtx> MockJournalRemoveRequest;
136 typedef librbd::mirror::DisableRequest<MockImageCtx> MockMirrorDisableRequest;
137
138 librbd::ImageCtx *m_test_imctx = NULL;
139 MockImageCtx *m_mock_imctx = NULL;
140
141
142 void TestImageRemoveSetUp() {
143 ASSERT_EQ(0, open_image(m_image_name, &m_test_imctx));
144 m_mock_imctx = new MockImageCtx(*m_test_imctx);
145 librbd::MockImageCtx::s_instance = m_mock_imctx;
146 }
147 void TestImageRemoveTearDown() {
148 librbd::MockImageCtx::s_instance = NULL;
149 delete m_mock_imctx;
150 }
151
152 void expect_state_open(MockImageCtx &mock_image_ctx, int r) {
153 EXPECT_CALL(*mock_image_ctx.state, open(_, _))
154 .WillOnce(Invoke([r](bool open_parent, Context *on_ready) {
155 on_ready->complete(r);
156 }));
31f18b77
FG
157 if (r < 0) {
158 EXPECT_CALL(mock_image_ctx, destroy());
159 }
7c673cae
FG
160 }
161
162 void expect_state_close(MockImageCtx &mock_image_ctx) {
163 EXPECT_CALL(*mock_image_ctx.state, close(_))
164 .WillOnce(Invoke([](Context *on_ready) {
165 on_ready->complete(0);
166 }));
31f18b77 167 EXPECT_CALL(mock_image_ctx, destroy());
7c673cae
FG
168 }
169
170 void expect_wq_queue(ContextWQ &wq, int r) {
171 EXPECT_CALL(wq, queue(_, r))
172 .WillRepeatedly(Invoke([](Context *on_ready, int r) {
173 on_ready->complete(r);
174 }));
175 }
176
177 void expect_get_group(MockImageCtx &mock_image_ctx, int r) {
178 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
179 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
180 StrEq("image_get_group"), _, _, _));
181 if (r < 0) {
182 expect.WillOnce(Return(r));
183 } else {
184 expect.WillOnce(DoDefault());
185 }
186 }
187
188 void expect_trim(MockImageCtx &mock_image_ctx,
189 MockTrimRequest &mock_trim_request, int r) {
190 EXPECT_CALL(mock_trim_request, send())
191 .WillOnce(FinishRequest(&mock_trim_request, r, &mock_image_ctx));
192 }
193
194 void expect_journal_remove(MockImageCtx &mock_image_ctx,
195 MockJournalRemoveRequest &mock_journal_remove_request, int r) {
196 EXPECT_CALL(mock_journal_remove_request, send())
197 .WillOnce(FinishRequest(&mock_journal_remove_request, r, &mock_image_ctx));
198 }
199
200 void expect_mirror_disable(MockImageCtx &mock_image_ctx,
201 MockMirrorDisableRequest &mock_mirror_disable_request, int r) {
202 EXPECT_CALL(mock_mirror_disable_request, send())
203 .WillOnce(FinishRequest(&mock_mirror_disable_request, r, &mock_image_ctx));
204 }
205
206 void expect_remove_child(MockImageCtx &mock_image_ctx, int r) {
207 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
208 exec(RBD_CHILDREN, _, StrEq("rbd"), StrEq("remove_child"), _,
209 _, _))
210 .WillOnce(Return(r));
211 }
212
213 void expect_remove_mirror_image(librados::IoCtx &ioctx, int r) {
214 EXPECT_CALL(get_mock_io_ctx(ioctx),
215 exec(StrEq("rbd_mirroring"), _, StrEq("rbd"), StrEq("mirror_image_remove"),
216 _, _, _))
217 .WillOnce(Return(r));
218 }
219
220 void expect_mirror_image_get(MockImageCtx &mock_image_ctx, int r) {
221 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
222 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get"),
223 _, _, _))
224 .WillOnce(Return(r));
225 }
226
227 void expect_dir_remove_image(librados::IoCtx &ioctx, int r) {
228 EXPECT_CALL(get_mock_io_ctx(ioctx),
229 exec(RBD_DIRECTORY, _, StrEq("rbd"), StrEq("dir_remove_image"),
230 _, _, _))
231 .WillOnce(Return(r));
232 }
233};
234
235TEST_F(TestMockImageRemoveRequest, SuccessV1) {
236 REQUIRE_FORMAT_V1();
237 TestImageRemoveSetUp();
238
239 C_SaferCond ctx;
240 librbd::NoOpProgressContext no_op;
241 ContextWQ op_work_queue;
242 MockTrimRequest mock_trim_request;
243 MockJournalRemoveRequest mock_journal_remove_request;
244
245 InSequence seq;
246 expect_state_open(*m_mock_imctx, 0);
247 expect_get_group(*m_mock_imctx, 0);
248 expect_trim(*m_mock_imctx, mock_trim_request, 0);
249 expect_op_work_queue(*m_mock_imctx);
250 expect_state_close(*m_mock_imctx);
251 expect_wq_queue(op_work_queue, 0);
252
253 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
254 true, false, no_op, &op_work_queue, &ctx);
255 req->send();
256
257 ASSERT_EQ(0, ctx.wait());
258
259 TestImageRemoveTearDown();
260}
261
262TEST_F(TestMockImageRemoveRequest, OpenFailV1) {
263 REQUIRE_FORMAT_V1();
264 TestImageRemoveSetUp();
265
266 C_SaferCond ctx;
267 librbd::NoOpProgressContext no_op;
268 ContextWQ op_work_queue;
269 MockTrimRequest mock_trim_request;
270
271 InSequence seq;
272 expect_state_open(*m_mock_imctx, -ENOENT);
273 expect_wq_queue(op_work_queue, 0);
274
275 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
276 true, false, no_op, &op_work_queue, &ctx);
277 req->send();
278
279 ASSERT_EQ(0, ctx.wait());
280
281 TestImageRemoveTearDown();
282}
283
284TEST_F(TestMockImageRemoveRequest, SuccessV2) {
285 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
286 TestImageRemoveSetUp();
287
288 C_SaferCond ctx;
289 librbd::NoOpProgressContext no_op;
290 ContextWQ op_work_queue;
291 MockTrimRequest mock_trim_request;
292 MockJournalRemoveRequest mock_journal_remove_request;
293 MockMirrorDisableRequest mock_mirror_disable_request;
294
295 InSequence seq;
296 expect_state_open(*m_mock_imctx, 0);
297 expect_mirror_image_get(*m_mock_imctx, 0);
298 expect_get_group(*m_mock_imctx, 0);
299 expect_trim(*m_mock_imctx, mock_trim_request, 0);
300 expect_op_work_queue(*m_mock_imctx);
301 expect_remove_child(*m_mock_imctx, 0);
302 expect_mirror_disable(*m_mock_imctx, mock_mirror_disable_request, 0);
303 expect_state_close(*m_mock_imctx);
304 expect_wq_queue(op_work_queue, 0);
305 expect_journal_remove(*m_mock_imctx, mock_journal_remove_request, 0);
306 expect_remove_mirror_image(m_ioctx, 0);
307 expect_dir_remove_image(m_ioctx, 0);
308
309 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
310 true, false, no_op, &op_work_queue, &ctx);
311 req->send();
312
313 ASSERT_EQ(0, ctx.wait());
314
315 TestImageRemoveTearDown();
316}
317
318TEST_F(TestMockImageRemoveRequest, NotExistsV2) {
319 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
320 TestImageRemoveSetUp();
321
322 C_SaferCond ctx;
323 librbd::NoOpProgressContext no_op;
324 ContextWQ op_work_queue;
325 MockTrimRequest mock_trim_request;
326 MockJournalRemoveRequest mock_journal_remove_request;
327 MockMirrorDisableRequest mock_mirror_disable_request;
328
329 InSequence seq;
330 expect_state_open(*m_mock_imctx, 0);
331 expect_mirror_image_get(*m_mock_imctx, 0);
332 expect_get_group(*m_mock_imctx, 0);
333 expect_trim(*m_mock_imctx, mock_trim_request, 0);
334 expect_op_work_queue(*m_mock_imctx);
335 expect_remove_child(*m_mock_imctx, 0);
336 expect_mirror_disable(*m_mock_imctx, mock_mirror_disable_request, 0);
337 expect_state_close(*m_mock_imctx);
338 expect_wq_queue(op_work_queue, 0);
339 expect_journal_remove(*m_mock_imctx, mock_journal_remove_request, 0);
340 expect_remove_mirror_image(m_ioctx, 0);
341 expect_dir_remove_image(m_ioctx, -ENOENT);
342
343 MockRemoveRequest *req = MockRemoveRequest::create(m_ioctx, m_image_name, "",
344 true, false, no_op, &op_work_queue, &ctx);
345 req->send();
346 ASSERT_EQ(-ENOENT, ctx.wait());
347
348 TestImageRemoveTearDown();
349}
350
351} // namespace image
352} // namespace librbd