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