Merge #19098: test: Remove duplicate NodeContext hacks

edc316020e test: Remove duplicate NodeContext hacks (Russell Yanofsky)

Pull request description:

  Qt tests currently are currently using two NodeContext structs at the same time, one in interfaces::NodeImpl::m_context, and the other in BasicTestingSetup::m_node, and the tests have hacks transferring state between them.

  Fix this by getting rid of the NodeImpl::m_context struct and making it a pointer. This way a common BitcoinApplication object can be used for all qt tests, but they can still have their own testing setups.

  Non-test code is changing but non-test behavior is still the same as before.

  Motivation for this PR is to be able to remove the "std::move(test.m_node.connman)" and mempool hacks for swapping individual NodeContext members in Qt tests, because followup PR #19099 adds yet another member (wallet_client) that needs to be swapped. After this change, the whole NodeContext struct can be swapped instead of individual members, so the workarounds are less fragile and invasive.

ACKs for top commit:
  MarcoFalke:
    crACK edc316020e 🌮
  promag:
    ACK edc316020e.

Tree-SHA512: c1650e4127f43a4020304ca7c13b5d9122fb5723aacd8fa1cf855d03c6052fcfb7685810aa2a5ef708561015f0022fecaacbad479295104ca45d2c17579466a4
This commit is contained in:
MarcoFalke 2020-08-07 08:05:38 +02:00
commit 4b705b1c98
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
7 changed files with 58 additions and 38 deletions

View file

