]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/operation/test_mock_ResizeRequest.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / librbd / operation / test_mock_ResizeRequest.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/librados_test_stub/MockTestMemIoCtxImpl.h"
8#include "common/bit_vector.hpp"
9#include "librbd/internal.h"
10#include "librbd/ObjectMap.h"
11#include "librbd/operation/ResizeRequest.h"
12#include "librbd/operation/TrimRequest.h"
13#include "gmock/gmock.h"
14#include "gtest/gtest.h"
15
16namespace librbd {
17namespace operation {
18
19template <>
20class TrimRequest<MockImageCtx> {
21public:
22 static TrimRequest *s_instance;
23 static TrimRequest *create(MockImageCtx &image_ctx, Context *on_finish,
24 uint64_t original_size, uint64_t new_size,
25 ProgressContext &prog_ctx) {
26 assert(s_instance != nullptr);
27 s_instance->on_finish = on_finish;
28 return s_instance;
29 }
30
31 Context *on_finish = nullptr;
32
33 TrimRequest() {
34 s_instance = this;
35 }
36
37 MOCK_METHOD0(send, void());
38};
39
40TrimRequest<MockImageCtx> *TrimRequest<MockImageCtx>::s_instance = nullptr;
41
42} // namespace operation
43} // namespace librbd
44
45// template definitions
46#include "librbd/operation/ResizeRequest.cc"
47#include "librbd/operation/TrimRequest.cc"
48
49namespace librbd {
50namespace operation {
51
52using ::testing::_;
53using ::testing::DoAll;
54using ::testing::InSequence;
55using ::testing::Return;
56using ::testing::StrEq;
57using ::testing::WithArg;
58
59class TestMockOperationResizeRequest : public TestMockFixture {
60public:
61 typedef ResizeRequest<MockImageCtx> MockResizeRequest;
62 typedef TrimRequest<MockImageCtx> MockTrimRequest;
63
64 void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
65 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
66 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
67 }
68
69 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
70 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
71 .Times(1);
72 }
73
74 void expect_is_lock_owner(MockImageCtx &mock_image_ctx) {
75 if (mock_image_ctx.exclusive_lock != nullptr) {
76 EXPECT_CALL(*mock_image_ctx.exclusive_lock, is_lock_owner())
77 .WillOnce(Return(true));
78 }
79 }
80
81 void expect_grow_object_map(MockImageCtx &mock_image_ctx) {
82 if (mock_image_ctx.object_map != nullptr) {
83 expect_is_lock_owner(mock_image_ctx);
84 EXPECT_CALL(*mock_image_ctx.object_map, aio_resize(_, _, _))
85 .WillOnce(WithArg<2>(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
86 }
87 }
88
89 void expect_shrink_object_map(MockImageCtx &mock_image_ctx) {
90 if (mock_image_ctx.object_map != nullptr) {
91 expect_is_lock_owner(mock_image_ctx);
92 EXPECT_CALL(*mock_image_ctx.object_map, aio_resize(_, _, _))
93 .WillOnce(WithArg<2>(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
94 }
95 }
96
97 void expect_update_header(MockImageCtx &mock_image_ctx, int r) {
98 if (mock_image_ctx.old_format) {
99 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
100 write(mock_image_ctx.header_oid, _, _, _, _))
101 .WillOnce(Return(r));
102 } else {
103 expect_is_lock_owner(mock_image_ctx);
104 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
105 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_size"), _, _, _))
106 .WillOnce(Return(r));
107 }
108 }
109
110 void expect_trim(MockImageCtx &mock_image_ctx,
111 MockTrimRequest &mock_trim_request, int r) {
112 EXPECT_CALL(mock_trim_request, send())
113 .WillOnce(FinishRequest(&mock_trim_request, r, &mock_image_ctx));
114 }
115
116 void expect_flush_cache(MockImageCtx &mock_image_ctx, int r) {
31f18b77
FG
117 if (!mock_image_ctx.image_ctx->cache) {
118 return;
119 }
7c673cae
FG
120 EXPECT_CALL(mock_image_ctx, flush_cache(_))
121 .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
122 expect_op_work_queue(mock_image_ctx);
123 }
124
125 void expect_invalidate_cache(MockImageCtx &mock_image_ctx, int r) {
31f18b77
FG
126 if (!mock_image_ctx.image_ctx->cache) {
127 return;
128 }
7c673cae
FG
129 EXPECT_CALL(mock_image_ctx, invalidate_cache(false, _))
130 .WillOnce(WithArg<1>(CompleteContext(r, static_cast<ContextWQ*>(NULL))));
131 expect_op_work_queue(mock_image_ctx);
132 }
133
134 void expect_resize_object_map(MockImageCtx &mock_image_ctx,
135 uint64_t new_size) {
136 EXPECT_CALL(*mock_image_ctx.object_map, aio_resize(new_size, _, _))
137 .WillOnce(WithArg<2>(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
138 }
139
140 int when_resize(MockImageCtx &mock_image_ctx, uint64_t new_size,
141 bool allow_shrink, uint64_t journal_op_tid,
142 bool disable_journal) {
143 C_SaferCond cond_ctx;
144 librbd::NoOpProgressContext prog_ctx;
145 MockResizeRequest *req = new MockResizeRequest(
146 mock_image_ctx, &cond_ctx, new_size, allow_shrink, prog_ctx,
147 journal_op_tid, disable_journal);
148 {
149 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
150 req->send();
151 }
152 return cond_ctx.wait();
153 }
154};
155
156TEST_F(TestMockOperationResizeRequest, NoOpSuccess) {
157 librbd::ImageCtx *ictx;
158 ASSERT_EQ(0, open_image(m_image_name, &ictx));
159
160 MockImageCtx mock_image_ctx(*ictx);
161 MockExclusiveLock mock_exclusive_lock;
162 MockJournal mock_journal;
163 MockObjectMap mock_object_map;
164 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
165 mock_object_map);
166
167 InSequence seq;
168 expect_block_writes(mock_image_ctx, 0);
169 expect_append_op_event(mock_image_ctx, true, 0);
170 expect_unblock_writes(mock_image_ctx);
171 expect_commit_op_event(mock_image_ctx, 0);
172 ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, true, 0, false));
173}
174
175TEST_F(TestMockOperationResizeRequest, GrowSuccess) {
176 librbd::ImageCtx *ictx;
177 ASSERT_EQ(0, open_image(m_image_name, &ictx));
178
179 MockImageCtx mock_image_ctx(*ictx);
180 MockExclusiveLock mock_exclusive_lock;
181 MockJournal mock_journal;
182 MockObjectMap mock_object_map;
183 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
184 mock_object_map);
185
186 InSequence seq;
187 expect_block_writes(mock_image_ctx, 0);
188 expect_append_op_event(mock_image_ctx, true, 0);
189 expect_unblock_writes(mock_image_ctx);
190 expect_grow_object_map(mock_image_ctx);
191 expect_block_writes(mock_image_ctx, 0);
192 expect_update_header(mock_image_ctx, 0);
193 expect_unblock_writes(mock_image_ctx);
194 expect_commit_op_event(mock_image_ctx, 0);
195 ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
196}
197
198TEST_F(TestMockOperationResizeRequest, ShrinkSuccess) {
199 librbd::ImageCtx *ictx;
200 ASSERT_EQ(0, open_image(m_image_name, &ictx));
201
202 MockImageCtx mock_image_ctx(*ictx);
203 MockExclusiveLock mock_exclusive_lock;
204 MockJournal mock_journal;
205 MockObjectMap mock_object_map;
206 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
207 mock_object_map);
208
209 InSequence seq;
210 expect_block_writes(mock_image_ctx, 0);
211 expect_append_op_event(mock_image_ctx, true, 0);
212 expect_unblock_writes(mock_image_ctx);
213
214 MockTrimRequest mock_trim_request;
215 expect_flush_cache(mock_image_ctx, 0);
216 expect_invalidate_cache(mock_image_ctx, 0);
217 expect_trim(mock_image_ctx, mock_trim_request, 0);
218 expect_block_writes(mock_image_ctx, 0);
219 expect_update_header(mock_image_ctx, 0);
220 expect_shrink_object_map(mock_image_ctx);
221 expect_unblock_writes(mock_image_ctx);
222 expect_commit_op_event(mock_image_ctx, 0);
223 ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
224}
225
226TEST_F(TestMockOperationResizeRequest, ShrinkError) {
227 librbd::ImageCtx *ictx;
228 ASSERT_EQ(0, open_image(m_image_name, &ictx));
229
230 MockImageCtx mock_image_ctx(*ictx);
231 MockExclusiveLock mock_exclusive_lock;
232 MockJournal mock_journal;
233 MockObjectMap mock_object_map;
234 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
235 mock_object_map);
236
237 InSequence seq;
238 expect_block_writes(mock_image_ctx, -EINVAL);
239 expect_unblock_writes(mock_image_ctx);
240 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, false, 0, false));
241}
242
243TEST_F(TestMockOperationResizeRequest, PreBlockWritesError) {
244 librbd::ImageCtx *ictx;
245 ASSERT_EQ(0, open_image(m_image_name, &ictx));
246
247 MockImageCtx mock_image_ctx(*ictx);
248 MockExclusiveLock mock_exclusive_lock;
249 MockJournal mock_journal;
250 MockObjectMap mock_object_map;
251 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
252 mock_object_map);
253
254 InSequence seq;
255 expect_block_writes(mock_image_ctx, -EINVAL);
256 expect_unblock_writes(mock_image_ctx);
257 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, true, 0, false));
258}
259
260TEST_F(TestMockOperationResizeRequest, TrimError) {
261 librbd::ImageCtx *ictx;
262 ASSERT_EQ(0, open_image(m_image_name, &ictx));
263
264 MockImageCtx mock_image_ctx(*ictx);
265 MockExclusiveLock mock_exclusive_lock;
266 MockJournal mock_journal;
267 MockObjectMap mock_object_map;
268 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
269 mock_object_map);
270
271 InSequence seq;
272 expect_block_writes(mock_image_ctx, 0);
273 expect_append_op_event(mock_image_ctx, true, 0);
274 expect_unblock_writes(mock_image_ctx);
275
276 MockTrimRequest mock_trim_request;
277 expect_flush_cache(mock_image_ctx, 0);
278 expect_invalidate_cache(mock_image_ctx, -EBUSY);
279 expect_trim(mock_image_ctx, mock_trim_request, -EINVAL);
280 expect_commit_op_event(mock_image_ctx, -EINVAL);
281 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
282}
283
284TEST_F(TestMockOperationResizeRequest, FlushCacheError) {
285 librbd::ImageCtx *ictx;
286 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 287 REQUIRE(ictx->cache);
7c673cae
FG
288
289 MockImageCtx mock_image_ctx(*ictx);
290 MockExclusiveLock mock_exclusive_lock;
291 MockJournal mock_journal;
292 MockObjectMap mock_object_map;
293 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
294 mock_object_map);
295
296 InSequence seq;
297 expect_block_writes(mock_image_ctx, 0);
298 expect_append_op_event(mock_image_ctx, true, 0);
299 expect_unblock_writes(mock_image_ctx);
300
301 MockTrimRequest mock_trim_request;
302 expect_flush_cache(mock_image_ctx, -EINVAL);
303 expect_commit_op_event(mock_image_ctx, -EINVAL);
304 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
305}
306
307TEST_F(TestMockOperationResizeRequest, InvalidateCacheError) {
308 librbd::ImageCtx *ictx;
309 ASSERT_EQ(0, open_image(m_image_name, &ictx));
31f18b77 310 REQUIRE(ictx->cache);
7c673cae
FG
311
312 MockImageCtx mock_image_ctx(*ictx);
313 MockExclusiveLock mock_exclusive_lock;
314 MockJournal mock_journal;
315 MockObjectMap mock_object_map;
316 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
317 mock_object_map);
318
319 InSequence seq;
320 expect_block_writes(mock_image_ctx, 0);
321 expect_append_op_event(mock_image_ctx, true, 0);
322 expect_unblock_writes(mock_image_ctx);
323
324 MockTrimRequest mock_trim_request;
325 expect_flush_cache(mock_image_ctx, 0);
326 expect_invalidate_cache(mock_image_ctx, -EINVAL);
327 expect_commit_op_event(mock_image_ctx, -EINVAL);
328 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size / 2, true, 0, false));
329}
330
331TEST_F(TestMockOperationResizeRequest, PostBlockWritesError) {
332 librbd::ImageCtx *ictx;
333 ASSERT_EQ(0, open_image(m_image_name, &ictx));
334
335 MockImageCtx mock_image_ctx(*ictx);
336 MockExclusiveLock mock_exclusive_lock;
337 MockJournal mock_journal;
338 MockObjectMap mock_object_map;
339 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
340 mock_object_map);
341
342 InSequence seq;
343 expect_block_writes(mock_image_ctx, 0);
344 expect_append_op_event(mock_image_ctx, true, 0);
345 expect_unblock_writes(mock_image_ctx);
346 expect_grow_object_map(mock_image_ctx);
347 expect_block_writes(mock_image_ctx, -EINVAL);
348 expect_unblock_writes(mock_image_ctx);
349 expect_commit_op_event(mock_image_ctx, -EINVAL);
350 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
351}
352
353TEST_F(TestMockOperationResizeRequest, UpdateHeaderError) {
354 librbd::ImageCtx *ictx;
355 ASSERT_EQ(0, open_image(m_image_name, &ictx));
356
357 MockImageCtx mock_image_ctx(*ictx);
358 MockExclusiveLock mock_exclusive_lock;
359 MockJournal mock_journal;
360 MockObjectMap mock_object_map;
361 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
362 mock_object_map);
363
364 InSequence seq;
365 expect_block_writes(mock_image_ctx, 0);
366 expect_append_op_event(mock_image_ctx, true, 0);
367 expect_unblock_writes(mock_image_ctx);
368 expect_grow_object_map(mock_image_ctx);
369 expect_block_writes(mock_image_ctx, 0);
370 expect_update_header(mock_image_ctx, -EINVAL);
371 expect_unblock_writes(mock_image_ctx);
372 expect_commit_op_event(mock_image_ctx, -EINVAL);
373 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size * 2, true, 0, false));
374}
375
376TEST_F(TestMockOperationResizeRequest, JournalAppendError) {
377 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
378
379 librbd::ImageCtx *ictx;
380 ASSERT_EQ(0, open_image(m_image_name, &ictx));
381
382 MockImageCtx mock_image_ctx(*ictx);
383 MockExclusiveLock mock_exclusive_lock;
384 MockJournal mock_journal;
385 MockObjectMap mock_object_map;
386 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
387 mock_object_map);
388
389 InSequence seq;
390 expect_block_writes(mock_image_ctx, 0);
391 expect_append_op_event(mock_image_ctx, true, -EINVAL);
392 expect_unblock_writes(mock_image_ctx);
393 ASSERT_EQ(-EINVAL, when_resize(mock_image_ctx, ictx->size, true, 0, false));
394}
395
396TEST_F(TestMockOperationResizeRequest, JournalDisabled) {
397 librbd::ImageCtx *ictx;
398 ASSERT_EQ(0, open_image(m_image_name, &ictx));
399
400 MockImageCtx mock_image_ctx(*ictx);
401 MockExclusiveLock mock_exclusive_lock;
402 MockJournal mock_journal;
403 MockObjectMap mock_object_map;
404 initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
405 mock_object_map);
406
407 InSequence seq;
408 expect_block_writes(mock_image_ctx, 0);
409 expect_unblock_writes(mock_image_ctx);
410 ASSERT_EQ(0, when_resize(mock_image_ctx, ictx->size, true, 0, true));
411}
412
413} // namespace operation
414} // namespace librbd