Skip to content

Commit 6eb09fd

Browse files
committed
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.
1 parent 9a9fb19 commit 6eb09fd

File tree

10 files changed

+107
-15
lines changed

10 files changed

+107
-15
lines changed

src/common/args.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,14 @@ void ArgsManager::AddHiddenArgs(const std::vector<std::string>& names)
589589
}
590590
}
591591

592+
void ArgsManager::ClearArgs()
593+
{
594+
LOCK(cs_args);
595+
m_settings = {};
596+
m_available_args.clear();
597+
m_network_only_args.clear();
598+
}
599+
592600
void ArgsManager::CheckMultipleCLIArgs() const
593601
{
594602
LOCK(cs_args);

src/common/args.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,7 @@ class ArgsManager
359359
/**
360360
* Clear available arguments
361361
*/
362-
void ClearArgs() {
363-
LOCK(cs_args);
364-
m_available_args.clear();
365-
m_network_only_args.clear();
366-
}
362+
void ClearArgs();
367363

368364
/**
369365
* Check CLI command args

src/net.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ std::optional<CService> GetLocalAddrForPeer(CNode& node)
266266
return std::nullopt;
267267
}
268268

269+
void ClearLocal()
270+
{
271+
LOCK(g_maplocalhost_mutex);
272+
return mapLocalHost.clear();
273+
}
274+
269275
// learn a new local address
270276
bool AddLocal(const CService& addr_, int nScore)
271277
{

src/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ enum
158158
/** Returns a local address that we should advertise to this peer. */
159159
std::optional<CService> GetLocalAddrForPeer(CNode& node);
160160

161+
void ClearLocal();
161162
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
162163
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
163164
void RemoveLocal(const CService& addr);

src/netbase.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ class ReachableNets {
121121
m_reachable.clear();
122122
}
123123

124+
void Reset() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
125+
{
126+
AssertLockNotHeld(m_mutex);
127+
LOCK(m_mutex);
128+
m_reachable = DefaultNets();
129+
}
130+
124131
[[nodiscard]] bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
125132
{
126133
AssertLockNotHeld(m_mutex);
@@ -142,17 +149,21 @@ class ReachableNets {
142149
}
143150

144151
private:
145-
mutable Mutex m_mutex;
146-
147-
std::unordered_set<Network> m_reachable GUARDED_BY(m_mutex){
148-
NET_UNROUTABLE,
149-
NET_IPV4,
150-
NET_IPV6,
151-
NET_ONION,
152-
NET_I2P,
153-
NET_CJDNS,
154-
NET_INTERNAL
152+
static std::unordered_set<Network> DefaultNets()
153+
{
154+
return {
155+
NET_UNROUTABLE,
156+
NET_IPV4,
157+
NET_IPV6,
158+
NET_ONION,
159+
NET_I2P,
160+
NET_CJDNS,
161+
NET_INTERNAL
162+
};
155163
};
164+
165+
mutable Mutex m_mutex;
166+
std::unordered_set<Network> m_reachable GUARDED_BY(m_mutex){DefaultNets()};
156167
};
157168

158169
extern ReachableNets g_reachable_nets;

src/rpc/server.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,12 @@ void SetRPCWarmupStatus(const std::string& newStatus)
327327
rpcWarmupStatus = newStatus;
328328
}
329329

330+
void SetRPCWarmupStarting()
331+
{
332+
LOCK(g_rpc_warmup_mutex);
333+
fRPCInWarmup = true;
334+
}
335+
330336
void SetRPCWarmupFinished()
331337
{
332338
LOCK(g_rpc_warmup_mutex);

src/rpc/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ void RpcInterruptionPoint();
2929
* immediately with RPC_IN_WARMUP.
3030
*/
3131
void SetRPCWarmupStatus(const std::string& newStatus);
32+
void SetRPCWarmupStarting();
3233
/* Mark warmup as done. RPC calls will be processed from now on. */
3334
void SetRPCWarmupFinished();
3435

src/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ add_executable(test_bitcoin
6464
net_peer_eviction_tests.cpp
6565
net_tests.cpp
6666
netbase_tests.cpp
67+
node_init_tests.cpp
6768
node_warnings_tests.cpp
6869
orphanage_tests.cpp
6970
pcp_tests.cpp

src/test/node_init_tests.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2025 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <init.h>
6+
#include <interfaces/init.h>
7+
#include <rpc/server.h>
8+
9+
#include <boost/test/unit_test.hpp>
10+
#include <test/util/setup_common.h>
11+
12+
using node::NodeContext;
13+
14+
BOOST_FIXTURE_TEST_SUITE(node_init_tests, BasicTestingSetup)
15+
16+
//! Custom implementation of interfaces::Init for testing.
17+
class TestInit : public interfaces::Init
18+
{
19+
public:
20+
TestInit(NodeContext& node) : m_node(node)
21+
{
22+
InitContext(m_node);
23+
m_node.init = this;
24+
}
25+
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
26+
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
27+
{
28+
return MakeWalletLoader(chain, *Assert(m_node.args));
29+
}
30+
NodeContext& m_node;
31+
};
32+
33+
BOOST_AUTO_TEST_CASE(init_test)
34+
{
35+
// Clear state set by BasicTestingSetup that AppInitMain assumes is unset.
36+
LogInstance().DisconnectTestLogger();
37+
m_node.args->SetConfigFilePath({});
38+
39+
// Prevent the test from trying to listen on ports 8332 and 8333.
40+
m_node.args->ForceSetArg("-server", "0");
41+
m_node.args->ForceSetArg("-listen", "0");
42+
43+
// Run through initialization and shutdown code.
44+
TestInit init{m_node};
45+
BOOST_CHECK(AppInitInterfaces(m_node));
46+
BOOST_CHECK(AppInitMain(m_node));
47+
Interrupt(m_node);
48+
Shutdown(m_node);
49+
}
50+
51+
BOOST_AUTO_TEST_SUITE_END()

src/test/util/setup_common.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ BasicTestingSetup::BasicTestingSetup(const ChainType chainType, TestOpts opts)
115115
if (!EnableFuzzDeterminism()) {
116116
SeedRandomForTest(SeedRand::FIXED_SEED);
117117
}
118+
119+
// Reset globals
120+
fDiscover = true;
121+
fListen = true;
122+
SetRPCWarmupStarting();
123+
g_reachable_nets.Reset();
124+
ClearLocal();
125+
118126
m_node.shutdown_signal = &m_interrupt;
119127
m_node.shutdown_request = [this]{ return m_interrupt(); };
120128
m_node.args = &gArgs;
@@ -214,7 +222,10 @@ BasicTestingSetup::~BasicTestingSetup()
214222
} else {
215223
fs::remove_all(m_path_root);
216224
}
225+
// Clear all arguments except for -datadir, which GUI tests currently rely
226+
// on to be set even after the testing setup is destroyed.
217227
gArgs.ClearArgs();
228+
gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));
218229
}
219230

220231
ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts)

0 commit comments

Comments
 (0)