Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librbd / test_mock_ExclusiveLock.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 "librbd/ExclusiveLock.h"
8 #include "librbd/ManagedLock.h"
9 #include "librbd/exclusive_lock/PreAcquireRequest.h"
10 #include "librbd/exclusive_lock/PostAcquireRequest.h"
11 #include "librbd/exclusive_lock/PreReleaseRequest.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 #include <list>
15
16 namespace librbd {
17
18 namespace {
19
20 struct MockExclusiveLockImageCtx : public MockImageCtx {
21   ContextWQ *op_work_queue;
22
23   MockExclusiveLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
24     op_work_queue = image_ctx.op_work_queue;
25   }
26 };
27
28 } // anonymous namespace
29
30 namespace watcher {
31 template <>
32 struct Traits<MockExclusiveLockImageCtx> {
33   typedef librbd::MockImageWatcher Watcher;
34 };
35 }
36
37 template <>
38 struct ManagedLock<MockExclusiveLockImageCtx> {
39   ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue,
40               const std::string& oid, librbd::MockImageWatcher *watcher,
41               managed_lock::Mode  mode, bool blacklist_on_break_lock,
42               uint32_t blacklist_expire_seconds)
43     : m_lock("ManagedLock::m_lock") {
44   }
45
46   virtual ~ManagedLock() = default;
47
48   mutable Mutex m_lock;
49
50   virtual void shutdown_handler(int r, Context *) = 0;
51   virtual void pre_acquire_lock_handler(Context *) = 0;
52   virtual void post_acquire_lock_handler(int, Context *) = 0;
53   virtual void pre_release_lock_handler(bool, Context *) = 0;
54   virtual void post_release_lock_handler(bool, int, Context *) = 0;
55   virtual void post_reacquire_lock_handler(int, Context *) = 0;
56
57   MOCK_CONST_METHOD0(is_lock_owner, bool());
58
59   MOCK_METHOD1(shut_down, void(Context*));
60   MOCK_METHOD1(acquire_lock, void(Context*));
61
62   void set_state_uninitialized() {
63   }
64
65   MOCK_METHOD0(set_state_initializing, void());
66   MOCK_METHOD0(set_state_unlocked, void());
67   MOCK_METHOD0(set_state_waiting_for_lock, void());
68   MOCK_METHOD0(set_state_post_acquiring, void());
69
70   MOCK_CONST_METHOD0(is_state_shutdown, bool());
71   MOCK_CONST_METHOD0(is_state_acquiring, bool());
72   MOCK_CONST_METHOD0(is_state_post_acquiring, bool());
73   MOCK_CONST_METHOD0(is_state_releasing, bool());
74   MOCK_CONST_METHOD0(is_state_pre_releasing, bool());
75   MOCK_CONST_METHOD0(is_state_locked, bool());
76   MOCK_CONST_METHOD0(is_state_waiting_for_lock, bool());
77
78   MOCK_CONST_METHOD0(is_action_acquire_lock, bool());
79   MOCK_METHOD0(execute_next_action, void());
80
81 };
82
83 namespace exclusive_lock {
84
85 using librbd::ImageWatcher;
86
87 template<typename T>
88 struct BaseRequest {
89   static std::list<T *> s_requests;
90   Context *on_lock_unlock = nullptr;
91   Context *on_finish = nullptr;
92
93   static T* create(MockExclusiveLockImageCtx &image_ctx,
94                    Context *on_lock_unlock, Context *on_finish) {
95     assert(!s_requests.empty());
96     T* req = s_requests.front();
97     req->on_lock_unlock = on_lock_unlock;
98     req->on_finish = on_finish;
99     s_requests.pop_front();
100     return req;
101   }
102
103   BaseRequest() {
104     s_requests.push_back(reinterpret_cast<T*>(this));
105   }
106 };
107
108 template<typename T>
109 std::list<T *> BaseRequest<T>::s_requests;
110
111 template <>
112 struct PreAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreAcquireRequest<MockExclusiveLockImageCtx> > {
113   static PreAcquireRequest<MockExclusiveLockImageCtx> *create(
114       MockExclusiveLockImageCtx &image_ctx, Context *on_finish) {
115     return BaseRequest::create(image_ctx, nullptr, on_finish);
116   }
117   MOCK_METHOD0(send, void());
118 };
119
120 template <>
121 struct PostAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PostAcquireRequest<MockExclusiveLockImageCtx> > {
122   MOCK_METHOD0(send, void());
123 };
124
125 template <>
126 struct PreReleaseRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreReleaseRequest<MockExclusiveLockImageCtx> > {
127   static PreReleaseRequest<MockExclusiveLockImageCtx> *create(
128       MockExclusiveLockImageCtx &image_ctx, bool shutting_down,
129       AsyncOpTracker &async_op_tracker, Context *on_finish) {
130     return BaseRequest::create(image_ctx, nullptr, on_finish);
131   }
132   MOCK_METHOD0(send, void());
133 };
134
135 } // namespace exclusive_lock
136 } // namespace librbd
137
138 // template definitions
139 #include "librbd/ExclusiveLock.cc"
140
141 ACTION_P(FinishLockUnlock, request) {
142   if (request->on_lock_unlock != nullptr) {
143     request->on_lock_unlock->complete(0);
144   }
145 }
146
147 ACTION_P2(CompleteRequest, request, ret) {
148   request->on_finish->complete(ret);
149 }
150
151 namespace librbd {
152
153 using ::testing::_;
154 using ::testing::DoAll;
155 using ::testing::Invoke;
156 using ::testing::InSequence;
157 using ::testing::Return;
158
159 class TestMockExclusiveLock : public TestMockFixture {
160 public:
161   typedef ManagedLock<MockExclusiveLockImageCtx> MockManagedLock;
162   typedef ExclusiveLock<MockExclusiveLockImageCtx> MockExclusiveLock;
163   typedef exclusive_lock::PreAcquireRequest<MockExclusiveLockImageCtx> MockPreAcquireRequest;
164   typedef exclusive_lock::PostAcquireRequest<MockExclusiveLockImageCtx> MockPostAcquireRequest;
165   typedef exclusive_lock::PreReleaseRequest<MockExclusiveLockImageCtx> MockPreReleaseRequest;
166
167   void expect_set_state_initializing(MockManagedLock &managed_lock) {
168     EXPECT_CALL(managed_lock, set_state_initializing());
169   }
170
171   void expect_set_state_unlocked(MockManagedLock &managed_lock) {
172     EXPECT_CALL(managed_lock, set_state_unlocked());
173   }
174
175   void expect_set_state_waiting_for_lock(MockManagedLock &managed_lock) {
176     EXPECT_CALL(managed_lock, set_state_waiting_for_lock());
177   }
178
179   void expect_is_state_acquiring(MockManagedLock &managed_lock, bool ret_val) {
180     EXPECT_CALL(managed_lock, is_state_acquiring())
181       .WillOnce(Return(ret_val));
182   }
183
184   void expect_is_state_waiting_for_lock(MockManagedLock &managed_lock,
185                                         bool ret_val) {
186     EXPECT_CALL(managed_lock, is_state_waiting_for_lock())
187       .WillOnce(Return(ret_val));
188   }
189
190   void expect_is_state_pre_releasing(MockManagedLock &managed_lock,
191                                      bool ret_val) {
192     EXPECT_CALL(managed_lock, is_state_pre_releasing())
193       .WillOnce(Return(ret_val));
194   }
195
196   void expect_is_state_releasing(MockManagedLock &managed_lock, bool ret_val) {
197     EXPECT_CALL(managed_lock, is_state_releasing())
198       .WillOnce(Return(ret_val));
199   }
200
201   void expect_is_state_locked(MockManagedLock &managed_lock, bool ret_val) {
202     EXPECT_CALL(managed_lock, is_state_locked())
203       .WillOnce(Return(ret_val));
204   }
205
206   void expect_is_state_shutdown(MockManagedLock &managed_lock, bool ret_val) {
207     EXPECT_CALL(managed_lock, is_state_shutdown())
208       .WillOnce(Return(ret_val));
209   }
210
211   void expect_is_action_acquire_lock(MockManagedLock &managed_lock,
212                                      bool ret_val) {
213     EXPECT_CALL(managed_lock, is_action_acquire_lock())
214       .WillOnce(Return(ret_val));
215   }
216
217   void expect_set_require_lock(MockExclusiveLockImageCtx &mock_image_ctx,
218                                io::Direction direction, bool enabled) {
219     EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock(direction,
220                                                                 enabled));
221   }
222
223   void expect_block_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
224     EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
225                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
226     if (mock_image_ctx.clone_copy_on_read ||
227         (mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
228       expect_set_require_lock(mock_image_ctx, io::DIRECTION_BOTH, true);
229     } else {
230       expect_set_require_lock(mock_image_ctx, io::DIRECTION_WRITE, true);
231     }
232   }
233
234   void expect_unblock_writes(MockExclusiveLockImageCtx &mock_image_ctx) {
235     expect_set_require_lock(mock_image_ctx, io::DIRECTION_BOTH, false);
236     EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes());
237   }
238
239   void expect_prepare_lock_complete(MockExclusiveLockImageCtx &mock_image_ctx) {
240     EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
241   }
242
243   void expect_pre_acquire_request(MockPreAcquireRequest &pre_acquire_request,
244                                   int r) {
245     EXPECT_CALL(pre_acquire_request, send())
246       .WillOnce(CompleteRequest(&pre_acquire_request, r));
247   }
248
249   void expect_post_acquire_request(MockPostAcquireRequest &post_acquire_request,
250                                    int r) {
251     EXPECT_CALL(post_acquire_request, send())
252       .WillOnce(CompleteRequest(&post_acquire_request, r));
253   }
254
255   void expect_pre_release_request(MockPreReleaseRequest &pre_release_request,
256                                   int r) {
257     EXPECT_CALL(pre_release_request, send())
258       .WillOnce(CompleteRequest(&pre_release_request, r));
259   }
260
261   void expect_notify_request_lock(MockExclusiveLockImageCtx &mock_image_ctx,
262                                   MockExclusiveLock &mock_exclusive_lock) {
263     EXPECT_CALL(*mock_image_ctx.image_watcher, notify_request_lock());
264   }
265
266   void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
267     EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock())
268       .Times(1);
269   }
270
271   void expect_notify_released_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
272     EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock())
273       .Times(1);
274   }
275
276   void expect_flush_notifies(MockExclusiveLockImageCtx &mock_image_ctx) {
277     EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
278                   .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
279   }
280
281   void expect_shut_down(MockManagedLock &managed_lock) {
282     EXPECT_CALL(managed_lock, shut_down(_))
283       .WillOnce(CompleteContext(0, static_cast<ContextWQ*>(nullptr)));
284   }
285
286   int when_init(MockExclusiveLockImageCtx &mock_image_ctx,
287                 MockExclusiveLock &exclusive_lock) {
288     C_SaferCond ctx;
289     {
290       RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
291       exclusive_lock.init(mock_image_ctx.features, &ctx);
292     }
293     return ctx.wait();
294   }
295
296   int when_pre_acquire_lock_handler(MockManagedLock &managed_lock) {
297     C_SaferCond ctx;
298     managed_lock.pre_acquire_lock_handler(&ctx);
299     return ctx.wait();
300   }
301
302   int when_post_acquire_lock_handler(MockManagedLock &managed_lock, int r) {
303     C_SaferCond ctx;
304     managed_lock.post_acquire_lock_handler(r, &ctx);
305     return ctx.wait();
306   }
307
308   int when_pre_release_lock_handler(MockManagedLock &managed_lock,
309                                     bool shutting_down) {
310     C_SaferCond ctx;
311     managed_lock.pre_release_lock_handler(shutting_down, &ctx);
312     return ctx.wait();
313   }
314
315   int when_post_release_lock_handler(MockManagedLock &managed_lock,
316                                      bool shutting_down, int r) {
317     C_SaferCond ctx;
318     managed_lock.post_release_lock_handler(shutting_down, r, &ctx);
319     return ctx.wait();
320   }
321
322   int when_post_reacquire_lock_handler(MockManagedLock &managed_lock, int r) {
323     C_SaferCond ctx;
324     managed_lock.post_reacquire_lock_handler(r, &ctx);
325     return ctx.wait();
326   }
327
328   int when_shut_down(MockExclusiveLockImageCtx &mock_image_ctx,
329                      MockExclusiveLock &exclusive_lock) {
330     C_SaferCond ctx;
331     {
332       RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
333       exclusive_lock.shut_down(&ctx);
334     }
335     return ctx.wait();
336   }
337
338   bool is_lock_owner(MockExclusiveLockImageCtx &mock_image_ctx,
339                      MockExclusiveLock &exclusive_lock) {
340     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
341     return exclusive_lock.is_lock_owner();
342   }
343 };
344
345 TEST_F(TestMockExclusiveLock, StateTransitions) {
346   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
347
348   librbd::ImageCtx *ictx;
349   ASSERT_EQ(0, open_image(m_image_name, &ictx));
350
351   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
352   MockExclusiveLock exclusive_lock(mock_image_ctx);
353   expect_op_work_queue(mock_image_ctx);
354
355   InSequence seq;
356   expect_set_state_initializing(exclusive_lock);
357   expect_block_writes(mock_image_ctx);
358   expect_set_state_unlocked(exclusive_lock);
359   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
360
361   // (try) acquire lock
362   MockPreAcquireRequest try_lock_pre_acquire;
363   expect_pre_acquire_request(try_lock_pre_acquire, 0);
364   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
365
366   MockPostAcquireRequest try_lock_post_acquire;
367   expect_post_acquire_request(try_lock_post_acquire, 0);
368   expect_is_state_acquiring(exclusive_lock, true);
369   expect_notify_acquired_lock(mock_image_ctx);
370   expect_unblock_writes(mock_image_ctx);
371   ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
372
373   // release lock
374   MockPreReleaseRequest pre_request_release;
375   expect_pre_release_request(pre_request_release, 0);
376   ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, false));
377
378   expect_is_state_pre_releasing(exclusive_lock, false);
379   expect_is_state_releasing(exclusive_lock, true);
380   expect_notify_released_lock(mock_image_ctx);
381   ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, false, 0));
382
383   // (try) acquire lock
384   MockPreAcquireRequest request_lock_pre_acquire;
385   expect_pre_acquire_request(request_lock_pre_acquire, 0);
386   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
387
388   MockPostAcquireRequest request_lock_post_acquire;
389   expect_post_acquire_request(request_lock_post_acquire, 0);
390   expect_is_state_acquiring(exclusive_lock, true);
391   expect_notify_acquired_lock(mock_image_ctx);
392   expect_unblock_writes(mock_image_ctx);
393   ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
394
395   // shut down (and release)
396   expect_shut_down(exclusive_lock);
397   expect_is_state_waiting_for_lock(exclusive_lock, false);
398   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
399
400   MockPreReleaseRequest shutdown_pre_release;
401   expect_pre_release_request(shutdown_pre_release, 0);
402   ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
403
404   expect_unblock_writes(mock_image_ctx);
405   expect_notify_released_lock(mock_image_ctx);
406   ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
407 }
408
409 TEST_F(TestMockExclusiveLock, TryLockAlreadyLocked) {
410   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
411
412   librbd::ImageCtx *ictx;
413   ASSERT_EQ(0, open_image(m_image_name, &ictx));
414
415   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
416   MockExclusiveLock exclusive_lock(mock_image_ctx);
417   expect_op_work_queue(mock_image_ctx);
418
419   InSequence seq;
420   expect_set_state_initializing(exclusive_lock);
421   expect_block_writes(mock_image_ctx);
422   expect_set_state_unlocked(exclusive_lock);
423   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
424
425   // try acquire lock
426   MockPreAcquireRequest try_lock_pre_acquire;
427   expect_pre_acquire_request(try_lock_pre_acquire, 0);
428   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
429
430   expect_is_state_acquiring(exclusive_lock, true);
431   expect_prepare_lock_complete(mock_image_ctx);
432   expect_is_action_acquire_lock(exclusive_lock, false);
433   ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, -EAGAIN));
434 }
435
436 TEST_F(TestMockExclusiveLock, TryLockError) {
437   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
438
439   librbd::ImageCtx *ictx;
440   ASSERT_EQ(0, open_image(m_image_name, &ictx));
441
442   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
443   MockExclusiveLock exclusive_lock(mock_image_ctx);
444   expect_op_work_queue(mock_image_ctx);
445
446   InSequence seq;
447   expect_set_state_initializing(exclusive_lock);
448   expect_block_writes(mock_image_ctx);
449   expect_set_state_unlocked(exclusive_lock);
450   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
451
452   // try acquire lock
453   MockPreAcquireRequest try_lock_pre_acquire;
454   expect_pre_acquire_request(try_lock_pre_acquire, 0);
455   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
456
457   expect_is_state_acquiring(exclusive_lock, true);
458   expect_prepare_lock_complete(mock_image_ctx);
459   expect_is_action_acquire_lock(exclusive_lock, false);
460   ASSERT_EQ(-EBUSY, when_post_acquire_lock_handler(exclusive_lock, -EBUSY));
461 }
462
463 TEST_F(TestMockExclusiveLock, AcquireLockAlreadyLocked) {
464   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
465
466   librbd::ImageCtx *ictx;
467   ASSERT_EQ(0, open_image(m_image_name, &ictx));
468
469   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
470   MockExclusiveLock exclusive_lock(mock_image_ctx);
471   expect_op_work_queue(mock_image_ctx);
472
473   InSequence seq;
474   expect_set_state_initializing(exclusive_lock);
475   expect_block_writes(mock_image_ctx);
476   expect_set_state_unlocked(exclusive_lock);
477   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
478
479   // acquire lock
480   MockPreAcquireRequest try_lock_pre_acquire;
481   expect_pre_acquire_request(try_lock_pre_acquire, 0);
482   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
483
484   expect_is_state_acquiring(exclusive_lock, true);
485   expect_prepare_lock_complete(mock_image_ctx);
486   expect_is_action_acquire_lock(exclusive_lock, true);
487   expect_set_state_waiting_for_lock(exclusive_lock);
488   expect_notify_request_lock(mock_image_ctx, exclusive_lock);
489   ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
490                                                        -EAGAIN));
491 }
492
493 TEST_F(TestMockExclusiveLock, AcquireLockBusy) {
494   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
495
496   librbd::ImageCtx *ictx;
497   ASSERT_EQ(0, open_image(m_image_name, &ictx));
498
499   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
500   MockExclusiveLock exclusive_lock(mock_image_ctx);
501   expect_op_work_queue(mock_image_ctx);
502
503   InSequence seq;
504   expect_set_state_initializing(exclusive_lock);
505   expect_block_writes(mock_image_ctx);
506   expect_set_state_unlocked(exclusive_lock);
507   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
508
509   // acquire lock
510   MockPreAcquireRequest try_lock_pre_acquire;
511   expect_pre_acquire_request(try_lock_pre_acquire, 0);
512   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
513
514   expect_is_state_acquiring(exclusive_lock, true);
515   expect_prepare_lock_complete(mock_image_ctx);
516   expect_is_action_acquire_lock(exclusive_lock, true);
517   expect_set_state_waiting_for_lock(exclusive_lock);
518   expect_notify_request_lock(mock_image_ctx, exclusive_lock);
519   ASSERT_EQ(-ECANCELED, when_post_acquire_lock_handler(exclusive_lock,
520                                                        -EBUSY));
521 }
522
523 TEST_F(TestMockExclusiveLock, AcquireLockError) {
524   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
525
526   librbd::ImageCtx *ictx;
527   ASSERT_EQ(0, open_image(m_image_name, &ictx));
528
529   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
530   MockExclusiveLock exclusive_lock(mock_image_ctx);
531   expect_op_work_queue(mock_image_ctx);
532
533   InSequence seq;
534   expect_set_state_initializing(exclusive_lock);
535   expect_block_writes(mock_image_ctx);
536   expect_set_state_unlocked(exclusive_lock);
537   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
538
539   // acquire lock
540   MockPreAcquireRequest try_lock_pre_acquire;
541   expect_pre_acquire_request(try_lock_pre_acquire, 0);
542   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
543
544   expect_is_state_acquiring(exclusive_lock, true);
545   expect_prepare_lock_complete(mock_image_ctx);
546   expect_is_action_acquire_lock(exclusive_lock, true);
547   ASSERT_EQ(-EBLACKLISTED, when_post_acquire_lock_handler(exclusive_lock,
548                                                           -EBLACKLISTED));
549 }
550
551 TEST_F(TestMockExclusiveLock, PostAcquireLockError) {
552   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
553
554   librbd::ImageCtx *ictx;
555   ASSERT_EQ(0, open_image(m_image_name, &ictx));
556
557   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
558   MockExclusiveLock exclusive_lock(mock_image_ctx);
559   expect_op_work_queue(mock_image_ctx);
560
561   InSequence seq;
562   expect_set_state_initializing(exclusive_lock);
563   expect_block_writes(mock_image_ctx);
564   expect_set_state_unlocked(exclusive_lock);
565   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
566
567   // (try) acquire lock
568   MockPreAcquireRequest request_lock_pre_acquire;
569   expect_pre_acquire_request(request_lock_pre_acquire, 0);
570   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
571
572   MockPostAcquireRequest request_lock_post_acquire;
573   expect_post_acquire_request(request_lock_post_acquire, -EPERM);
574   expect_is_state_acquiring(exclusive_lock, true);
575   ASSERT_EQ(-EPERM, when_post_acquire_lock_handler(exclusive_lock, 0));
576 }
577
578 TEST_F(TestMockExclusiveLock, PreReleaseLockError) {
579   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
580
581   librbd::ImageCtx *ictx;
582   ASSERT_EQ(0, open_image(m_image_name, &ictx));
583
584   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
585   MockExclusiveLock exclusive_lock(mock_image_ctx);
586   expect_op_work_queue(mock_image_ctx);
587
588   InSequence seq;
589   expect_set_state_initializing(exclusive_lock);
590   expect_block_writes(mock_image_ctx);
591   expect_set_state_unlocked(exclusive_lock);
592   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
593
594   // release lock
595   MockPreReleaseRequest pre_request_release;
596   expect_pre_release_request(pre_request_release, -EINVAL);
597   ASSERT_EQ(-EINVAL, when_pre_release_lock_handler(exclusive_lock, false));
598
599   expect_is_state_pre_releasing(exclusive_lock, true);
600   ASSERT_EQ(-EINVAL, when_post_release_lock_handler(exclusive_lock, false,
601                                                     -EINVAL));
602 }
603
604 TEST_F(TestMockExclusiveLock, ReacquireLock) {
605   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
606
607   librbd::ImageCtx *ictx;
608   ASSERT_EQ(0, open_image(m_image_name, &ictx));
609
610   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
611   MockExclusiveLock exclusive_lock(mock_image_ctx);
612   expect_op_work_queue(mock_image_ctx);
613
614   InSequence seq;
615   expect_set_state_initializing(exclusive_lock);
616   expect_block_writes(mock_image_ctx);
617   expect_set_state_unlocked(exclusive_lock);
618   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
619
620   // (try) acquire lock
621   MockPreAcquireRequest try_lock_pre_acquire;
622   expect_pre_acquire_request(try_lock_pre_acquire, 0);
623   ASSERT_EQ(0, when_pre_acquire_lock_handler(exclusive_lock));
624
625   MockPostAcquireRequest try_lock_post_acquire;
626   expect_post_acquire_request(try_lock_post_acquire, 0);
627   expect_is_state_acquiring(exclusive_lock, true);
628   expect_notify_acquired_lock(mock_image_ctx);
629   expect_unblock_writes(mock_image_ctx);
630   ASSERT_EQ(0, when_post_acquire_lock_handler(exclusive_lock, 0));
631
632   // reacquire lock
633   expect_notify_acquired_lock(mock_image_ctx);
634   ASSERT_EQ(0, when_post_reacquire_lock_handler(exclusive_lock, 0));
635
636   // shut down (and release)
637   expect_shut_down(exclusive_lock);
638   expect_is_state_waiting_for_lock(exclusive_lock, false);
639   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
640
641   MockPreReleaseRequest shutdown_pre_release;
642   expect_pre_release_request(shutdown_pre_release, 0);
643   ASSERT_EQ(0, when_pre_release_lock_handler(exclusive_lock, true));
644
645   expect_unblock_writes(mock_image_ctx);
646   expect_notify_released_lock(mock_image_ctx);
647   ASSERT_EQ(0, when_post_release_lock_handler(exclusive_lock, true, 0));
648 }
649
650 TEST_F(TestMockExclusiveLock, BlockRequests) {
651   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
652
653   librbd::ImageCtx *ictx;
654   ASSERT_EQ(0, open_image(m_image_name, &ictx));
655
656   MockExclusiveLockImageCtx mock_image_ctx(*ictx);
657   MockExclusiveLock exclusive_lock(mock_image_ctx);
658
659   expect_op_work_queue(mock_image_ctx);
660
661   InSequence seq;
662   expect_set_state_initializing(exclusive_lock);
663   expect_block_writes(mock_image_ctx);
664   expect_set_state_unlocked(exclusive_lock);
665   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
666
667   int ret_val;
668   expect_is_state_shutdown(exclusive_lock, false);
669   expect_is_state_locked(exclusive_lock, true);
670   ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
671   ASSERT_EQ(0, ret_val);
672
673   exclusive_lock.block_requests(-EROFS);
674   expect_is_state_shutdown(exclusive_lock, false);
675   expect_is_state_locked(exclusive_lock, true);
676   ASSERT_FALSE(exclusive_lock.accept_requests(&ret_val));
677   ASSERT_EQ(-EROFS, ret_val);
678
679   exclusive_lock.unblock_requests();
680   expect_is_state_shutdown(exclusive_lock, false);
681   expect_is_state_locked(exclusive_lock, true);
682   ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
683   ASSERT_EQ(0, ret_val);
684 }
685
686 } // namespace librbd
687