/ src / test / reverselock_tests.cpp
reverselock_tests.cpp
 1  // Copyright (c) 2015-2021 The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #include <sync.h>
 6  #include <test/util/setup_common.h>
 7  
 8  #include <boost/test/unit_test.hpp>
 9  
10  #include <stdexcept>
11  
12  BOOST_AUTO_TEST_SUITE(reverselock_tests)
13  
14  BOOST_AUTO_TEST_CASE(reverselock_basics)
15  {
16      Mutex mutex;
17      WAIT_LOCK(mutex, lock);
18  
19      BOOST_CHECK(lock.owns_lock());
20      {
21          REVERSE_LOCK(lock);
22          BOOST_CHECK(!lock.owns_lock());
23      }
24      BOOST_CHECK(lock.owns_lock());
25  }
26  
27  BOOST_AUTO_TEST_CASE(reverselock_multiple)
28  {
29      Mutex mutex2;
30      Mutex mutex;
31      WAIT_LOCK(mutex2, lock2);
32      WAIT_LOCK(mutex, lock);
33  
34      // Make sure undoing two locks succeeds
35      {
36          REVERSE_LOCK(lock);
37          BOOST_CHECK(!lock.owns_lock());
38          REVERSE_LOCK(lock2);
39          BOOST_CHECK(!lock2.owns_lock());
40      }
41      BOOST_CHECK(lock.owns_lock());
42      BOOST_CHECK(lock2.owns_lock());
43  }
44  
45  BOOST_AUTO_TEST_CASE(reverselock_errors)
46  {
47      Mutex mutex2;
48      Mutex mutex;
49      WAIT_LOCK(mutex2, lock2);
50      WAIT_LOCK(mutex, lock);
51  
52  #ifdef DEBUG_LOCKORDER
53      bool prev = g_debug_lockorder_abort;
54      g_debug_lockorder_abort = false;
55  
56      // Make sure trying to reverse lock a previous lock fails
57      BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2), std::logic_error, HasReason("lock2 was not most recent critical section locked"));
58      BOOST_CHECK(lock2.owns_lock());
59  
60      g_debug_lockorder_abort = prev;
61  #endif
62  
63      // Make sure trying to reverse lock an unlocked lock fails
64      lock.unlock();
65  
66      BOOST_CHECK(!lock.owns_lock());
67  
68      bool failed = false;
69      try {
70          REVERSE_LOCK(lock);
71      } catch(...) {
72          failed = true;
73      }
74  
75      BOOST_CHECK(failed);
76      BOOST_CHECK(!lock.owns_lock());
77  
78      // Locking the original lock after it has been taken by a reverse lock
79      // makes no sense. Ensure that the original lock no longer owns the lock
80      // after giving it to a reverse one.
81  
82      lock.lock();
83      BOOST_CHECK(lock.owns_lock());
84      {
85          REVERSE_LOCK(lock);
86          BOOST_CHECK(!lock.owns_lock());
87      }
88  
89      BOOST_CHECK(failed);
90      BOOST_CHECK(lock.owns_lock());
91  }
92  
93  BOOST_AUTO_TEST_SUITE_END()