From 68f77dd21e4aaf4f09d36d6e5ddd7d260824b94b Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Wed, 14 Aug 2024 08:46:20 -0400 Subject: [PATCH] test: refactor: Pass rng parameters to test functions Add FastRandomContext parameter to the utility function AddTestCoin(), and a few local test functions and classes. --- src/test/coins_tests.cpp | 7 ++++-- src/test/cuckoocache_tests.cpp | 6 ++--- src/test/net_tests.cpp | 28 +++++++++++++----------- src/test/orphanage_tests.cpp | 10 ++++++--- src/test/pmt_tests.cpp | 6 ++++- src/test/prevector_tests.cpp | 8 +++---- src/test/txrequest_tests.cpp | 5 +++-- src/test/util/coins.cpp | 4 ++-- src/test/util/coins.h | 3 ++- src/test/validation_chainstate_tests.cpp | 2 +- src/test/validation_flush_tests.cpp | 12 +++++----- src/test/versionbits_tests.cpp | 7 ++++-- 12 files changed, 58 insertions(+), 40 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index d9fbed11ec..ac52cb9b2b 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -35,10 +35,13 @@ bool operator==(const Coin &a, const Coin &b) { class CCoinsViewTest : public CCoinsView { + FastRandomContext& m_rng; uint256 hashBestBlock_; std::map map_; public: + CCoinsViewTest(FastRandomContext& rng) : m_rng{rng} {} + [[nodiscard]] bool GetCoin(const COutPoint& outpoint, Coin& coin) const override { std::map::const_iterator it = map_.find(outpoint); @@ -283,7 +286,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block) // Run the above simulation for multiple base types. 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}, {}}; @@ -322,7 +325,7 @@ BOOST_FIXTURE_TEST_CASE(updatecoins_simulation_test, UpdateTest) std::map result; // The cache stack. - CCoinsViewTest base; // A CCoinsViewTest at the bottom. + CCoinsViewTest base{m_rng}; // A CCoinsViewTest at the bottom. std::vector> stack; // A stack of CCoinsViewCaches on top. stack.push_back(std::make_unique(&base)); // Start with one cache. diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index c80b06a57a..ac4fe4404e 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -309,7 +309,7 @@ void test_cache_generations() // immediately and never uses the other half. struct block_activity { std::vector reads; - block_activity(uint32_t n_insert, Cache& c) : reads() + block_activity(uint32_t n_insert, FastRandomContext& rng, Cache& c) { std::vector inserts; inserts.resize(n_insert); @@ -317,7 +317,7 @@ void test_cache_generations() for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)inserts[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = InsecureRand32(); + *(ptr++) = rng.rand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); @@ -351,7 +351,7 @@ void test_cache_generations() for (uint32_t i = 0; i < total; ++i) { if (last_few.size() == WINDOW_SIZE) last_few.pop_front(); - last_few.emplace_back(BLOCK_SIZE, set); + last_few.emplace_back(BLOCK_SIZE, m_rng, set); uint32_t count = 0; for (auto& act : last_few) for (uint32_t k = 0; k < POP_AMOUNT; ++k) { diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 46a6a33b34..a0d5743276 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1011,10 +1011,10 @@ BOOST_AUTO_TEST_CASE(advertise_local_address) namespace { -CKey GenerateRandomTestKey() noexcept +CKey GenerateRandomTestKey(FastRandomContext& rng) noexcept { CKey key; - uint256 key_data = InsecureRand256(); + uint256 key_data = rng.rand256(); key.Set(key_data.begin(), key_data.end(), true); return key; } @@ -1029,6 +1029,7 @@ CKey GenerateRandomTestKey() noexcept */ class V2TransportTester { + FastRandomContext& m_rng; V2Transport m_transport; //!< V2Transport being tested BIP324Cipher m_cipher; //!< Cipher to help with the other side bool m_test_initiator; //!< Whether m_transport is the initiator (true) or responder (false) @@ -1042,9 +1043,10 @@ class V2TransportTester public: /** Construct a tester object. test_initiator: whether the tested transport is initiator. */ - explicit V2TransportTester(bool test_initiator) - : m_transport{0, test_initiator}, - m_cipher{GenerateRandomTestKey(), MakeByteSpan(InsecureRand256())}, + explicit V2TransportTester(FastRandomContext& rng, bool test_initiator) + : m_rng{rng}, + m_transport{0, test_initiator}, + m_cipher{GenerateRandomTestKey(m_rng), MakeByteSpan(m_rng.rand256())}, m_test_initiator(test_initiator) {} /** Data type returned by Interact: @@ -1345,7 +1347,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) { // A mostly normal scenario, testing a transport in initiator mode. for (int i = 0; i < 10; ++i) { - V2TransportTester tester(true); + V2TransportTester tester(m_rng, true); auto ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.SendKey(); @@ -1386,7 +1388,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Normal scenario, with a transport in responder node. for (int i = 0; i < 10; ++i) { - V2TransportTester tester(false); + V2TransportTester tester(m_rng, false); tester.SendKey(); tester.SendGarbage(); auto ret = tester.Interact(); @@ -1429,7 +1431,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) bool send_immediately = !initiator || InsecureRandBool(); /** How many decoy packets to send before the first and second real message. */ unsigned num_decoys_1 = InsecureRandRange(1000), num_decoys_2 = InsecureRandRange(1000); - V2TransportTester tester(initiator); + V2TransportTester tester(m_rng, initiator); if (send_immediately) { tester.SendKey(); tester.SendGarbage(garb_len); @@ -1480,7 +1482,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Too long garbage (initiator). { - V2TransportTester tester(true); + V2TransportTester tester(m_rng, true); auto ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.SendKey(); @@ -1493,7 +1495,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Too long garbage (responder). { - V2TransportTester tester(false); + V2TransportTester tester(m_rng, false); tester.SendKey(); tester.SendGarbage(V2Transport::MAX_GARBAGE_LEN + 1); auto ret = tester.Interact(); @@ -1506,7 +1508,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Send garbage that includes the first 15 garbage terminator bytes somewhere. { - V2TransportTester tester(true); + V2TransportTester tester(m_rng, true); auto ret = tester.Interact(); BOOST_REQUIRE(ret && ret->empty()); tester.SendKey(); @@ -1545,7 +1547,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Send correct network's V1 header { - V2TransportTester tester(false); + V2TransportTester tester(m_rng, false); tester.SendV1Version(Params().MessageStart()); auto ret = tester.Interact(); BOOST_CHECK(ret); @@ -1553,7 +1555,7 @@ BOOST_AUTO_TEST_CASE(v2transport_test) // Send wrong network's V1 header { - V2TransportTester tester(false); + V2TransportTester tester(m_rng, false); tester.SendV1Version(CChainParams::Main()->MessageStart()); auto ret = tester.Interact(); BOOST_CHECK(!ret); diff --git a/src/test/orphanage_tests.cpp b/src/test/orphanage_tests.cpp index d2dab94526..63aad8eb4f 100644 --- a/src/test/orphanage_tests.cpp +++ b/src/test/orphanage_tests.cpp @@ -21,6 +21,8 @@ BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup) class TxOrphanageTest : public TxOrphanage { public: + TxOrphanageTest(FastRandomContext& rng) : m_rng{rng} {} + inline size_t CountOrphans() const { return m_orphans.size(); @@ -34,9 +36,11 @@ public: it = m_orphans.begin(); return it->second.tx; } + + FastRandomContext& m_rng; }; -static void MakeNewKeyWithFastRandomContext(CKey& key, FastRandomContext& rand_ctx = g_insecure_rand_ctx) +static void MakeNewKeyWithFastRandomContext(CKey& key, FastRandomContext& rand_ctx) { std::vector keydata; keydata = rand_ctx.randbytes(32); @@ -106,9 +110,9 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) // signature's R and S values have leading zeros. g_insecure_rand_ctx.Reseed(uint256{33}); - TxOrphanageTest orphanage; + TxOrphanageTest orphanage{m_rng}; CKey key; - MakeNewKeyWithFastRandomContext(key); + MakeNewKeyWithFastRandomContext(key, m_rng); FillableSigningProvider keystore; BOOST_CHECK(keystore.AddKey(key)); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 5b7ccc8e7a..a4225e7488 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -17,12 +17,16 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree { public: + CPartialMerkleTreeTester(FastRandomContext& rng) : m_rng{rng} {} + // flip one bit in one of the hashes - this should break the authentication void Damage() { unsigned int n = InsecureRandRange(vHash.size()); int bit = InsecureRandBits(8); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } + + FastRandomContext& m_rng; }; BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) @@ -77,7 +81,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) BOOST_CHECK(ss.size() <= 10 + (258*n+7)/8); // deserialize into a tester copy - CPartialMerkleTreeTester pmt2; + CPartialMerkleTreeTester pmt2{m_rng}; ss >> pmt2; // extract merkle root and matched txids from copy diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 1f6e6c04c2..560bbbb6b2 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -207,16 +207,16 @@ public: BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString()); } - prevector_tester() { - rand_seed = InsecureRand256(); - g_insecure_rand_ctx.Reseed(rand_seed); + prevector_tester(FastRandomContext& rng) { + rand_seed = rng.rand256(); + rng.Reseed(rand_seed); } }; BOOST_AUTO_TEST_CASE(PrevectorTestInt) { for (int j = 0; j < 64; j++) { - prevector_tester<8, int> test; + prevector_tester<8, int> test{m_rng}; for (int i = 0; i < 2048; i++) { if (InsecureRandBits(2) == 0) { test.insert(InsecureRandRange(test.size() + 1), int(InsecureRand32())); diff --git a/src/test/txrequest_tests.cpp b/src/test/txrequest_tests.cpp index f7f54a8459..885495e891 100644 --- a/src/test/txrequest_tests.cpp +++ b/src/test/txrequest_tests.cpp @@ -78,12 +78,13 @@ std::chrono::microseconds TxRequestTest::RandomTime1y() { return std::chrono::mi */ class Scenario { + FastRandomContext& m_rng; Runner& m_runner; std::chrono::microseconds m_now; std::string m_testname; public: - Scenario(Runner& runner, std::chrono::microseconds starttime) : m_runner(runner), m_now(starttime) {} + Scenario(FastRandomContext& rng, Runner& runner, std::chrono::microseconds starttime) : m_rng(rng), m_runner(runner), m_now(starttime) {} /** Set a name for the current test, to give more clear error messages. */ void SetTestName(std::string testname) @@ -719,7 +720,7 @@ void TxRequestTest::TestInterleavedScenarios() // Introduce some variation in the start time of each scenario, so they don't all start off // concurrently, but get a more random interleaving. auto scenario_start = starttime + RandomTime8s() + RandomTime8s() + RandomTime8s(); - Scenario scenario(runner, scenario_start); + Scenario scenario(m_rng, runner, scenario_start); for (int j = 0; builders.size() && j < 10; ++j) { builders.back()(scenario); builders.pop_back(); diff --git a/src/test/util/coins.cpp b/src/test/util/coins.cpp index 742dbc04d1..0a52581d0e 100644 --- a/src/test/util/coins.cpp +++ b/src/test/util/coins.cpp @@ -13,10 +13,10 @@ #include #include -COutPoint AddTestCoin(CCoinsViewCache& coins_view) +COutPoint AddTestCoin(FastRandomContext& rng, CCoinsViewCache& coins_view) { Coin new_coin; - COutPoint outpoint{Txid::FromUint256(InsecureRand256()), /*nIn=*/0}; + COutPoint outpoint{Txid::FromUint256(rng.rand256()), /*nIn=*/0}; new_coin.nHeight = 1; new_coin.out.nValue = InsecureRandMoneyAmount(); new_coin.out.scriptPubKey.assign(uint32_t{56}, 1); diff --git a/src/test/util/coins.h b/src/test/util/coins.h index 5e6f4293ae..89a9e7b329 100644 --- a/src/test/util/coins.h +++ b/src/test/util/coins.h @@ -8,12 +8,13 @@ #include class CCoinsViewCache; +class FastRandomContext; /** * Create a Coin with DynamicMemoryUsage of 80 bytes and add it to the given view. * @param[in,out] coins_view The coins view cache to add the new coin to. * @returns the COutPoint of the created coin. */ -COutPoint AddTestCoin(CCoinsViewCache& coins_view); +COutPoint AddTestCoin(FastRandomContext& rng, CCoinsViewCache& coins_view); #endif // BITCOIN_TEST_UTIL_COINS_H diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp index 1c02066047..7cc9193038 100644 --- a/src/test/validation_chainstate_tests.cpp +++ b/src/test/validation_chainstate_tests.cpp @@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches) // Add a coin to the in-memory cache, upsize once, then downsize. { LOCK(::cs_main); - const auto outpoint = AddTestCoin(c1.CoinsTip()); + const auto outpoint = AddTestCoin(m_rng, c1.CoinsTip()); // Set a meaningless bestblock value in the coinsview cache - otherwise we won't // flush during ResizecoinsCaches() and will subsequently hit an assertion. diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp index 7398091215..77b3d3228a 100644 --- a/src/test/validation_flush_tests.cpp +++ b/src/test/validation_flush_tests.cpp @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) // Add a bunch of coins to see that we at least flip over to CRITICAL. for (int i{0}; i < 1000; ++i) { - const COutPoint res = AddTestCoin(view); + const COutPoint res = AddTestCoin(m_rng, view); BOOST_CHECK_EQUAL(view.AccessCoin(res).DynamicMemoryUsage(), COIN_SIZE); } @@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) CoinsCacheSizeState::OK); for (int i{0}; i < COINS_UNTIL_CRITICAL; ++i) { - const COutPoint res = AddTestCoin(view); + const COutPoint res = AddTestCoin(m_rng, view); print_view_mem_usage(view); BOOST_CHECK_EQUAL(view.AccessCoin(res).DynamicMemoryUsage(), COIN_SIZE); @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) // Adding some additional coins will push us over the edge to CRITICAL. for (int i{0}; i < 4; ++i) { - AddTestCoin(view); + AddTestCoin(m_rng, view); print_view_mem_usage(view); if (chainstate.GetCoinsCacheSizeState(MAX_COINS_CACHE_BYTES, /*max_mempool_size_bytes=*/0) == CoinsCacheSizeState::CRITICAL) { @@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) CoinsCacheSizeState::OK); for (int i{0}; i < 3; ++i) { - AddTestCoin(view); + AddTestCoin(m_rng, view); print_view_mem_usage(view); BOOST_CHECK_EQUAL( chainstate.GetCoinsCacheSizeState(MAX_COINS_CACHE_BYTES, /*max_mempool_size_bytes=*/ 1 << 19), @@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) // Adding another coin with the additional mempool room will put us >90% // but not yet critical. - AddTestCoin(view); + AddTestCoin(m_rng, view); print_view_mem_usage(view); // Only perform these checks on 64 bit hosts; I haven't done the math for 32. @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) // Using the default max_* values permits way more coins to be added. for (int i{0}; i < 1000; ++i) { - AddTestCoin(view); + AddTestCoin(m_rng, view); BOOST_CHECK_EQUAL( chainstate.GetCoinsCacheSizeState(), CoinsCacheSizeState::OK); diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 42730d40c4..8bcf6828f9 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -67,6 +67,7 @@ public: class VersionBitsTester { + FastRandomContext& m_rng; // A fake blockchain std::vector vpblock; @@ -85,6 +86,8 @@ class VersionBitsTester int num{1000}; public: + VersionBitsTester(FastRandomContext& rng) : m_rng{rng} {} + VersionBitsTester& Reset() { // Have each group of tests be counted by the 1000s part, starting at 1000 num = num - (num % 1000) + 1000; @@ -190,7 +193,7 @@ BOOST_AUTO_TEST_CASE(versionbits_test) { for (int i = 0; i < 64; i++) { // DEFINED -> STARTED after timeout reached -> FAILED - VersionBitsTester().TestDefined().TestStateSinceHeight(0) + VersionBitsTester(m_rng).TestDefined().TestStateSinceHeight(0) .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0) .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0) .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0) @@ -296,7 +299,7 @@ void check_computeblockversion(VersionBitsCache& versionbitscache, const Consens // In the first chain, test that the bit is set by CBV until it has failed. // In the second chain, test the bit is set by CBV while STARTED and // LOCKED-IN, and then no longer set while ACTIVE. - VersionBitsTester firstChain, secondChain; + VersionBitsTester firstChain{m_rng}, secondChain{m_rng}; int64_t nTime = nStartTime;