reverselock_tests.cpp
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()