Branch data Line data Source code
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 : 0 : BOOST_AUTO_TEST_SUITE(reverselock_tests) 13 : : 14 : 0 : BOOST_AUTO_TEST_CASE(reverselock_basics) 15 : : { 16 : 0 : Mutex mutex; 17 : 0 : WAIT_LOCK(mutex, lock); 18 : : 19 : 0 : BOOST_CHECK(lock.owns_lock()); 20 : : { 21 : 0 : REVERSE_LOCK(lock); 22 : 0 : BOOST_CHECK(!lock.owns_lock()); 23 : 0 : } 24 : 0 : BOOST_CHECK(lock.owns_lock()); 25 : 0 : } 26 : : 27 : 0 : BOOST_AUTO_TEST_CASE(reverselock_multiple) 28 : : { 29 : 0 : Mutex mutex2; 30 : 0 : Mutex mutex; 31 : 0 : WAIT_LOCK(mutex2, lock2); 32 : 0 : WAIT_LOCK(mutex, lock); 33 : : 34 : : // Make sure undoing two locks succeeds 35 : : { 36 : 0 : REVERSE_LOCK(lock); 37 : 0 : BOOST_CHECK(!lock.owns_lock()); 38 : 0 : REVERSE_LOCK(lock2); 39 : 0 : BOOST_CHECK(!lock2.owns_lock()); 40 : 0 : } 41 : 0 : BOOST_CHECK(lock.owns_lock()); 42 : 0 : BOOST_CHECK(lock2.owns_lock()); 43 : 0 : } 44 : : 45 : 0 : BOOST_AUTO_TEST_CASE(reverselock_errors) 46 : : { 47 : 0 : Mutex mutex2; 48 : 0 : Mutex mutex; 49 : 0 : WAIT_LOCK(mutex2, lock2); 50 : 0 : 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 : 0 : lock.unlock(); 65 : : 66 : 0 : BOOST_CHECK(!lock.owns_lock()); 67 : : 68 : 0 : bool failed = false; 69 : : try { 70 : 0 : REVERSE_LOCK(lock); 71 : 0 : } catch(...) { 72 : 0 : failed = true; 73 : 0 : } 74 : 0 : 75 : 0 : BOOST_CHECK(failed); 76 : 0 : 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 : 0 : lock.lock(); 83 : 0 : BOOST_CHECK(lock.owns_lock()); 84 : : { 85 : 0 : REVERSE_LOCK(lock); 86 : 0 : BOOST_CHECK(!lock.owns_lock()); 87 : 0 : } 88 : : 89 : 0 : BOOST_CHECK(failed); 90 : 0 : BOOST_CHECK(lock.owns_lock()); 91 : 0 : } 92 : : 93 : 0 : BOOST_AUTO_TEST_SUITE_END()