diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 6f06399a56a..70facae7b36 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -31,14 +32,6 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund namespace { -//! equality test -bool operator==(const Coin &a, const Coin &b) { - // Empty Coin objects are always equal. - if (a.IsSpent() && b.IsSpent()) return true; - return a.fCoinBase == b.fCoinBase && - a.nHeight == b.nHeight && - a.out == b.out; -} class CCoinsViewTest : public CoinsViewEmpty { @@ -166,7 +159,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block) // former just delegates to the latter and returns the first unspent in a txn. const Coin& entry = (m_rng.randrange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); - BOOST_CHECK(coin == entry); + BOOST_CHECK_EQUAL(coin, entry); if (test_havecoin_before) { BOOST_CHECK(result_havecoin == !entry.IsSpent()); @@ -220,7 +213,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block) bool have = stack.back()->HaveCoin(entry.first); const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == entry.second); + BOOST_CHECK_EQUAL(coin, entry.second); if (coin.IsSpent()) { missed_an_entry = true; } else { @@ -479,7 +472,7 @@ BOOST_FIXTURE_TEST_CASE(updatecoins_simulation_test, UpdateTest) bool have = stack.back()->HaveCoin(entry.first); const Coin& coin = stack.back()->AccessCoin(entry.first); BOOST_CHECK(have == !coin.IsSpent()); - BOOST_CHECK(coin == entry.second); + BOOST_CHECK_EQUAL(coin, entry.second); } } @@ -1081,7 +1074,7 @@ BOOST_FIXTURE_TEST_CASE(coins_db_leveldb_layout, FlushTest) WITH_LOCK(::cs_main, return base.CompactFullAsync()).wait(); BOOST_CHECK_EQUAL(level2_files(base), 1); - BOOST_CHECK(*Assert(base.GetCoin(outpoint)) == coin); + BOOST_CHECK_EQUAL(*Assert(base.GetCoin(outpoint)), coin); BOOST_CHECK_EQUAL(base.GetBestBlock(), block_hash); } @@ -1124,7 +1117,7 @@ BOOST_AUTO_TEST_CASE(ccoins_addcoin_exception_keeps_usage_balanced) BOOST_CHECK_THROW(cache.AddCoin(outpoint, Coin{coin2}, /*possible_overwrite=*/false), std::logic_error); cache.SelfTest(); - BOOST_CHECK(cache.AccessCoin(outpoint) == coin1); + BOOST_CHECK_EQUAL(cache.AccessCoin(outpoint), coin1); } BOOST_AUTO_TEST_CASE(ccoins_emplace_duplicate_keeps_usage_balanced) @@ -1141,7 +1134,7 @@ BOOST_AUTO_TEST_CASE(ccoins_emplace_duplicate_keeps_usage_balanced) cache.EmplaceCoinInternalDANGER(outpoint, Coin{coin2}); cache.SelfTest(); - BOOST_CHECK(cache.AccessCoin(outpoint) == coin1); + BOOST_CHECK_EQUAL(cache.AccessCoin(outpoint), coin1); } BOOST_AUTO_TEST_CASE(ccoins_reset_guard) @@ -1165,7 +1158,7 @@ BOOST_AUTO_TEST_CASE(ccoins_reset_guard) { const auto reset_guard{cache.CreateResetGuard()}; - BOOST_CHECK(cache.AccessCoin(outpoint) == coin); + BOOST_CHECK_EQUAL(cache.AccessCoin(outpoint), coin); BOOST_CHECK(!cache.AccessCoin(outpoint).IsSpent()); BOOST_CHECK_EQUAL(cache.GetCacheSize(), 1); BOOST_CHECK_EQUAL(cache.GetDirtyCount(), 1); @@ -1212,7 +1205,7 @@ BOOST_AUTO_TEST_CASE(ccoins_peekcoin) CCoinsViewCacheTest main_cache{&base}; const auto fetched{main_cache.PeekCoin(outpoint)}; BOOST_CHECK(fetched.has_value()); - BOOST_CHECK(*fetched == coin); + BOOST_CHECK_EQUAL(*fetched, coin); BOOST_CHECK(!main_cache.HaveCoinInCache(outpoint)); } diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 6f5dbd62414..0cc38d8a878 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -35,14 +36,6 @@ #include namespace { -const Coin EMPTY_COIN{}; - -bool operator==(const Coin& a, const Coin& b) -{ - if (a.IsSpent() && b.IsSpent()) return true; - return a.fCoinBase == b.fCoinBase && a.nHeight == b.nHeight && a.out == b.out; -} - /** * MutationGuardCoinsViewCache asserts that nothing mutates cacheCoins until * BatchWrite is called. It keeps a snapshot of the cacheCoins state, which it @@ -370,7 +363,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsViewCache& co { const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point); - const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN); + const bool exists_using_access_coin = !coin_using_access_coin.IsSpent(); const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point); const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point); if (auto coin{coins_view_cache.GetCoin(random_out_point)}) { diff --git a/src/test/util/coins.h b/src/test/util/coins.h index 4f729be8a6f..0b57488ce21 100644 --- a/src/test/util/coins.h +++ b/src/test/util/coins.h @@ -5,7 +5,12 @@ #ifndef BITCOIN_TEST_UTIL_COINS_H #define BITCOIN_TEST_UTIL_COINS_H +#include +#include #include +#include + +#include class CCoinsViewCache; class FastRandomContext; @@ -17,4 +22,17 @@ class FastRandomContext; */ COutPoint AddTestCoin(FastRandomContext& rng, CCoinsViewCache& coins_view); +//! Strict equality, including fields of spent coins +inline bool operator==(const Coin& a, const Coin& b) +{ + return a.fCoinBase == b.fCoinBase && a.nHeight == b.nHeight && a.out == b.out; +} + +//! Printed when a coin comparison fails +inline std::ostream& operator<<(std::ostream& os, const Coin& coin) +{ + return os << strprintf("Coin(spent=%d, coinbase=%d, height=%d, value=%d, scriptPubKey=%s)", + coin.IsSpent(), coin.fCoinBase, coin.nHeight, coin.out.nValue, HexStr(coin.out.scriptPubKey)); +} + #endif // BITCOIN_TEST_UTIL_COINS_H