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