reverselock_tests.cpp raw

   1  // Copyright (c) 2015-2021 The Limenka 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()
  94