reverselock_tests.cpp raw

   1  // Copyright (c) 2015-present 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/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      AssertLockHeld(mutex);
  21      {
  22          REVERSE_LOCK(lock, mutex);
  23          AssertLockNotHeld(mutex);
  24          BOOST_CHECK(!lock.owns_lock());
  25      }
  26      BOOST_CHECK(lock.owns_lock());
  27  }
  28  
  29  BOOST_AUTO_TEST_CASE(reverselock_multiple)
  30  {
  31      Mutex mutex2;
  32      Mutex mutex;
  33      WAIT_LOCK(mutex2, lock2);
  34      WAIT_LOCK(mutex, lock);
  35  
  36      // Make sure undoing two locks succeeds
  37      {
  38          REVERSE_LOCK(lock, mutex);
  39          BOOST_CHECK(!lock.owns_lock());
  40          REVERSE_LOCK(lock2, mutex2);
  41          BOOST_CHECK(!lock2.owns_lock());
  42      }
  43      BOOST_CHECK(lock.owns_lock());
  44      BOOST_CHECK(lock2.owns_lock());
  45  }
  46  
  47  BOOST_AUTO_TEST_CASE(reverselock_errors)
  48  {
  49      Mutex mutex2;
  50      Mutex mutex;
  51      WAIT_LOCK(mutex2, lock2);
  52      WAIT_LOCK(mutex, lock);
  53  
  54  #ifdef DEBUG_LOCKORDER
  55      bool prev = g_debug_lockorder_abort;
  56      g_debug_lockorder_abort = false;
  57  
  58      // Make sure trying to reverse lock a previous lock fails
  59      BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2, mutex2), std::logic_error, HasReason("mutex2 was not most recent critical section locked"));
  60      BOOST_CHECK(lock2.owns_lock());
  61  
  62      g_debug_lockorder_abort = prev;
  63  #endif
  64  
  65      // Make sure trying to reverse lock an unlocked lock fails
  66      lock.unlock();
  67  
  68      BOOST_CHECK(!lock.owns_lock());
  69  
  70      bool failed = false;
  71      try {
  72          REVERSE_LOCK(lock, mutex);
  73      } catch(...) {
  74          failed = true;
  75      }
  76  
  77      BOOST_CHECK(failed);
  78      BOOST_CHECK(!lock.owns_lock());
  79  
  80      // Locking the original lock after it has been taken by a reverse lock
  81      // makes no sense. Ensure that the original lock no longer owns the lock
  82      // after giving it to a reverse one.
  83  
  84      lock.lock();
  85      BOOST_CHECK(lock.owns_lock());
  86      {
  87          REVERSE_LOCK(lock, mutex);
  88          BOOST_CHECK(!lock.owns_lock());
  89      }
  90  
  91      BOOST_CHECK(failed);
  92      BOOST_CHECK(lock.owns_lock());
  93  }
  94  
  95  BOOST_AUTO_TEST_SUITE_END()
  96