]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc
update sources to v12.1.1
[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"
31f18b77 10#include "common/AsyncOpTracker.h"
7c673cae
FG
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"
18template class librbd::exclusive_lock::PreReleaseRequest<librbd::MockImageCtx>;
19
20namespace librbd {
21
22namespace exclusive_lock {
23
24namespace {
25
26struct MockContext : public Context {
27 MOCK_METHOD1(complete, void(int));
28 MOCK_METHOD1(finish, void(int));
29};
30
31} // anonymous namespace
32
33using ::testing::_;
34using ::testing::InSequence;
35using ::testing::Invoke;
36using ::testing::Return;
37using ::testing::StrEq;
38using ::testing::WithArg;
39
40static const std::string TEST_COOKIE("auto 123");
41
42class TestMockExclusiveLockPreReleaseRequest : public TestMockFixture {
43public:
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
224ce89b
WB
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));
7c673cae
FG
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));
224ce89b
WB
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);
7c673cae
FG
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
31f18b77 128 AsyncOpTracker m_async_op_tracker;
7c673cae
FG
129};
130
131TEST_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(
31f18b77 160 mock_image_ctx, false, m_async_op_tracker, &ctx);
7c673cae
FG
161 req->send();
162 ASSERT_EQ(0, ctx.wait());
163}
164
165TEST_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(
31f18b77 190 mock_image_ctx, false, m_async_op_tracker, &ctx);
7c673cae
FG
191 req->send();
192 ASSERT_EQ(0, ctx.wait());
193}
194
195TEST_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(
31f18b77 214 mock_image_ctx, true, m_async_op_tracker, &ctx);
7c673cae
FG
215 req->send();
216 ASSERT_EQ(0, ctx.wait());
217}
218
219TEST_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(
31f18b77 250 mock_image_ctx, false, m_async_op_tracker, &ctx);
7c673cae
FG
251 req->send();
252 ASSERT_EQ(0, ctx.wait());
253}
254
255TEST_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(
31f18b77 272 mock_image_ctx, true, m_async_op_tracker, &ctx);
7c673cae
FG
273 req->send();
274 ASSERT_EQ(-EINVAL, ctx.wait());
275}
276
277TEST_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(
31f18b77 295 mock_image_ctx, true, m_async_op_tracker, &ctx);
7c673cae
FG
296 req->send();
297 ASSERT_EQ(0, ctx.wait());
298}
299
300} // namespace exclusive_lock
301} // namespace librbd