]>
Commit | Line | Data |
---|---|---|
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 "cls/lock/cls_lock_ops.h" | |
9 | #include "librbd/ObjectMap.h" | |
10 | #include "librbd/object_map/LockRequest.h" | |
11 | ||
12 | // template definitions | |
13 | #include "librbd/object_map/LockRequest.cc" | |
14 | ||
15 | namespace librbd { | |
16 | namespace object_map { | |
17 | ||
18 | using ::testing::_; | |
19 | using ::testing::DoAll; | |
20 | using ::testing::InSequence; | |
21 | using ::testing::Return; | |
22 | using ::testing::StrEq; | |
23 | using ::testing::WithArg; | |
24 | ||
25 | class TestMockObjectMapLockRequest : public TestMockFixture { | |
26 | public: | |
27 | typedef LockRequest<MockImageCtx> MockLockRequest; | |
28 | ||
29 | void expect_lock(MockImageCtx &mock_image_ctx, int r) { | |
30 | std::string oid(ObjectMap<>::object_map_name(mock_image_ctx.id, | |
31 | CEPH_NOSNAP)); | |
32 | EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
33 | exec(oid, _, StrEq("lock"), StrEq("lock"), _, _, _)) | |
34 | .WillOnce(Return(r)); | |
35 | } | |
36 | ||
37 | void expect_get_lock_info(MockImageCtx &mock_image_ctx, int r) { | |
38 | std::string oid(ObjectMap<>::object_map_name(mock_image_ctx.id, | |
39 | CEPH_NOSNAP)); | |
40 | auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
41 | exec(oid, _, StrEq("lock"), StrEq("get_info"), _, _, _)); | |
42 | if (r < 0) { | |
43 | expect.WillOnce(Return(r)); | |
44 | } else { | |
45 | entity_name_t entity1(entity_name_t::CLIENT(1)); | |
46 | entity_name_t entity2(entity_name_t::CLIENT(2)); | |
47 | ||
48 | cls_lock_get_info_reply reply; | |
9f95a23c TL |
49 | reply.lockers = decltype(reply.lockers){ |
50 | {rados::cls::lock::locker_id_t(entity1, "cookie1"), | |
51 | rados::cls::lock::locker_info_t()}, | |
52 | {rados::cls::lock::locker_id_t(entity2, "cookie2"), | |
53 | rados::cls::lock::locker_info_t()}}; | |
7c673cae FG |
54 | |
55 | bufferlist bl; | |
11fdf7f2 | 56 | encode(reply, bl, CEPH_FEATURES_SUPPORTED_DEFAULT); |
7c673cae FG |
57 | |
58 | std::string str(bl.c_str(), bl.length()); | |
59 | expect.WillOnce(DoAll(WithArg<5>(CopyInBufferlist(str)), Return(r))); | |
60 | } | |
61 | } | |
62 | ||
63 | void expect_break_lock(MockImageCtx &mock_image_ctx, int r) { | |
64 | std::string oid(ObjectMap<>::object_map_name(mock_image_ctx.id, | |
65 | CEPH_NOSNAP)); | |
66 | auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), | |
67 | exec(oid, _, StrEq("lock"), StrEq("break_lock"), _, _, _)); | |
68 | if (r < 0) { | |
69 | expect.WillOnce(Return(r)); | |
70 | } else { | |
71 | expect.Times(2).WillRepeatedly(Return(0)); | |
72 | } | |
73 | } | |
74 | }; | |
75 | ||
76 | TEST_F(TestMockObjectMapLockRequest, Success) { | |
77 | librbd::ImageCtx *ictx; | |
78 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
79 | ||
80 | MockImageCtx mock_image_ctx(*ictx); | |
81 | ||
82 | C_SaferCond ctx; | |
83 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
84 | ||
85 | InSequence seq; | |
86 | expect_lock(mock_image_ctx, 0); | |
87 | req->send(); | |
88 | ||
89 | ASSERT_EQ(0, ctx.wait()); | |
90 | } | |
91 | ||
92 | TEST_F(TestMockObjectMapLockRequest, LockBusy) { | |
93 | librbd::ImageCtx *ictx; | |
94 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
95 | ||
96 | MockImageCtx mock_image_ctx(*ictx); | |
97 | ||
98 | C_SaferCond ctx; | |
99 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
100 | ||
101 | InSequence seq; | |
102 | expect_lock(mock_image_ctx, -EBUSY); | |
103 | expect_get_lock_info(mock_image_ctx, 0); | |
104 | expect_break_lock(mock_image_ctx, 0); | |
105 | expect_lock(mock_image_ctx, 0); | |
106 | req->send(); | |
107 | ||
108 | ASSERT_EQ(0, ctx.wait()); | |
109 | } | |
110 | ||
111 | TEST_F(TestMockObjectMapLockRequest, LockError) { | |
112 | librbd::ImageCtx *ictx; | |
113 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
114 | ||
115 | MockImageCtx mock_image_ctx(*ictx); | |
116 | ||
117 | C_SaferCond ctx; | |
118 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
119 | ||
120 | InSequence seq; | |
121 | expect_lock(mock_image_ctx, -ENOENT); | |
122 | req->send(); | |
123 | ||
124 | ASSERT_EQ(0, ctx.wait()); | |
125 | } | |
126 | ||
127 | TEST_F(TestMockObjectMapLockRequest, GetLockInfoMissing) { | |
128 | librbd::ImageCtx *ictx; | |
129 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
130 | ||
131 | MockImageCtx mock_image_ctx(*ictx); | |
132 | ||
133 | C_SaferCond ctx; | |
134 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
135 | ||
136 | InSequence seq; | |
137 | expect_lock(mock_image_ctx, -EBUSY); | |
138 | expect_get_lock_info(mock_image_ctx, -ENOENT); | |
139 | expect_lock(mock_image_ctx, 0); | |
140 | req->send(); | |
141 | ||
142 | ASSERT_EQ(0, ctx.wait()); | |
143 | } | |
144 | ||
145 | TEST_F(TestMockObjectMapLockRequest, GetLockInfoError) { | |
146 | librbd::ImageCtx *ictx; | |
147 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
148 | ||
149 | MockImageCtx mock_image_ctx(*ictx); | |
150 | ||
151 | C_SaferCond ctx; | |
152 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
153 | ||
154 | InSequence seq; | |
155 | expect_lock(mock_image_ctx, -EBUSY); | |
156 | expect_get_lock_info(mock_image_ctx, -EINVAL); | |
157 | req->send(); | |
158 | ||
159 | ASSERT_EQ(0, ctx.wait()); | |
160 | } | |
161 | ||
162 | TEST_F(TestMockObjectMapLockRequest, BreakLockMissing) { | |
163 | librbd::ImageCtx *ictx; | |
164 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
165 | ||
166 | MockImageCtx mock_image_ctx(*ictx); | |
167 | ||
168 | C_SaferCond ctx; | |
169 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
170 | ||
171 | InSequence seq; | |
172 | expect_lock(mock_image_ctx, -EBUSY); | |
173 | expect_get_lock_info(mock_image_ctx, 0); | |
174 | expect_break_lock(mock_image_ctx, -ENOENT); | |
175 | expect_lock(mock_image_ctx, 0); | |
176 | req->send(); | |
177 | ||
178 | ASSERT_EQ(0, ctx.wait()); | |
179 | } | |
180 | ||
181 | TEST_F(TestMockObjectMapLockRequest, BreakLockError) { | |
182 | librbd::ImageCtx *ictx; | |
183 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
184 | ||
185 | MockImageCtx mock_image_ctx(*ictx); | |
186 | ||
187 | C_SaferCond ctx; | |
188 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
189 | ||
190 | InSequence seq; | |
191 | expect_lock(mock_image_ctx, -EBUSY); | |
192 | expect_get_lock_info(mock_image_ctx, 0); | |
193 | expect_break_lock(mock_image_ctx, -EINVAL); | |
194 | req->send(); | |
195 | ||
196 | ASSERT_EQ(0, ctx.wait()); | |
197 | } | |
198 | ||
199 | TEST_F(TestMockObjectMapLockRequest, LockErrorAfterBrokeLock) { | |
200 | librbd::ImageCtx *ictx; | |
201 | ASSERT_EQ(0, open_image(m_image_name, &ictx)); | |
202 | ||
203 | MockImageCtx mock_image_ctx(*ictx); | |
204 | ||
205 | C_SaferCond ctx; | |
206 | MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); | |
207 | ||
208 | InSequence seq; | |
209 | expect_lock(mock_image_ctx, -EBUSY); | |
210 | expect_get_lock_info(mock_image_ctx, 0); | |
211 | expect_break_lock(mock_image_ctx, 0); | |
212 | expect_lock(mock_image_ctx, -EBUSY); | |
213 | req->send(); | |
214 | ||
215 | ASSERT_EQ(0, ctx.wait()); | |
216 | } | |
217 | ||
218 | } // namespace object_map | |
219 | } // namespace librbd |