]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / librbd / operation / test_mock_SnapshotCreateRequest.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/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/SnapshotCreateRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14
15 // template definitions
16 #include "librbd/operation/SnapshotCreateRequest.cc"
17
18 namespace librbd {
19 namespace operation {
20
21 using ::testing::_;
22 using ::testing::DoAll;
23 using ::testing::DoDefault;
24 using ::testing::Return;
25 using ::testing::SetArgPointee;
26 using ::testing::StrEq;
27 using ::testing::WithArg;
28
29 class TestMockOperationSnapshotCreateRequest : public TestMockFixture {
30 public:
31 typedef SnapshotCreateRequest<MockImageCtx> MockSnapshotCreateRequest;
32
33 void expect_block_writes(MockImageCtx &mock_image_ctx) {
34 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
35 .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
36 }
37
38 void expect_verify_lock_ownership(MockImageCtx &mock_image_ctx) {
39 if (mock_image_ctx.exclusive_lock != nullptr) {
40 EXPECT_CALL(*mock_image_ctx.exclusive_lock, is_lock_owner())
41 .WillRepeatedly(Return(true));
42 }
43 }
44
45 void expect_allocate_snap_id(MockImageCtx &mock_image_ctx, int r) {
46 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
47 selfmanaged_snap_create(_));
48 if (r < 0 && r != -ESTALE) {
49 expect.WillOnce(Return(r));
50 } else {
51 expect.Times(r < 0 ? 2 : 1).WillRepeatedly(DoDefault());
52 }
53 }
54
55 void expect_release_snap_id(MockImageCtx &mock_image_ctx, int r) {
56 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
57 selfmanaged_snap_remove(_));
58 if (r < 0) {
59 expect.WillOnce(Return(r));
60 } else {
61 expect.WillOnce(DoDefault());
62 }
63 }
64
65 void expect_snap_create(MockImageCtx &mock_image_ctx, int r) {
66 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
67 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
68 StrEq(mock_image_ctx.old_format ? "snap_add" :
69 "snapshot_add"),
70 _, _, _));
71 if (r == -ESTALE) {
72 expect.WillOnce(Return(r)).WillOnce(DoDefault());
73 } else if (r < 0) {
74 expect.WillOnce(Return(r));
75 } else {
76 expect.WillOnce(DoDefault());
77 }
78 }
79
80 void expect_object_map_snap_create(MockImageCtx &mock_image_ctx) {
81 if (mock_image_ctx.object_map != nullptr) {
82 EXPECT_CALL(*mock_image_ctx.object_map, snapshot_add(_, _))
83 .WillOnce(WithArg<1>(CompleteContext(
84 0, mock_image_ctx.image_ctx->op_work_queue)));
85 }
86 }
87
88 void expect_update_snap_context(MockImageCtx &mock_image_ctx) {
89 // state machine checks to ensure a refresh hasn't already added the snap
90 EXPECT_CALL(mock_image_ctx, get_snap_info(_))
91 .WillOnce(Return(static_cast<const librbd::SnapInfo*>(NULL)));
92 EXPECT_CALL(mock_image_ctx, add_snap(_, "snap1", _, _, _, _, _, _));
93 }
94
95 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
96 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
97 .Times(1);
98 }
99
100 };
101
102 TEST_F(TestMockOperationSnapshotCreateRequest, Success) {
103 REQUIRE_FORMAT_V2();
104
105 librbd::ImageCtx *ictx;
106 ASSERT_EQ(0, open_image(m_image_name, &ictx));
107
108 MockImageCtx mock_image_ctx(*ictx);
109
110 MockExclusiveLock mock_exclusive_lock;
111 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
112 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
113 }
114
115 MockObjectMap mock_object_map;
116 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
117 mock_image_ctx.object_map = &mock_object_map;
118 }
119
120 expect_verify_lock_ownership(mock_image_ctx);
121 expect_op_work_queue(mock_image_ctx);
122
123 ::testing::InSequence seq;
124 expect_block_writes(mock_image_ctx);
125 expect_allocate_snap_id(mock_image_ctx, 0);
126 expect_snap_create(mock_image_ctx, 0);
127 if (!mock_image_ctx.old_format) {
128 expect_update_snap_context(mock_image_ctx);
129 expect_object_map_snap_create(mock_image_ctx);
130 }
131 expect_unblock_writes(mock_image_ctx);
132
133 C_SaferCond cond_ctx;
134 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
135 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
136 "snap1", 0, false);
137 {
138 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
139 req->send();
140 }
141 ASSERT_EQ(0, cond_ctx.wait());
142 }
143
144 TEST_F(TestMockOperationSnapshotCreateRequest, AllocateSnapIdError) {
145 librbd::ImageCtx *ictx;
146 ASSERT_EQ(0, open_image(m_image_name, &ictx));
147
148 MockImageCtx mock_image_ctx(*ictx);
149
150 MockExclusiveLock mock_exclusive_lock;
151 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
152 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
153 }
154
155 expect_verify_lock_ownership(mock_image_ctx);
156 expect_op_work_queue(mock_image_ctx);
157
158 ::testing::InSequence seq;
159 expect_block_writes(mock_image_ctx);
160 expect_allocate_snap_id(mock_image_ctx, -EINVAL);
161 expect_unblock_writes(mock_image_ctx);
162
163 C_SaferCond cond_ctx;
164 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
165 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
166 "snap1", 0, false);
167 {
168 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
169 req->send();
170 }
171 ASSERT_EQ(-EINVAL, cond_ctx.wait());
172 }
173
174 TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapStale) {
175 librbd::ImageCtx *ictx;
176 ASSERT_EQ(0, open_image(m_image_name, &ictx));
177
178 MockImageCtx mock_image_ctx(*ictx);
179
180 MockExclusiveLock mock_exclusive_lock;
181 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
182 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
183 }
184
185 MockObjectMap mock_object_map;
186 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
187 mock_image_ctx.object_map = &mock_object_map;
188 }
189
190 expect_verify_lock_ownership(mock_image_ctx);
191 expect_op_work_queue(mock_image_ctx);
192
193 expect_block_writes(mock_image_ctx);
194 expect_allocate_snap_id(mock_image_ctx, -ESTALE);
195 expect_snap_create(mock_image_ctx, -ESTALE);
196 if (!mock_image_ctx.old_format) {
197 expect_update_snap_context(mock_image_ctx);
198 expect_object_map_snap_create(mock_image_ctx);
199 }
200 expect_unblock_writes(mock_image_ctx);
201
202 C_SaferCond cond_ctx;
203 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
204 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
205 "snap1", 0, false);
206 {
207 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
208 req->send();
209 }
210 ASSERT_EQ(0, cond_ctx.wait());
211 }
212
213 TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapError) {
214 librbd::ImageCtx *ictx;
215 ASSERT_EQ(0, open_image(m_image_name, &ictx));
216
217 MockImageCtx mock_image_ctx(*ictx);
218
219 MockExclusiveLock mock_exclusive_lock;
220 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
221 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
222 }
223
224 expect_verify_lock_ownership(mock_image_ctx);
225 expect_op_work_queue(mock_image_ctx);
226
227 expect_block_writes(mock_image_ctx);
228 expect_allocate_snap_id(mock_image_ctx, 0);
229 expect_snap_create(mock_image_ctx, -EINVAL);
230 expect_release_snap_id(mock_image_ctx, 0);
231 expect_unblock_writes(mock_image_ctx);
232
233 C_SaferCond cond_ctx;
234 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
235 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
236 "snap1", 0, false);
237 {
238 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
239 req->send();
240 }
241 ASSERT_EQ(-EINVAL, cond_ctx.wait());
242 }
243
244 TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) {
245 librbd::ImageCtx *ictx;
246 ASSERT_EQ(0, open_image(m_image_name, &ictx));
247
248 MockImageCtx mock_image_ctx(*ictx);
249
250 MockExclusiveLock mock_exclusive_lock;
251 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
252 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
253 }
254
255 expect_verify_lock_ownership(mock_image_ctx);
256 expect_op_work_queue(mock_image_ctx);
257
258 expect_block_writes(mock_image_ctx);
259 expect_allocate_snap_id(mock_image_ctx, 0);
260 expect_snap_create(mock_image_ctx, -EINVAL);
261 expect_release_snap_id(mock_image_ctx, -ESTALE);
262 expect_unblock_writes(mock_image_ctx);
263
264 C_SaferCond cond_ctx;
265 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
266 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
267 "snap1", 0, false);
268 {
269 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
270 req->send();
271 }
272 ASSERT_EQ(-EINVAL, cond_ctx.wait());
273 }
274
275 TEST_F(TestMockOperationSnapshotCreateRequest, SkipObjectMap) {
276 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
277
278 librbd::ImageCtx *ictx;
279 ASSERT_EQ(0, open_image(m_image_name, &ictx));
280
281 MockImageCtx mock_image_ctx(*ictx);
282
283 MockExclusiveLock mock_exclusive_lock;
284 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
285 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
286 }
287
288 MockObjectMap mock_object_map;
289 mock_image_ctx.object_map = &mock_object_map;
290
291 expect_verify_lock_ownership(mock_image_ctx);
292 expect_op_work_queue(mock_image_ctx);
293
294 ::testing::InSequence seq;
295 expect_block_writes(mock_image_ctx);
296 expect_allocate_snap_id(mock_image_ctx, 0);
297 expect_snap_create(mock_image_ctx, 0);
298 expect_update_snap_context(mock_image_ctx);
299 expect_unblock_writes(mock_image_ctx);
300
301 C_SaferCond cond_ctx;
302 MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest(
303 mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(),
304 "snap1", 0, true);
305 {
306 RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
307 req->send();
308 }
309 ASSERT_EQ(0, cond_ctx.wait());
310 }
311
312 } // namespace operation
313 } // namespace librbd