Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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.data_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.data_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