initial code repo
[stor4nfv.git] / src / ceph / src / test / librbd / managed_lock / test_mock_BreakRequest.cc
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"
11 #include "librbd/managed_lock/GetLockerRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <arpa/inet.h>
15 #include <list>
16
17 namespace librbd {
18 namespace {
19
20 struct MockTestImageCtx : public librbd::MockImageCtx {
21   MockTestImageCtx(librbd::ImageCtx &image_ctx)
22     : librbd::MockImageCtx(image_ctx) {
23   }
24 };
25
26 } // anonymous namespace
27
28 namespace managed_lock {
29
30 template <>
31 struct 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) {
38     assert(s_instance != nullptr);
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
51 GetLockerRequest<librbd::MockTestImageCtx> *GetLockerRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
52
53 } // namespace managed_lock
54 } // namespace librbd
55
56 // template definitions
57 #include "librbd/managed_lock/BreakRequest.cc"
58
59 namespace librbd {
60 namespace managed_lock {
61
62 using ::testing::_;
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;
70
71 class TestMockManagedLockBreakRequest : public TestMockFixture {
72 public:
73   typedef BreakRequest<MockTestImageCtx> MockBreakRequest;
74   typedef GetLockerRequest<MockTestImageCtx> MockGetLockerRequest;
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;
84       strcpy(watcher.addr, (address + ":0/0").c_str());
85       watcher.cookie = watch_handle;
86
87       std::list<obj_watch_t> watchers;
88       watchers.push_back(watcher);
89
90       expect.WillOnce(DoAll(SetArgPointee<1>(watchers), Return(0)));
91     }
92   }
93
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);
102         }));
103   }
104
105
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(),
108                 blacklist_add(_, _))
109                   .WillOnce(Return(r));
110   }
111
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));
116   }
117
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));
121   }
122 };
123
124 TEST_F(TestMockManagedLockBreakRequest, DeadLockOwner) {
125   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
126
127   librbd::ImageCtx *ictx;
128   ASSERT_EQ(0, open_image(m_image_name, &ictx));
129
130   MockTestImageCtx mock_image_ctx(*ictx);
131   expect_op_work_queue(mock_image_ctx);
132
133   InSequence seq;
134   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
135
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},
139                     0);
140
141   expect_blacklist_add(mock_image_ctx, 0);
142   expect_break_lock(mock_image_ctx, 0);
143
144   C_SaferCond ctx;
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);
149   req->send();
150   ASSERT_EQ(0, ctx.wait());
151 }
152
153 TEST_F(TestMockManagedLockBreakRequest, ForceBreak) {
154   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
155
156   librbd::ImageCtx *ictx;
157   ASSERT_EQ(0, open_image(m_image_name, &ictx));
158
159   MockTestImageCtx mock_image_ctx(*ictx);
160   expect_op_work_queue(mock_image_ctx);
161
162   InSequence seq;
163   expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
164
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},
168                     0);
169
170   expect_blacklist_add(mock_image_ctx, 0);
171   expect_break_lock(mock_image_ctx, 0);
172
173   C_SaferCond ctx;
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);
178   req->send();
179   ASSERT_EQ(0, ctx.wait());
180 }
181
182 TEST_F(TestMockManagedLockBreakRequest, GetWatchersError) {
183   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
184
185   librbd::ImageCtx *ictx;
186   ASSERT_EQ(0, open_image(m_image_name, &ictx));
187
188   MockTestImageCtx mock_image_ctx(*ictx);
189   expect_op_work_queue(mock_image_ctx);
190
191   InSequence seq;
192   expect_list_watchers(mock_image_ctx, -EINVAL, "dead client", 123);
193
194   C_SaferCond ctx;
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);
199   req->send();
200   ASSERT_EQ(-EINVAL, ctx.wait());
201 }
202
203 TEST_F(TestMockManagedLockBreakRequest, GetWatchersAlive) {
204   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
205
206   librbd::ImageCtx *ictx;
207   ASSERT_EQ(0, open_image(m_image_name, &ictx));
208
209   MockTestImageCtx mock_image_ctx(*ictx);
210   expect_op_work_queue(mock_image_ctx);
211
212   InSequence seq;
213   expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
214
215   C_SaferCond ctx;
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);
220   req->send();
221   ASSERT_EQ(-EAGAIN, ctx.wait());
222 }
223
224 TEST_F(TestMockManagedLockBreakRequest, GetLockerUpdated) {
225   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
226
227   librbd::ImageCtx *ictx;
228   ASSERT_EQ(0, open_image(m_image_name, &ictx));
229
230   MockTestImageCtx mock_image_ctx(*ictx);
231   expect_op_work_queue(mock_image_ctx);
232
233   InSequence seq;
234   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
235
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},
239                     0);
240
241   C_SaferCond ctx;
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);
246   req->send();
247   ASSERT_EQ(-EAGAIN, ctx.wait());
248 }
249
250 TEST_F(TestMockManagedLockBreakRequest, GetLockerBusy) {
251   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
252
253   librbd::ImageCtx *ictx;
254   ASSERT_EQ(0, open_image(m_image_name, &ictx));
255
256   MockTestImageCtx mock_image_ctx(*ictx);
257   expect_op_work_queue(mock_image_ctx);
258
259   InSequence seq;
260   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
261
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},
265                     -EBUSY);
266
267   C_SaferCond ctx;
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);
272   req->send();
273   ASSERT_EQ(-EAGAIN, ctx.wait());
274 }
275
276 TEST_F(TestMockManagedLockBreakRequest, GetLockerMissing) {
277   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
278
279   librbd::ImageCtx *ictx;
280   ASSERT_EQ(0, open_image(m_image_name, &ictx));
281
282   MockTestImageCtx mock_image_ctx(*ictx);
283   expect_op_work_queue(mock_image_ctx);
284
285   InSequence seq;
286   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
287
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},
291                     -ENOENT);
292
293   C_SaferCond ctx;
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);
298   req->send();
299   ASSERT_EQ(0, ctx.wait());
300 }
301
302 TEST_F(TestMockManagedLockBreakRequest, GetLockerError) {
303   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
304
305   librbd::ImageCtx *ictx;
306   ASSERT_EQ(0, open_image(m_image_name, &ictx));
307
308   MockTestImageCtx mock_image_ctx(*ictx);
309   expect_op_work_queue(mock_image_ctx);
310
311   InSequence seq;
312   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
313
314   MockGetLockerRequest mock_get_locker_request;
315   expect_get_locker(mock_image_ctx, mock_get_locker_request, {}, -EINVAL);
316
317   C_SaferCond ctx;
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);
322   req->send();
323   ASSERT_EQ(-EINVAL, ctx.wait());
324 }
325
326 TEST_F(TestMockManagedLockBreakRequest, BlacklistDisabled) {
327   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
328
329   librbd::ImageCtx *ictx;
330   ASSERT_EQ(0, open_image(m_image_name, &ictx));
331
332   MockTestImageCtx mock_image_ctx(*ictx);
333   expect_op_work_queue(mock_image_ctx);
334
335   InSequence seq;
336   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
337
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},
341                     0);
342
343   expect_break_lock(mock_image_ctx, 0);
344
345   C_SaferCond ctx;
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);
350   req->send();
351   ASSERT_EQ(0, ctx.wait());
352 }
353
354 TEST_F(TestMockManagedLockBreakRequest, BlacklistSelf) {
355   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
356
357   librbd::ImageCtx *ictx;
358   ASSERT_EQ(0, open_image(m_image_name, &ictx));
359
360   MockTestImageCtx mock_image_ctx(*ictx);
361   expect_op_work_queue(mock_image_ctx);
362
363   InSequence seq;
364   expect_list_watchers(mock_image_ctx, 0, "dead client", 456);
365
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",
369                      123}, 0);
370
371   expect_get_instance_id(mock_image_ctx, 456);
372
373   C_SaferCond ctx;
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);
378   req->send();
379   ASSERT_EQ(-EINVAL, ctx.wait());
380 }
381
382 TEST_F(TestMockManagedLockBreakRequest, BlacklistError) {
383   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
384
385   librbd::ImageCtx *ictx;
386   ASSERT_EQ(0, open_image(m_image_name, &ictx));
387
388   MockTestImageCtx mock_image_ctx(*ictx);
389   expect_op_work_queue(mock_image_ctx);
390
391   InSequence seq;
392   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
393
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},
397                     0);
398
399   expect_blacklist_add(mock_image_ctx, -EINVAL);
400
401   C_SaferCond ctx;
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);
406   req->send();
407   ASSERT_EQ(-EINVAL, ctx.wait());
408 }
409
410 TEST_F(TestMockManagedLockBreakRequest, BreakLockMissing) {
411   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
412
413   librbd::ImageCtx *ictx;
414   ASSERT_EQ(0, open_image(m_image_name, &ictx));
415
416   MockTestImageCtx mock_image_ctx(*ictx);
417   expect_op_work_queue(mock_image_ctx);
418
419   InSequence seq;
420   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
421
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},
425                     0);
426
427   expect_blacklist_add(mock_image_ctx, 0);
428   expect_break_lock(mock_image_ctx, -ENOENT);
429
430   C_SaferCond ctx;
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);
435   req->send();
436   ASSERT_EQ(0, ctx.wait());
437 }
438
439 TEST_F(TestMockManagedLockBreakRequest, BreakLockError) {
440   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
441
442   librbd::ImageCtx *ictx;
443   ASSERT_EQ(0, open_image(m_image_name, &ictx));
444
445   MockTestImageCtx mock_image_ctx(*ictx);
446   expect_op_work_queue(mock_image_ctx);
447
448   InSequence seq;
449   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
450
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},
454                     0);
455
456   expect_blacklist_add(mock_image_ctx, 0);
457   expect_break_lock(mock_image_ctx, -EINVAL);
458
459   C_SaferCond ctx;
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);
464   req->send();
465   ASSERT_EQ(-EINVAL, ctx.wait());
466 }
467
468 } // namespace managed_lock
469 } // namespace librbd
470