mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-02 17:24:58 +02:00
Merge bitcoin/bitcoin#32113: fuzz: enable running fuzz test cases in Debug mode
3669ecd4ccdoc: Document fuzz build options (Anthony Towns)c1d01f59acfuzz: enable running fuzz test cases in Debug mode (Anthony Towns) Pull request description: When building with BUILD_FOR_FUZZING=OFF BUILD_FUZZ_BINARY=ON CMAKE_BUILD_TYPE=Debug allow the fuzz binary to execute given test cases (without actual fuzzing) to make it easier to reproduce fuzz test failures in a more normal debug build. In Debug builds, deterministic fuzz behaviour is controlled via a runtime variable, which is normally false, but set to true automatically in the fuzz binary, unless the FUZZ_NONDETERMINISM environment variable is set. ACKs for top commit: maflcko: re-ACK3669ecd4cc🏉 marcofleon: re ACK3669ecd4ccryanofsky: Code review ACK3669ecd4ccwith just variable renamed and documentation added since last review Tree-SHA512: 5da5736462f98437d0aa1bd01aeacb9d46a9cc446a748080291067f7a27854c89f560f3a6481b760b9a0ea15a8d3ad90cd329ee2a008e5e347a101ed2516449e
This commit is contained in:
@@ -149,10 +149,18 @@ static void initialize()
|
||||
std::cerr << "No fuzz target compiled for " << g_fuzz_target << "." << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
if constexpr (!G_FUZZING) {
|
||||
std::cerr << "Must compile with -DBUILD_FOR_FUZZING=ON to execute a fuzz target." << std::endl;
|
||||
if constexpr (!G_FUZZING_BUILD && !G_ABORT_ON_FAILED_ASSUME) {
|
||||
std::cerr << "Must compile with -DBUILD_FOR_FUZZING=ON or in Debug mode to execute a fuzz target." << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!EnableFuzzDeterminism()) {
|
||||
if (std::getenv("FUZZ_NONDETERMINISM")) {
|
||||
std::cerr << "Warning: FUZZ_NONDETERMINISM env var set, results may be inconsistent with fuzz build" << std::endl;
|
||||
} else {
|
||||
g_enable_dynamic_fuzz_determinism = true;
|
||||
assert(EnableFuzzDeterminism());
|
||||
}
|
||||
}
|
||||
Assert(!g_test_one_input);
|
||||
g_test_one_input = &it->second.test_one_input;
|
||||
it->second.opts.init();
|
||||
|
||||
@@ -25,7 +25,7 @@ void SeedRandomStateForTest(SeedRand seedtype)
|
||||
// no longer truly random. It should be enough to get the seed once for the
|
||||
// process.
|
||||
static const auto g_ctx_seed = []() -> std::optional<uint256> {
|
||||
if constexpr (G_FUZZING) return {};
|
||||
if (EnableFuzzDeterminism()) return {};
|
||||
// If RANDOM_CTX_SEED is set, use that as seed.
|
||||
if (const char* num{std::getenv(RANDOM_CTX_SEED)}) {
|
||||
if (auto num_parsed{uint256::FromUserHex(num)}) {
|
||||
@@ -40,7 +40,7 @@ void SeedRandomStateForTest(SeedRand seedtype)
|
||||
}();
|
||||
|
||||
g_seeded_g_prng_zero = seedtype == SeedRand::ZEROS;
|
||||
if constexpr (G_FUZZING) {
|
||||
if (EnableFuzzDeterminism()) {
|
||||
Assert(g_seeded_g_prng_zero); // Only SeedRandomStateForTest(SeedRand::ZEROS) is allowed in fuzz tests
|
||||
Assert(!g_used_g_prng); // The global PRNG must not have been used before SeedRandomStateForTest(SeedRand::ZEROS)
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ static void ExitFailure(std::string_view str_err)
|
||||
BasicTestingSetup::BasicTestingSetup(const ChainType chainType, TestOpts opts)
|
||||
: m_args{}
|
||||
{
|
||||
if constexpr (!G_FUZZING) {
|
||||
if (!EnableFuzzDeterminism()) {
|
||||
SeedRandomForTest(SeedRand::FIXED_SEED);
|
||||
}
|
||||
m_node.shutdown_signal = &m_interrupt;
|
||||
@@ -203,7 +203,7 @@ BasicTestingSetup::~BasicTestingSetup()
|
||||
{
|
||||
m_node.ecc_context.reset();
|
||||
m_node.kernel.reset();
|
||||
if constexpr (!G_FUZZING) {
|
||||
if (!EnableFuzzDeterminism()) {
|
||||
SetMockTime(0s); // Reset mocktime for following tests
|
||||
}
|
||||
LogInstance().DisconnectTestLogger();
|
||||
@@ -229,8 +229,9 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)
|
||||
m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); });
|
||||
m_node.validation_signals =
|
||||
// Use synchronous task runner while fuzzing to avoid non-determinism
|
||||
G_FUZZING ? std::make_unique<ValidationSignals>(std::make_unique<util::ImmediateTaskRunner>()) :
|
||||
std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(*m_node.scheduler));
|
||||
EnableFuzzDeterminism() ?
|
||||
std::make_unique<ValidationSignals>(std::make_unique<util::ImmediateTaskRunner>()) :
|
||||
std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(*m_node.scheduler));
|
||||
{
|
||||
// Ensure deterministic coverage by waiting for m_service_thread to be running
|
||||
std::promise<void> promise;
|
||||
@@ -255,7 +256,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)
|
||||
.notifications = *m_node.notifications,
|
||||
.signals = m_node.validation_signals.get(),
|
||||
// Use no worker threads while fuzzing to avoid non-determinism
|
||||
.worker_threads_num = G_FUZZING ? 0 : 2,
|
||||
.worker_threads_num = EnableFuzzDeterminism() ? 0 : 2,
|
||||
};
|
||||
if (opts.min_validation_cache) {
|
||||
chainman_opts.script_execution_cache_bytes = 0;
|
||||
|
||||
Reference in New Issue
Block a user