From cf1c26a3a23edfa3f24695652aa3ad46d1b391b7 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Fri, 18 Apr 2025 18:12:46 -0400 Subject: [PATCH] test: Add unit test coverage for Init and Shutdown code Currently this code is not called in unit tests. Calling should make it possible to write tests for things like IPC exceptions being thrown during shutdown. --- src/common/args.cpp | 8 ++++++ src/common/args.h | 6 +---- src/netbase.h | 31 ++++++++++++++------- src/rpc/server.cpp | 6 +++++ src/rpc/server.h | 1 + src/test/CMakeLists.txt | 1 + src/test/net_tests.cpp | 1 + src/test/node_init_tests.cpp | 49 ++++++++++++++++++++++++++++++++++ src/test/util/setup_common.cpp | 3 +++ 9 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 src/test/node_init_tests.cpp diff --git a/src/common/args.cpp b/src/common/args.cpp index 1e3f6d1b88d..3679d3d698e 100644 --- a/src/common/args.cpp +++ b/src/common/args.cpp @@ -589,6 +589,14 @@ void ArgsManager::AddHiddenArgs(const std::vector& names) } } +void ArgsManager::ClearArgs() +{ + LOCK(cs_args); + m_settings = {}; + m_available_args.clear(); + m_network_only_args.clear(); +} + void ArgsManager::CheckMultipleCLIArgs() const { LOCK(cs_args); diff --git a/src/common/args.h b/src/common/args.h index 8d9daf5f65d..69a04a048a9 100644 --- a/src/common/args.h +++ b/src/common/args.h @@ -359,11 +359,7 @@ protected: /** * Clear available arguments */ - void ClearArgs() { - LOCK(cs_args); - m_available_args.clear(); - m_network_only_args.clear(); - } + void ClearArgs(); /** * Check CLI command args diff --git a/src/netbase.h b/src/netbase.h index 3ac23050115..de9b35bc761 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -121,6 +121,13 @@ public: m_reachable.clear(); } + void Reset() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) + { + AssertLockNotHeld(m_mutex); + LOCK(m_mutex); + m_reachable = DefaultNets(); + } + [[nodiscard]] bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) { AssertLockNotHeld(m_mutex); @@ -142,17 +149,21 @@ public: } private: - mutable Mutex m_mutex; - - std::unordered_set m_reachable GUARDED_BY(m_mutex){ - NET_UNROUTABLE, - NET_IPV4, - NET_IPV6, - NET_ONION, - NET_I2P, - NET_CJDNS, - NET_INTERNAL + static std::unordered_set DefaultNets() + { + return { + NET_UNROUTABLE, + NET_IPV4, + NET_IPV6, + NET_ONION, + NET_I2P, + NET_CJDNS, + NET_INTERNAL + }; }; + + mutable Mutex m_mutex; + std::unordered_set m_reachable GUARDED_BY(m_mutex){DefaultNets()}; }; extern ReachableNets g_reachable_nets; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 34f19df2564..fae7fe3a2d3 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -323,6 +323,12 @@ void SetRPCWarmupStatus(const std::string& newStatus) rpcWarmupStatus = newStatus; } +void SetRPCWarmupStarting() +{ + LOCK(g_rpc_warmup_mutex); + fRPCInWarmup = true; +} + void SetRPCWarmupFinished() { LOCK(g_rpc_warmup_mutex); diff --git a/src/rpc/server.h b/src/rpc/server.h index 5a22279a58e..55ec36d9c7a 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -30,6 +30,7 @@ void RpcInterruptionPoint(); */ void SetRPCWarmupStatus(const std::string& newStatus); /* Mark warmup as done. RPC calls will be processed from now on. */ +void SetRPCWarmupStarting(); void SetRPCWarmupFinished(); /* returns the current warmup state. */ diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 48c2eb5c32e..b850c799ca4 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -63,6 +63,7 @@ add_executable(test_bitcoin net_peer_eviction_tests.cpp net_tests.cpp netbase_tests.cpp + node_init_tests.cpp node_warnings_tests.cpp orphanage_tests.cpp pcp_tests.cpp diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 0036d94c2fa..5089e1acc1b 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -702,6 +702,7 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port) BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network) { + g_reachable_nets.Reset(); BOOST_CHECK(g_reachable_nets.Contains(NET_IPV4)); BOOST_CHECK(g_reachable_nets.Contains(NET_IPV6)); BOOST_CHECK(g_reachable_nets.Contains(NET_ONION)); diff --git a/src/test/node_init_tests.cpp b/src/test/node_init_tests.cpp new file mode 100644 index 00000000000..ed676e3c05a --- /dev/null +++ b/src/test/node_init_tests.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2025 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include + +#include +#include + +using node::NodeContext; + +BOOST_FIXTURE_TEST_SUITE(node_init_tests, BasicTestingSetup) + +//! Custom implementation of interfaces::Init for testing. +class TestInit : public interfaces::Init +{ +public: + TestInit(NodeContext& node) : m_node(node) + { + InitContext(m_node); + m_node.init = this; + } + std::unique_ptr makeChain() override { return interfaces::MakeChain(m_node); } + std::unique_ptr makeWalletLoader(interfaces::Chain& chain) override + { + return MakeWalletLoader(chain, *Assert(m_node.args)); + } + NodeContext& m_node; +}; + +BOOST_AUTO_TEST_CASE(init_test) +{ + // Reset logging, config file path, rpc state, reachable nets to avoid errors in AppInitMain + LogInstance().DisconnectTestLogger(); + m_node.args->SetConfigFilePath({}); + SetRPCWarmupStarting(); + g_reachable_nets.Reset(); + + // Run through initialization and shutdown code. + TestInit init{m_node}; + BOOST_CHECK(AppInitInterfaces(m_node)); + BOOST_CHECK(AppInitMain(m_node)); + Interrupt(m_node); + Shutdown(m_node); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 82bbc4adcba..ec88cda3e0f 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -214,7 +214,10 @@ BasicTestingSetup::~BasicTestingSetup() } else { fs::remove_all(m_path_root); } + // Clear all arguments except for -datadir, which GUI tests currently rely + // on to be set even after the testing setup is destroyed. gArgs.ClearArgs(); + gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root)); } ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)