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