diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index 4005701caea6b7..b5204ccbdf35b0 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -22,7 +22,7 @@ static void AssembleBlock(benchmark::Bench& bench) { - const auto test_setup = MakeNoLogFileContext(); + const auto test_setup = MakeNoLogFileContext(); CScriptWitness witness; witness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE); diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 9f22fa36464eb4..af193a00f9500c 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -28,7 +28,7 @@ static void DuplicateInputs(benchmark::Bench& bench) { - const auto testing_setup = MakeNoLogFileContext(); + const auto testing_setup = MakeNoLogFileContext(); const CScript SCRIPT_PUB{CScript(OP_TRUE)}; diff --git a/src/bench/load_external.cpp b/src/bench/load_external.cpp index 8f9399c60d5722..3138da464ecac2 100644 --- a/src/bench/load_external.cpp +++ b/src/bench/load_external.cpp @@ -35,7 +35,7 @@ */ static void LoadExternalBlockFile(benchmark::Bench& bench) { - const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; + const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; // Create a single block as in the blocks files (magic bytes, block size, // block data) as a stream object. diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index 84f873d18394f6..e301a7bc64f248 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -36,7 +36,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po // unique transactions for a more meaningful performance measurement. static void MempoolEviction(benchmark::Bench& bench) { - const auto testing_setup = MakeNoLogFileContext(); + const auto testing_setup = MakeNoLogFileContext(); CMutableTransaction tx1 = CMutableTransaction(); tx1.vin.resize(1); diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp index 67f689e4eaf4bc..78d0779165b10e 100644 --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -98,7 +98,7 @@ static void ComplexMemPool(benchmark::Bench& bench) childTxs = static_cast(bench.complexityN()); } std::vector ordered_coins = CreateOrderedCoins(det_rand, childTxs, /*min_ancestors=*/1); - const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); + const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); CTxMemPool& pool = *testing_setup.get()->m_node.mempool; LOCK2(cs_main, pool.cs); bench.run([&]() NO_THREAD_SAFETY_ANALYSIS { diff --git a/src/bench/readblock.cpp b/src/bench/readblock.cpp index 058d953b4e96dc..3128eaacf05ad3 100644 --- a/src/bench/readblock.cpp +++ b/src/bench/readblock.cpp @@ -30,7 +30,7 @@ static FlatFilePos WriteBlockToDisk(ChainstateManager& chainman) static void ReadBlockFromDiskTest(benchmark::Bench& bench) { - const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; + const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; ChainstateManager& chainman{*testing_setup->m_node.chainman}; CBlock block; @@ -44,7 +44,7 @@ static void ReadBlockFromDiskTest(benchmark::Bench& bench) static void ReadRawBlockFromDiskTest(benchmark::Bench& bench) { - const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; + const auto testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; ChainstateManager& chainman{*testing_setup->m_node.chainman}; std::vector block_data; diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 7e3e2d8e48ab02..fbd7a4721431d9 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -24,7 +24,7 @@ namespace { struct TestBlockAndIndex { - const std::unique_ptr testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; + const std::unique_ptr testing_setup{MakeNoLogFileContext(ChainType::MAIN)}; CBlock block{}; uint256 blockHash{}; CBlockIndex blockindex{}; diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index 6e8757bbd5f89c..0a1f8844410756 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -26,7 +26,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& poo static void RpcMempool(benchmark::Bench& bench) { - const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); + const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); CTxMemPool& pool = *Assert(testing_setup->m_node.mempool); LOCK2(cs_main, pool.cs); diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp index 8d3f7f9673471f..9b14c33c157af0 100644 --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -26,7 +26,7 @@ namespace wallet { static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const bool add_mine) { - const auto test_setup = MakeNoLogFileContext(); + const auto test_setup = MakeNoLogFileContext(); const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE; diff --git a/src/bench/wallet_create_tx.cpp b/src/bench/wallet_create_tx.cpp index 3c4b2f4f83a51d..23e628ee941a73 100644 --- a/src/bench/wallet_create_tx.cpp +++ b/src/bench/wallet_create_tx.cpp @@ -105,7 +105,7 @@ struct PreSelectInputs { static void WalletCreateTx(benchmark::Bench& bench, const OutputType output_type, bool allow_other_inputs, std::optional preset_inputs) { - const auto test_setup = MakeNoLogFileContext(); + const auto test_setup = MakeNoLogFileContext(); // Set clock to genesis block, so the descriptors/keys creation time don't interfere with the blocks scanning process. SetMockTime(test_setup->m_node.chainman->GetParams().GenesisBlock().nTime); @@ -161,7 +161,7 @@ static void WalletCreateTx(benchmark::Bench& bench, const OutputType output_type static void AvailableCoins(benchmark::Bench& bench, const std::vector& output_type) { - const auto test_setup = MakeNoLogFileContext(); + const auto test_setup = MakeNoLogFileContext(); // Set clock to genesis block, so the descriptors/keys creation time don't interfere with the blocks scanning process. SetMockTime(test_setup->m_node.chainman->GetParams().GenesisBlock().nTime); CWallet wallet{test_setup->m_node.chain.get(), "", CreateMockableWalletDatabase()}; diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 3d5cb4a863ad5b..9f2c26351d12e8 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -73,6 +73,7 @@ void EditAddressAndSubmit( void TestAddAddressesToSendBook(interfaces::Node& node) { TestChain100Setup test; + test.setup(); auto wallet_loader = interfaces::MakeWalletLoader(*test.m_node.chain, *Assert(test.m_node.args)); test.m_node.wallet_loader = wallet_loader.get(); node.setContext(&test.m_node); diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 0797d31a71a921..892010b16ba1fb 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -47,6 +47,7 @@ void RPCNestedTests::rpcNestedTests() } TestingSetup test; + test.setup(); m_node.setContext(&test.m_node); if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 172c06f4ea6d9c..0b7672c07631fc 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -45,6 +45,7 @@ int main(int argc, char* argv[]) // All tests must use their own testing setup (if needed). fs::create_directories([] { BasicTestingSetup dummy{ChainType::REGTEST}; + dummy.setup(); return gArgs.GetDataDirNet() / "blocks"; }()); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 98dfe12f084ec2..f8a1dbb9280530 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -449,6 +449,7 @@ void TestGUI(interfaces::Node& node) { // Set up wallet and chain with 105 blocks (5 mature blocks for spending). TestChain100Setup test; + test.setup(); for (int i = 0; i < 5; ++i) { test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); } diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index beefc9d82edbe7..6d8fdfe995346c 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -24,7 +24,7 @@ const TestingSetup* g_setup; void initialize_connman() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp index 6460261f0f5e33..a25d78e20ed855 100644 --- a/src/test/fuzz/load_external_block_file.cpp +++ b/src/test/fuzz/load_external_block_file.cpp @@ -20,7 +20,7 @@ const TestingSetup* g_setup; void initialize_load_external_block_file() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/test/fuzz/mini_miner.cpp b/src/test/fuzz/mini_miner.cpp index 51de4d0166df6e..09115c219a7c36 100644 --- a/src/test/fuzz/mini_miner.cpp +++ b/src/test/fuzz/mini_miner.cpp @@ -24,7 +24,7 @@ const TestingSetup* g_setup; std::deque g_available_coins; void initialize_miner() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); for (uint32_t i = 0; i < uint32_t{100}; ++i) { g_available_coins.emplace_back(Txid::FromUint256(uint256::ZERO), i); diff --git a/src/test/fuzz/p2p_handshake.cpp b/src/test/fuzz/p2p_handshake.cpp index 6c1ed11d456a25..3954cfdc17be61 100644 --- a/src/test/fuzz/p2p_handshake.cpp +++ b/src/test/fuzz/p2p_handshake.cpp @@ -31,7 +31,7 @@ const TestingSetup* g_setup; void initialize() { - static const auto testing_setup = MakeNoLogFileContext( + static const auto testing_setup = MakeNoLogFileContext( /*chain_type=*/ChainType::REGTEST); g_setup = testing_setup.get(); } diff --git a/src/test/fuzz/p2p_headers_presync.cpp b/src/test/fuzz/p2p_headers_presync.cpp index 2670aa8ee4e1a8..1a59a7588ba388 100644 --- a/src/test/fuzz/p2p_headers_presync.cpp +++ b/src/test/fuzz/p2p_headers_presync.cpp @@ -23,6 +23,12 @@ class HeadersSyncSetup : public TestingSetup public: HeadersSyncSetup(const ChainType chain_type, TestOpts opts) : TestingSetup(chain_type, opts) { + + } + + void setup() + { + TestingSetup::setup(); PeerManager::Options peerman_opts; node::ApplyArgsManOptions(*m_node.args, peerman_opts); peerman_opts.max_headers_result = FUZZ_MAX_HEADERS_RESULTS; diff --git a/src/test/fuzz/package_eval.cpp b/src/test/fuzz/package_eval.cpp index 652c7a7609f4bf..9b0f3085c2d925 100644 --- a/src/test/fuzz/package_eval.cpp +++ b/src/test/fuzz/package_eval.cpp @@ -39,7 +39,7 @@ struct MockedTxPool : public CTxMemPool { void initialize_tx_pool() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { diff --git a/src/test/fuzz/partially_downloaded_block.cpp b/src/test/fuzz/partially_downloaded_block.cpp index 77952cab9e5a58..a46966567592b2 100644 --- a/src/test/fuzz/partially_downloaded_block.cpp +++ b/src/test/fuzz/partially_downloaded_block.cpp @@ -27,7 +27,7 @@ const TestingSetup* g_setup; void initialize_pdb() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 6373eac1c32403..a8398c89a6b526 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -40,7 +40,7 @@ void initialize_process_message() Assert(std::count(ALL_NET_MESSAGE_TYPES.begin(), ALL_NET_MESSAGE_TYPES.end(), LIMIT_TO_MESSAGE_TYPE)); // Unknown message type passed } - static const auto testing_setup = MakeNoLogFileContext( + static const auto testing_setup = MakeNoLogFileContext( /*chain_type=*/ChainType::REGTEST, {.extra_args = {"-txreconciliation"}}); g_setup = testing_setup.get(); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index 62f38967a391df..f0a31f533f2d29 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -30,7 +30,7 @@ const TestingSetup* g_setup; void initialize_process_messages() { - static const auto testing_setup = MakeNoLogFileContext( + static const auto testing_setup = MakeNoLogFileContext( /*chain_type=*/ChainType::REGTEST, {.extra_args = {"-txreconciliation"}}); g_setup = testing_setup.get(); diff --git a/src/test/fuzz/socks5.cpp b/src/test/fuzz/socks5.cpp index 17d17875865ede..7cb24bfaf1d371 100644 --- a/src/test/fuzz/socks5.cpp +++ b/src/test/fuzz/socks5.cpp @@ -22,7 +22,7 @@ decltype(g_socks5_recv_timeout) default_socks5_recv_timeout; void initialize_socks5() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); default_socks5_recv_timeout = g_socks5_recv_timeout; } diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp index 39aa404484e2eb..595187c13eb839 100644 --- a/src/test/fuzz/tx_pool.cpp +++ b/src/test/fuzz/tx_pool.cpp @@ -42,7 +42,7 @@ struct MockedTxPool : public CTxMemPool { void initialize_tx_pool() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp index c70d9ddf1ec028..6ffb80f708c1e3 100644 --- a/src/test/fuzz/validation_load_mempool.cpp +++ b/src/test/fuzz/validation_load_mempool.cpp @@ -32,7 +32,7 @@ const TestingSetup* g_setup; void initialize_validation_load_mempool() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 0dec327a47a64d..47ee1cabf8b5a7 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -100,94 +100,111 @@ static void ExitFailure(std::string_view str_err) exit(EXIT_FAILURE); } +void BasicTestingSetup::inner_setup() +{ + std::cout << "Running setup()" << std::endl; + + std::vector arguments = Cat( + { + "dummy", + "-printtoconsole=0", + "-logsourcelocations", + "-logtimemicros", + "-logthreadnames", + "-loglevel=trace", + "-debug", + "-debugexclude=libevent", + "-debugexclude=leveldb", + }, + m_opts.extra_args); + if (G_TEST_COMMAND_LINE_ARGUMENTS) { + arguments = Cat(arguments, G_TEST_COMMAND_LINE_ARGUMENTS()); + } + + { + SetupServerArgs(*m_node.args); + SetupCommonTestArgs(*m_node.args); + std::string error; + if (!m_node.args->ParseParameters(arguments.size(), arguments.data(), error)) { + m_node.args->ClearArgs(); + throw std::runtime_error{error}; + } + } + + // Use randomly chosen seed for deterministic PRNG, so that (by default) test + // data directories use a random name that doesn't overlap with other tests. + SeedRandomForTest(SeedRand::FIXED_SEED); + + const std::string test_name{G_TEST_GET_FULL_NAME ? G_TEST_GET_FULL_NAME() : ""}; + if (!m_node.args->IsArgSet("-testdatadir")) { + // By default, the data directory has a random name on each test run + const auto rand_str{g_rng_temp_path.rand256().ToString()}; + m_path_root = fs::temp_directory_path() / TEST_DIR_PATH_ELEMENT / test_name / rand_str; + TryCreateDirectories(m_path_root); + } else { + // Custom data directory + m_has_custom_datadir = true; + fs::path root_dir{m_node.args->GetPathArg("-testdatadir")}; + if (root_dir.empty()) ExitFailure("-testdatadir argument is empty, please specify a path"); + + root_dir = fs::absolute(root_dir); + m_path_lock = root_dir / TEST_DIR_PATH_ELEMENT / fs::PathFromString(test_name); + m_path_root = m_path_lock / "datadir"; + + // Try to obtain the lock; if unsuccessful don't disturb the existing test. + TryCreateDirectories(m_path_lock); + if (util::LockDirectory(m_path_lock, ".lock", /*probe_only=*/false) != util::LockResult::Success) { + ExitFailure("Cannot obtain a lock on test data lock directory " + fs::PathToString(m_path_lock) + '\n' + + "The test executable is probably already running."); + } + + // Always start with a fresh data directory; this doesn't delete the .lock file located one level above. + fs::remove_all(m_path_root); + if (!TryCreateDirectories(m_path_root)) ExitFailure("Cannot create test data directory"); + + // Print the test directory name if custom. + std::cout << "Test directory (will not be deleted): " << m_path_root << std::endl; + } + m_args.ForceSetArg("-datadir", fs::PathToString(m_path_root)); + gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root)); + + SelectParams(m_chain_type); + if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN); + InitLogging(*m_node.args); + AppInitParameterInteraction(*m_node.args); + LogInstance().StartLogging(); + m_node.warnings = std::make_unique(); + m_node.kernel = std::make_unique(); + m_node.ecc_context = std::make_unique(); + SetupEnvironment(); + + m_node.chain = interfaces::MakeChain(m_node); + static bool noui_connected = false; + if (!noui_connected) { + noui_connect(); + noui_connected = true; + } +} + +void BasicTestingSetup::setup() +{ + try { + inner_setup(); + } catch (const std::exception& e) { + ExitFailure(strprintf("Error during test context setup. Message: %s", e.what())); + } +} + BasicTestingSetup::BasicTestingSetup(const ChainType chainType, TestOpts opts) - : m_args{} + : m_args{}, m_opts{opts}, m_chain_type{chainType} { + std::cout << "Running constructor()" << std::endl; try { m_node.shutdown_signal = &m_interrupt; m_node.shutdown_request = [this] { return m_interrupt(); }; m_node.args = &gArgs; - std::vector arguments = Cat( - { - "dummy", - "-printtoconsole=0", - "-logsourcelocations", - "-logtimemicros", - "-logthreadnames", - "-loglevel=trace", - "-debug", - "-debugexclude=libevent", - "-debugexclude=leveldb", - }, - opts.extra_args); - if (G_TEST_COMMAND_LINE_ARGUMENTS) { - arguments = Cat(arguments, G_TEST_COMMAND_LINE_ARGUMENTS()); - } util::ThreadRename("test"); gArgs.ClearPathCache(); - { - SetupServerArgs(*m_node.args); - SetupCommonTestArgs(*m_node.args); - std::string error; - if (!m_node.args->ParseParameters(arguments.size(), arguments.data(), error)) { - m_node.args->ClearArgs(); - throw std::runtime_error{error}; - } - } - - // Use randomly chosen seed for deterministic PRNG, so that (by default) test - // data directories use a random name that doesn't overlap with other tests. - SeedRandomForTest(SeedRand::FIXED_SEED); - - const std::string test_name{G_TEST_GET_FULL_NAME ? G_TEST_GET_FULL_NAME() : ""}; - if (!m_node.args->IsArgSet("-testdatadir")) { - // By default, the data directory has a random name on each test run - const auto rand_str{g_rng_temp_path.rand256().ToString()}; - m_path_root = fs::temp_directory_path() / TEST_DIR_PATH_ELEMENT / test_name / rand_str; - TryCreateDirectories(m_path_root); - } else { - // Custom data directory - m_has_custom_datadir = true; - fs::path root_dir{m_node.args->GetPathArg("-testdatadir")}; - if (root_dir.empty()) ExitFailure("-testdatadir argument is empty, please specify a path"); - - root_dir = fs::absolute(root_dir); - m_path_lock = root_dir / TEST_DIR_PATH_ELEMENT / fs::PathFromString(test_name); - m_path_root = m_path_lock / "datadir"; - - // Try to obtain the lock; if unsuccessful don't disturb the existing test. - TryCreateDirectories(m_path_lock); - if (util::LockDirectory(m_path_lock, ".lock", /*probe_only=*/false) != util::LockResult::Success) { - ExitFailure("Cannot obtain a lock on test data lock directory " + fs::PathToString(m_path_lock) + '\n' + - "The test executable is probably already running."); - } - - // Always start with a fresh data directory; this doesn't delete the .lock file located one level above. - fs::remove_all(m_path_root); - if (!TryCreateDirectories(m_path_root)) ExitFailure("Cannot create test data directory"); - - // Print the test directory name if custom. - std::cout << "Test directory (will not be deleted): " << m_path_root << std::endl; - } - m_args.ForceSetArg("-datadir", fs::PathToString(m_path_root)); - gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root)); - - SelectParams(chainType); - if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN); - InitLogging(*m_node.args); - AppInitParameterInteraction(*m_node.args); - LogInstance().StartLogging(); - m_node.warnings = std::make_unique(); - m_node.kernel = std::make_unique(); - m_node.ecc_context = std::make_unique(); - SetupEnvironment(); - - m_node.chain = interfaces::MakeChain(m_node); - static bool noui_connected = false; - if (!noui_connected) { - noui_connect(); - noui_connected = true; - } } catch (const std::exception& e) { ExitFailure(strprintf("Error during context setup, message: %s", e.what())); } @@ -209,14 +226,17 @@ BasicTestingSetup::~BasicTestingSetup() gArgs.ClearArgs(); } -ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) - : BasicTestingSetup(chainType, opts) +void ChainTestingSetup::setup() { + BasicTestingSetup::setup(); + + std::cout << "Running ChainTestingSetup setup()" << std::endl; + const CChainParams& chainparams = Params(); // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. - if (opts.setup_validation_interface) { + if (m_opts.setup_validation_interface) { m_node.scheduler = std::make_unique(); m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); }); m_node.validation_signals = std::make_unique(std::make_unique(*m_node.scheduler)); @@ -231,6 +251,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) m_node.notifications = std::make_unique(Assert(m_node.shutdown_request), m_node.exit_status, *Assert(m_node.warnings)); + auto opts = m_opts; m_make_chainman = [this, &chainparams, opts] { Assert(!m_node.chainman); ChainstateManager::Options chainman_opts{ @@ -241,7 +262,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) .signals = m_node.validation_signals.get(), .worker_threads_num = 2, }; - if (opts.min_validation_cache) { + if (m_opts.min_validation_cache) { chainman_opts.script_execution_cache_bytes = 0; chainman_opts.signature_cache_bytes = 0; } @@ -261,6 +282,11 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) m_make_chainman(); } +ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) + : BasicTestingSetup(chainType, opts) +{ +} + ChainTestingSetup::~ChainTestingSetup() { if (m_node.scheduler) m_node.scheduler->stop(); @@ -302,24 +328,22 @@ void ChainTestingSetup::LoadVerifyActivateChainstate() } } -TestingSetup::TestingSetup( - const ChainType chainType, - TestOpts opts) - : ChainTestingSetup(chainType, opts) +void TestingSetup::setup() { - m_coins_db_in_memory = opts.coins_db_in_memory; - m_block_tree_db_in_memory = opts.block_tree_db_in_memory; + ChainTestingSetup::setup(); + std::cout << "Running TestingSetup setup()" << std::endl; + // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); LoadVerifyActivateChainstate(); - if (!opts.setup_net) return; + if (!m_opts.setup_net) return; m_node.netgroupman = std::make_unique(/*asmap=*/std::vector()); m_node.addrman = std::make_unique(*m_node.netgroupman, - /*deterministic=*/false, + /*deterministic=*/false, m_node.args->GetIntArg("-checkaddrman", 0)); m_node.banman = std::make_unique(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params()); // Deterministic randomness for tests. @@ -338,14 +362,22 @@ TestingSetup::TestingSetup( } } -TestChain100Setup::TestChain100Setup( - const ChainType chain_type, +TestingSetup::TestingSetup( + const ChainType chainType, TestOpts opts) - : TestingSetup{ChainType::REGTEST, opts} + : ChainTestingSetup(chainType, opts) { + m_coins_db_in_memory = opts.coins_db_in_memory; + m_block_tree_db_in_memory = opts.block_tree_db_in_memory; +} + +void TestChain100Setup::inner_setup() +{ + TestingSetup::setup(); + SetMockTime(1598887952); constexpr std::array vchKey = { - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}; + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}; coinbaseKey.Set(vchKey.begin(), vchKey.end(), true); // Generate a 100-block chain: @@ -354,11 +386,27 @@ TestChain100Setup::TestChain100Setup( { LOCK(::cs_main); assert( - m_node.chainman->ActiveChain().Tip()->GetBlockHash().ToString() == - "571d80a9967ae599cec0448b0b0ba1cfb606f584d8069bd7166b86854ba7a191"); + m_node.chainman->ActiveChain().Tip()->GetBlockHash().ToString() == + "571d80a9967ae599cec0448b0b0ba1cfb606f584d8069bd7166b86854ba7a191"); + } +} + +void TestChain100Setup::setup() +{ + try { + inner_setup(); + } catch (const std::exception& e) { + ExitFailure(strprintf("Error during test context setup. Message: %s", e.what())); } } +TestChain100Setup::TestChain100Setup( + const ChainType chain_type, + TestOpts opts) + : TestingSetup{ChainType::REGTEST, opts} +{ +} + void TestChain100Setup::mineBlocks(int num_blocks) { CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index b0f7bdade20cfd..121bcab238bd1b 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -75,6 +75,10 @@ struct BasicTestingSetup { explicit BasicTestingSetup(const ChainType chainType = ChainType::MAIN, TestOpts = {}); ~BasicTestingSetup(); + // Test setup function + void setup(); + void inner_setup(); + fs::path m_path_root; fs::path m_path_lock; bool m_has_custom_datadir{false}; @@ -96,6 +100,8 @@ struct BasicTestingSetup { * @see https://github.com/bitcoin/bitcoin/issues/25055 for additional context. */ ArgsManager m_args; + TestOpts m_opts; + ChainType m_chain_type; }; /** Testing setup that performs all steps up until right before @@ -111,6 +117,8 @@ struct ChainTestingSetup : public BasicTestingSetup { explicit ChainTestingSetup(const ChainType chainType = ChainType::MAIN, TestOpts = {}); ~ChainTestingSetup(); + void setup(); + // Supplies a chainstate, if one is needed void LoadVerifyActivateChainstate(); }; @@ -121,6 +129,7 @@ struct TestingSetup : public ChainTestingSetup { explicit TestingSetup( const ChainType chainType = ChainType::MAIN, TestOpts = {}); + void setup(); }; /** Identical to TestingSetup, but chain set to regtest */ @@ -141,6 +150,9 @@ struct TestChain100Setup : public TestingSetup { const ChainType chain_type = ChainType::REGTEST, TestOpts = {}); + void setup(); + void inner_setup(); + /** * Create a new block with just given transactions, coinbase paying to * scriptPubKey, and try to add it to the current chain. @@ -260,7 +272,9 @@ std::unique_ptr MakeNoLogFileContext(const ChainType chain_type = ChainType:: }, opts.extra_args); - return std::make_unique(chain_type, opts); + auto t = std::make_unique(chain_type, opts); + t->setup(); + return t; } CBlock getBlock13b8a(); diff --git a/src/wallet/test/fuzz/coincontrol.cpp b/src/wallet/test/fuzz/coincontrol.cpp index f1efbc1cb81205..2673e7674ab13e 100644 --- a/src/wallet/test/fuzz/coincontrol.cpp +++ b/src/wallet/test/fuzz/coincontrol.cpp @@ -16,7 +16,7 @@ const TestingSetup* g_setup; void initialize_coincontrol() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/wallet/test/fuzz/crypter.cpp b/src/wallet/test/fuzz/crypter.cpp index 7869f5f39c8c9b..37051f1420225a 100644 --- a/src/wallet/test/fuzz/crypter.cpp +++ b/src/wallet/test/fuzz/crypter.cpp @@ -14,7 +14,7 @@ namespace { const TestingSetup* g_setup; void initialize_crypter() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/wallet/test/fuzz/fees.cpp b/src/wallet/test/fuzz/fees.cpp index c2e785651ad4a0..df2b9d8cf2a2e7 100644 --- a/src/wallet/test/fuzz/fees.cpp +++ b/src/wallet/test/fuzz/fees.cpp @@ -19,7 +19,7 @@ static std::unique_ptr g_wallet_ptr; void initialize_setup() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); const auto& node{g_setup->m_node}; g_wallet_ptr = std::make_unique(node.chain.get(), "", CreateMockableWalletDatabase()); diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp index a7015f6685b273..f9ea7d84d8c1ba 100644 --- a/src/wallet/test/fuzz/notifications.cpp +++ b/src/wallet/test/fuzz/notifications.cpp @@ -49,7 +49,7 @@ const TestingSetup* g_setup; void initialize_setup() { - static const auto testing_setup = MakeNoLogFileContext(); + static const auto testing_setup = MakeNoLogFileContext(); g_setup = testing_setup.get(); } diff --git a/src/wallet/test/fuzz/scriptpubkeyman.cpp b/src/wallet/test/fuzz/scriptpubkeyman.cpp index 091d42f6cf5287..cc19bfa3846f3f 100644 --- a/src/wallet/test/fuzz/scriptpubkeyman.cpp +++ b/src/wallet/test/fuzz/scriptpubkeyman.cpp @@ -43,7 +43,7 @@ MockedDescriptorConverter MOCKED_DESC_CONVERTER; void initialize_spkm() { - static const auto testing_setup{MakeNoLogFileContext()}; + static const auto testing_setup{MakeNoLogFileContext()}; g_setup = testing_setup.get(); SelectParams(ChainType::MAIN); MOCKED_DESC_CONVERTER.Init(); diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp index 09057114a0bd12..8d3789e0b82e77 100644 --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -32,8 +32,8 @@ static void import_descriptor(CWallet& wallet, const std::string& descriptor) BOOST_AUTO_TEST_CASE(psbt_updater_test) { - LOCK(m_wallet.cs_wallet); - m_wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); + LOCK(m_wallet->cs_wallet); + m_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); // Create prevtxs and add to wallet DataStream s_prev_tx1{ @@ -41,19 +41,19 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test) }; CTransactionRef prev_tx1; s_prev_tx1 >> TX_WITH_WITNESS(prev_tx1); - m_wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx1->GetHash()), std::forward_as_tuple(prev_tx1, TxStateInactive{})); + m_wallet->mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx1->GetHash()), std::forward_as_tuple(prev_tx1, TxStateInactive{})); DataStream s_prev_tx2{ "0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000"_hex, }; CTransactionRef prev_tx2; s_prev_tx2 >> TX_WITH_WITNESS(prev_tx2); - m_wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx2->GetHash()), std::forward_as_tuple(prev_tx2, TxStateInactive{})); + m_wallet->mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx2->GetHash()), std::forward_as_tuple(prev_tx2, TxStateInactive{})); // Import descriptors for keys and scripts - import_descriptor(m_wallet, "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/0h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/1h))"); - import_descriptor(m_wallet, "sh(wsh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/2h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/3h)))"); - import_descriptor(m_wallet, "wpkh(xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/*h)"); + import_descriptor(*m_wallet, "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/0h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/1h))"); + import_descriptor(*m_wallet, "sh(wsh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/2h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/3h)))"); + import_descriptor(*m_wallet, "wpkh(xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/*h)"); // Call FillPSBT PartiallySignedTransaction psbtx; @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test) // Fill transaction with our data bool complete = true; - BOOST_REQUIRE(!m_wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, false, true)); + BOOST_REQUIRE(!m_wallet->FillPSBT(psbtx, complete, SIGHASH_ALL, false, true)); // Get the final tx DataStream ssTx{}; @@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test) // Try to sign the mutated input SignatureData sigdata; - BOOST_CHECK(m_wallet.FillPSBT(psbtx, complete, SIGHASH_ALL, true, true)); + BOOST_CHECK(m_wallet->FillPSBT(psbtx, complete, SIGHASH_ALL, true, true)); } BOOST_AUTO_TEST_CASE(parse_hd_keypath) diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 57c538e4ef4c0b..5d3fab04b3db42 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -10,12 +10,18 @@ namespace wallet { WalletTestingSetup::WalletTestingSetup(const ChainType chainType) - : TestingSetup(chainType), - m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args))}, - m_wallet(m_node.chain.get(), "", CreateMockableWalletDatabase()) + : TestingSetup(chainType) { - m_wallet.LoadWallet(); - m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} }); +} + +void WalletTestingSetup::setup() +{ + TestingSetup::setup(); + + m_wallet_loader = interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args)); + m_wallet = std::make_unique(m_node.chain.get(), "", CreateMockableWalletDatabase()); + m_wallet->LoadWallet(); + m_chain_notifications_handler = m_node.chain->handleNotifications({ m_wallet.get(), [](CWallet*) {} }); m_wallet_loader->registerRpcs(); } diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index 4aae02e075a142..a0462c5e3627fd 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -23,8 +23,10 @@ struct WalletTestingSetup : public TestingSetup { explicit WalletTestingSetup(const ChainType chainType = ChainType::MAIN); ~WalletTestingSetup(); + void setup(); + std::unique_ptr m_wallet_loader; - CWallet m_wallet; + std::unique_ptr m_wallet; std::unique_ptr m_chain_notifications_handler; }; } // namespace wallet diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index b5de4b4b3d3f0a..d0e77d72fa86fe 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -423,24 +423,24 @@ static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lock BOOST_AUTO_TEST_CASE(ComputeTimeSmart) { // New transaction should use clock time if lower than block time. - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 100, 120), 100); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 1, 100, 120), 100); // Test that updating existing transaction does not change smart time. - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 1, 200, 220), 100); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 1, 200, 220), 100); // New transaction should use clock time if there's no block time. - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 2, 300, 0), 300); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 2, 300, 0), 300); // New transaction should use block time if lower than clock time. - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 3, 420, 400), 400); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 3, 420, 400), 400); // New transaction should use latest entry time if higher than // min(block time, clock time). - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 4, 500, 390), 400); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 4, 500, 390), 400); // If there are future entries, new transaction should use time of the // newest entry that is no more than 300 seconds ahead of the clock time. - BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, m_wallet, 5, 50, 600), 300); + BOOST_CHECK_EQUAL(AddTx(*m_node.chainman, *m_wallet, 5, 50, 600), 300); } void TestLoadWallet(const std::string& name, DatabaseFormat format, std::function)> f) @@ -547,7 +547,7 @@ BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) { CKey key; CPubKey pubkey; - LegacyScriptPubKeyMan* spk_man = m_wallet.GetOrCreateLegacyScriptPubKeyMan(); + LegacyScriptPubKeyMan* spk_man = m_wallet->GetOrCreateLegacyScriptPubKeyMan(); BOOST_CHECK(!spk_man->HaveWatchOnly()); @@ -581,6 +581,11 @@ class ListCoinsTestingSetup : public TestChain100Setup public: ListCoinsTestingSetup() { + } + + void setup() + { + TestChain100Setup::setup(); CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), coinbaseKey); }