mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-28 18:25:48 +01:00
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()`.
This commit is contained in:
@@ -1050,6 +1050,93 @@ BOOST_FIXTURE_TEST_CASE(ccoins_flush_behavior, FlushTest)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_haveinputs_cache_miss_uses_base_getcoin)
|
||||
{
|
||||
const COutPoint prevout{Txid::FromUint256(m_rng.rand256()), 0};
|
||||
|
||||
CCoinsViewDB db{{.path = "test", .cache_bytes = 1_MiB, .memory_only = true}, {}};
|
||||
{
|
||||
CCoinsViewCache write_cache{&db};
|
||||
write_cache.SetBestBlock(m_rng.rand256());
|
||||
write_cache.AddCoin(prevout, Coin{CTxOut{1, CScript{}}, 1, false}, /*possible_overwrite=*/false);
|
||||
write_cache.Flush();
|
||||
}
|
||||
|
||||
class CCoinsViewSpy final : public CCoinsViewBacked
|
||||
{
|
||||
public:
|
||||
const COutPoint expected;
|
||||
mutable size_t havecoin_calls{0}, getcoin_calls{0};
|
||||
|
||||
explicit CCoinsViewSpy(CCoinsView* view, const COutPoint& out) : CCoinsViewBacked(view), expected{out} {}
|
||||
|
||||
std::optional<Coin> GetCoin(const COutPoint& out) const override
|
||||
{
|
||||
++getcoin_calls;
|
||||
BOOST_CHECK(out == expected);
|
||||
return CCoinsViewBacked::GetCoin(out);
|
||||
}
|
||||
|
||||
bool HaveCoin(const COutPoint& out) const override
|
||||
{
|
||||
++havecoin_calls;
|
||||
BOOST_CHECK(out == expected);
|
||||
return CCoinsViewBacked::HaveCoin(out);
|
||||
}
|
||||
};
|
||||
|
||||
CCoinsViewSpy base{&db, 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);
|
||||
BOOST_CHECK_EQUAL(base.havecoin_calls, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_cache_hit_does_not_call_base)
|
||||
{
|
||||
class CCoinsViewNoCall final : public CCoinsView
|
||||
{
|
||||
public:
|
||||
std::optional<Coin> GetCoin(const COutPoint&) const override
|
||||
{
|
||||
BOOST_FAIL("Base GetCoin should not be called when input is cached");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool HaveCoin(const COutPoint&) const override
|
||||
{
|
||||
BOOST_FAIL("Base HaveCoin should not be called when input is cached");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const COutPoint prevout{Txid::FromUint256(m_rng.rand256()), 0};
|
||||
CCoinsViewNoCall base;
|
||||
CCoinsViewCache cache{&base};
|
||||
|
||||
cache.AddCoin(prevout, Coin{CTxOut{1, CScript{}}, 1, false}, /*possible_overwrite=*/false);
|
||||
BOOST_CHECK(cache.HaveCoinInCache(prevout));
|
||||
|
||||
BOOST_CHECK(!cache.AccessCoin(prevout).IsSpent());
|
||||
BOOST_CHECK(cache.GetCoin(prevout));
|
||||
BOOST_CHECK(cache.HaveCoin(prevout));
|
||||
|
||||
CMutableTransaction mtx;
|
||||
mtx.vin.emplace_back(prevout);
|
||||
const CTransaction tx{mtx};
|
||||
BOOST_CHECK(!tx.IsCoinBase());
|
||||
BOOST_CHECK(cache.HaveInputs(tx));
|
||||
|
||||
BOOST_CHECK(cache.SpendCoin(prevout));
|
||||
BOOST_CHECK(!cache.HaveCoinInCache(prevout));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(coins_resource_is_used)
|
||||
{
|
||||
CCoinsMapMemoryResource resource;
|
||||
|
||||
Reference in New Issue
Block a user