@ -56,6 +56,7 @@ namespace {
class NodeImpl : public Node class NodeImpl : public Node
{ {
public: public:
NodeImpl(NodeContext* context) { setContext(context); }
void initError(const bilingual_str& message) override { InitError(message); } void initError(const bilingual_str& message) override { InitError(message); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override bool parseParameters(int argc, const char* const argv[], std::string& error) override
{ {
@ -81,13 +82,13 @@ public:
} }
bool appInitMain() override bool appInitMain() override
{ {
m_context.chain = MakeChain(m_context); m_context->chain = MakeChain(*m_context);
return AppInitMain(m_context_ref, m_context); return AppInitMain(m_context_ref, *m_context);
} }
void appShutdown() override void appShutdown() override
{ {
Interrupt(m_context); Interrupt(*m_context);
Shutdown(m_context); Shutdown(*m_context);
} }
void startShutdown() override void startShutdown() override
{ {
@ -108,19 +109,19 @@ public:
StopMapPort(); StopMapPort();
} }
} }
void setupServerArgs() override { return SetupServerArgs(m_context); } void setupServerArgs() override { return SetupServerArgs(*m_context); }
bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); } bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
size_t getNodeCount(CConnman::NumConnections flags) override size_t getNodeCount(CConnman::NumConnections flags) override
{ {
return m_context.connman ? m_context.connman->GetNodeCount(flags) : 0; return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0;
} }
bool getNodesStats(NodesStats& stats) override bool getNodesStats(NodesStats& stats) override
{ {
stats.clear(); stats.clear();
if (m_context.connman) { if (m_context->connman) {
std::vector<CNodeStats> stats_temp; std::vector<CNodeStats> stats_temp;
m_context.connman->GetNodeStats(stats_temp); m_context->connman->GetNodeStats(stats_temp);
stats.reserve(stats_temp.size()); stats.reserve(stats_temp.size());
for (auto& node_stats_temp : stats_temp) { for (auto& node_stats_temp : stats_temp) {
@ -141,46 +142,46 @@ public:
} }
bool getBanned(banmap_t& banmap) override bool getBanned(banmap_t& banmap) override
{ {
if (m_context.banman) { if (m_context->banman) {
m_context.banman->GetBanned(banmap); m_context->banman->GetBanned(banmap);
return true; return true;
} }
return false; return false;
} }
bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override
{ {
if (m_context.banman) { if (m_context->banman) {
m_context.banman->Ban(net_addr, ban_time_offset); m_context->banman->Ban(net_addr, ban_time_offset);
return true; return true;
} }
return false; return false;
} }
bool unban(const CSubNet& ip) override bool unban(const CSubNet& ip) override
{ {
if (m_context.banman) { if (m_context->banman) {
m_context.banman->Unban(ip); m_context->banman->Unban(ip);
return true; return true;
} }
return false; return false;
} }
bool disconnectByAddress(const CNetAddr& net_addr) override bool disconnectByAddress(const CNetAddr& net_addr) override
{ {
if (m_context.connman) { if (m_context->connman) {
return m_context.connman->DisconnectNode(net_addr); return m_context->connman->DisconnectNode(net_addr);
} }
return false; return false;
} }
bool disconnectById(NodeId id) override bool disconnectById(NodeId id) override
{ {
if (m_context.connman) { if (m_context->connman) {
return m_context.connman->DisconnectNode(id); return m_context->connman->DisconnectNode(id);
} }
return false; return false;
} }
int64_t getTotalBytesRecv() override { return m_context.connman ? m_context.connman->GetTotalBytesRecv() : 0; } int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; }
int64_t getTotalBytesSent() override { return m_context.connman ? m_context.connman->GetTotalBytesSent() : 0; } int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; }
size_t getMempoolSize() override { return m_context.mempool ? m_context.mempool->size() : 0; } size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; }
size_t getMempoolDynamicUsage() override { return m_context.mempool ? m_context.mempool->DynamicMemoryUsage() : 0; } size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; }
bool getHeaderTip(int& height, int64_t& block_time) override bool getHeaderTip(int& height, int64_t& block_time) override
{ {
LOCK(::cs_main); LOCK(::cs_main);
@ -223,11 +224,11 @@ public:
bool getImporting() override { return ::fImporting; } bool getImporting() override { return ::fImporting; }
void setNetworkActive(bool active) override void setNetworkActive(bool active) override
{ {
if (m_context.connman) { if (m_context->connman) {
m_context.connman->SetNetworkActive(active); m_context->connman->SetNetworkActive(active);
} }
} }
bool getNetworkActive() override { return m_context.connman && m_context.connman->GetNetworkActive(); } bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
{ {
FeeCalculation fee_calc; FeeCalculation fee_calc;
@ -269,7 +270,7 @@ public:
std::vector<std::unique_ptr<Wallet>> getWallets() override std::vector<std::unique_ptr<Wallet>> getWallets() override
{ {
std::vector<std::unique_ptr<Wallet>> wallets; std::vector<std::unique_ptr<Wallet>> wallets;
for (auto& client : m_context.chain_clients) { for (auto& client : m_context->chain_clients) {
auto client_wallets = client->getWallets(); auto client_wallets = client->getWallets();
std::move(client_wallets.begin(), client_wallets.end(), std::back_inserter(wallets)); std::move(client_wallets.begin(), client_wallets.end(), std::back_inserter(wallets));
} }
@ -277,12 +278,12 @@ public:
} }
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{ {
return MakeWallet(LoadWallet(*m_context.chain, name, error, warnings)); return MakeWallet(LoadWallet(*m_context->chain, name, error, warnings));
} }
std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) override std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) override
{ {
std::shared_ptr<CWallet> wallet; std::shared_ptr<CWallet> wallet;
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet); status = CreateWallet(*m_context->chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
return MakeWallet(wallet); return MakeWallet(wallet);
} }
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
@ -336,13 +337,22 @@ public:
/* verification progress is unused when a header was received */ 0); /* verification progress is unused when a header was received */ 0);
})); }));
} }
NodeContext* context() override { return &m_context; } NodeContext* context() override { return m_context; }
NodeContext m_context; void setContext(NodeContext* context) override
util::Ref m_context_ref{m_context}; {
m_context = context;
if (context) {
m_context_ref.Set(*context);
} else {
m_context_ref.Clear();
}
}
NodeContext* m_context{nullptr};
util::Ref m_context_ref;
}; };
} // namespace } // namespace
std::unique_ptr<Node> MakeNode() { return MakeUnique<NodeImpl>(); } std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<NodeImpl>(context); }
} // namespace interfaces } // namespace interfaces

View file

