merge bitcoin#24714: Don't use a lambda for Assert/Assume

Co-authored-by: Konstantin Akimov <knstqq@gmail.com>
This commit is contained in:
Kittywhiskers Van Gogh 2023-08-24 13:59:24 +05:30 committed by PastaPastaPasta
parent c2014e447b
commit 0761496ce4
6 changed files with 66 additions and 9 deletions

View File

@ -735,6 +735,7 @@ libbitcoin_util_a_SOURCES = \
util/asmap.cpp \
util/bip32.cpp \
util/bytevectorhash.cpp \
util/check.cpp \
util/error.cpp \
util/fees.cpp \
util/getuniquepath.cpp \

View File

@ -51,6 +51,31 @@ namespace BCLog {
BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
namespace {
class NoCopyOrMove
{
public:
int i;
explicit NoCopyOrMove(int i) : i{i} { }
NoCopyOrMove() = delete;
NoCopyOrMove(const NoCopyOrMove&) = delete;
NoCopyOrMove(NoCopyOrMove&&) = delete;
NoCopyOrMove& operator=(const NoCopyOrMove&) = delete;
NoCopyOrMove& operator=(NoCopyOrMove&&) = delete;
operator bool() const { return i != 0; }
int get_ip1() { return i + 1; }
bool test()
{
// Check that Assume can be used within a lambda and still call methods
[&]() { Assume(get_ip1()); }();
return Assume(get_ip1() != 5);
}
};
} // namespace
BOOST_AUTO_TEST_CASE(util_check)
{
// Check that Assert can forward
@ -62,6 +87,14 @@ BOOST_AUTO_TEST_CASE(util_check)
// Check that Assume can be used as unary expression
const bool result{Assume(two == 2)};
Assert(result);
// Check that Assert doesn't require copy/move
NoCopyOrMove x{9};
Assert(x).i += 3;
Assert(x).test();
// Check nested Asserts
BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3);
}
BOOST_AUTO_TEST_CASE(util_criticalsection)

14
src/util/check.cpp Normal file
View File

@ -0,0 +1,14 @@
// Copyright (c) 2022 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/check.h>
#include <tinyformat.h>
void assertion_fail(const char* file, int line, const char* func, const char* assertion)
{
auto str = strprintf("%s:%s %s: Assertion `%s' failed.\n", file, line, func, assertion);
fwrite(str.data(), 1, str.size(), stderr);
std::abort();
}

View File

@ -47,14 +47,26 @@ class NonFatalCheckError : public std::runtime_error
#endif
/** Helper for Assert() */
template <typename T>
T get_pure_r_value(T&& val)
void assertion_fail(const char* file, int line, const char* func, const char* assertion);
/** Helper for Assert()/Assume() */
template <bool IS_ASSERT, typename T>
T&& inline_assertion_check(T&& val, const char* file, int line, const char* func, const char* assertion)
{
if constexpr (IS_ASSERT
#ifdef ABORT_ON_FAILED_ASSUME
|| true
#endif
) {
if (!val) {
assertion_fail(file, line, func, assertion);
}
}
return std::forward<T>(val);
}
/** Identity function. Abort if the value compares equal to zero */
#define Assert(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }())
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
/**
* Assume is the identity function.
@ -66,10 +78,6 @@ T get_pure_r_value(T&& val)
* - For non-fatal errors in interactive sessions (e.g. RPC or command line
* interfaces), CHECK_NONFATAL() might be more appropriate.
*/
#ifdef ABORT_ON_FAILED_ASSUME
#define Assume(val) Assert(val)
#else
#define Assume(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); return std::forward<decltype(get_pure_r_value(val))>(check); }())
#endif
#define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
#endif // BITCOIN_UTIL_CHECK_H

View File

@ -7,6 +7,7 @@
WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
: TestingSetup(chainName),
m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args))},
m_wallet(m_node.chain.get(), "", CreateMockWalletDatabase())
{
bool fFirstRun;

View File

@ -20,7 +20,7 @@
struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
std::unique_ptr<interfaces::WalletLoader> m_wallet_loader = interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args));
std::unique_ptr<interfaces::WalletLoader> m_wallet_loader;
CWallet m_wallet;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};