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 "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 #include <arpa/inet.h>
19 struct MockTestImageCtx
: public librbd::MockImageCtx
{
20 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
21 : librbd::MockImageCtx(image_ctx
) {
25 } // anonymous namespace
28 // template definitions
29 #include "librbd/managed_lock/BreakRequest.cc"
32 namespace managed_lock
{
35 using ::testing::DoAll
;
36 using ::testing::InSequence
;
37 using ::testing::Return
;
38 using ::testing::SetArgPointee
;
39 using ::testing::StrEq
;
40 using ::testing::WithArg
;
42 class TestMockManagedLockBreakRequest
: public TestMockFixture
{
44 typedef BreakRequest
<MockTestImageCtx
> MockBreakRequest
;
46 void expect_list_watchers(MockTestImageCtx
&mock_image_ctx
, int r
,
47 const std::string
&address
, uint64_t watch_handle
) {
48 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
49 list_watchers(mock_image_ctx
.header_oid
, _
));
51 expect
.WillOnce(Return(r
));
54 strcpy(watcher
.addr
, (address
+ ":0/0").c_str());
55 watcher
.cookie
= watch_handle
;
57 std::list
<obj_watch_t
> watchers
;
58 watchers
.push_back(watcher
);
60 expect
.WillOnce(DoAll(SetArgPointee
<1>(watchers
), Return(0)));
64 void expect_blacklist_add(MockTestImageCtx
&mock_image_ctx
, int r
) {
65 EXPECT_CALL(*get_mock_io_ctx(mock_image_ctx
.md_ctx
).get_mock_rados_client(),
70 void expect_break_lock(MockTestImageCtx
&mock_image_ctx
, int r
) {
71 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
72 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("break_lock"), _
, _
, _
))
76 void expect_get_instance_id(MockTestImageCtx
&mock_image_ctx
, uint64_t id
) {
77 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
), get_instance_id())
78 .WillOnce(Return(id
));
82 TEST_F(TestMockManagedLockBreakRequest
, DeadLockOwner
) {
83 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
85 librbd::ImageCtx
*ictx
;
86 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
88 MockTestImageCtx
mock_image_ctx(*ictx
);
89 expect_op_work_queue(mock_image_ctx
);
92 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
93 expect_blacklist_add(mock_image_ctx
, 0);
94 expect_break_lock(mock_image_ctx
, 0);
97 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
98 MockBreakRequest
*req
= MockBreakRequest::create(
99 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
100 locker
, true, 0, false, &ctx
);
102 ASSERT_EQ(0, ctx
.wait());
105 TEST_F(TestMockManagedLockBreakRequest
, ForceBreak
) {
106 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
108 librbd::ImageCtx
*ictx
;
109 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
111 MockTestImageCtx
mock_image_ctx(*ictx
);
112 expect_op_work_queue(mock_image_ctx
);
115 expect_list_watchers(mock_image_ctx
, 0, "1.2.3.4", 123);
116 expect_blacklist_add(mock_image_ctx
, 0);
117 expect_break_lock(mock_image_ctx
, 0);
120 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
121 MockBreakRequest
*req
= MockBreakRequest::create(
122 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
123 locker
, true, 0, true, &ctx
);
125 ASSERT_EQ(0, ctx
.wait());
128 TEST_F(TestMockManagedLockBreakRequest
, GetWatchersError
) {
129 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
131 librbd::ImageCtx
*ictx
;
132 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
134 MockTestImageCtx
mock_image_ctx(*ictx
);
135 expect_op_work_queue(mock_image_ctx
);
138 expect_list_watchers(mock_image_ctx
, -EINVAL
, "dead client", 123);
141 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
142 MockBreakRequest
*req
= MockBreakRequest::create(
143 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
144 locker
, true, 0, false, &ctx
);
146 ASSERT_EQ(-EINVAL
, ctx
.wait());
149 TEST_F(TestMockManagedLockBreakRequest
, GetWatchersAlive
) {
150 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
152 librbd::ImageCtx
*ictx
;
153 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
155 MockTestImageCtx
mock_image_ctx(*ictx
);
156 expect_op_work_queue(mock_image_ctx
);
159 expect_list_watchers(mock_image_ctx
, 0, "1.2.3.4", 123);
162 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
163 MockBreakRequest
*req
= MockBreakRequest::create(
164 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
165 locker
, true, 0, false, &ctx
);
167 ASSERT_EQ(-EAGAIN
, ctx
.wait());
170 TEST_F(TestMockManagedLockBreakRequest
, BlacklistDisabled
) {
171 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
173 librbd::ImageCtx
*ictx
;
174 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
176 MockTestImageCtx
mock_image_ctx(*ictx
);
177 expect_op_work_queue(mock_image_ctx
);
180 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
181 expect_break_lock(mock_image_ctx
, 0);
184 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
185 MockBreakRequest
*req
= MockBreakRequest::create(
186 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
187 locker
, false, 0, false, &ctx
);
189 ASSERT_EQ(0, ctx
.wait());
192 TEST_F(TestMockManagedLockBreakRequest
, BlacklistSelf
) {
193 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
195 librbd::ImageCtx
*ictx
;
196 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
198 MockTestImageCtx
mock_image_ctx(*ictx
);
199 expect_op_work_queue(mock_image_ctx
);
202 expect_list_watchers(mock_image_ctx
, 0, "dead client", 456);
203 expect_get_instance_id(mock_image_ctx
, 456);
206 Locker locker
{entity_name_t::CLIENT(456), "auto 123", "1.2.3.4:0/0", 123};
207 MockBreakRequest
*req
= MockBreakRequest::create(
208 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
209 locker
, true, 0, false, &ctx
);
211 ASSERT_EQ(-EINVAL
, ctx
.wait());
214 TEST_F(TestMockManagedLockBreakRequest
, BlacklistError
) {
215 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
217 librbd::ImageCtx
*ictx
;
218 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
220 MockTestImageCtx
mock_image_ctx(*ictx
);
221 expect_op_work_queue(mock_image_ctx
);
224 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
225 expect_blacklist_add(mock_image_ctx
, -EINVAL
);
228 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
229 MockBreakRequest
*req
= MockBreakRequest::create(
230 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
231 locker
, true, 0, false, &ctx
);
233 ASSERT_EQ(-EINVAL
, ctx
.wait());
236 TEST_F(TestMockManagedLockBreakRequest
, BreakLockMissing
) {
237 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
239 librbd::ImageCtx
*ictx
;
240 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
242 MockTestImageCtx
mock_image_ctx(*ictx
);
243 expect_op_work_queue(mock_image_ctx
);
246 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
247 expect_blacklist_add(mock_image_ctx
, 0);
248 expect_break_lock(mock_image_ctx
, -ENOENT
);
251 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
252 MockBreakRequest
*req
= MockBreakRequest::create(
253 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
254 locker
, true, 0, false, &ctx
);
256 ASSERT_EQ(0, ctx
.wait());
259 TEST_F(TestMockManagedLockBreakRequest
, BreakLockError
) {
260 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
262 librbd::ImageCtx
*ictx
;
263 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
265 MockTestImageCtx
mock_image_ctx(*ictx
);
266 expect_op_work_queue(mock_image_ctx
);
269 expect_list_watchers(mock_image_ctx
, 0, "dead client", 123);
270 expect_blacklist_add(mock_image_ctx
, 0);
271 expect_break_lock(mock_image_ctx
, -EINVAL
);
274 Locker locker
{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
275 MockBreakRequest
*req
= MockBreakRequest::create(
276 mock_image_ctx
.md_ctx
, ictx
->op_work_queue
, mock_image_ctx
.header_oid
,
277 locker
, true, 0, false, &ctx
);
279 ASSERT_EQ(-EINVAL
, ctx
.wait());
282 } // namespace managed_lock
283 } // namespace librbd