]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/test_mock_LeaderWatcher.cc
update sources to 12.2.10
[ceph.git] / ceph / src / test / rbd_mirror / test_mock_LeaderWatcher.cc
CommitLineData
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 "librbd/Utils.h"
5#include "test/librbd/mock/MockImageCtx.h"
6#include "test/rbd_mirror/test_mock_fixture.h"
7#include "tools/rbd_mirror/LeaderWatcher.h"
8#include "tools/rbd_mirror/Threads.h"
9
10using librbd::util::create_async_context_callback;
11
12namespace librbd {
13
14namespace {
15
16struct MockTestImageCtx : public MockImageCtx {
17 MockTestImageCtx(librbd::ImageCtx &image_ctx)
18 : librbd::MockImageCtx(image_ctx) {
19 }
20};
21
22} // anonymous namespace
23
24struct MockManagedLock {
25 static MockManagedLock *s_instance;
26 static MockManagedLock &get_instance() {
27 assert(s_instance != nullptr);
28 return *s_instance;
29 }
30
31 MockManagedLock() {
32 s_instance = this;
33 }
34
35 bool m_release_lock_on_shutdown = false;
36
37 MOCK_METHOD0(construct, void());
38 MOCK_METHOD0(destroy, void());
39
40 MOCK_CONST_METHOD0(is_lock_owner, bool());
41
42 MOCK_METHOD1(shut_down, void(Context *));
43 MOCK_METHOD1(try_acquire_lock, void(Context *));
44 MOCK_METHOD1(release_lock, void(Context *));
91327a77 45 MOCK_METHOD0(reacquire_lock, void());
7c673cae
FG
46 MOCK_METHOD3(break_lock, void(const managed_lock::Locker &, bool, Context *));
47 MOCK_METHOD2(get_locker, void(managed_lock::Locker *, Context *));
48
49 MOCK_METHOD0(set_state_post_acquiring, void());
50
51 MOCK_CONST_METHOD0(is_shutdown, bool());
52
53 MOCK_CONST_METHOD0(is_state_post_acquiring, bool());
31f18b77 54 MOCK_CONST_METHOD0(is_state_pre_releasing, bool());
7c673cae
FG
55 MOCK_CONST_METHOD0(is_state_locked, bool());
56};
57
58MockManagedLock *MockManagedLock::s_instance = nullptr;
59
60template <>
61struct ManagedLock<MockTestImageCtx> {
62 ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue,
63 const std::string& oid, librbd::Watcher *watcher,
64 managed_lock::Mode mode, bool blacklist_on_break_lock,
65 uint32_t blacklist_expire_seconds)
66 : m_work_queue(work_queue), m_lock("ManagedLock::m_lock") {
67 MockManagedLock::get_instance().construct();
68 }
69
70 virtual ~ManagedLock() {
71 MockManagedLock::get_instance().destroy();
72 }
73
74 ContextWQ *m_work_queue;
75
76 mutable Mutex m_lock;
77
78 bool is_lock_owner() const {
79 return MockManagedLock::get_instance().is_lock_owner();
80 }
81
82 void shut_down(Context *on_shutdown) {
83 if (MockManagedLock::get_instance().m_release_lock_on_shutdown) {
84 on_shutdown = new FunctionContext(
85 [this, on_shutdown](int r) {
86 MockManagedLock::get_instance().m_release_lock_on_shutdown = false;
87 shut_down(on_shutdown);
88 });
89 release_lock(on_shutdown);
90 return;
91 }
92
93 MockManagedLock::get_instance().shut_down(on_shutdown);
94 }
95
96 void try_acquire_lock(Context *on_acquired) {
97 Context *post_acquire_ctx = create_async_context_callback(
98 m_work_queue, new FunctionContext(
99 [this, on_acquired](int r) {
100 post_acquire_lock_handler(r, on_acquired);
101 }));
102 MockManagedLock::get_instance().try_acquire_lock(post_acquire_ctx);
103 }
104
105 void release_lock(Context *on_released) {
106 Context *post_release_ctx = new FunctionContext(
107 [this, on_released](int r) {
108 post_release_lock_handler(false, r, on_released);
109 });
110
111 Context *release_ctx = new FunctionContext(
112 [this, on_released, post_release_ctx](int r) {
113 if (r < 0) {
114 on_released->complete(r);
115 } else {
116 MockManagedLock::get_instance().release_lock(post_release_ctx);
117 }
118 });
119
120 Context *pre_release_ctx = new FunctionContext(
121 [this, release_ctx](int r) {
122 bool shutting_down =
123 MockManagedLock::get_instance().m_release_lock_on_shutdown;
124 pre_release_lock_handler(shutting_down, release_ctx);
125 });
126
127 m_work_queue->queue(pre_release_ctx, 0);
128 }
129
91327a77
AA
130 void reacquire_lock(Context* on_finish) {
131 MockManagedLock::get_instance().reacquire_lock();
132 }
133
7c673cae
FG
134 void get_locker(managed_lock::Locker *locker, Context *on_finish) {
135 MockManagedLock::get_instance().get_locker(locker, on_finish);
136 }
137
138 void break_lock(const managed_lock::Locker &locker, bool force_break_lock,
139 Context *on_finish) {
140 MockManagedLock::get_instance().break_lock(locker, force_break_lock,
141 on_finish);
142 }
143
144 void set_state_post_acquiring() {
145 MockManagedLock::get_instance().set_state_post_acquiring();
146 }
147
148 bool is_shutdown() const {
149 return MockManagedLock::get_instance().is_shutdown();
150 }
151
152 bool is_state_post_acquiring() const {
153 return MockManagedLock::get_instance().is_state_post_acquiring();
154 }
155
31f18b77
FG
156 bool is_state_pre_releasing() const {
157 return MockManagedLock::get_instance().is_state_pre_releasing();
158 }
159
7c673cae
FG
160 bool is_state_locked() const {
161 return MockManagedLock::get_instance().is_state_locked();
162 }
163
164 virtual void post_acquire_lock_handler(int r, Context *on_finish) = 0;
165 virtual void pre_release_lock_handler(bool shutting_down,
166 Context *on_finish) = 0;
167 virtual void post_release_lock_handler(bool shutting_down, int r,
168 Context *on_finish) = 0;
169};
170
171} // namespace librbd
172
173namespace rbd {
174namespace mirror {
175
176template <>
177struct Threads<librbd::MockTestImageCtx> {
178 Mutex &timer_lock;
179 SafeTimer *timer;
180 ContextWQ *work_queue;
181
182 Threads(Threads<librbd::ImageCtx> *threads)
183 : timer_lock(threads->timer_lock), timer(threads->timer),
184 work_queue(threads->work_queue) {
185 }
186};
187
188template <>
189struct MirrorStatusWatcher<librbd::MockTestImageCtx> {
190 static MirrorStatusWatcher* s_instance;
191
192 static MirrorStatusWatcher *create(librados::IoCtx &io_ctx,
193 ContextWQ *work_queue) {
194 assert(s_instance != nullptr);
195 return s_instance;
196 }
197
198 MirrorStatusWatcher() {
199 assert(s_instance == nullptr);
200 s_instance = this;
201 }
202
203 ~MirrorStatusWatcher() {
204 assert(s_instance == this);
205 s_instance = nullptr;
206 }
207
208 MOCK_METHOD0(destroy, void());
209 MOCK_METHOD1(init, void(Context *));
210 MOCK_METHOD1(shut_down, void(Context *));
211};
212
213MirrorStatusWatcher<librbd::MockTestImageCtx> *MirrorStatusWatcher<librbd::MockTestImageCtx>::s_instance = nullptr;
214
215template <>
216struct Instances<librbd::MockTestImageCtx> {
217 static Instances* s_instance;
218
219 static Instances *create(Threads<librbd::MockTestImageCtx> *threads,
220 librados::IoCtx &ioctx) {
221 assert(s_instance != nullptr);
222 return s_instance;
223 }
224
225 Instances() {
226 assert(s_instance == nullptr);
227 s_instance = this;
228 }
229
230 ~Instances() {
231 assert(s_instance == this);
232 s_instance = nullptr;
233 }
234
235 MOCK_METHOD0(destroy, void());
236 MOCK_METHOD1(init, void(Context *));
237 MOCK_METHOD1(shut_down, void(Context *));
238 MOCK_METHOD1(notify, void(const std::string &));
239};
240
241Instances<librbd::MockTestImageCtx> *Instances<librbd::MockTestImageCtx>::s_instance = nullptr;
242
243} // namespace mirror
244} // namespace rbd
245
246
247// template definitions
248#include "tools/rbd_mirror/LeaderWatcher.cc"
249
250namespace rbd {
251namespace mirror {
252
253using ::testing::_;
254using ::testing::AtLeast;
255using ::testing::DoAll;
256using ::testing::InSequence;
257using ::testing::Invoke;
258using ::testing::Return;
259
260using librbd::MockManagedLock;
261
262struct MockListener : public LeaderWatcher<librbd::MockTestImageCtx>::Listener {
263 static MockListener* s_instance;
264
265 MockListener() {
266 assert(s_instance == nullptr);
267 s_instance = this;
268 }
269
270 ~MockListener() override {
271 assert(s_instance == this);
272 s_instance = nullptr;
273 }
274
275 MOCK_METHOD1(post_acquire_handler, void(Context *));
276 MOCK_METHOD1(pre_release_handler, void(Context *));
31f18b77
FG
277
278 MOCK_METHOD1(update_leader_handler, void(const std::string &));
7c673cae
FG
279};
280
281MockListener *MockListener::s_instance = nullptr;
282
283class TestMockLeaderWatcher : public TestMockFixture {
284public:
285 typedef MirrorStatusWatcher<librbd::MockTestImageCtx> MockMirrorStatusWatcher;
286 typedef Instances<librbd::MockTestImageCtx> MockInstances;
287 typedef LeaderWatcher<librbd::MockTestImageCtx> MockLeaderWatcher;
288 typedef Threads<librbd::MockTestImageCtx> MockThreads;
289
290 void SetUp() override {
291 TestMockFixture::SetUp();
292 m_mock_threads = new MockThreads(m_threads);
293 }
294
295 void TearDown() override {
296 delete m_mock_threads;
297 TestMockFixture::TearDown();
298 }
299
300 void expect_construct(MockManagedLock &mock_managed_lock) {
301 EXPECT_CALL(mock_managed_lock, construct());
302 }
303
304 void expect_destroy(MockManagedLock &mock_managed_lock) {
305 EXPECT_CALL(mock_managed_lock, destroy());
306 }
307
308 void expect_is_lock_owner(MockManagedLock &mock_managed_lock, bool owner) {
309 EXPECT_CALL(mock_managed_lock, is_lock_owner())
310 .WillOnce(Return(owner));
311 }
312
313 void expect_shut_down(MockManagedLock &mock_managed_lock,
314 bool release_lock_on_shutdown, int r) {
315 mock_managed_lock.m_release_lock_on_shutdown = release_lock_on_shutdown;
316 EXPECT_CALL(mock_managed_lock, shut_down(_))
317 .WillOnce(CompleteContext(r));
318 }
319
320 void expect_try_acquire_lock(MockManagedLock &mock_managed_lock, int r) {
321 EXPECT_CALL(mock_managed_lock, try_acquire_lock(_))
322 .WillOnce(CompleteContext(r));
323 if (r == 0) {
324 expect_set_state_post_acquiring(mock_managed_lock);
325 }
326 }
327
328 void expect_release_lock(MockManagedLock &mock_managed_lock, int r,
329 Context *on_finish = nullptr) {
330 EXPECT_CALL(mock_managed_lock, release_lock(_))
331 .WillOnce(Invoke([on_finish, r](Context *ctx) {
332 ctx->complete(r);
333 if (on_finish != nullptr) {
334 on_finish->complete(0);
335 }
336 }));
337 }
338
339 void expect_get_locker(MockManagedLock &mock_managed_lock,
340 const librbd::managed_lock::Locker &locker, int r) {
341 EXPECT_CALL(mock_managed_lock, get_locker(_, _))
342 .WillOnce(Invoke([r, locker](librbd::managed_lock::Locker *out,
343 Context *ctx) {
344 if (r == 0) {
345 *out = locker;
346 }
347 ctx->complete(r);
348 }));
349 }
350
351 void expect_break_lock(MockManagedLock &mock_managed_lock,
352 const librbd::managed_lock::Locker &locker, int r,
353 Context *on_finish) {
354 EXPECT_CALL(mock_managed_lock, break_lock(locker, true, _))
355 .WillOnce(Invoke([on_finish, r](const librbd::managed_lock::Locker &,
356 bool, Context *ctx) {
357 ctx->complete(r);
358 on_finish->complete(0);
359 }));
360 }
361
362 void expect_set_state_post_acquiring(MockManagedLock &mock_managed_lock) {
363 EXPECT_CALL(mock_managed_lock, set_state_post_acquiring());
364 }
365
366 void expect_is_shutdown(MockManagedLock &mock_managed_lock) {
367 EXPECT_CALL(mock_managed_lock, is_shutdown())
368 .Times(AtLeast(0)).WillRepeatedly(Return(false));
369 }
370
371 void expect_is_leader(MockManagedLock &mock_managed_lock, bool post_acquiring,
372 bool locked) {
373 EXPECT_CALL(mock_managed_lock, is_state_post_acquiring())
374 .WillOnce(Return(post_acquiring));
375 if (!post_acquiring) {
376 EXPECT_CALL(mock_managed_lock, is_state_locked())
377 .WillOnce(Return(locked));
378 }
379 }
380
381 void expect_is_leader(MockManagedLock &mock_managed_lock) {
382 EXPECT_CALL(mock_managed_lock, is_state_post_acquiring())
383 .Times(AtLeast(0)).WillRepeatedly(Return(false));
384 EXPECT_CALL(mock_managed_lock, is_state_locked())
385 .Times(AtLeast(0)).WillRepeatedly(Return(false));
31f18b77
FG
386 EXPECT_CALL(mock_managed_lock, is_state_pre_releasing())
387 .Times(AtLeast(0)).WillRepeatedly(Return(false));
7c673cae
FG
388 }
389
390 void expect_notify_heartbeat(MockManagedLock &mock_managed_lock,
391 Context *on_finish) {
392 // is_leader in notify_heartbeat
393 EXPECT_CALL(mock_managed_lock, is_state_post_acquiring())
394 .WillOnce(Return(false));
395 EXPECT_CALL(mock_managed_lock, is_state_locked())
396 .WillOnce(Return(true));
397
398 // is_leader in handle_notify_heartbeat
399 EXPECT_CALL(mock_managed_lock, is_state_post_acquiring())
400 .WillOnce(Return(false));
401 EXPECT_CALL(mock_managed_lock, is_state_locked())
402 .WillOnce(DoAll(Invoke([on_finish]() {
403 on_finish->complete(0);
404 }),
405 Return(true)));
406 }
407
408 void expect_destroy(MockMirrorStatusWatcher &mock_mirror_status_watcher) {
409 EXPECT_CALL(mock_mirror_status_watcher, destroy());
410 }
411
412 void expect_init(MockMirrorStatusWatcher &mock_mirror_status_watcher, int r) {
413 EXPECT_CALL(mock_mirror_status_watcher, init(_))
414 .WillOnce(CompleteContext(m_mock_threads->work_queue, r));
415 }
416
417 void expect_shut_down(MockMirrorStatusWatcher &mock_mirror_status_watcher, int r) {
418 EXPECT_CALL(mock_mirror_status_watcher, shut_down(_))
419 .WillOnce(CompleteContext(m_mock_threads->work_queue, r));
420 expect_destroy(mock_mirror_status_watcher);
421 }
422
423 void expect_destroy(MockInstances &mock_instances) {
424 EXPECT_CALL(mock_instances, destroy());
425 }
426
427 void expect_init(MockInstances &mock_instances, int r) {
428 EXPECT_CALL(mock_instances, init(_))
429 .WillOnce(CompleteContext(m_mock_threads->work_queue, r));
430 }
431
432 void expect_shut_down(MockInstances &mock_instances, int r) {
433 EXPECT_CALL(mock_instances, shut_down(_))
434 .WillOnce(CompleteContext(m_mock_threads->work_queue, r));
435 expect_destroy(mock_instances);
436 }
437
438 void expect_acquire_notify(MockManagedLock &mock_managed_lock,
439 MockListener &mock_listener, int r) {
440 expect_is_leader(mock_managed_lock, true, false);
441 EXPECT_CALL(mock_listener, post_acquire_handler(_))
442 .WillOnce(CompleteContext(r));
443 expect_is_leader(mock_managed_lock, true, false);
444 }
445
446 void expect_release_notify(MockManagedLock &mock_managed_lock,
447 MockListener &mock_listener, int r) {
448 expect_is_leader(mock_managed_lock, false, false);
449 EXPECT_CALL(mock_listener, pre_release_handler(_))
450 .WillOnce(CompleteContext(r));
451 expect_is_leader(mock_managed_lock, false, false);
452 }
453
454 MockThreads *m_mock_threads;
455};
456
457TEST_F(TestMockLeaderWatcher, InitShutdown) {
458 MockManagedLock mock_managed_lock;
459 MockMirrorStatusWatcher mock_mirror_status_watcher;
460 MockInstances mock_instances;
461 MockListener listener;
462
463 expect_is_shutdown(mock_managed_lock);
464 expect_destroy(mock_managed_lock);
465
466 InSequence seq;
467
468 expect_construct(mock_managed_lock);
469 MockLeaderWatcher leader_watcher(m_mock_threads, m_local_io_ctx, &listener);
470
471 // Inint
472 C_SaferCond on_heartbeat_finish;
473 expect_is_leader(mock_managed_lock, false, false);
474 expect_try_acquire_lock(mock_managed_lock, 0);
475 expect_init(mock_mirror_status_watcher, 0);
476 expect_init(mock_instances, 0);
477 expect_acquire_notify(mock_managed_lock, listener, 0);
478 expect_notify_heartbeat(mock_managed_lock, &on_heartbeat_finish);
479
480 ASSERT_EQ(0, leader_watcher.init());
481 ASSERT_EQ(0, on_heartbeat_finish.wait());
482
483 // Shutdown
484 expect_release_notify(mock_managed_lock, listener, 0);
485 expect_shut_down(mock_instances, 0);
486 expect_shut_down(mock_mirror_status_watcher, 0);
487 expect_is_leader(mock_managed_lock, false, false);
488 expect_release_lock(mock_managed_lock, 0);
489 expect_shut_down(mock_managed_lock, true, 0);
490 expect_is_leader(mock_managed_lock, false, false);
491
492 leader_watcher.shut_down();
493}
494
495TEST_F(TestMockLeaderWatcher, InitReleaseShutdown) {
496 MockManagedLock mock_managed_lock;
497 MockMirrorStatusWatcher mock_mirror_status_watcher;
498 MockInstances mock_instances;
499 MockListener listener;
500
501 expect_is_shutdown(mock_managed_lock);
502 expect_destroy(mock_managed_lock);
503
504 InSequence seq;
505
506 expect_construct(mock_managed_lock);
507 MockLeaderWatcher leader_watcher(m_mock_threads, m_local_io_ctx, &listener);
508
509 // Inint
510 C_SaferCond on_heartbeat_finish;
511 expect_is_leader(mock_managed_lock, false, false);
512 expect_try_acquire_lock(mock_managed_lock, 0);
513 expect_init(mock_mirror_status_watcher, 0);
514 expect_init(mock_instances, 0);
515 expect_acquire_notify(mock_managed_lock, listener, 0);
516 expect_notify_heartbeat(mock_managed_lock, &on_heartbeat_finish);
517
518 ASSERT_EQ(0, leader_watcher.init());
519 ASSERT_EQ(0, on_heartbeat_finish.wait());
520
521 // Release
522 expect_is_leader(mock_managed_lock, false, true);
523 expect_release_notify(mock_managed_lock, listener, 0);
524 expect_shut_down(mock_instances, 0);
525 expect_shut_down(mock_mirror_status_watcher, 0);
526 expect_is_leader(mock_managed_lock, false, false);
527 C_SaferCond on_release;
528 expect_release_lock(mock_managed_lock, 0, &on_release);
529
530 leader_watcher.release_leader();
531 ASSERT_EQ(0, on_release.wait());
532
533 // Shutdown
534 expect_shut_down(mock_managed_lock, false, 0);
535 expect_is_leader(mock_managed_lock, false, false);
536
537 leader_watcher.shut_down();
538}
539
540TEST_F(TestMockLeaderWatcher, AcquireError) {
541 MockManagedLock mock_managed_lock;
542 MockMirrorStatusWatcher mock_mirror_status_watcher;
543 MockInstances mock_instances;
544 MockListener listener;
545
546 expect_is_shutdown(mock_managed_lock);
547 expect_is_leader(mock_managed_lock);
548 expect_destroy(mock_managed_lock);
549
550 InSequence seq;
551
552 expect_construct(mock_managed_lock);
553 MockLeaderWatcher leader_watcher(m_mock_threads, m_local_io_ctx, &listener);
554
555 // Inint
556 C_SaferCond on_heartbeat_finish;
557 expect_is_leader(mock_managed_lock, false, false);
558 expect_try_acquire_lock(mock_managed_lock, -EAGAIN);
559 expect_get_locker(mock_managed_lock, librbd::managed_lock::Locker(), -ENOENT);
560 expect_try_acquire_lock(mock_managed_lock, 0);
561 expect_init(mock_mirror_status_watcher, 0);
562 expect_init(mock_instances, 0);
563 expect_acquire_notify(mock_managed_lock, listener, 0);
564 expect_notify_heartbeat(mock_managed_lock, &on_heartbeat_finish);
565
566 ASSERT_EQ(0, leader_watcher.init());
567 ASSERT_EQ(0, on_heartbeat_finish.wait());
568
569 // Shutdown
570 expect_release_notify(mock_managed_lock, listener, 0);
571 expect_shut_down(mock_instances, 0);
572 expect_shut_down(mock_mirror_status_watcher, 0);
573 expect_is_leader(mock_managed_lock, false, false);
574 expect_release_lock(mock_managed_lock, 0);
575 expect_shut_down(mock_managed_lock, true, 0);
576 expect_is_leader(mock_managed_lock, false, false);
577
578 leader_watcher.shut_down();
579}
580
581TEST_F(TestMockLeaderWatcher, ReleaseError) {
582 MockManagedLock mock_managed_lock;
583 MockMirrorStatusWatcher mock_mirror_status_watcher;
584 MockInstances mock_instances;
585 MockListener listener;
586
587 expect_is_shutdown(mock_managed_lock);
588 expect_destroy(mock_managed_lock);
589
590 InSequence seq;
591
592 expect_construct(mock_managed_lock);
593 MockLeaderWatcher leader_watcher(m_mock_threads, m_local_io_ctx, &listener);
594
595 // Inint
596 C_SaferCond on_heartbeat_finish;
597 expect_is_leader(mock_managed_lock, false, false);
598 expect_try_acquire_lock(mock_managed_lock, 0);
599 expect_init(mock_mirror_status_watcher, 0);
600 expect_init(mock_instances, 0);
601 expect_acquire_notify(mock_managed_lock, listener, 0);
602 expect_notify_heartbeat(mock_managed_lock, &on_heartbeat_finish);
603
604 ASSERT_EQ(0, leader_watcher.init());
605 ASSERT_EQ(0, on_heartbeat_finish.wait());
606
607 // Release
608 expect_is_leader(mock_managed_lock, false, true);
609 expect_release_notify(mock_managed_lock, listener, -EINVAL);
610 expect_shut_down(mock_instances, 0);
611 expect_shut_down(mock_mirror_status_watcher, -EINVAL);
612 expect_is_leader(mock_managed_lock, false, false);
613 C_SaferCond on_release;
614 expect_release_lock(mock_managed_lock, -EINVAL, &on_release);
615
616 leader_watcher.release_leader();
617 ASSERT_EQ(0, on_release.wait());
618
619 // Shutdown
620 expect_shut_down(mock_managed_lock, false, 0);
621 expect_is_leader(mock_managed_lock, false, false);
622
623 leader_watcher.shut_down();
624}
625
626TEST_F(TestMockLeaderWatcher, Break) {
627 EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_heartbeat_interval", "1"));
628 EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_max_missed_heartbeats",
629 "1"));
630 CephContext *cct = reinterpret_cast<CephContext *>(m_local_io_ctx.cct());
181888fb
FG
631 int max_acquire_attempts = cct->_conf->get_val<int64_t>(
632 "rbd_mirror_leader_max_acquire_attempts_before_break");
7c673cae
FG
633
634 MockManagedLock mock_managed_lock;
635 MockMirrorStatusWatcher mock_mirror_status_watcher;
636 MockInstances mock_instances;
637 MockListener listener;
638 librbd::managed_lock::Locker
639 locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
640
641 expect_is_shutdown(mock_managed_lock);
642 expect_is_leader(mock_managed_lock);
643 expect_destroy(mock_managed_lock);
31f18b77 644 EXPECT_CALL(listener, update_leader_handler(_));
7c673cae
FG
645
646 InSequence seq;
647
648 expect_construct(mock_managed_lock);
649 MockLeaderWatcher leader_watcher(m_mock_threads, m_local_io_ctx, &listener);
650
651 // Init
652 expect_is_leader(mock_managed_lock, false, false);
653 for (int i = 0; i < max_acquire_attempts; i++) {
654 expect_try_acquire_lock(mock_managed_lock, -EAGAIN);
655 expect_get_locker(mock_managed_lock, locker, 0);
656 }
657 C_SaferCond on_break;
658 expect_break_lock(mock_managed_lock, locker, 0, &on_break);
659 C_SaferCond on_heartbeat_finish;
660 expect_try_acquire_lock(mock_managed_lock, 0);
661 expect_init(mock_mirror_status_watcher, 0);
662 expect_init(mock_instances, 0);
663 expect_acquire_notify(mock_managed_lock, listener, 0);
664 expect_notify_heartbeat(mock_managed_lock, &on_heartbeat_finish);
665
666 ASSERT_EQ(0, leader_watcher.init());
667 ASSERT_EQ(0, on_heartbeat_finish.wait());
668
669 // Shutdown
670 expect_release_notify(mock_managed_lock, listener, 0);
671 expect_shut_down(mock_instances, 0);
672 expect_shut_down(mock_mirror_status_watcher, 0);
673 expect_is_leader(mock_managed_lock, false, false);
674 expect_release_lock(mock_managed_lock, 0);
675 expect_shut_down(mock_managed_lock, true, 0);
676 expect_is_leader(mock_managed_lock, false, false);
677
678 leader_watcher.shut_down();
679}
680
681} // namespace mirror
682} // namespace rbd