aboutsummaryrefslogtreecommitdiff
path: root/src/test/coins_tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/coins_tests.cpp')
-rw-r--r--src/test/coins_tests.cpp176
1 files changed, 96 insertions, 80 deletions
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index b6d3e7d567..0d18cd0c2b 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -19,6 +19,8 @@
#include <boost/test/unit_test.hpp>
+using namespace util::hex_literals;
+
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out);
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
@@ -35,10 +37,13 @@ bool operator==(const Coin &a, const Coin &b) {
class CCoinsViewTest : public CCoinsView
{
+ FastRandomContext& m_rng;
uint256 hashBestBlock_;
std::map<COutPoint, Coin> map_;
public:
+ CCoinsViewTest(FastRandomContext& rng) : m_rng{rng} {}
+
[[nodiscard]] bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
{
std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint);
@@ -46,7 +51,7 @@ public:
return false;
}
coin = it->second;
- if (coin.IsSpent() && InsecureRandBool() == 0) {
+ if (coin.IsSpent() && m_rng.randbool() == 0) {
// Randomly return false in case of an empty entry.
return false;
}
@@ -55,13 +60,13 @@ public:
uint256 GetBestBlock() const override { return hashBestBlock_; }
- bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock, bool erase = true) override
+ bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override
{
- for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = erase ? mapCoins.erase(it) : std::next(it)) {
- if (it->second.flags & CCoinsCacheEntry::DIRTY) {
+ for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)){
+ if (it->second.IsDirty()) {
// Same optimization used in CCoinsViewDB is to only write dirty entries.
map_[it->first] = it->second.coin;
- if (it->second.coin.IsSpent() && InsecureRandRange(3) == 0) {
+ if (it->second.coin.IsSpent() && m_rng.randrange(3) == 0) {
// Randomly delete empty entries on write.
map_.erase(it->first);
}
@@ -78,7 +83,7 @@ class CCoinsViewCacheTest : public CCoinsViewCache
public:
explicit CCoinsViewCacheTest(CCoinsView* _base) : CCoinsViewCache(_base) {}
- void SelfTest() const
+ void SelfTest(bool sanity_check = true) const
{
// Manually recompute the dynamic usage of the whole data, and compare it.
size_t ret = memusage::DynamicUsage(cacheCoins);
@@ -89,9 +94,13 @@ public:
}
BOOST_CHECK_EQUAL(GetCacheSize(), count);
BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret);
+ if (sanity_check) {
+ SanityCheck();
+ }
}
CCoinsMap& map() const { return cacheCoins; }
+ CoinsCachePair& sentinel() const { return m_sentinel; }
size_t& usage() const { return cachedCoinsUsage; }
};
@@ -101,6 +110,7 @@ BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)
static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
+struct CacheTest : BasicTestingSetup {
// This is a large randomized insert/remove simulation test on a variable-size
// stack of caches on top of CCoinsViewTest.
//
@@ -140,26 +150,26 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
std::vector<Txid> txids;
txids.resize(NUM_SIMULATION_ITERATIONS / 8);
for (unsigned int i = 0; i < txids.size(); i++) {
- txids[i] = Txid::FromUint256(InsecureRand256());
+ txids[i] = Txid::FromUint256(m_rng.rand256());
}
for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
// Do a random modification.
{
- auto txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration.
+ auto txid = txids[m_rng.randrange(txids.size())]; // txid we're going to modify in this iteration.
Coin& coin = result[COutPoint(txid, 0)];
// Determine whether to test HaveCoin before or after Access* (or both). As these functions
// can influence each other's behaviour by pulling things into the cache, all combinations
// are tested.
- bool test_havecoin_before = InsecureRandBits(2) == 0;
- bool test_havecoin_after = InsecureRandBits(2) == 0;
+ bool test_havecoin_before = m_rng.randbits(2) == 0;
+ bool test_havecoin_after = m_rng.randbits(2) == 0;
bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false;
// Infrequently, test usage of AccessByTxid instead of AccessCoin - the
// former just delegates to the latter and returns the first unspent in a txn.
- const Coin& entry = (InsecureRandRange(500) == 0) ?
+ const Coin& entry = (m_rng.randrange(500) == 0) ?
AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
BOOST_CHECK(coin == entry);
@@ -172,23 +182,23 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
BOOST_CHECK(ret == !entry.IsSpent());
}
- if (InsecureRandRange(5) == 0 || coin.IsSpent()) {
+ if (m_rng.randrange(5) == 0 || coin.IsSpent()) {
Coin newcoin;
- newcoin.out.nValue = InsecureRandMoneyAmount();
+ newcoin.out.nValue = RandMoney(m_rng);
newcoin.nHeight = 1;
// Infrequently test adding unspendable coins.
- if (InsecureRandRange(16) == 0 && coin.IsSpent()) {
- newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN);
+ if (m_rng.randrange(16) == 0 && coin.IsSpent()) {
+ newcoin.out.scriptPubKey.assign(1 + m_rng.randbits(6), OP_RETURN);
BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
added_an_unspendable_entry = true;
} else {
// Random sizes so we can test memory usage accounting
- newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0);
+ newcoin.out.scriptPubKey.assign(m_rng.randbits(6), 0);
(coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
coin = newcoin;
}
- bool is_overwrite = !coin.IsSpent() || InsecureRand32() & 1;
+ bool is_overwrite = !coin.IsSpent() || m_rng.rand32() & 1;
stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), is_overwrite);
} else {
// Spend the coin.
@@ -199,15 +209,15 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
}
// Once every 10 iterations, remove a random entry from the cache
- if (InsecureRandRange(10) == 0) {
- COutPoint out(txids[InsecureRand32() % txids.size()], 0);
- int cacheid = InsecureRand32() % stack.size();
+ if (m_rng.randrange(10) == 0) {
+ COutPoint out(txids[m_rng.rand32() % txids.size()], 0);
+ int cacheid = m_rng.rand32() % stack.size();
stack[cacheid]->Uncache(out);
uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out);
}
// Once every 1000 iterations and at the end, verify the full cache.
- if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ if (m_rng.randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
for (const auto& entry : result) {
bool have = stack.back()->HaveCoin(entry.first);
const Coin& coin = stack.back()->AccessCoin(entry.first);
@@ -225,27 +235,27 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
}
}
- if (InsecureRandRange(100) == 0) {
+ if (m_rng.randrange(100) == 0) {
// Every 100 iterations, flush an intermediate cache
- if (stack.size() > 1 && InsecureRandBool() == 0) {
- unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
- if (fake_best_block) stack[flushIndex]->SetBestBlock(InsecureRand256());
- bool should_erase = InsecureRandRange(4) < 3;
+ if (stack.size() > 1 && m_rng.randbool() == 0) {
+ unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
+ if (fake_best_block) stack[flushIndex]->SetBestBlock(m_rng.rand256());
+ bool should_erase = m_rng.randrange(4) < 3;
BOOST_CHECK(should_erase ? stack[flushIndex]->Flush() : stack[flushIndex]->Sync());
flushed_without_erase |= !should_erase;
}
}
- if (InsecureRandRange(100) == 0) {
+ if (m_rng.randrange(100) == 0) {
// Every 100 iterations, change the cache stack.
- if (stack.size() > 0 && InsecureRandBool() == 0) {
+ if (stack.size() > 0 && m_rng.randbool() == 0) {
//Remove the top cache
- if (fake_best_block) stack.back()->SetBestBlock(InsecureRand256());
- bool should_erase = InsecureRandRange(4) < 3;
+ if (fake_best_block) stack.back()->SetBestBlock(m_rng.rand256());
+ bool should_erase = m_rng.randrange(4) < 3;
BOOST_CHECK(should_erase ? stack.back()->Flush() : stack.back()->Sync());
flushed_without_erase |= !should_erase;
stack.pop_back();
}
- if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
+ if (stack.size() == 0 || (stack.size() < 4 && m_rng.randbool())) {
//Add a new cache
CCoinsView* tip = base;
if (stack.size() > 0) {
@@ -273,24 +283,26 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
BOOST_CHECK(uncached_an_entry);
BOOST_CHECK(flushed_without_erase);
}
+}; // struct CacheTest
// Run the above simulation for multiple base types.
-BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
+BOOST_FIXTURE_TEST_CASE(coins_cache_simulation_test, CacheTest)
{
- CCoinsViewTest base;
+ CCoinsViewTest base{m_rng};
SimulationTest(&base, false);
CCoinsViewDB db_base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}};
SimulationTest(&db_base, true);
}
+struct UpdateTest : BasicTestingSetup {
// Store of all necessary tx and undo data for next test
typedef std::map<COutPoint, std::tuple<CTransaction,CTxUndo,Coin>> UtxoData;
UtxoData utxoData;
UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
assert(utxoSet.size());
- auto utxoSetIt = utxoSet.lower_bound(COutPoint(Txid::FromUint256(InsecureRand256()), 0));
+ auto utxoSetIt = utxoSet.lower_bound(COutPoint(Txid::FromUint256(m_rng.rand256()), 0));
if (utxoSetIt == utxoSet.end()) {
utxoSetIt = utxoSet.begin();
}
@@ -298,6 +310,7 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
assert(utxoDataIt != utxoData.end());
return utxoDataIt;
}
+}; // struct UpdateTest
// This test is similar to the previous test
@@ -305,17 +318,16 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
// random txs are created and UpdateCoins is used to update the cache stack
// In particular it is tested that spending a duplicate coinbase tx
// has the expected effect (the other duplicate is overwritten at all cache levels)
-BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
+BOOST_FIXTURE_TEST_CASE(updatecoins_simulation_test, UpdateTest)
{
- SeedInsecureRand(SeedRand::ZEROS);
- g_mock_deterministic_tests = true;
+ SeedRandomForTest(SeedRand::ZEROS);
bool spent_a_duplicate_coinbase = false;
// A simple map to track what we expect the cache stack to represent.
std::map<COutPoint, Coin> result;
// The cache stack.
- CCoinsViewTest base; // A CCoinsViewTest at the bottom.
+ CCoinsViewTest base{m_rng}; // A CCoinsViewTest at the bottom.
std::vector<std::unique_ptr<CCoinsViewCacheTest>> stack; // A stack of CCoinsViewCaches on top.
stack.push_back(std::make_unique<CCoinsViewCacheTest>(&base)); // Start with one cache.
@@ -326,7 +338,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
std::set<COutPoint> utxoset;
for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
- uint32_t randiter = InsecureRand32();
+ uint32_t randiter = m_rng.rand32();
// 19/20 txs add a new transaction
if (randiter % 20 < 19) {
@@ -334,14 +346,14 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
tx.vin.resize(1);
tx.vout.resize(1);
tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate
- tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting
- const int height{int(InsecureRand32() >> 1)};
+ tx.vout[0].scriptPubKey.assign(m_rng.rand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting
+ const int height{int(m_rng.rand32() >> 1)};
Coin old_coin;
// 2/20 times create a new coinbase
if (randiter % 20 < 2 || coinbase_coins.size() < 10) {
// 1/10 of those times create a duplicate coinbase
- if (InsecureRandRange(10) == 0 && coinbase_coins.size()) {
+ if (m_rng.randrange(10) == 0 && coinbase_coins.size()) {
auto utxod = FindRandomFrom(coinbase_coins);
// Reuse the exact same coinbase
tx = CMutableTransaction{std::get<0>(utxod->second)};
@@ -451,7 +463,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
}
// Once every 1000 iterations and at the end, verify the full cache.
- if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ if (m_rng.randrange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
for (const auto& entry : result) {
bool have = stack.back()->HaveCoin(entry.first);
const Coin& coin = stack.back()->AccessCoin(entry.first);
@@ -461,30 +473,30 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
}
// One every 10 iterations, remove a random entry from the cache
- if (utxoset.size() > 1 && InsecureRandRange(30) == 0) {
- stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first);
+ if (utxoset.size() > 1 && m_rng.randrange(30) == 0) {
+ stack[m_rng.rand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first);
}
- if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) {
- stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first);
+ if (disconnected_coins.size() > 1 && m_rng.randrange(30) == 0) {
+ stack[m_rng.rand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first);
}
- if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) {
- stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first);
+ if (duplicate_coins.size() > 1 && m_rng.randrange(30) == 0) {
+ stack[m_rng.rand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first);
}
- if (InsecureRandRange(100) == 0) {
+ if (m_rng.randrange(100) == 0) {
// Every 100 iterations, flush an intermediate cache
- if (stack.size() > 1 && InsecureRandBool() == 0) {
- unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
+ if (stack.size() > 1 && m_rng.randbool() == 0) {
+ unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
BOOST_CHECK(stack[flushIndex]->Flush());
}
}
- if (InsecureRandRange(100) == 0) {
+ if (m_rng.randrange(100) == 0) {
// Every 100 iterations, change the cache stack.
- if (stack.size() > 0 && InsecureRandBool() == 0) {
+ if (stack.size() > 0 && m_rng.randbool() == 0) {
BOOST_CHECK(stack.back()->Flush());
stack.pop_back();
}
- if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
+ if (stack.size() == 0 || (stack.size() < 4 && m_rng.randbool())) {
CCoinsView* tip = &base;
if (stack.size() > 0) {
tip = stack.back().get();
@@ -496,32 +508,30 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// Verify coverage.
BOOST_CHECK(spent_a_duplicate_coinbase);
-
- g_mock_deterministic_tests = false;
}
BOOST_AUTO_TEST_CASE(ccoins_serialization)
{
// Good example
- DataStream ss1{ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35")};
+ DataStream ss1{"97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35"_hex};
Coin cc1;
ss1 >> cc1;
BOOST_CHECK_EQUAL(cc1.fCoinBase, false);
BOOST_CHECK_EQUAL(cc1.nHeight, 203998U);
BOOST_CHECK_EQUAL(cc1.out.nValue, CAmount{60000000000});
- BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));
+ BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160("816115944e077fe7c803cfa57f29b36bf87c1d35"_hex_u8)))));
// Good example
- DataStream ss2{ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4")};
+ DataStream ss2{"8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"_hex};
Coin cc2;
ss2 >> cc2;
BOOST_CHECK_EQUAL(cc2.fCoinBase, true);
BOOST_CHECK_EQUAL(cc2.nHeight, 120891U);
BOOST_CHECK_EQUAL(cc2.out.nValue, 110397);
- BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));
+ BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(PKHash(uint160("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"_hex_u8)))));
// Smallest possible example
- DataStream ss3{ParseHex("000006")};
+ DataStream ss3{"000006"_hex};
Coin cc3;
ss3 >> cc3;
BOOST_CHECK_EQUAL(cc3.fCoinBase, false);
@@ -530,7 +540,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
BOOST_CHECK_EQUAL(cc3.out.scriptPubKey.size(), 0U);
// scriptPubKey that ends beyond the end of the stream
- DataStream ss4{ParseHex("000007")};
+ DataStream ss4{"000007"_hex};
try {
Coin cc4;
ss4 >> cc4;
@@ -543,7 +553,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
uint64_t x = 3000000000ULL;
tmp << VARINT(x);
BOOST_CHECK_EQUAL(HexStr(tmp), "8a95c0bb00");
- DataStream ss5{ParseHex("00008a95c0bb00")};
+ DataStream ss5{"00008a95c0bb00"_hex};
try {
Coin cc5;
ss5 >> cc5;
@@ -579,7 +589,7 @@ static void SetCoinsValue(CAmount value, Coin& coin)
}
}
-static size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
+static size_t InsertCoinsMapEntry(CCoinsMap& map, CoinsCachePair& sentinel, CAmount value, char flags)
{
if (value == ABSENT) {
assert(flags == NO_ENTRY);
@@ -587,10 +597,10 @@ static size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
}
assert(flags != NO_ENTRY);
CCoinsCacheEntry entry;
- entry.flags = flags;
SetCoinsValue(value, entry.coin);
auto inserted = map.emplace(OUTPOINT, std::move(entry));
assert(inserted.second);
+ inserted.first->second.AddFlags(flags, *inserted.first, sentinel);
return inserted.first->second.coin.DynamicMemoryUsage();
}
@@ -606,17 +616,20 @@ void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags, const C
} else {
value = it->second.coin.out.nValue;
}
- flags = it->second.flags;
+ flags = it->second.GetFlags();
assert(flags != NO_ENTRY);
}
}
void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags)
{
+ CoinsCachePair sentinel{};
+ sentinel.second.SelfRef(sentinel);
CCoinsMapMemoryResource resource;
CCoinsMap map{0, CCoinsMap::hasher{}, CCoinsMap::key_equal{}, &resource};
- InsertCoinsMapEntry(map, value, flags);
- BOOST_CHECK(view.BatchWrite(map, {}));
+ auto usage{InsertCoinsMapEntry(map, sentinel, value, flags)};
+ auto cursor{CoinsViewCacheCursor(usage, sentinel, map, /*will_erase=*/true)};
+ BOOST_CHECK(view.BatchWrite(cursor, {}));
}
class SingleEntryCacheTest
@@ -625,7 +638,7 @@ public:
SingleEntryCacheTest(CAmount base_value, CAmount cache_value, char cache_flags)
{
WriteCoinsViewEntry(base, base_value, base_value == ABSENT ? NO_ENTRY : DIRTY);
- cache.usage() += InsertCoinsMapEntry(cache.map(), cache_value, cache_flags);
+ cache.usage() += InsertCoinsMapEntry(cache.map(), cache.sentinel(), cache_value, cache_flags);
}
CCoinsView root;
@@ -637,7 +650,7 @@ static void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount exp
{
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
test.cache.AccessCoin(OUTPOINT);
- test.cache.SelfTest();
+ test.cache.SelfTest(/*sanity_check=*/false);
CAmount result_value;
char result_flags;
@@ -806,7 +819,7 @@ void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected
char result_flags;
try {
WriteCoinsViewEntry(test.cache, child_value, child_flags);
- test.cache.SelfTest();
+ test.cache.SelfTest(/*sanity_check=*/false);
GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
} catch (std::logic_error&) {
result_value = FAIL;
@@ -884,11 +897,12 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
}
+struct FlushTest : BasicTestingSetup {
Coin MakeCoin()
{
Coin coin;
- coin.out.nValue = InsecureRand32();
- coin.nHeight = InsecureRandRange(4096);
+ coin.out.nValue = m_rng.rand32();
+ coin.nHeight = m_rng.randrange(4096);
coin.fCoinBase = 0;
return coin;
}
@@ -915,18 +929,19 @@ void TestFlushBehavior(
size_t cache_usage;
size_t cache_size;
- auto flush_all = [&all_caches](bool erase) {
+ auto flush_all = [this, &all_caches](bool erase) {
// Flush in reverse order to ensure that flushes happen from children up.
for (auto i = all_caches.rbegin(); i != all_caches.rend(); ++i) {
auto& cache = *i;
+ cache->SanityCheck();
// hashBlock must be filled before flushing to disk; value is
// unimportant here. This is normally done during connect/disconnect block.
- cache->SetBestBlock(InsecureRand256());
+ cache->SetBestBlock(m_rng.rand256());
erase ? cache->Flush() : cache->Sync();
}
};
- Txid txid = Txid::FromUint256(InsecureRand256());
+ Txid txid = Txid::FromUint256(m_rng.rand256());
COutPoint outp = COutPoint(txid, 0);
Coin coin = MakeCoin();
// Ensure the coins views haven't seen this coin before.
@@ -1017,7 +1032,7 @@ void TestFlushBehavior(
// --- Bonus check: ensure that a coin added to the base view via one cache
// can be spent by another cache which has never seen it.
//
- txid = Txid::FromUint256(InsecureRand256());
+ txid = Txid::FromUint256(m_rng.rand256());
outp = COutPoint(txid, 0);
coin = MakeCoin();
BOOST_CHECK(!base.HaveCoin(outp));
@@ -1040,7 +1055,7 @@ void TestFlushBehavior(
// --- Bonus check 2: ensure that a FRESH, spent coin is deleted by Sync()
//
- txid = Txid::FromUint256(InsecureRand256());
+ txid = Txid::FromUint256(m_rng.rand256());
outp = COutPoint(txid, 0);
coin = MakeCoin();
CAmount coin_val = coin.out.nValue;
@@ -1069,8 +1084,9 @@ void TestFlushBehavior(
BOOST_CHECK(!all_caches[0]->HaveCoinInCache(outp));
BOOST_CHECK(!base.HaveCoin(outp));
}
+}; // struct FlushTest
-BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
+BOOST_FIXTURE_TEST_CASE(ccoins_flush_behavior, FlushTest)
{
// Create two in-memory caches atop a leveldb view.
CCoinsViewDB base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}};