test: add HaveInputs call-path unit tests

Add unit tests covering `CCoinsViewCache::HaveInputs()`.

The tests document that `HaveInputs()` consults the cache first and that a cache miss pulls from the backing view via `GetCoin()`.

Co-authored-by: Novo <eunovo9@gmail.com>
This commit is contained in:
Lőrinc
2026-01-14 23:43:24 +01:00
parent 139aa4b27e
commit 277c57f0c5

View File

@@ -1059,6 +1059,69 @@ BOOST_FIXTURE_TEST_CASE(ccoins_flush_behavior, FlushTest)
}
}
BOOST_AUTO_TEST_CASE(ccoins_cache_behavior)
{
class CCoinsViewSpy final : public CCoinsView
{
public:
const COutPoint expected;
mutable size_t getcoin_calls{0};
bool allow_getcoin{true};
explicit CCoinsViewSpy(const COutPoint& out) : expected{out} {}
std::optional<Coin> GetCoin(const COutPoint& out) const override
{
BOOST_CHECK(out == expected);
if (!allow_getcoin) {
BOOST_FAIL("Base GetCoin should not be called when input is cached");
return std::nullopt;
}
++getcoin_calls;
return Coin{CTxOut{1, CScript{}}, 1, false};
}
bool HaveCoin(const COutPoint& out) const override
{
BOOST_CHECK(out == expected);
BOOST_FAIL("Base HaveCoin should never be called");
return false;
}
};
const COutPoint prevout{Txid::FromUint256(m_rng.rand256()), 0};
CCoinsViewSpy base{prevout};
CCoinsViewCache cache{&base};
CMutableTransaction mtx;
mtx.vin.emplace_back(prevout);
const CTransaction tx{mtx};
BOOST_CHECK(!tx.IsCoinBase());
BOOST_CHECK(cache.HaveInputs(tx));
BOOST_CHECK_EQUAL(base.getcoin_calls, 1);
base.allow_getcoin = false;
BOOST_CHECK(cache.HaveInputs(tx));
BOOST_CHECK(cache.GetCoin(prevout));
BOOST_CHECK(!cache.AccessCoin(prevout).IsSpent());
BOOST_CHECK(cache.HaveCoin(prevout));
BOOST_CHECK_EQUAL(base.getcoin_calls, 1);
const COutPoint prefilled_prevout{Txid::FromUint256(m_rng.rand256()), 0};
cache.AddCoin(prefilled_prevout, Coin{CTxOut{1, CScript{}}, 1, false}, /*possible_overwrite=*/false);
BOOST_CHECK(cache.HaveCoinInCache(prefilled_prevout));
CMutableTransaction prefilled_mtx;
prefilled_mtx.vin.emplace_back(prefilled_prevout);
const CTransaction prefilled_tx{prefilled_mtx};
BOOST_CHECK(!prefilled_tx.IsCoinBase());
BOOST_CHECK(cache.HaveInputs(prefilled_tx));
BOOST_CHECK(cache.SpendCoin(prevout));
BOOST_CHECK(!cache.HaveCoinInCache(prevout));
}
BOOST_AUTO_TEST_CASE(coins_resource_is_used)
{
CCoinsMapMemoryResource resource;