diff options
Diffstat (limited to 'src/test/coins_tests.cpp')
-rw-r--r-- | src/test/coins_tests.cpp | 176 |
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}, {}}; |