Changeset View
Changeset View
Standalone View
Standalone View
src/test/reverselock_tests.cpp
// Copyright (c) 2015-2019 The Bitcoin Core developers | // Copyright (c) 2015-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <reverselock.h> | #include <sync.h> | ||||
#include <test/util/setup_common.h> | #include <test/util/setup_common.h> | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup) | BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup) | ||||
BOOST_AUTO_TEST_CASE(reverselock_basics) { | BOOST_AUTO_TEST_CASE(reverselock_basics) { | ||||
boost::mutex mutex; | Mutex mutex; | ||||
boost::unique_lock<boost::mutex> lock(mutex); | WAIT_LOCK(mutex, lock); | ||||
BOOST_CHECK(lock.owns_lock()); | BOOST_CHECK(lock.owns_lock()); | ||||
{ | { | ||||
reverse_lock<boost::unique_lock<boost::mutex>> rlock(lock); | REVERSE_LOCK(lock); | ||||
BOOST_CHECK(!lock.owns_lock()); | BOOST_CHECK(!lock.owns_lock()); | ||||
} | } | ||||
BOOST_CHECK(lock.owns_lock()); | BOOST_CHECK(lock.owns_lock()); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(reverselock_multiple) { | |||||
Mutex mutex2; | |||||
Mutex mutex; | |||||
WAIT_LOCK(mutex2, lock2); | |||||
WAIT_LOCK(mutex, lock); | |||||
// Make sure undoing two locks succeeds | |||||
{ | |||||
REVERSE_LOCK(lock); | |||||
BOOST_CHECK(!lock.owns_lock()); | |||||
REVERSE_LOCK(lock2); | |||||
BOOST_CHECK(!lock2.owns_lock()); | |||||
} | |||||
BOOST_CHECK(lock.owns_lock()); | |||||
BOOST_CHECK(lock2.owns_lock()); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(reverselock_errors) { | BOOST_AUTO_TEST_CASE(reverselock_errors) { | ||||
boost::mutex mutex; | Mutex mutex2; | ||||
boost::unique_lock<boost::mutex> lock(mutex); | Mutex mutex; | ||||
WAIT_LOCK(mutex2, lock2); | |||||
WAIT_LOCK(mutex, lock); | |||||
#ifdef DEBUG_LOCKORDER | |||||
// Make sure trying to reverse lock a previous lock fails | |||||
try { | |||||
REVERSE_LOCK(lock2); | |||||
BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded | |||||
} catch (...) { | |||||
} | |||||
BOOST_CHECK(lock2.owns_lock()); | |||||
#endif | |||||
// Make sure trying to reverse lock an unlocked lock fails | // Make sure trying to reverse lock an unlocked lock fails | ||||
lock.unlock(); | lock.unlock(); | ||||
BOOST_CHECK(!lock.owns_lock()); | BOOST_CHECK(!lock.owns_lock()); | ||||
bool failed = false; | bool failed = false; | ||||
try { | try { | ||||
reverse_lock<boost::unique_lock<boost::mutex>> rlock(lock); | REVERSE_LOCK(lock); | ||||
} catch (...) { | } catch (...) { | ||||
failed = true; | failed = true; | ||||
} | } | ||||
BOOST_CHECK(failed); | BOOST_CHECK(failed); | ||||
BOOST_CHECK(!lock.owns_lock()); | BOOST_CHECK(!lock.owns_lock()); | ||||
// Locking the original lock after it has been taken by a reverse lock | // Locking the original lock after it has been taken by a reverse lock | ||||
// makes no sense. Ensure that the original lock no longer owns the lock | // makes no sense. Ensure that the original lock no longer owns the lock | ||||
// after giving it to a reverse one. | // after giving it to a reverse one. | ||||
lock.lock(); | lock.lock(); | ||||
BOOST_CHECK(lock.owns_lock()); | BOOST_CHECK(lock.owns_lock()); | ||||
{ | { | ||||
reverse_lock<boost::unique_lock<boost::mutex>> rlock(lock); | REVERSE_LOCK(lock); | ||||
BOOST_CHECK(!lock.owns_lock()); | BOOST_CHECK(!lock.owns_lock()); | ||||
} | } | ||||
BOOST_CHECK(failed); | BOOST_CHECK(failed); | ||||
BOOST_CHECK(lock.owns_lock()); | BOOST_CHECK(lock.owns_lock()); | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |