Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / test_mock_ManagedLock.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 "librbd/ManagedLock.h"
7 #include "librbd/managed_lock/AcquireRequest.h"
8 #include "librbd/managed_lock/BreakRequest.h"
9 #include "librbd/managed_lock/GetLockerRequest.h"
10 #include "librbd/managed_lock/ReacquireRequest.h"
11 #include "librbd/managed_lock/ReleaseRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <list>
15
16 namespace librbd {
17
18 struct MockManagedLockImageCtx : public MockImageCtx {
19   MockManagedLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {}
20 };
21
22 namespace watcher {
23 template <>
24 struct Traits<MockManagedLockImageCtx> {
25   typedef librbd::MockImageWatcher Watcher;
26 };
27 }
28
29 namespace managed_lock {
30
31 template<typename T>
32 struct BaseRequest {
33   static std::list<T *> s_requests;
34   Context *on_finish = nullptr;
35
36   static T* create(librados::IoCtx& ioctx, MockImageWatcher *watcher,
37                    ContextWQ *work_queue, const std::string& oid,
38                    const std::string& cookie, Context *on_finish) {
39     assert(!s_requests.empty());
40     T* req = s_requests.front();
41     req->on_finish = on_finish;
42     s_requests.pop_front();
43     return req;
44   }
45
46   BaseRequest() {
47     s_requests.push_back(reinterpret_cast<T*>(this));
48   }
49 };
50
51 template<typename T>
52 std::list<T *> BaseRequest<T>::s_requests;
53
54 template <>
55 struct AcquireRequest<MockManagedLockImageCtx> : public BaseRequest<AcquireRequest<MockManagedLockImageCtx> > {
56   static AcquireRequest* create(librados::IoCtx& ioctx,
57                                 MockImageWatcher *watcher,
58                                 ContextWQ *work_queue, const std::string& oid,
59                                 const std::string& cookie,
60                                 bool exclusive, bool blacklist_on_break_lock,
61                                 uint32_t blacklist_expire_seconds,
62                                 Context *on_finish) {
63     return BaseRequest::create(ioctx, watcher, work_queue, oid, cookie, on_finish);
64   }
65
66   MOCK_METHOD0(send, void());
67 };
68
69 template <>
70 struct ReacquireRequest<MockManagedLockImageCtx> : public BaseRequest<ReacquireRequest<MockManagedLockImageCtx> > {
71   static ReacquireRequest* create(librados::IoCtx &ioctx, const std::string& oid,
72                                 const string& old_cookie, const std::string& new_cookie,
73                                 bool exclusive, Context *on_finish) {
74     return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie,
75                                on_finish);
76   }
77
78   MOCK_METHOD0(send, void());
79 };
80
81 template <>
82 struct ReleaseRequest<MockManagedLockImageCtx> : public BaseRequest<ReleaseRequest<MockManagedLockImageCtx> > {
83   static ReleaseRequest* create(librados::IoCtx& ioctx, MockImageWatcher *watcher,
84                                 ContextWQ *work_queue, const std::string& oid,
85                                 const std::string& cookie, Context *on_finish) {
86     return BaseRequest::create(ioctx, watcher, work_queue, oid, cookie,
87                                on_finish);
88   }
89   MOCK_METHOD0(send, void());
90 };
91
92 template <>
93 struct GetLockerRequest<MockManagedLockImageCtx> {
94   static GetLockerRequest* create(librados::IoCtx& ioctx,
95                                   const std::string& oid, bool exclusive,
96                                   Locker *locker, Context *on_finish) {
97     assert(0 == "unexpected call");
98   }
99
100   void send() {
101     assert(0 == "unexpected call");
102   }
103 };
104
105 template <>
106 struct BreakRequest<MockManagedLockImageCtx> {
107   static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue,
108                               const std::string& oid, const Locker &locker,
109                               bool exclusive, bool blacklist_locker,
110                               uint32_t blacklist_expire_seconds,
111                               bool force_break_lock, Context *on_finish) {
112     assert(0 == "unexpected call");
113   }
114
115   void send() {
116     assert(0 == "unexpected call");
117   }
118 };
119
120 } // namespace managed_lock
121 } // namespace librbd
122
123 // template definitions
124 #include "librbd/ManagedLock.cc"
125 template class librbd::ManagedLock<librbd::MockManagedLockImageCtx>;
126
127
128 ACTION_P3(QueueRequest, request, r, wq) {
129   if (request->on_finish != nullptr) {
130     if (wq != nullptr) {
131       wq->queue(request->on_finish, r);
132     } else {
133       request->on_finish->complete(r);
134     }
135   }
136 }
137
138 ACTION_P2(QueueContext, r, wq) {
139   wq->queue(arg0, r);
140 }
141
142 namespace librbd {
143
144 using ::testing::_;
145 using ::testing::DoAll;
146 using ::testing::Invoke;
147 using ::testing::InSequence;
148 using ::testing::Return;
149
150 class TestMockManagedLock : public TestMockFixture {
151 public:
152   typedef ManagedLock<MockManagedLockImageCtx> MockManagedLock;
153   typedef managed_lock::AcquireRequest<MockManagedLockImageCtx> MockAcquireRequest;
154   typedef managed_lock::ReacquireRequest<MockManagedLockImageCtx> MockReacquireRequest;
155   typedef managed_lock::ReleaseRequest<MockManagedLockImageCtx> MockReleaseRequest;
156
157   void expect_get_watch_handle(MockImageWatcher &mock_watcher,
158                                uint64_t watch_handle = 1234567890) {
159     EXPECT_CALL(mock_watcher, get_watch_handle())
160       .WillOnce(Return(watch_handle));
161   }
162
163   void expect_acquire_lock(MockImageWatcher &watcher,
164                            ContextWQ *work_queue,
165                            MockAcquireRequest &acquire_request, int r) {
166     expect_get_watch_handle(watcher);
167     EXPECT_CALL(acquire_request, send())
168                   .WillOnce(QueueRequest(&acquire_request, r, work_queue));
169   }
170
171   void expect_release_lock(ContextWQ *work_queue,
172                            MockReleaseRequest &release_request, int r) {
173     EXPECT_CALL(release_request, send())
174                   .WillOnce(QueueRequest(&release_request, r, work_queue));
175   }
176
177   void expect_reacquire_lock(MockImageWatcher& watcher,
178                              ContextWQ *work_queue,
179                              MockReacquireRequest &mock_reacquire_request,
180                              int r) {
181     expect_get_watch_handle(watcher, 98765);
182     EXPECT_CALL(mock_reacquire_request, send())
183                   .WillOnce(QueueRequest(&mock_reacquire_request, r, work_queue));
184   }
185
186   void expect_flush_notifies(MockImageWatcher *mock_watcher) {
187     EXPECT_CALL(*mock_watcher, flush(_))
188                   .WillOnce(CompleteContext(0, (ContextWQ *)nullptr));
189   }
190
191   int when_acquire_lock(MockManagedLock &managed_lock) {
192     C_SaferCond ctx;
193     {
194       managed_lock.acquire_lock(&ctx);
195     }
196     return ctx.wait();
197   }
198   int when_release_lock(MockManagedLock &managed_lock) {
199     C_SaferCond ctx;
200     {
201       managed_lock.release_lock(&ctx);
202     }
203     return ctx.wait();
204   }
205   int when_shut_down(MockManagedLock &managed_lock) {
206     C_SaferCond ctx;
207     {
208       managed_lock.shut_down(&ctx);
209     }
210     return ctx.wait();
211   }
212
213   bool is_lock_owner(MockManagedLock &managed_lock) {
214     return managed_lock.is_lock_owner();
215   }
216 };
217
218 TEST_F(TestMockManagedLock, StateTransitions) {
219   librbd::ImageCtx *ictx;
220   ASSERT_EQ(0, open_image(m_image_name, &ictx));
221
222   MockManagedLockImageCtx mock_image_ctx(*ictx);
223   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
224                                ictx->header_oid, mock_image_ctx.image_watcher,
225                                librbd::managed_lock::EXCLUSIVE, true, 0);
226   InSequence seq;
227
228   MockAcquireRequest request_lock_acquire1;
229   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire1, 0);
230   ASSERT_EQ(0, when_acquire_lock(managed_lock));
231   ASSERT_TRUE(is_lock_owner(managed_lock));
232
233   MockReleaseRequest request_release;
234   expect_release_lock(ictx->op_work_queue, request_release, 0);
235   ASSERT_EQ(0, when_release_lock(managed_lock));
236   ASSERT_FALSE(is_lock_owner(managed_lock));
237
238   MockAcquireRequest request_lock_acquire2;
239   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire2, 0);
240   ASSERT_EQ(0, when_acquire_lock(managed_lock));
241   ASSERT_TRUE(is_lock_owner(managed_lock));
242
243   MockReleaseRequest shutdown_release;
244   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
245   ASSERT_EQ(0, when_shut_down(managed_lock));
246   ASSERT_FALSE(is_lock_owner(managed_lock));
247 }
248
249 TEST_F(TestMockManagedLock, AcquireLockLockedState) {
250   librbd::ImageCtx *ictx;
251   ASSERT_EQ(0, open_image(m_image_name, &ictx));
252
253   MockManagedLockImageCtx mock_image_ctx(*ictx);
254   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
255                                ictx->header_oid, mock_image_ctx.image_watcher,
256                                librbd::managed_lock::EXCLUSIVE, true, 0);
257   InSequence seq;
258
259   MockAcquireRequest try_lock_acquire;
260   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
261   ASSERT_EQ(0, when_acquire_lock(managed_lock));
262   ASSERT_EQ(0, when_acquire_lock(managed_lock));
263
264   MockReleaseRequest shutdown_release;
265   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
266   ASSERT_EQ(0, when_shut_down(managed_lock));
267 }
268
269 TEST_F(TestMockManagedLock, AcquireLockAlreadyLocked) {
270   librbd::ImageCtx *ictx;
271   ASSERT_EQ(0, open_image(m_image_name, &ictx));
272
273   MockManagedLockImageCtx mock_image_ctx(*ictx);
274   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
275                                ictx->header_oid, mock_image_ctx.image_watcher,
276                                librbd::managed_lock::EXCLUSIVE, true, 0);
277   InSequence seq;
278
279   MockAcquireRequest try_lock_acquire;
280   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EAGAIN);
281   ASSERT_EQ(-EAGAIN, when_acquire_lock(managed_lock));
282   ASSERT_FALSE(is_lock_owner(managed_lock));
283
284   ASSERT_EQ(0, when_shut_down(managed_lock));
285 }
286
287 TEST_F(TestMockManagedLock, AcquireLockBusy) {
288   librbd::ImageCtx *ictx;
289   ASSERT_EQ(0, open_image(m_image_name, &ictx));
290
291   MockManagedLockImageCtx mock_image_ctx(*ictx);
292   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
293                                ictx->header_oid, mock_image_ctx.image_watcher,
294                                librbd::managed_lock::EXCLUSIVE, true, 0);
295   InSequence seq;
296
297   MockAcquireRequest try_lock_acquire;
298   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EBUSY);
299   ASSERT_EQ(-EBUSY, when_acquire_lock(managed_lock));
300   ASSERT_FALSE(is_lock_owner(managed_lock));
301
302   ASSERT_EQ(0, when_shut_down(managed_lock));
303 }
304
305 TEST_F(TestMockManagedLock, AcquireLockError) {
306   librbd::ImageCtx *ictx;
307   ASSERT_EQ(0, open_image(m_image_name, &ictx));
308
309   MockManagedLockImageCtx mock_image_ctx(*ictx);
310   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
311                                ictx->header_oid, mock_image_ctx.image_watcher,
312                                librbd::managed_lock::EXCLUSIVE, true, 0);
313   InSequence seq;
314
315   MockAcquireRequest try_lock_acquire;
316   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, -EINVAL);
317
318   ASSERT_EQ(-EINVAL, when_acquire_lock(managed_lock));
319   ASSERT_FALSE(is_lock_owner(managed_lock));
320
321   ASSERT_EQ(0, when_shut_down(managed_lock));
322 }
323
324 TEST_F(TestMockManagedLock, AcquireLockBlacklist) {
325   librbd::ImageCtx *ictx;
326   ASSERT_EQ(0, open_image(m_image_name, &ictx));
327
328   MockManagedLockImageCtx mock_image_ctx(*ictx);
329   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
330                                ictx->header_oid, mock_image_ctx.image_watcher,
331                                librbd::managed_lock::EXCLUSIVE, true, 0);
332   InSequence seq;
333
334   // will abort after seeing blacklist error (avoid infinite request loop)
335   MockAcquireRequest request_lock_acquire;
336   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, -EBLACKLISTED);
337   ASSERT_EQ(-EBLACKLISTED, when_acquire_lock(managed_lock));
338   ASSERT_FALSE(is_lock_owner(managed_lock));
339
340   ASSERT_EQ(0, when_shut_down(managed_lock));
341 }
342
343 TEST_F(TestMockManagedLock, ReleaseLockUnlockedState) {
344   librbd::ImageCtx *ictx;
345   ASSERT_EQ(0, open_image(m_image_name, &ictx));
346
347   MockManagedLockImageCtx mock_image_ctx(*ictx);
348   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
349                                ictx->header_oid, mock_image_ctx.image_watcher,
350                                librbd::managed_lock::EXCLUSIVE, true, 0);
351   InSequence seq;
352
353   ASSERT_EQ(0, when_release_lock(managed_lock));
354
355   ASSERT_EQ(0, when_shut_down(managed_lock));
356 }
357
358 TEST_F(TestMockManagedLock, ReleaseLockError) {
359   librbd::ImageCtx *ictx;
360   ASSERT_EQ(0, open_image(m_image_name, &ictx));
361
362   MockManagedLockImageCtx mock_image_ctx(*ictx);
363   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
364                                ictx->header_oid, mock_image_ctx.image_watcher,
365                                librbd::managed_lock::EXCLUSIVE, true, 0);
366   InSequence seq;
367
368   MockAcquireRequest try_lock_acquire;
369   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, try_lock_acquire, 0);
370   ASSERT_EQ(0, when_acquire_lock(managed_lock));
371
372   MockReleaseRequest release;
373   expect_release_lock(ictx->op_work_queue, release, -EINVAL);
374
375   ASSERT_EQ(-EINVAL, when_release_lock(managed_lock));
376   ASSERT_TRUE(is_lock_owner(managed_lock));
377
378   MockReleaseRequest shutdown_release;
379   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
380   ASSERT_EQ(0, when_shut_down(managed_lock));
381   ASSERT_FALSE(is_lock_owner(managed_lock));
382 }
383
384 TEST_F(TestMockManagedLock, ConcurrentRequests) {
385   librbd::ImageCtx *ictx;
386   ASSERT_EQ(0, open_image(m_image_name, &ictx));
387
388   MockManagedLockImageCtx mock_image_ctx(*ictx);
389   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
390                                ictx->header_oid, mock_image_ctx.image_watcher,
391                                librbd::managed_lock::EXCLUSIVE, true, 0);
392   InSequence seq;
393
394   expect_get_watch_handle(*mock_image_ctx.image_watcher);
395
396   C_SaferCond wait_for_send_ctx1;
397   MockAcquireRequest acquire_error;
398   EXPECT_CALL(acquire_error, send())
399                 .WillOnce(Notify(&wait_for_send_ctx1));
400
401   MockAcquireRequest request_acquire;
402   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_acquire, 0);
403
404   MockReleaseRequest release;
405   C_SaferCond wait_for_send_ctx2;
406   EXPECT_CALL(release, send())
407                 .WillOnce(Notify(&wait_for_send_ctx2));
408
409   C_SaferCond acquire_request_ctx1;
410   managed_lock.acquire_lock(&acquire_request_ctx1);
411
412   C_SaferCond acquire_lock_ctx1;
413   C_SaferCond acquire_lock_ctx2;
414   managed_lock.acquire_lock(&acquire_lock_ctx1);
415   managed_lock.acquire_lock(&acquire_lock_ctx2);
416
417   // fail the try_lock
418   ASSERT_EQ(0, wait_for_send_ctx1.wait());
419   acquire_error.on_finish->complete(-EINVAL);
420   ASSERT_EQ(-EINVAL, acquire_request_ctx1.wait());
421
422   C_SaferCond acquire_lock_ctx3;
423   managed_lock.acquire_lock(&acquire_lock_ctx3);
424
425   C_SaferCond release_lock_ctx1;
426   managed_lock.release_lock(&release_lock_ctx1);
427
428   // all three pending request locks should complete
429   ASSERT_EQ(-EINVAL, acquire_lock_ctx1.wait());
430   ASSERT_EQ(-EINVAL, acquire_lock_ctx2.wait());
431   ASSERT_EQ(0, acquire_lock_ctx3.wait());
432
433   // proceed with the release
434   ASSERT_EQ(0, wait_for_send_ctx2.wait());
435   release.on_finish->complete(0);
436   ASSERT_EQ(0, release_lock_ctx1.wait());
437
438   ASSERT_EQ(0, when_shut_down(managed_lock));
439 }
440
441 TEST_F(TestMockManagedLock, ReacquireLock) {
442   librbd::ImageCtx *ictx;
443   ASSERT_EQ(0, open_image(m_image_name, &ictx));
444
445   MockManagedLockImageCtx mock_image_ctx(*ictx);
446   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
447                                ictx->header_oid, mock_image_ctx.image_watcher,
448                                librbd::managed_lock::EXCLUSIVE, true, 0);
449   InSequence seq;
450
451   MockAcquireRequest request_lock_acquire;
452   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, 0);
453   ASSERT_EQ(0, when_acquire_lock(managed_lock));
454   ASSERT_TRUE(is_lock_owner(managed_lock));
455
456   MockReacquireRequest mock_reacquire_request;
457   C_SaferCond reacquire_ctx;
458   expect_reacquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, mock_reacquire_request, 0);
459   managed_lock.reacquire_lock(&reacquire_ctx);
460   ASSERT_EQ(0, reacquire_ctx.wait());
461
462   MockReleaseRequest shutdown_release;
463   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
464   ASSERT_EQ(0, when_shut_down(managed_lock));
465   ASSERT_FALSE(is_lock_owner(managed_lock));
466 }
467
468 TEST_F(TestMockManagedLock, ReacquireLockError) {
469   librbd::ImageCtx *ictx;
470   ASSERT_EQ(0, open_image(m_image_name, &ictx));
471
472   MockManagedLockImageCtx mock_image_ctx(*ictx);
473   MockManagedLock managed_lock(ictx->md_ctx, ictx->op_work_queue,
474                                ictx->header_oid, mock_image_ctx.image_watcher,
475                                librbd::managed_lock::EXCLUSIVE, true, 0);
476   InSequence seq;
477
478   MockAcquireRequest request_lock_acquire;
479   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, request_lock_acquire, 0);
480   ASSERT_EQ(0, when_acquire_lock(managed_lock));
481   ASSERT_TRUE(is_lock_owner(managed_lock));
482
483   MockReacquireRequest mock_reacquire_request;
484   C_SaferCond reacquire_ctx;
485   expect_reacquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, mock_reacquire_request, -EOPNOTSUPP);
486
487   MockReleaseRequest reacquire_lock_release;
488   expect_release_lock(ictx->op_work_queue, reacquire_lock_release, 0);
489
490   MockAcquireRequest reacquire_lock_acquire;
491   expect_acquire_lock(*mock_image_ctx.image_watcher, ictx->op_work_queue, reacquire_lock_acquire, 0);
492
493   managed_lock.reacquire_lock(&reacquire_ctx);
494   ASSERT_EQ(-EOPNOTSUPP, reacquire_ctx.wait());
495
496   MockReleaseRequest shutdown_release;
497   expect_release_lock(ictx->op_work_queue, shutdown_release, 0);
498   ASSERT_EQ(0, when_shut_down(managed_lock));
499   ASSERT_FALSE(is_lock_owner(managed_lock));
500 }
501
502 } // namespace librbd