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