Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / exclusive_lock / test_mock_PreReleaseRequest.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/librbd/mock/MockJournal.h"
8 #include "test/librbd/mock/MockObjectMap.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "common/AsyncOpTracker.h"
11 #include "librbd/exclusive_lock/PreReleaseRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <list>
15
16 // template definitions
17 #include "librbd/exclusive_lock/PreReleaseRequest.cc"
18 template class librbd::exclusive_lock::PreReleaseRequest<librbd::MockImageCtx>;
19
20 namespace librbd {
21
22 namespace exclusive_lock {
23
24 namespace {
25
26 struct MockContext : public Context {
27   MOCK_METHOD1(complete, void(int));
28   MOCK_METHOD1(finish, void(int));
29 };
30
31 } // anonymous namespace
32
33 using ::testing::_;
34 using ::testing::InSequence;
35 using ::testing::Invoke;
36 using ::testing::Return;
37 using ::testing::StrEq;
38 using ::testing::WithArg;
39
40 static const std::string TEST_COOKIE("auto 123");
41
42 class TestMockExclusiveLockPreReleaseRequest : public TestMockFixture {
43 public:
44   typedef PreReleaseRequest<MockImageCtx> MockPreReleaseRequest;
45
46   void expect_complete_context(MockContext &mock_context, int r) {
47     EXPECT_CALL(mock_context, complete(r));
48   }
49
50   void expect_test_features(MockImageCtx &mock_image_ctx, uint64_t features,
51                             bool enabled) {
52     EXPECT_CALL(mock_image_ctx, test_features(features))
53                   .WillOnce(Return(enabled));
54   }
55
56   void expect_set_require_lock(MockImageCtx &mock_image_ctx,
57                                librbd::io::Direction direction, bool enabled) {
58     EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock(direction,
59                                                                 enabled));
60   }
61
62   void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
63     expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
64                          ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0));
65     if (mock_image_ctx.clone_copy_on_read ||
66         (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
67       expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_BOTH, true);
68     } else {
69       expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_WRITE,
70                               true);
71     }
72     EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
73                   .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
74   }
75
76   void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
77     EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes());
78   }
79
80   void expect_cancel_op_requests(MockImageCtx &mock_image_ctx, int r) {
81     EXPECT_CALL(mock_image_ctx, cancel_async_requests(_))
82                   .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
83   }
84
85   void expect_close_journal(MockImageCtx &mock_image_ctx,
86                            MockJournal &mock_journal, int r) {
87     EXPECT_CALL(mock_journal, close(_))
88                   .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
89   }
90
91   void expect_close_object_map(MockImageCtx &mock_image_ctx,
92                                MockObjectMap &mock_object_map) {
93     EXPECT_CALL(mock_object_map, close(_))
94                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
95   }
96
97   void expect_invalidate_cache(MockImageCtx &mock_image_ctx, bool purge,
98                                int r) {
99     if (mock_image_ctx.object_cacher != nullptr) {
100       EXPECT_CALL(mock_image_ctx, invalidate_cache(purge, _))
101                     .WillOnce(WithArg<1>(CompleteContext(r, static_cast<ContextWQ*>(NULL)))); 
102     }
103   }
104
105   void expect_is_cache_empty(MockImageCtx &mock_image_ctx, bool empty) {
106     if (mock_image_ctx.object_cacher != nullptr) {
107       EXPECT_CALL(mock_image_ctx, is_cache_empty())
108         .WillOnce(Return(empty));
109     }
110   }
111
112   void expect_flush_notifies(MockImageCtx &mock_image_ctx) {
113     EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
114                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
115   }
116
117   void expect_prepare_lock(MockImageCtx &mock_image_ctx) {
118     EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
119       .WillOnce(Invoke([](Context *on_ready) {
120                   on_ready->complete(0);
121                 }));
122   }
123
124   void expect_handle_prepare_lock_complete(MockImageCtx &mock_image_ctx) {
125     EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
126   }
127
128   AsyncOpTracker m_async_op_tracker;
129 };
130
131 TEST_F(TestMockExclusiveLockPreReleaseRequest, Success) {
132   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
133
134   librbd::ImageCtx *ictx;
135   ASSERT_EQ(0, open_image(m_image_name, &ictx));
136
137   MockImageCtx mock_image_ctx(*ictx);
138   expect_op_work_queue(mock_image_ctx);
139
140   InSequence seq;
141
142   expect_prepare_lock(mock_image_ctx);
143   expect_cancel_op_requests(mock_image_ctx, 0);
144   expect_block_writes(mock_image_ctx, 0);
145   expect_invalidate_cache(mock_image_ctx, false, 0);
146   expect_flush_notifies(mock_image_ctx);
147
148   MockJournal *mock_journal = new MockJournal();
149   mock_image_ctx.journal = mock_journal;
150   expect_close_journal(mock_image_ctx, *mock_journal, -EINVAL);
151
152   MockObjectMap *mock_object_map = new MockObjectMap();
153   mock_image_ctx.object_map = mock_object_map;
154   expect_close_object_map(mock_image_ctx, *mock_object_map);
155
156   expect_handle_prepare_lock_complete(mock_image_ctx);
157
158   C_SaferCond ctx;
159   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
160     mock_image_ctx, false, m_async_op_tracker, &ctx);
161   req->send();
162   ASSERT_EQ(0, ctx.wait());
163 }
164
165 TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessJournalDisabled) {
166   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
167
168   librbd::ImageCtx *ictx;
169   ASSERT_EQ(0, open_image(m_image_name, &ictx));
170
171   MockImageCtx mock_image_ctx(*ictx);
172
173   expect_block_writes(mock_image_ctx, 0);
174   expect_op_work_queue(mock_image_ctx);
175
176   InSequence seq;
177   expect_prepare_lock(mock_image_ctx);
178   expect_cancel_op_requests(mock_image_ctx, 0);
179   expect_invalidate_cache(mock_image_ctx, false, 0);
180   expect_flush_notifies(mock_image_ctx);
181
182   MockObjectMap *mock_object_map = new MockObjectMap();
183   mock_image_ctx.object_map = mock_object_map;
184   expect_close_object_map(mock_image_ctx, *mock_object_map);
185
186   expect_handle_prepare_lock_complete(mock_image_ctx);
187
188   C_SaferCond ctx;
189   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
190     mock_image_ctx, false, m_async_op_tracker, &ctx);
191   req->send();
192   ASSERT_EQ(0, ctx.wait());
193 }
194
195 TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessObjectMapDisabled) {
196   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
197
198   librbd::ImageCtx *ictx;
199   ASSERT_EQ(0, open_image(m_image_name, &ictx));
200
201   MockImageCtx mock_image_ctx(*ictx);
202
203   expect_block_writes(mock_image_ctx, 0);
204   expect_op_work_queue(mock_image_ctx);
205
206   InSequence seq;
207   expect_cancel_op_requests(mock_image_ctx, 0);
208   expect_invalidate_cache(mock_image_ctx, false, 0);
209   expect_flush_notifies(mock_image_ctx);
210
211   C_SaferCond release_ctx;
212   C_SaferCond ctx;
213   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
214     mock_image_ctx, true, m_async_op_tracker, &ctx);
215   req->send();
216   ASSERT_EQ(0, ctx.wait());
217 }
218
219 TEST_F(TestMockExclusiveLockPreReleaseRequest, Blacklisted) {
220   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
221
222   librbd::ImageCtx *ictx;
223   ASSERT_EQ(0, open_image(m_image_name, &ictx));
224
225   MockImageCtx mock_image_ctx(*ictx);
226   expect_op_work_queue(mock_image_ctx);
227
228   InSequence seq;
229   expect_prepare_lock(mock_image_ctx);
230   expect_cancel_op_requests(mock_image_ctx, 0);
231   expect_block_writes(mock_image_ctx, -EBLACKLISTED);
232   expect_invalidate_cache(mock_image_ctx, false, -EBLACKLISTED);
233   expect_is_cache_empty(mock_image_ctx, false);
234   expect_invalidate_cache(mock_image_ctx, true, -EBLACKLISTED);
235   expect_is_cache_empty(mock_image_ctx, true);
236   expect_flush_notifies(mock_image_ctx);
237
238   MockJournal *mock_journal = new MockJournal();
239   mock_image_ctx.journal = mock_journal;
240   expect_close_journal(mock_image_ctx, *mock_journal, -EBLACKLISTED);
241
242   MockObjectMap *mock_object_map = new MockObjectMap();
243   mock_image_ctx.object_map = mock_object_map;
244   expect_close_object_map(mock_image_ctx, *mock_object_map);
245
246   expect_handle_prepare_lock_complete(mock_image_ctx);
247
248   C_SaferCond ctx;
249   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
250     mock_image_ctx, false, m_async_op_tracker, &ctx);
251   req->send();
252   ASSERT_EQ(0, ctx.wait());
253 }
254
255 TEST_F(TestMockExclusiveLockPreReleaseRequest, BlockWritesError) {
256   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
257
258   librbd::ImageCtx *ictx;
259   ASSERT_EQ(0, open_image(m_image_name, &ictx));
260
261   MockImageCtx mock_image_ctx(*ictx);
262
263   expect_op_work_queue(mock_image_ctx);
264
265   InSequence seq;
266   expect_cancel_op_requests(mock_image_ctx, 0);
267   expect_block_writes(mock_image_ctx, -EINVAL);
268   expect_unblock_writes(mock_image_ctx);
269
270   C_SaferCond ctx;
271   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
272     mock_image_ctx, true, m_async_op_tracker, &ctx);
273   req->send();
274   ASSERT_EQ(-EINVAL, ctx.wait());
275 }
276
277 TEST_F(TestMockExclusiveLockPreReleaseRequest, UnlockError) {
278   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
279
280   librbd::ImageCtx *ictx;
281   ASSERT_EQ(0, open_image(m_image_name, &ictx));
282
283   MockImageCtx mock_image_ctx(*ictx);
284
285   expect_op_work_queue(mock_image_ctx);
286
287   InSequence seq;
288   expect_cancel_op_requests(mock_image_ctx, 0);
289   expect_block_writes(mock_image_ctx, 0);
290   expect_invalidate_cache(mock_image_ctx, false, 0);
291   expect_flush_notifies(mock_image_ctx);
292
293   C_SaferCond ctx;
294   MockPreReleaseRequest *req = MockPreReleaseRequest::create(
295     mock_image_ctx, true, m_async_op_tracker, &ctx);
296   req->send();
297   ASSERT_EQ(0, ctx.wait());
298 }
299
300 } // namespace exclusive_lock
301 } // namespace librbd