Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / operation / test_mock_SnapshotRollbackRequest.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 "include/stringify.h"
9 #include "common/bit_vector.hpp"
10 #include "librbd/ImageState.h"
11 #include "librbd/internal.h"
12 #include "librbd/operation/SnapshotRollbackRequest.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15
16 namespace librbd {
17
18 namespace {
19
20 struct MockOperationImageCtx : public MockImageCtx {
21   MockOperationImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
22   }
23 };
24
25 } // anonymous namespace
26
27 namespace operation {
28
29 template <>
30 struct ResizeRequest<MockOperationImageCtx> {
31   static ResizeRequest *s_instance;
32   Context *on_finish = nullptr;
33
34   static ResizeRequest* create(MockOperationImageCtx &image_ctx, Context *on_finish,
35                                uint64_t new_size, bool allow_shrink,
36                                ProgressContext &prog_ctx, uint64_t journal_op_tid,
37                                bool disable_journal) {
38     assert(s_instance != nullptr);
39     assert(journal_op_tid == 0);
40     assert(disable_journal);
41     s_instance->on_finish = on_finish;
42     return s_instance;
43   }
44
45   ResizeRequest() {
46     s_instance = this;
47   }
48
49   MOCK_METHOD0(send, void());
50 };
51
52 ResizeRequest<MockOperationImageCtx> *ResizeRequest<MockOperationImageCtx>::s_instance = nullptr;
53
54 } // namespace operation
55
56 template <>
57 struct AsyncRequest<MockOperationImageCtx> : public AsyncRequest<MockImageCtx> {
58   MockOperationImageCtx &m_image_ctx;
59
60   AsyncRequest(MockOperationImageCtx &image_ctx, Context *on_finish)
61     : AsyncRequest<MockImageCtx>(image_ctx, on_finish), m_image_ctx(image_ctx) {
62   }
63 };
64
65 } // namespace librbd
66
67 // template definitions
68 #include "librbd/AsyncRequest.cc"
69 #include "librbd/AsyncObjectThrottle.cc"
70 #include "librbd/operation/Request.cc"
71 #include "librbd/operation/SnapshotRollbackRequest.cc"
72
73 namespace librbd {
74 namespace operation {
75
76 using ::testing::_;
77 using ::testing::InSequence;
78 using ::testing::Return;
79 using ::testing::WithArg;
80
81 class TestMockOperationSnapshotRollbackRequest : public TestMockFixture {
82 public:
83   typedef SnapshotRollbackRequest<MockOperationImageCtx> MockSnapshotRollbackRequest;
84   typedef ResizeRequest<MockOperationImageCtx> MockResizeRequest;
85
86   void expect_block_writes(MockOperationImageCtx &mock_image_ctx, int r) {
87     EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
88                   .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
89   }
90
91   void expect_unblock_writes(MockOperationImageCtx &mock_image_ctx) {
92     EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
93                   .Times(1);
94   }
95
96   void expect_get_image_size(MockOperationImageCtx &mock_image_ctx,
97                              uint64_t size) {
98     EXPECT_CALL(mock_image_ctx, get_image_size(CEPH_NOSNAP))
99                   .WillOnce(Return(size));
100   }
101
102   void expect_resize(MockOperationImageCtx &mock_image_ctx,
103                      MockResizeRequest &mock_resize_request, int r) {
104     expect_get_image_size(mock_image_ctx, 123);
105     EXPECT_CALL(mock_resize_request, send())
106                   .WillOnce(FinishRequest(&mock_resize_request, r,
107                                           &mock_image_ctx));
108   }
109
110   void expect_rollback_object_map(MockOperationImageCtx &mock_image_ctx,
111                                   MockObjectMap &mock_object_map) {
112     if (mock_image_ctx.object_map != nullptr) {
113       EXPECT_CALL(mock_object_map, rollback(_, _))
114                     .WillOnce(WithArg<1>(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
115     }
116   }
117
118   void expect_get_object_name(MockOperationImageCtx &mock_image_ctx,
119                               uint64_t object_num) {
120     EXPECT_CALL(mock_image_ctx, get_object_name(object_num))
121                   .WillOnce(Return("object-name-" + stringify(object_num)));
122   }
123
124   void expect_get_current_size(MockOperationImageCtx &mock_image_ctx, uint64_t size) {
125     EXPECT_CALL(mock_image_ctx, get_current_size())
126                   .WillOnce(Return(size));
127   }
128
129   void expect_rollback_snap_id(MockOperationImageCtx &mock_image_ctx,
130                                const std::string &oid, int r) {
131     EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
132                 selfmanaged_snap_rollback(oid, _))
133                   .WillOnce(Return(r));
134   }
135
136   void expect_rollback(MockOperationImageCtx &mock_image_ctx, int r) {
137     expect_get_current_size(mock_image_ctx, 1);
138     expect_get_object_name(mock_image_ctx, 0);
139     expect_rollback_snap_id(mock_image_ctx, "object-name-0", r);
140   }
141
142   void expect_create_object_map(MockOperationImageCtx &mock_image_ctx,
143                                 MockObjectMap *mock_object_map) {
144     EXPECT_CALL(mock_image_ctx, create_object_map(_))
145                   .WillOnce(Return(mock_object_map));
146   }
147
148   void expect_open_object_map(MockOperationImageCtx &mock_image_ctx,
149                               MockObjectMap &mock_object_map) {
150     EXPECT_CALL(mock_object_map, open(_))
151                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
152   }
153
154   void expect_refresh_object_map(MockOperationImageCtx &mock_image_ctx,
155                                  MockObjectMap &mock_object_map) {
156     if (mock_image_ctx.object_map != nullptr) {
157       expect_create_object_map(mock_image_ctx, &mock_object_map);
158       expect_open_object_map(mock_image_ctx, mock_object_map);
159     }
160   }
161
162   void expect_invalidate_cache(MockOperationImageCtx &mock_image_ctx, int r) {
163     if (mock_image_ctx.object_cacher != nullptr) {
164       EXPECT_CALL(mock_image_ctx, invalidate_cache(true, _))
165                     .WillOnce(WithArg<1>(CompleteContext(r, static_cast<ContextWQ*>(NULL))));
166     }
167   }
168
169   int when_snap_rollback(MockOperationImageCtx &mock_image_ctx,
170                          const std::string &snap_name,
171                          uint64_t snap_id, uint64_t snap_size) {
172     C_SaferCond cond_ctx;
173     librbd::NoOpProgressContext prog_ctx;
174     MockSnapshotRollbackRequest *req = new MockSnapshotRollbackRequest(
175         mock_image_ctx, &cond_ctx, cls::rbd::UserSnapshotNamespace(), snap_name,
176         snap_id, snap_size, prog_ctx);
177     {
178       RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
179       req->send();
180     }
181     return cond_ctx.wait();
182   }
183 };
184
185 TEST_F(TestMockOperationSnapshotRollbackRequest, Success) {
186   librbd::ImageCtx *ictx;
187   ASSERT_EQ(0, open_image(m_image_name, &ictx));
188
189   MockOperationImageCtx mock_image_ctx(*ictx);
190   MockExclusiveLock mock_exclusive_lock;
191   MockJournal mock_journal;
192   MockObjectMap *mock_object_map = new MockObjectMap();
193   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
194                       *mock_object_map);
195   expect_op_work_queue(mock_image_ctx);
196
197   InSequence seq;
198   MockResizeRequest mock_resize_request;
199   expect_append_op_event(mock_image_ctx, false, 0);
200   expect_block_writes(mock_image_ctx, 0);
201   expect_resize(mock_image_ctx, mock_resize_request, 0);
202   expect_rollback_object_map(mock_image_ctx, *mock_object_map);
203   expect_rollback(mock_image_ctx, 0);
204   expect_refresh_object_map(mock_image_ctx, *mock_object_map);
205   expect_invalidate_cache(mock_image_ctx, 0);
206   expect_commit_op_event(mock_image_ctx, 0);
207   expect_unblock_writes(mock_image_ctx);
208   ASSERT_EQ(0, when_snap_rollback(mock_image_ctx, "snap", 123, 0));
209 }
210
211 TEST_F(TestMockOperationSnapshotRollbackRequest, BlockWritesError) {
212   librbd::ImageCtx *ictx;
213   ASSERT_EQ(0, open_image(m_image_name, &ictx));
214
215   MockOperationImageCtx mock_image_ctx(*ictx);
216   MockExclusiveLock mock_exclusive_lock;
217   MockJournal mock_journal;
218   MockObjectMap mock_object_map;
219   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
220                       mock_object_map);
221   expect_op_work_queue(mock_image_ctx);
222
223   InSequence seq;
224   expect_append_op_event(mock_image_ctx, false, 0);
225   expect_block_writes(mock_image_ctx, -EINVAL);
226   expect_commit_op_event(mock_image_ctx, -EINVAL);
227   expect_unblock_writes(mock_image_ctx);
228   ASSERT_EQ(-EINVAL, when_snap_rollback(mock_image_ctx, "snap", 123, 0));
229 }
230
231 TEST_F(TestMockOperationSnapshotRollbackRequest, SkipResize) {
232   librbd::ImageCtx *ictx;
233   ASSERT_EQ(0, open_image(m_image_name, &ictx));
234
235   MockOperationImageCtx mock_image_ctx(*ictx);
236   MockExclusiveLock mock_exclusive_lock;
237   MockJournal mock_journal;
238   MockObjectMap *mock_object_map = new MockObjectMap();
239   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
240                       *mock_object_map);
241   expect_op_work_queue(mock_image_ctx);
242
243   InSequence seq;
244   expect_append_op_event(mock_image_ctx, false, 0);
245   expect_block_writes(mock_image_ctx, 0);
246   expect_get_image_size(mock_image_ctx, 345);
247   expect_rollback_object_map(mock_image_ctx, *mock_object_map);
248   expect_rollback(mock_image_ctx, 0);
249   expect_refresh_object_map(mock_image_ctx, *mock_object_map);
250   expect_invalidate_cache(mock_image_ctx, 0);
251   expect_commit_op_event(mock_image_ctx, 0);
252   expect_unblock_writes(mock_image_ctx);
253   ASSERT_EQ(0, when_snap_rollback(mock_image_ctx, "snap", 123, 345));
254 }
255
256 TEST_F(TestMockOperationSnapshotRollbackRequest, ResizeError) {
257   librbd::ImageCtx *ictx;
258   ASSERT_EQ(0, open_image(m_image_name, &ictx));
259
260   MockOperationImageCtx mock_image_ctx(*ictx);
261   MockExclusiveLock mock_exclusive_lock;
262   MockJournal mock_journal;
263   MockObjectMap mock_object_map;
264   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
265                       mock_object_map);
266   expect_op_work_queue(mock_image_ctx);
267
268   InSequence seq;
269   MockResizeRequest mock_resize_request;
270   expect_append_op_event(mock_image_ctx, false, 0);
271   expect_block_writes(mock_image_ctx, 0);
272   expect_resize(mock_image_ctx, mock_resize_request, -EINVAL);
273   expect_commit_op_event(mock_image_ctx, -EINVAL);
274   expect_unblock_writes(mock_image_ctx);
275   ASSERT_EQ(-EINVAL, when_snap_rollback(mock_image_ctx, "snap", 123, 0));
276 }
277
278 TEST_F(TestMockOperationSnapshotRollbackRequest, RollbackObjectsError) {
279   librbd::ImageCtx *ictx;
280   ASSERT_EQ(0, open_image(m_image_name, &ictx));
281
282   MockOperationImageCtx mock_image_ctx(*ictx);
283   MockExclusiveLock mock_exclusive_lock;
284   MockJournal mock_journal;
285   MockObjectMap mock_object_map;
286   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
287                       mock_object_map);
288   expect_op_work_queue(mock_image_ctx);
289
290   InSequence seq;
291   MockResizeRequest mock_resize_request;
292   expect_append_op_event(mock_image_ctx, false, 0);
293   expect_block_writes(mock_image_ctx, 0);
294   expect_resize(mock_image_ctx, mock_resize_request, 0);
295   expect_rollback_object_map(mock_image_ctx, mock_object_map);
296   expect_rollback(mock_image_ctx, -EINVAL);
297   expect_commit_op_event(mock_image_ctx, -EINVAL);
298   expect_unblock_writes(mock_image_ctx);
299   ASSERT_EQ(-EINVAL, when_snap_rollback(mock_image_ctx, "snap", 123, 0));
300 }
301
302 TEST_F(TestMockOperationSnapshotRollbackRequest, InvalidateCacheError) {
303   librbd::ImageCtx *ictx;
304   ASSERT_EQ(0, open_image(m_image_name, &ictx));
305   REQUIRE(ictx->cache);
306
307   MockOperationImageCtx mock_image_ctx(*ictx);
308   MockExclusiveLock mock_exclusive_lock;
309   MockJournal mock_journal;
310   MockObjectMap *mock_object_map = new MockObjectMap();
311   initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
312                       *mock_object_map);
313   expect_op_work_queue(mock_image_ctx);
314
315   InSequence seq;
316   MockResizeRequest mock_resize_request;
317   expect_append_op_event(mock_image_ctx, false, 0);
318   expect_block_writes(mock_image_ctx, 0);
319   expect_resize(mock_image_ctx, mock_resize_request, 0);
320   expect_rollback_object_map(mock_image_ctx, *mock_object_map);
321   expect_rollback(mock_image_ctx, 0);
322   expect_refresh_object_map(mock_image_ctx, *mock_object_map);
323   expect_invalidate_cache(mock_image_ctx, -EINVAL);
324   expect_commit_op_event(mock_image_ctx, -EINVAL);
325   expect_unblock_writes(mock_image_ctx);
326   ASSERT_EQ(-EINVAL, when_snap_rollback(mock_image_ctx, "snap", 123, 0));
327 }
328
329 } // namespace operation
330 } // namespace librbd