0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

test: refactor: Pass rng parameters to test functions

Add FastRandomContext parameter to the utility function
AddTestCoin(), and a few local test functions and classes.
This commit is contained in:
Ryan Ofsky 2024-08-14 08:46:20 -04:00 committed by MarcoFalke
parent fa19af555d
commit 68f77dd21e
12 changed files with 58 additions and 40 deletions

View file

@ -35,10 +35,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);
@ -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<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.

View file

@ -309,7 +309,7 @@ void test_cache_generations()
// immediately and never uses the other half.
struct block_activity {
std::vector<uint256> reads;
block_activity(uint32_t n_insert, Cache& c) : reads()
block_activity(uint32_t n_insert, FastRandomContext& rng, Cache& c)
{
std::vector<uint256> 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) {

View file

@ -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);

View file

@ -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<unsigned char> 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));

View file

@ -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

View file

@ -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()));

View file

@ -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();

View file

@ -13,10 +13,10 @@
#include <stdint.h>
#include <utility>
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);

View file

@ -8,12 +8,13 @@
#include <primitives/transaction.h>
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

View file

@ -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.

View file

@ -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);

View file

@ -67,6 +67,7 @@ public:
class VersionBitsTester
{
FastRandomContext& m_rng;
// A fake blockchain
std::vector<CBlockIndex*> 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;