]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/managed_lock/test_mock_BreakRequest.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / librbd / managed_lock / test_mock_BreakRequest.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 "test/librados_test_stub/MockTestMemRadosClient.h"
9 #include "cls/lock/cls_lock_ops.h"
10 #include "librbd/managed_lock/BreakRequest.h"
11 #include "librbd/managed_lock/GetLockerRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <arpa/inet.h>
15 #include <list>
16
17 namespace librbd {
18 namespace {
19
20 struct MockTestImageCtx : public librbd::MockImageCtx {
21 MockTestImageCtx(librbd::ImageCtx &image_ctx)
22 : librbd::MockImageCtx(image_ctx) {
23 }
24 };
25
26 } // anonymous namespace
27
28 namespace managed_lock {
29
30 template <>
31 struct GetLockerRequest<librbd::MockTestImageCtx> {
32 Locker *locker;
33 Context *on_finish = nullptr;
34 static GetLockerRequest *s_instance;
35 static GetLockerRequest* create(librados::IoCtx& ioctx,
36 const std::string& oid, bool exclusive,
37 Locker *locker, Context *on_finish) {
38 assert(s_instance != nullptr);
39 s_instance->locker = locker;
40 s_instance->on_finish = on_finish;
41 return s_instance;
42 }
43
44
45 GetLockerRequest() {
46 s_instance = this;
47 }
48 MOCK_METHOD0(send, void());
49 };
50
51 GetLockerRequest<librbd::MockTestImageCtx> *GetLockerRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
52
53 } // namespace managed_lock
54 } // namespace librbd
55
56 // template definitions
57 #include "librbd/managed_lock/BreakRequest.cc"
58
59 namespace librbd {
60 namespace managed_lock {
61
62 using ::testing::_;
63 using ::testing::DoAll;
64 using ::testing::InSequence;
65 using ::testing::Invoke;
66 using ::testing::Return;
67 using ::testing::SetArgPointee;
68 using ::testing::StrEq;
69 using ::testing::WithArg;
70
71 class TestMockManagedLockBreakRequest : public TestMockFixture {
72 public:
73 typedef BreakRequest<MockTestImageCtx> MockBreakRequest;
74 typedef GetLockerRequest<MockTestImageCtx> MockGetLockerRequest;
75
76 void expect_list_watchers(MockTestImageCtx &mock_image_ctx, int r,
77 const std::string &address, uint64_t watch_handle) {
78 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
79 list_watchers(mock_image_ctx.header_oid, _));
80 if (r < 0) {
81 expect.WillOnce(Return(r));
82 } else {
83 obj_watch_t watcher;
84 strcpy(watcher.addr, (address + ":0/0").c_str());
85 watcher.cookie = watch_handle;
86
87 std::list<obj_watch_t> watchers;
88 watchers.push_back(watcher);
89
90 expect.WillOnce(DoAll(SetArgPointee<1>(watchers), Return(0)));
91 }
92 }
93
94 void expect_get_locker(MockImageCtx &mock_image_ctx,
95 MockGetLockerRequest &mock_get_locker_request,
96 const Locker &locker, int r) {
97 EXPECT_CALL(mock_get_locker_request, send())
98 .WillOnce(Invoke([&mock_image_ctx, &mock_get_locker_request, locker, r]() {
99 *mock_get_locker_request.locker = locker;
100 mock_image_ctx.image_ctx->op_work_queue->queue(
101 mock_get_locker_request.on_finish, r);
102 }));
103 }
104
105
106 void expect_blacklist_add(MockTestImageCtx &mock_image_ctx, int r) {
107 EXPECT_CALL(*get_mock_io_ctx(mock_image_ctx.md_ctx).get_mock_rados_client(),
108 blacklist_add(_, _))
109 .WillOnce(Return(r));
110 }
111
112 void expect_break_lock(MockTestImageCtx &mock_image_ctx, int r) {
113 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
114 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("break_lock"), _, _, _))
115 .WillOnce(Return(r));
116 }
117
118 void expect_get_instance_id(MockTestImageCtx &mock_image_ctx, uint64_t id) {
119 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), get_instance_id())
120 .WillOnce(Return(id));
121 }
122 };
123
124 TEST_F(TestMockManagedLockBreakRequest, DeadLockOwner) {
125 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
126
127 librbd::ImageCtx *ictx;
128 ASSERT_EQ(0, open_image(m_image_name, &ictx));
129
130 MockTestImageCtx mock_image_ctx(*ictx);
131 expect_op_work_queue(mock_image_ctx);
132
133 InSequence seq;
134 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
135
136 MockGetLockerRequest mock_get_locker_request;
137 expect_get_locker(mock_image_ctx, mock_get_locker_request,
138 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
139 0);
140
141 expect_blacklist_add(mock_image_ctx, 0);
142 expect_break_lock(mock_image_ctx, 0);
143
144 C_SaferCond ctx;
145 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
146 MockBreakRequest *req = MockBreakRequest::create(
147 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
148 locker, true, true, 0, false, &ctx);
149 req->send();
150 ASSERT_EQ(0, ctx.wait());
151 }
152
153 TEST_F(TestMockManagedLockBreakRequest, ForceBreak) {
154 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
155
156 librbd::ImageCtx *ictx;
157 ASSERT_EQ(0, open_image(m_image_name, &ictx));
158
159 MockTestImageCtx mock_image_ctx(*ictx);
160 expect_op_work_queue(mock_image_ctx);
161
162 InSequence seq;
163 expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
164
165 MockGetLockerRequest mock_get_locker_request;
166 expect_get_locker(mock_image_ctx, mock_get_locker_request,
167 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
168 0);
169
170 expect_blacklist_add(mock_image_ctx, 0);
171 expect_break_lock(mock_image_ctx, 0);
172
173 C_SaferCond ctx;
174 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
175 MockBreakRequest *req = MockBreakRequest::create(
176 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
177 locker, true, true, 0, true, &ctx);
178 req->send();
179 ASSERT_EQ(0, ctx.wait());
180 }
181
182 TEST_F(TestMockManagedLockBreakRequest, GetWatchersError) {
183 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
184
185 librbd::ImageCtx *ictx;
186 ASSERT_EQ(0, open_image(m_image_name, &ictx));
187
188 MockTestImageCtx mock_image_ctx(*ictx);
189 expect_op_work_queue(mock_image_ctx);
190
191 InSequence seq;
192 expect_list_watchers(mock_image_ctx, -EINVAL, "dead client", 123);
193
194 C_SaferCond ctx;
195 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
196 MockBreakRequest *req = MockBreakRequest::create(
197 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
198 locker, true, true, 0, false, &ctx);
199 req->send();
200 ASSERT_EQ(-EINVAL, ctx.wait());
201 }
202
203 TEST_F(TestMockManagedLockBreakRequest, GetWatchersAlive) {
204 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
205
206 librbd::ImageCtx *ictx;
207 ASSERT_EQ(0, open_image(m_image_name, &ictx));
208
209 MockTestImageCtx mock_image_ctx(*ictx);
210 expect_op_work_queue(mock_image_ctx);
211
212 InSequence seq;
213 expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
214
215 C_SaferCond ctx;
216 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
217 MockBreakRequest *req = MockBreakRequest::create(
218 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
219 locker, true, true, 0, false, &ctx);
220 req->send();
221 ASSERT_EQ(-EAGAIN, ctx.wait());
222 }
223
224 TEST_F(TestMockManagedLockBreakRequest, GetLockerUpdated) {
225 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
226
227 librbd::ImageCtx *ictx;
228 ASSERT_EQ(0, open_image(m_image_name, &ictx));
229
230 MockTestImageCtx mock_image_ctx(*ictx);
231 expect_op_work_queue(mock_image_ctx);
232
233 InSequence seq;
234 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
235
236 MockGetLockerRequest mock_get_locker_request;
237 expect_get_locker(mock_image_ctx, mock_get_locker_request,
238 {entity_name_t::CLIENT(2), "auto 123", "1.2.3.4:0/0", 123},
239 0);
240
241 C_SaferCond ctx;
242 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
243 MockBreakRequest *req = MockBreakRequest::create(
244 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
245 locker, true, false, 0, false, &ctx);
246 req->send();
247 ASSERT_EQ(-EAGAIN, ctx.wait());
248 }
249
250 TEST_F(TestMockManagedLockBreakRequest, GetLockerBusy) {
251 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
252
253 librbd::ImageCtx *ictx;
254 ASSERT_EQ(0, open_image(m_image_name, &ictx));
255
256 MockTestImageCtx mock_image_ctx(*ictx);
257 expect_op_work_queue(mock_image_ctx);
258
259 InSequence seq;
260 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
261
262 MockGetLockerRequest mock_get_locker_request;
263 expect_get_locker(mock_image_ctx, mock_get_locker_request,
264 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
265 -EBUSY);
266
267 C_SaferCond ctx;
268 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
269 MockBreakRequest *req = MockBreakRequest::create(
270 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
271 locker, true, false, 0, false, &ctx);
272 req->send();
273 ASSERT_EQ(-EAGAIN, ctx.wait());
274 }
275
276 TEST_F(TestMockManagedLockBreakRequest, GetLockerMissing) {
277 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
278
279 librbd::ImageCtx *ictx;
280 ASSERT_EQ(0, open_image(m_image_name, &ictx));
281
282 MockTestImageCtx mock_image_ctx(*ictx);
283 expect_op_work_queue(mock_image_ctx);
284
285 InSequence seq;
286 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
287
288 MockGetLockerRequest mock_get_locker_request;
289 expect_get_locker(mock_image_ctx, mock_get_locker_request,
290 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
291 -ENOENT);
292
293 C_SaferCond ctx;
294 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
295 MockBreakRequest *req = MockBreakRequest::create(
296 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
297 locker, true, false, 0, false, &ctx);
298 req->send();
299 ASSERT_EQ(0, ctx.wait());
300 }
301
302 TEST_F(TestMockManagedLockBreakRequest, GetLockerError) {
303 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
304
305 librbd::ImageCtx *ictx;
306 ASSERT_EQ(0, open_image(m_image_name, &ictx));
307
308 MockTestImageCtx mock_image_ctx(*ictx);
309 expect_op_work_queue(mock_image_ctx);
310
311 InSequence seq;
312 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
313
314 MockGetLockerRequest mock_get_locker_request;
315 expect_get_locker(mock_image_ctx, mock_get_locker_request, {}, -EINVAL);
316
317 C_SaferCond ctx;
318 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
319 MockBreakRequest *req = MockBreakRequest::create(
320 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
321 locker, true, false, 0, false, &ctx);
322 req->send();
323 ASSERT_EQ(-EINVAL, ctx.wait());
324 }
325
326 TEST_F(TestMockManagedLockBreakRequest, BlacklistDisabled) {
327 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
328
329 librbd::ImageCtx *ictx;
330 ASSERT_EQ(0, open_image(m_image_name, &ictx));
331
332 MockTestImageCtx mock_image_ctx(*ictx);
333 expect_op_work_queue(mock_image_ctx);
334
335 InSequence seq;
336 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
337
338 MockGetLockerRequest mock_get_locker_request;
339 expect_get_locker(mock_image_ctx, mock_get_locker_request,
340 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
341 0);
342
343 expect_break_lock(mock_image_ctx, 0);
344
345 C_SaferCond ctx;
346 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
347 MockBreakRequest *req = MockBreakRequest::create(
348 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
349 locker, true, false, 0, false, &ctx);
350 req->send();
351 ASSERT_EQ(0, ctx.wait());
352 }
353
354 TEST_F(TestMockManagedLockBreakRequest, BlacklistSelf) {
355 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
356
357 librbd::ImageCtx *ictx;
358 ASSERT_EQ(0, open_image(m_image_name, &ictx));
359
360 MockTestImageCtx mock_image_ctx(*ictx);
361 expect_op_work_queue(mock_image_ctx);
362
363 InSequence seq;
364 expect_list_watchers(mock_image_ctx, 0, "dead client", 456);
365
366 MockGetLockerRequest mock_get_locker_request;
367 expect_get_locker(mock_image_ctx, mock_get_locker_request,
368 {entity_name_t::CLIENT(456), "auto 123", "1.2.3.4:0/0",
369 123}, 0);
370
371 expect_get_instance_id(mock_image_ctx, 456);
372
373 C_SaferCond ctx;
374 Locker locker{entity_name_t::CLIENT(456), "auto 123", "1.2.3.4:0/0", 123};
375 MockBreakRequest *req = MockBreakRequest::create(
376 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
377 locker, true, true, 0, false, &ctx);
378 req->send();
379 ASSERT_EQ(-EINVAL, ctx.wait());
380 }
381
382 TEST_F(TestMockManagedLockBreakRequest, BlacklistError) {
383 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
384
385 librbd::ImageCtx *ictx;
386 ASSERT_EQ(0, open_image(m_image_name, &ictx));
387
388 MockTestImageCtx mock_image_ctx(*ictx);
389 expect_op_work_queue(mock_image_ctx);
390
391 InSequence seq;
392 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
393
394 MockGetLockerRequest mock_get_locker_request;
395 expect_get_locker(mock_image_ctx, mock_get_locker_request,
396 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
397 0);
398
399 expect_blacklist_add(mock_image_ctx, -EINVAL);
400
401 C_SaferCond ctx;
402 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
403 MockBreakRequest *req = MockBreakRequest::create(
404 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
405 locker, true, true, 0, false, &ctx);
406 req->send();
407 ASSERT_EQ(-EINVAL, ctx.wait());
408 }
409
410 TEST_F(TestMockManagedLockBreakRequest, BreakLockMissing) {
411 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
412
413 librbd::ImageCtx *ictx;
414 ASSERT_EQ(0, open_image(m_image_name, &ictx));
415
416 MockTestImageCtx mock_image_ctx(*ictx);
417 expect_op_work_queue(mock_image_ctx);
418
419 InSequence seq;
420 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
421
422 MockGetLockerRequest mock_get_locker_request;
423 expect_get_locker(mock_image_ctx, mock_get_locker_request,
424 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
425 0);
426
427 expect_blacklist_add(mock_image_ctx, 0);
428 expect_break_lock(mock_image_ctx, -ENOENT);
429
430 C_SaferCond ctx;
431 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
432 MockBreakRequest *req = MockBreakRequest::create(
433 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
434 locker, true, true, 0, false, &ctx);
435 req->send();
436 ASSERT_EQ(0, ctx.wait());
437 }
438
439 TEST_F(TestMockManagedLockBreakRequest, BreakLockError) {
440 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
441
442 librbd::ImageCtx *ictx;
443 ASSERT_EQ(0, open_image(m_image_name, &ictx));
444
445 MockTestImageCtx mock_image_ctx(*ictx);
446 expect_op_work_queue(mock_image_ctx);
447
448 InSequence seq;
449 expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
450
451 MockGetLockerRequest mock_get_locker_request;
452 expect_get_locker(mock_image_ctx, mock_get_locker_request,
453 {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
454 0);
455
456 expect_blacklist_add(mock_image_ctx, 0);
457 expect_break_lock(mock_image_ctx, -EINVAL);
458
459 C_SaferCond ctx;
460 Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
461 MockBreakRequest *req = MockBreakRequest::create(
462 mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
463 locker, true, true, 0, false, &ctx);
464 req->send();
465 ASSERT_EQ(-EINVAL, ctx.wait());
466 }
467
468 } // namespace managed_lock
469 } // namespace librbd
470