Merge pull request #5073 from kittywhiskers/20323

backport: merge bitcoin#20323 (Create or use existing properly initialized NodeContexts)
This commit is contained in:
PastaPastaPasta 2022-11-07 11:37:10 -06:00 committed by GitHub
commit d72a31f87c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 74 deletions

View File

@ -36,41 +36,41 @@ void RPCNestedTests::rpcNestedTests()
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
TestingSetup test;
m_node.setContext(&test.m_node);
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
std::string result;
std::string result2;
std::string filtered;
interfaces::Node* node = &m_node;
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
QVERIFY(result=="main");
QVERIFY(filtered == "getblockchaininfo()[chain]");
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getblock(getbestblockhash())[hash], true)");
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getblock(getbestblockhash())[hash], true)");
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo");
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo");
QVERIFY(result.substr(0,1) == "{");
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()");
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()");
QVERIFY(result.substr(0,1) == "{");
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
QVERIFY(result.substr(0,1) == "{");
(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
QVERIFY(result == "null");
(RPCConsole::RPCExecuteCommandLine(*node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
(RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
(RPCConsole::RPCExecuteCommandLine(m_node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
(RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
QVERIFY(result == result2);
(RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
(RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
QVERIFY(result == result2);
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
QVERIFY(result == "e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7");
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
@ -95,35 +95,35 @@ void RPCNestedTests::rpcNestedTests()
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey(abc), walletpassphrase(def))", false, &filtered);
QVERIFY(filtered == "help(importprivkey(…), walletpassphrase(…))");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
QVERIFY(result == "[]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest ''");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest ''");
QVERIFY(result == "[\"\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest \"\"");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest \"\"");
QVERIFY(result == "[\"\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest '' abc");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest '' abc");
QVERIFY(result == "[\"\",\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc '' abc");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc '' abc");
QVERIFY(result == "[\"abc\",\"\",\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc abc");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc abc");
QVERIFY(result == "[\"abc\",\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc\t\tabc");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc\t\tabc");
QVERIFY(result == "[\"abc\",\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc )");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc )");
QVERIFY(result == "[\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc )");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc )");
QVERIFY(result == "[\"abc\"]");
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc , cba )");
RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc , cba )");
QVERIFY(result == "[\"abc\",\"cba\"]");
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()()()")); //tolerate non command brackts
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()()()")); //tolerate non command brackts
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
}

View File

@ -153,49 +153,22 @@ BasicTestingSetup::~BasicTestingSetup()
ECC_Stop();
}
TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
: BasicTestingSetup(chainName, extra_args)
{
const CChainParams& chainparams = Params();
// 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);
m_node.scheduler = std::make_unique<CScheduler>();
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
m_node.scheduler = std::make_unique<CScheduler>();
threadGroup.create_thread([&] { TraceThread("scheduler", [&] { m_node.scheduler->serviceQueue(); }); });
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
m_node.chainman = &::g_chainman;
m_node.chainman->InitializeChainstate(llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor);
::ChainstateActive().InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
assert(!::ChainstateActive().CanFlushToDisk());
::ChainstateActive().InitCoinsCache(1 << 23);
assert(::ChainstateActive().CanFlushToDisk());
if (!LoadGenesisBlock(chainparams)) {
throw std::runtime_error("LoadGenesisBlock failed.");
}
m_node.mempool = &::mempool;
m_node.mempool->setSanityCheck(1.0);
m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
m_node.peer_logic = std::make_unique<PeerLogicValidation>(
m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool,
llmq::quorumBlockProcessor, llmq::quorumDKGSessionManager, llmq::quorumManager,
llmq::quorumSigSharesManager, llmq::quorumSigningManager, llmq::chainLocksHandler,
llmq::quorumInstantSendManager, false
);
{
CConnman::Options options;
options.m_msgproc = m_node.peer_logic.get();
m_node.connman->Init(options);
}
::sporkManager = std::make_unique<CSporkManager>();
::governance = std::make_unique<CGovernanceManager>();
@ -208,18 +181,13 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
deterministicMNManager.reset(new CDeterministicMNManager(*evoDb, *m_node.connman));
llmq::InitLLMQSystem(*evoDb, *m_node.mempool, *m_node.connman, *sporkManager, true);
CValidationState state;
if (!ActivateBestChain(state, chainparams)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
}
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
constexpr int script_check_threads = 2;
StartScriptCheckWorkerThreads(script_check_threads);
g_parallel_script_checks = true;
}
TestingSetup::~TestingSetup()
ChainTestingSetup::~ChainTestingSetup()
{
m_node.scheduler->stop();
deterministicMNManager.reset();
@ -249,6 +217,43 @@ TestingSetup::~TestingSetup()
pblocktree.reset();
}
TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
: ChainTestingSetup(chainName, extra_args)
{
const CChainParams& chainparams = Params();
// 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);
m_node.chainman->InitializeChainstate(llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor);
::ChainstateActive().InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
assert(!::ChainstateActive().CanFlushToDisk());
::ChainstateActive().InitCoinsCache(1 << 23);
assert(::ChainstateActive().CanFlushToDisk());
if (!LoadGenesisBlock(chainparams)) {
throw std::runtime_error("LoadGenesisBlock failed.");
}
m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.peer_logic = std::make_unique<PeerLogicValidation>(
m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool,
llmq::quorumBlockProcessor, llmq::quorumDKGSessionManager, llmq::quorumManager,
llmq::quorumSigSharesManager, llmq::quorumSigningManager, llmq::chainLocksHandler,
llmq::quorumInstantSendManager, false
);
{
CConnman::Options options;
options.m_msgproc = m_node.peer_logic.get();
m_node.connman->Init(options);
}
CValidationState state;
if (!ActivateBestChain(state, chainparams)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
}
}
TestChainSetup::TestChainSetup(int blockCount)
{
// Make sure CreateAndProcessBlock() support building <deployment_name> blocks before activating it in these tests.

View File

@ -84,14 +84,21 @@ private:
const fs::path m_path_root;
};
/** Testing setup that configures a complete environment.
* Included are coins database, script check threads setup.
/** Testing setup that performs all steps up until right before
* ChainstateManager gets initialized. Meant for testing ChainstateManager
* initialization behaviour.
*/
struct TestingSetup : public BasicTestingSetup {
struct ChainTestingSetup : public BasicTestingSetup {
boost::thread_group threadGroup;
explicit ChainTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
~ChainTestingSetup();
};
/** Testing setup that configures a complete environment.
*/
struct TestingSetup : public ChainTestingSetup {
explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
~TestingSetup();
};
/** Identical to TestingSetup, but chain set to regtest */

View File

@ -19,14 +19,14 @@
#include <boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
//! Basic tests for ChainstateManager.
//!
//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager)
{
ChainstateManager manager;
ChainstateManager& manager = *m_node.chainman;
std::vector<CChainState*> chainstates;
const CChainParams& chainparams = Params();
@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
//! Test rebalancing the caches associated with each chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
ChainstateManager manager;
ChainstateManager& manager = *m_node.chainman;
size_t max_cache = 10000;
manager.m_total_coinsdb_cache = max_cache;
manager.m_total_coinstip_cache = max_cache;
@ -124,6 +124,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c1.InitCoinsCache(1 << 23);
BOOST_REQUIRE(c1.LoadGenesisBlock(Params()));
c1.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}
@ -141,6 +142,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c2.InitCoinsCache(1 << 23);
BOOST_REQUIRE(c2.LoadGenesisBlock(Params()));
c2.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}