1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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>
20 struct MockTestImageCtx
: public librbd::MockImageCtx
{
21 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
22 : librbd::MockImageCtx(image_ctx
) {
26 } // anonymous namespace
28 namespace managed_lock
{
31 struct GetLockerRequest
<librbd::MockTestImageCtx
> {
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
;
48 MOCK_METHOD0(send
, void());
51 GetLockerRequest
<librbd::MockTestImageCtx
> *GetLockerRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
53 } // namespace managed_lock
56 // template definitions
57 #include "librbd/managed_lock/BreakRequest.cc"
60 namespace managed_lock
{
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
;
71 class TestMockManagedLockBreakRequest
: public TestMockFixture
{
73 typedef BreakRequest
<MockTestImageCtx
> MockBreakRequest
;
74 typedef GetLockerRequest
<MockTestImageCtx
> MockGetLockerRequest
;
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
, _
));
81 expect
.WillOnce(Return(r
));
84 strcpy(watcher
.addr
, (address
+ ":0/0").c_str());
85 watcher
.cookie
= watch_handle
;
87 std::list
<obj_watch_t
> watchers
;
88 watchers
.push_back(watcher
);
90 expect
.WillOnce(DoAll(SetArgPointee
<1>(watchers
), Return(0)));
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
);
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(),
109 .WillOnce(Return(r
));
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
));
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
));
124 TEST_F(TestMockManagedLockBreakRequest
, DeadLockOwner
) {
125 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
127 librbd::ImageCtx
*ictx
;
128 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
130 MockTestImageCtx
mock_image_ctx(*ictx
);
131 expect_op_work_queue(mock_image_ctx
);
134 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
141 expect_blacklist_add(mock_image_ctx
, 0);
142 expect_break_lock(mock_image_ctx
, 0);
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
);
150 ASSERT_EQ(0, ctx
.wait());
153 TEST_F(TestMockManagedLockBreakRequest
, ForceBreak
) {
154 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
156 librbd::ImageCtx
*ictx
;
157 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
159 MockTestImageCtx
mock_image_ctx(*ictx
);
160 expect_op_work_queue(mock_image_ctx
);
163 expect_list_watchers(mock_image_ctx
, 0, "1.2.3.4", 123);
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},
170 expect_blacklist_add(mock_image_ctx
, 0);
171 expect_break_lock(mock_image_ctx
, 0);
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
);
179 ASSERT_EQ(0, ctx
.wait());
182 TEST_F(TestMockManagedLockBreakRequest
, GetWatchersError
) {
183 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
185 librbd::ImageCtx
*ictx
;
186 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
188 MockTestImageCtx
mock_image_ctx(*ictx
);
189 expect_op_work_queue(mock_image_ctx
);
192 expect_list_watchers(mock_image_ctx
, -EINVAL
, "dead client", 123);
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
);
200 ASSERT_EQ(-EINVAL
, ctx
.wait());
203 TEST_F(TestMockManagedLockBreakRequest
, GetWatchersAlive
) {
204 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
206 librbd::ImageCtx
*ictx
;
207 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
209 MockTestImageCtx
mock_image_ctx(*ictx
);
210 expect_op_work_queue(mock_image_ctx
);
213 expect_list_watchers(mock_image_ctx
, 0, "1.2.3.4", 123);
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
);
221 ASSERT_EQ(-EAGAIN
, ctx
.wait());
224 TEST_F(TestMockManagedLockBreakRequest
, GetLockerUpdated
) {
225 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
227 librbd::ImageCtx
*ictx
;
228 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
230 MockTestImageCtx
mock_image_ctx(*ictx
);
231 expect_op_work_queue(mock_image_ctx
);
234 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
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
);
247 ASSERT_EQ(-EAGAIN
, ctx
.wait());
250 TEST_F(TestMockManagedLockBreakRequest
, GetLockerBusy
) {
251 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
253 librbd::ImageCtx
*ictx
;
254 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
256 MockTestImageCtx
mock_image_ctx(*ictx
);
257 expect_op_work_queue(mock_image_ctx
);
260 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
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
);
273 ASSERT_EQ(-EAGAIN
, ctx
.wait());
276 TEST_F(TestMockManagedLockBreakRequest
, GetLockerMissing
) {
277 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
279 librbd::ImageCtx
*ictx
;
280 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
282 MockTestImageCtx
mock_image_ctx(*ictx
);
283 expect_op_work_queue(mock_image_ctx
);
286 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
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
);
299 ASSERT_EQ(0, ctx
.wait());
302 TEST_F(TestMockManagedLockBreakRequest
, GetLockerError
) {
303 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
305 librbd::ImageCtx
*ictx
;
306 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
308 MockTestImageCtx
mock_image_ctx(*ictx
);
309 expect_op_work_queue(mock_image_ctx
);
312 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
314 MockGetLockerRequest mock_get_locker_request
;
315 expect_get_locker(mock_image_ctx
, mock_get_locker_request
, {}, -EINVAL
);
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
);
323 ASSERT_EQ(-EINVAL
, ctx
.wait());
326 TEST_F(TestMockManagedLockBreakRequest
, BlacklistDisabled
) {
327 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
329 librbd::ImageCtx
*ictx
;
330 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
332 MockTestImageCtx
mock_image_ctx(*ictx
);
333 expect_op_work_queue(mock_image_ctx
);
336 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
343 expect_break_lock(mock_image_ctx
, 0);
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
);
351 ASSERT_EQ(0, ctx
.wait());
354 TEST_F(TestMockManagedLockBreakRequest
, BlacklistSelf
) {
355 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
357 librbd::ImageCtx
*ictx
;
358 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
360 MockTestImageCtx
mock_image_ctx(*ictx
);
361 expect_op_work_queue(mock_image_ctx
);
364 expect_list_watchers(mock_image_ctx
, 0, "dead client", 456);
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",
371 expect_get_instance_id(mock_image_ctx
, 456);
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
);
379 ASSERT_EQ(-EINVAL
, ctx
.wait());
382 TEST_F(TestMockManagedLockBreakRequest
, BlacklistError
) {
383 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
385 librbd::ImageCtx
*ictx
;
386 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
388 MockTestImageCtx
mock_image_ctx(*ictx
);
389 expect_op_work_queue(mock_image_ctx
);
392 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
399 expect_blacklist_add(mock_image_ctx
, -EINVAL
);
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
);
407 ASSERT_EQ(-EINVAL
, ctx
.wait());
410 TEST_F(TestMockManagedLockBreakRequest
, BreakLockMissing
) {
411 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
413 librbd::ImageCtx
*ictx
;
414 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
416 MockTestImageCtx
mock_image_ctx(*ictx
);
417 expect_op_work_queue(mock_image_ctx
);
420 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
427 expect_blacklist_add(mock_image_ctx
, 0);
428 expect_break_lock(mock_image_ctx
, -ENOENT
);
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
);
436 ASSERT_EQ(0, ctx
.wait());
439 TEST_F(TestMockManagedLockBreakRequest
, BreakLockError
) {
440 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
442 librbd::ImageCtx
*ictx
;
443 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
445 MockTestImageCtx
mock_image_ctx(*ictx
);
446 expect_op_work_queue(mock_image_ctx
);
449 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
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},
456 expect_blacklist_add(mock_image_ctx
, 0);
457 expect_break_lock(mock_image_ctx
, -EINVAL
);
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
);
465 ASSERT_EQ(-EINVAL
, ctx
.wait());
468 } // namespace managed_lock
469 } // namespace librbd