@ -268,12 +268,14 @@ public:
std::function<void(SynchronizationState, interfaces::BlockTip tip, double verification_progress)>; std::function<void(SynchronizationState, interfaces::BlockTip tip, double verification_progress)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0; virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
//! Return pointer to internal chain interface, useful for testing. //! Get and set internal node context. Useful for testing, but not
//! accessible across processes.
virtual NodeContext* context() { return nullptr; } virtual NodeContext* context() { return nullptr; }
virtual void setContext(NodeContext* context) { }
}; };
//! Return implementation of Node interface. //! Return implementation of Node interface.
std::unique_ptr<Node> MakeNode(); std::unique_ptr<Node> MakeNode(NodeContext* context = nullptr);
//! Block tip (could be a header or not, depends on the subscribed signal). //! Block tip (could be a header or not, depends on the subscribed signal).
struct BlockTip { struct BlockTip {

View file

@ -29,6 +29,7 @@
#include <interfaces/handler.h> #include <interfaces/handler.h>
#include <interfaces/node.h> #include <interfaces/node.h>
#include <node/context.h>
#include <noui.h> #include <noui.h>
#include <uint256.h> #include <uint256.h>
#include <util/system.h> #include <util/system.h>
@ -430,7 +431,8 @@ int GuiMain(int argc, char* argv[])
SetupEnvironment(); SetupEnvironment();
util::ThreadSetInternalName("main"); util::ThreadSetInternalName("main");
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(); NodeContext node_context;
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(&node_context);
// Subscribe to global signals from core // Subscribe to global signals from core
std::unique_ptr<interfaces::Handler> handler_message_box = node->handleMessageBox(noui_ThreadSafeMessageBox); std::unique_ptr<interfaces::Handler> handler_message_box = node->handleMessageBox(noui_ThreadSafeMessageBox);

View file

@ -18,6 +18,7 @@
#include <key.h> #include <key.h>
#include <key_io.h> #include <key_io.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <walletinitinterface.h>
#include <QApplication> #include <QApplication>
#include <QTimer> #include <QTimer>
@ -59,6 +60,7 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook(interfaces::Node& node) void TestAddAddressesToSendBook(interfaces::Node& node)
{ {
TestChain100Setup test; TestChain100Setup test;
node.setContext(&test.m_node);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan(); wallet->SetupLegacyScriptPubKeyMan();
bool firstRun; bool firstRun;

View file

@ -52,7 +52,8 @@ int main(int argc, char* argv[])
BasicTestingSetup dummy{CBaseChainParams::REGTEST}; BasicTestingSetup dummy{CBaseChainParams::REGTEST};
} }
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(); NodeContext node_context;
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(&node_context);
bool fInvalid = false; bool fInvalid = false;

View file

@ -138,8 +138,7 @@ void TestGUI(interfaces::Node& node)
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
} }
node.context()->connman = std::move(test.m_node.connman); node.setContext(&test.m_node);
node.context()->mempool = std::move(test.m_node.mempool);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase()); std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase());
bool firstRun; bool firstRun;
wallet->LoadWallet(firstRun); wallet->LoadWallet(firstRun);

View file

@ -11,6 +11,7 @@
#include <consensus/validation.h> #include <consensus/validation.h>
#include <crypto/sha256.h> #include <crypto/sha256.h>
#include <init.h> #include <init.h>
#include <interfaces/chain.h>
#include <miner.h> #include <miner.h>
#include <net.h> #include <net.h>
#include <net_processing.h> #include <net_processing.h>
@ -32,6 +33,7 @@
#include <util/vector.h> #include <util/vector.h>
#include <validation.h> #include <validation.h>
#include <validationinterface.h> #include <validationinterface.h>
#include <walletinitinterface.h>
#include <functional> #include <functional>
@ -104,6 +106,8 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
SetupNetworking(); SetupNetworking();
InitSignatureCache(); InitSignatureCache();
InitScriptExecutionCache(); InitScriptExecutionCache();
m_node.chain = interfaces::MakeChain(m_node);
g_wallet_init_interface.Construct(m_node);
fCheckBlockIndex = true; fCheckBlockIndex = true;
static bool noui_connected = false; static bool noui_connected = false;
if (!noui_connected) { if (!noui_connected) {