aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/coinstatsindex_tests.cpp61
-rw-r--r--src/test/fs_tests.cpp6
-rw-r--r--src/test/fuzz/netaddress.cpp3
-rw-r--r--src/test/fuzz/script_format.cpp5
-rw-r--r--src/test/getarg_tests.cpp492
-rw-r--r--src/test/miner_tests.cpp32
-rw-r--r--src/test/net_peer_eviction_tests.cpp163
-rw-r--r--src/test/net_tests.cpp191
-rw-r--r--src/test/netbase_tests.cpp20
-rw-r--r--src/test/script_segwit_tests.cpp164
-rw-r--r--src/test/timedata_tests.cpp3
-rw-r--r--src/test/util/setup_common.cpp3
-rw-r--r--src/test/util/validation.cpp6
-rw-r--r--src/test/util/validation.h8
-rw-r--r--src/test/util_tests.cpp49
-rw-r--r--src/test/validation_chainstate_tests.cpp3
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp2
17 files changed, 975 insertions, 236 deletions
diff --git a/src/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp
index 92de4ec7ba..5b73481bc1 100644
--- a/src/test/coinstatsindex_tests.cpp
+++ b/src/test/coinstatsindex_tests.cpp
@@ -2,8 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <chainparams.h>
#include <index/coinstatsindex.h>
#include <test/util/setup_common.h>
+#include <test/util/validation.h>
#include <util/time.h>
#include <validation.h>
@@ -16,6 +18,17 @@ using node::CoinStatsHashType;
BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
+static void IndexWaitSynced(BaseIndex& index)
+{
+ // Allow the CoinStatsIndex to catch up with the block index that is syncing
+ // in a background thread.
+ const auto timeout = GetTime<std::chrono::seconds>() + 120s;
+ while (!index.BlockUntilSyncedToCurrentChain()) {
+ BOOST_REQUIRE(timeout > GetTime<std::chrono::milliseconds>());
+ UninterruptibleSleep(100ms);
+ }
+}
+
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
{
CoinStatsIndex coin_stats_index{1 << 20, true};
@@ -36,13 +49,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
- // Allow the CoinStatsIndex to catch up with the block index that is syncing
- // in a background thread.
- const auto timeout = GetTime<std::chrono::seconds>() + 120s;
- while (!coin_stats_index.BlockUntilSyncedToCurrentChain()) {
- BOOST_REQUIRE(timeout > GetTime<std::chrono::milliseconds>());
- UninterruptibleSleep(100ms);
- }
+ IndexWaitSynced(coin_stats_index);
// Check that CoinStatsIndex works for genesis block.
const CBlockIndex* genesis_block_index;
@@ -78,4 +85,44 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
// Rest of shutdown sequence and destructors happen in ~TestingSetup()
}
+// Test shutdown between BlockConnected and ChainStateFlushed notifications,
+// make sure index is not corrupted and is able to reload.
+BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
+{
+ CChainState& chainstate = Assert(m_node.chainman)->ActiveChainstate();
+ const CChainParams& params = Params();
+ {
+ CoinStatsIndex index{1 << 20};
+ BOOST_REQUIRE(index.Start(chainstate));
+ IndexWaitSynced(index);
+ std::shared_ptr<const CBlock> new_block;
+ CBlockIndex* new_block_index = nullptr;
+ {
+ const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
+ const CBlock block = this->CreateBlock({}, script_pub_key, chainstate);
+
+ new_block = std::make_shared<CBlock>(block);
+
+ LOCK(cs_main);
+ BlockValidationState state;
+ BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
+ BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr));
+ CCoinsViewCache view(&chainstate.CoinsTip());
+ BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
+ }
+ // Send block connected notification, then stop the index without
+ // sending a chainstate flushed notification. Prior to #24138, this
+ // would cause the index to be corrupted and fail to reload.
+ ValidationInterfaceTest::BlockConnected(index, new_block, new_block_index);
+ index.Stop();
+ }
+
+ {
+ CoinStatsIndex index{1 << 20};
+ // Make sure the index can be loaded.
+ BOOST_REQUIRE(index.Start(chainstate));
+ index.Stop();
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp
index 5875f0218f..d2554483d4 100644
--- a/src/test/fs_tests.cpp
+++ b/src/test/fs_tests.cpp
@@ -46,8 +46,8 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
{
fs::path tmpfolder = m_args.GetDataDirBase();
// tmpfile1 should be the same as tmpfile2
- fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃";
- fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃";
+ fs::path tmpfile1 = tmpfolder / fs::u8path("fs_tests_₿_🏃");
+ fs::path tmpfile2 = tmpfolder / fs::u8path("fs_tests_₿_🏃");
{
std::ofstream file{tmpfile1};
file << "bitcoin";
@@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
}
{
// Join an absolute path and a relative path.
- fs::path p = fsbridge::AbsPathJoin(tmpfolder, "fs_tests_₿_🏃");
+ fs::path p = fsbridge::AbsPathJoin(tmpfolder, fs::u8path("fs_tests_₿_🏃"));
BOOST_CHECK(p.is_absolute());
BOOST_CHECK_EQUAL(tmpfile1, p);
}
diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp
index 6cb81901cb..35e6688c61 100644
--- a/src/test/fuzz/netaddress.cpp
+++ b/src/test/fuzz/netaddress.cpp
@@ -16,7 +16,6 @@ FUZZ_TARGET(netaddress)
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CNetAddr net_addr = ConsumeNetAddr(fuzzed_data_provider);
- (void)net_addr.GetHash();
(void)net_addr.GetNetClass();
if (net_addr.GetNetwork() == Network::NET_IPV4) {
assert(net_addr.IsIPv4());
@@ -84,6 +83,8 @@ FUZZ_TARGET(netaddress)
(void)service.ToString();
(void)service.ToStringIPPort();
(void)service.ToStringPort();
+ (void)CServiceHash()(service);
+ (void)CServiceHash(0, 0)(service);
const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider);
(void)net_addr.GetReachabilityFrom(&other_net_addr);
diff --git a/src/test/fuzz/script_format.cpp b/src/test/fuzz/script_format.cpp
index 2fa893f812..241bdfe666 100644
--- a/src/test/fuzz/script_format.cpp
+++ b/src/test/fuzz/script_format.cpp
@@ -3,7 +3,9 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
+#include <consensus/consensus.h>
#include <core_io.h>
+#include <policy/policy.h>
#include <script/script.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -19,6 +21,9 @@ FUZZ_TARGET_INIT(script_format, initialize_script_format)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CScript script{ConsumeScript(fuzzed_data_provider)};
+ if (script.size() > MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR) {
+ return;
+ }
(void)FormatScript(script);
(void)ScriptToAsmStr(script, /*fAttemptSighashDecode=*/fuzzed_data_provider.ConsumeBool());
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index 597d774673..c877105fe7 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/util/setup_common.h>
+#include <univalue.h>
+#include <util/settings.h>
#include <util/strencodings.h>
#include <util/system.h>
@@ -14,22 +16,13 @@
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
-namespace getarg_tests{
- class LocalTestingSetup : BasicTestingSetup {
- protected:
- void SetupArgs(const std::vector<std::pair<std::string, unsigned int>>& args);
- void ResetArgs(const std::string& strArg);
- ArgsManager m_local_args;
- };
-}
+BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup)
-BOOST_FIXTURE_TEST_SUITE(getarg_tests, LocalTestingSetup)
-
-void LocalTestingSetup :: ResetArgs(const std::string& strArg)
+void ResetArgs(ArgsManager& local_args, const std::string& strArg)
{
std::vector<std::string> vecArg;
if (strArg.size())
- boost::split(vecArg, strArg, IsSpace, boost::token_compress_on);
+ boost::split(vecArg, strArg, IsSpace, boost::token_compress_on);
// Insert dummy executable name:
vecArg.insert(vecArg.begin(), "testbitcoin");
@@ -40,264 +33,403 @@ void LocalTestingSetup :: ResetArgs(const std::string& strArg)
vecChar.push_back(s.c_str());
std::string error;
- BOOST_CHECK(m_local_args.ParseParameters(vecChar.size(), vecChar.data(), error));
+ BOOST_CHECK(local_args.ParseParameters(vecChar.size(), vecChar.data(), error));
}
-void LocalTestingSetup :: SetupArgs(const std::vector<std::pair<std::string, unsigned int>>& args)
+void SetupArgs(ArgsManager& local_args, const std::vector<std::pair<std::string, unsigned int>>& args)
{
- m_local_args.ClearArgs();
for (const auto& arg : args) {
- m_local_args.AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
+ local_args.AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
}
}
+// Test behavior of GetArg functions when string, integer, and boolean types
+// are specified in the settings.json file. GetArg functions are convenience
+// functions. The GetSetting method can always be used instead of GetArg
+// methods to retrieve original values, and there's not always an objective
+// answer to what GetArg behavior is best in every case. This test makes sure
+// there's test coverage for whatever the current behavior is, so it's not
+// broken or changed unintentionally.
+BOOST_AUTO_TEST_CASE(setting_args)
+{
+ ArgsManager args;
+ SetupArgs(args, {{"-foo", ArgsManager::ALLOW_ANY}});
+
+ auto set_foo = [&](const util::SettingsValue& value) {
+ args.LockSettings([&](util::Settings& settings) {
+ settings.rw_settings["foo"] = value;
+ });
+ };
+
+ set_foo("str");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"str\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "str");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo("99");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"99\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo("3.25");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"3.25\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 3);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo("0");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"0\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo("");
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "\"\"");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo(99);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "99");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(3.25);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "3.25");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25");
+ BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(0);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "0");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(true);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "true");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "1");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 1);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), true);
+
+ set_foo(false);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "false");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), false);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+
+ set_foo(UniValue::VOBJ);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "{}");
+ BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(UniValue::VARR);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "[]");
+ BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
+ BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
+
+ set_foo(UniValue::VNULL);
+ BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "null");
+ BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "default");
+ BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 100);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", true), true);
+ BOOST_CHECK_EQUAL(args.GetBoolArg("foo", false), false);
+}
+
BOOST_AUTO_TEST_CASE(boolarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
- SetupArgs({foo});
- ResetArgs("-foo");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ SetupArgs(local_args, {foo});
+ ResetArgs(local_args, "-foo");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-fo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-fo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-fo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-fo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-fooo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-fooo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-fooo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-fooo", true));
- ResetArgs("-foo=0");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=0");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=1");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=1");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
// New 0.6 feature: auto-map -nosomething to !-something:
- ResetArgs("-nofoo");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-nofoo");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo -nofoo"); // -nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo -nofoo"); // -nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=1 -nofoo=1"); // -nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=1 -nofoo=1"); // -nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
- ResetArgs("-foo=0 -nofoo=0"); // -nofoo=0 should win
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "-foo=0 -nofoo=0"); // -nofoo=0 should win
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
// New 0.6 feature: treat -- same as -:
- ResetArgs("--foo=1");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
-
- ResetArgs("--nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "--foo=1");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ ResetArgs(local_args, "--nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
}
BOOST_AUTO_TEST_CASE(stringarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "eleven");
-
- ResetArgs("-foo -bar");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "");
-
- ResetArgs("-foo=");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "");
-
- ResetArgs("-foo=11");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "11");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "11");
-
- ResetArgs("-foo=eleven");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "eleven");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", "eleven"), "eleven");
-
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven");
+
+ ResetArgs(local_args, "-foo -bar");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "");
+
+ ResetArgs(local_args, "-foo=");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "");
+
+ ResetArgs(local_args, "-foo=11");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "11");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "11");
+
+ ResetArgs(local_args, "-foo=eleven");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "eleven");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", "eleven"), "eleven");
}
BOOST_AUTO_TEST_CASE(intarg)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 11), 11);
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 0), 0);
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 11);
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 0);
- ResetArgs("-foo -bar");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 11), 0);
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0);
+ ResetArgs(local_args, "-foo -bar");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 11), 0);
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0);
// Check under-/overflow behavior.
- ResetArgs("-foo=-9223372036854775809 -bar=9223372036854775808");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 0), std::numeric_limits<int64_t>::min());
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 0), std::numeric_limits<int64_t>::max());
+ ResetArgs(local_args, "-foo=-9223372036854775809 -bar=9223372036854775808");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), std::numeric_limits<int64_t>::min());
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 0), std::numeric_limits<int64_t>::max());
- ResetArgs("-foo=11 -bar=12");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 0), 11);
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 12);
+ ResetArgs(local_args, "-foo=11 -bar=12");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 0), 11);
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 12);
- ResetArgs("-foo=NaN -bar=NotANumber");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-foo", 1), 0);
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 11), 0);
+ ResetArgs(local_args, "-foo=NaN -bar=NotANumber");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-foo", 1), 0);
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 11), 0);
}
BOOST_AUTO_TEST_CASE(patharg)
{
+ ArgsManager local_args;
+
const auto dir = std::make_pair("-dir", ArgsManager::ALLOW_ANY);
- SetupArgs({dir});
- ResetArgs("");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), fs::path{});
+ SetupArgs(local_args, {dir});
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), fs::path{});
const fs::path root_path{"/"};
- ResetArgs("-dir=/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
- ResetArgs("-dir=/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), root_path);
+ ResetArgs(local_args, "-dir=/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), root_path);
#ifdef WIN32
const fs::path win_root_path{"C:\\"};
- ResetArgs("-dir=C:\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
- ResetArgs("-dir=C:\\.\\\\");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), win_root_path);
+ ResetArgs(local_args, "-dir=C:\\.\\\\");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), win_root_path);
#endif
const fs::path absolute_path{"/home/user/.bitcoin"};
- ResetArgs("-dir=/home/user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/root/../home/user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/root/../home/user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/./user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/./user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
- ResetArgs("-dir=/home/user/.bitcoin/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), absolute_path);
+ ResetArgs(local_args, "-dir=/home/user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), absolute_path);
const fs::path relative_path{"user/.bitcoin"};
- ResetArgs("-dir=user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=somewhere/../user/.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/./.bitcoin");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/.bitcoin/");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/.bitcoin//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/.bitcoin/.");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/.bitcoin/./");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
-
- ResetArgs("-dir=user/.bitcoin/.//");
- BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
+ ResetArgs(local_args, "-dir=user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=somewhere/../user/.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/./.bitcoin");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/.bitcoin/");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/.bitcoin//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/.bitcoin/.");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/.bitcoin/./");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ ResetArgs(local_args, "-dir=user/.bitcoin/.//");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir"), relative_path);
+
+ // Check negated and default argument handling. Specifying an empty argument
+ // is the same as not specifying the argument. This is convenient for
+ // scripting so later command line arguments can override earlier command
+ // line arguments or bitcoin.conf values. Currently the -dir= case cannot be
+ // distinguished from -dir case with no assignment, but #16545 would add the
+ // ability to distinguish these in the future (and treat the no-assign case
+ // like an imperative command or an error).
+ ResetArgs(local_args, "");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-dir=override");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"override"});
+ ResetArgs(local_args, "-dir=");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-dir");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{"default"});
+ ResetArgs(local_args, "-nodir");
+ BOOST_CHECK_EQUAL(local_args.GetPathArg("-dir", "default"), fs::path{""});
}
BOOST_AUTO_TEST_CASE(doubledash)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("--foo");
- BOOST_CHECK_EQUAL(m_local_args.GetBoolArg("-foo", false), true);
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "--foo");
+ BOOST_CHECK_EQUAL(local_args.GetBoolArg("-foo", false), true);
- ResetArgs("--foo=verbose --bar=1");
- BOOST_CHECK_EQUAL(m_local_args.GetArg("-foo", ""), "verbose");
- BOOST_CHECK_EQUAL(m_local_args.GetIntArg("-bar", 0), 1);
+ ResetArgs(local_args, "--foo=verbose --bar=1");
+ BOOST_CHECK_EQUAL(local_args.GetArg("-foo", ""), "verbose");
+ BOOST_CHECK_EQUAL(local_args.GetIntArg("-bar", 0), 1);
}
BOOST_AUTO_TEST_CASE(boolargno)
{
+ ArgsManager local_args;
+
const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
- SetupArgs({foo, bar});
- ResetArgs("-nofoo");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo=1");
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo=0");
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-foo --nofoo"); // --nofoo should win
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(!m_local_args.GetBoolArg("-foo", false));
-
- ResetArgs("-nofoo -foo"); // foo always wins:
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", true));
- BOOST_CHECK(m_local_args.GetBoolArg("-foo", false));
+ SetupArgs(local_args, {foo, bar});
+ ResetArgs(local_args, "-nofoo");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo=1");
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo=0");
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-foo --nofoo"); // --nofoo should win
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(!local_args.GetBoolArg("-foo", false));
+
+ ResetArgs(local_args, "-nofoo -foo"); // foo always wins:
+ BOOST_CHECK(local_args.GetBoolArg("-foo", true));
+ BOOST_CHECK(local_args.GetBoolArg("-foo", false));
}
BOOST_AUTO_TEST_CASE(logargs)
{
+ ArgsManager local_args;
+
const auto okaylog_bool = std::make_pair("-okaylog-bool", ArgsManager::ALLOW_ANY);
const auto okaylog_negbool = std::make_pair("-okaylog-negbool", ArgsManager::ALLOW_ANY);
const auto okaylog = std::make_pair("-okaylog", ArgsManager::ALLOW_ANY);
const auto dontlog = std::make_pair("-dontlog", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE);
- SetupArgs({okaylog_bool, okaylog_negbool, okaylog, dontlog});
- ResetArgs("-okaylog-bool -nookaylog-negbool -okaylog=public -dontlog=private");
+ SetupArgs(local_args, {okaylog_bool, okaylog_negbool, okaylog, dontlog});
+ ResetArgs(local_args, "-okaylog-bool -nookaylog-negbool -okaylog=public -dontlog=private");
// Everything logged to debug.log will also append to str
std::string str;
@@ -307,7 +439,7 @@ BOOST_AUTO_TEST_CASE(logargs)
});
// Log the arguments
- m_local_args.LogArgs();
+ local_args.LogArgs();
LogInstance().DeleteCallback(print_connection);
// Check that what should appear does, and what shouldn't doesn't.
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index c453dae701..f6c1d1efad 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -30,10 +30,10 @@ using node::CBlockTemplate;
namespace miner_tests {
struct MinerTestingSetup : public TestingSetup {
void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
- bool TestSequenceLocks(const CTransaction& tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
+ bool TestSequenceLocks(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
{
CCoinsViewMemPool view_mempool(&m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool);
- return CheckSequenceLocks(m_node.chainman->ActiveChain().Tip(), view_mempool, tx, flags);
+ return CheckSequenceLocksAtTip(m_node.chainman->ActiveChain().Tip(), view_mempool, tx);
}
BlockAssembler AssemblerForTest(const CChainParams& params);
};
@@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// non-final txs in mempool
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1);
- int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
+ const int flags{LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST};
// height map
std::vector<int> prevheights;
@@ -429,8 +429,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = 0;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
{
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
@@ -443,8 +443,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 2;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
@@ -464,8 +464,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
// absolute time locked
@@ -475,8 +475,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = baseheight + 4;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime fails
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
// mempool-dependent transactions (not added)
@@ -484,14 +484,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
tx.nLockTime = 0;
tx.vin[0].nSequence = 0;
- BOOST_CHECK(CheckFinalTx(m_node.chainman->ActiveChain().Tip(), CTransaction(tx), flags)); // Locktime passes
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = 1;
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
- BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
+ BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
- BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
+ BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/test/net_peer_eviction_tests.cpp b/src/test/net_peer_eviction_tests.cpp
index 78ad24a408..6ec3fb0c6b 100644
--- a/src/test/net_peer_eviction_tests.cpp
+++ b/src/test/net_peer_eviction_tests.cpp
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
// Test protection of onion, localhost, and I2P peers...
// Expect 1/4 onion peers to be protected from eviction,
- // if no localhost or I2P peers.
+ // if no localhost, I2P, or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_is_local = false;
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
random_context));
// Expect 1/4 onion peers and 1/4 of the other peers to be protected,
- // sorted by longest uptime (lowest m_connected), if no localhost or I2P peers.
+ // sorted by longest uptime (lowest m_connected), if no localhost, I2P or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_connected = std::chrono::seconds{c.id};
@@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
random_context));
// Expect 1/4 localhost peers to be protected from eviction,
- // if no onion or I2P peers.
+ // if no onion, I2P, or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_is_local = (c.id == 1 || c.id == 9 || c.id == 11);
@@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
random_context));
// Expect 1/4 localhost peers and 1/4 of the other peers to be protected,
- // sorted by longest uptime (lowest m_connected), if no onion or I2P peers.
+ // sorted by longest uptime (lowest m_connected), if no onion, I2P, or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_connected = std::chrono::seconds{c.id};
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
random_context));
// Expect 1/4 I2P peers to be protected from eviction,
- // if no onion or localhost peers.
+ // if no onion, localhost, or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_is_local = false;
@@ -146,8 +146,8 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
/*unprotected_peer_ids=*/{},
random_context));
- // Expect 1/4 I2P peers and 1/4 of the other peers to be protected,
- // sorted by longest uptime (lowest m_connected), if no onion or localhost peers.
+ // Expect 1/4 I2P peers and 1/4 of the other peers to be protected, sorted
+ // by longest uptime (lowest m_connected), if no onion, localhost, or CJDNS peers.
BOOST_CHECK(IsProtected(
num_peers, [](NodeEvictionCandidate& c) {
c.m_connected = std::chrono::seconds{c.id};
@@ -158,6 +158,29 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
/*unprotected_peer_ids=*/{3, 5, 6, 7, 8, 11},
random_context));
+ // Expect 1/4 CJDNS peers to be protected from eviction,
+ // if no onion, localhost, or I2P peers.
+ BOOST_CHECK(IsProtected(
+ num_peers, [](NodeEvictionCandidate& c) {
+ c.m_is_local = false;
+ c.m_network = (c.id == 2 || c.id == 7 || c.id == 10) ? NET_CJDNS : NET_IPV4;
+ },
+ /*protected_peer_ids=*/{2, 7, 10},
+ /*unprotected_peer_ids=*/{},
+ random_context));
+
+ // Expect 1/4 CJDNS peers and 1/4 of the other peers to be protected, sorted
+ // by longest uptime (lowest m_connected), if no onion, localhost, or I2P peers.
+ BOOST_CHECK(IsProtected(
+ num_peers, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = false;
+ c.m_network = (c.id == 4 || c.id > 8) ? NET_CJDNS : NET_IPV6;
+ },
+ /*protected_peer_ids=*/{0, 1, 2, 4, 9, 10},
+ /*unprotected_peer_ids=*/{3, 5, 6, 7, 8, 11},
+ random_context));
+
// Tests with 2 networks...
// Combined test: expect having 1 localhost and 1 onion peer out of 4 to
@@ -289,16 +312,16 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
BOOST_CHECK(IsProtected(
4, [](NodeEvictionCandidate& c) {
c.m_connected = std::chrono::seconds{c.id};
- c.m_is_local = (c.id == 3);
- if (c.id == 4) {
+ c.m_is_local = (c.id == 2);
+ if (c.id == 3) {
c.m_network = NET_I2P;
- } else if (c.id == 2) {
+ } else if (c.id == 1) {
c.m_network = NET_ONION;
} else {
c.m_network = NET_IPV6;
}
},
- /*protected_peer_ids=*/{0, 4},
+ /*protected_peer_ids=*/{0, 3},
/*unprotected_peer_ids=*/{1, 2},
random_context));
@@ -416,15 +439,15 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
/*unprotected_peer_ids=*/{6, 7, 8, 9, 10, 11, 16, 19, 20, 21, 22, 23},
random_context));
- // Combined test: expect having 8 localhost, 4 I2P, and 3 onion peers out of
- // 24 to protect 2 of each (6 total), plus 6 others for 12/24 total, sorted
- // by longest uptime.
+ // Combined test: expect having 8 localhost, 4 CJDNS, and 3 onion peers out
+ // of 24 to protect 2 of each (6 total), plus 6 others for 12/24 total,
+ // sorted by longest uptime.
BOOST_CHECK(IsProtected(
24, [](NodeEvictionCandidate& c) {
c.m_connected = std::chrono::seconds{c.id};
c.m_is_local = (c.id > 15);
if (c.id > 10 && c.id < 15) {
- c.m_network = NET_I2P;
+ c.m_network = NET_CJDNS;
} else if (c.id > 6 && c.id < 10) {
c.m_network = NET_ONION;
} else {
@@ -434,6 +457,116 @@ BOOST_AUTO_TEST_CASE(peer_protection_test)
/*protected_peer_ids=*/{0, 1, 2, 3, 4, 5, 7, 8, 11, 12, 16, 17},
/*unprotected_peer_ids=*/{6, 9, 10, 13, 14, 15, 18, 19, 20, 21, 22, 23},
random_context));
+
+ // Tests with 4 networks...
+
+ // Combined test: expect having 1 CJDNS, 1 I2P, 1 localhost and 1 onion peer
+ // out of 5 to protect 1 CJDNS, 0 I2P, 0 localhost, 0 onion and 1 other peer
+ // (2 total), sorted by longest uptime; stable sort breaks tie with array
+ // order of CJDNS first.
+ BOOST_CHECK(IsProtected(
+ 5, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = (c.id == 3);
+ if (c.id == 4) {
+ c.m_network = NET_CJDNS;
+ } else if (c.id == 1) {
+ c.m_network = NET_I2P;
+ } else if (c.id == 2) {
+ c.m_network = NET_ONION;
+ } else {
+ c.m_network = NET_IPV6;
+ }
+ },
+ /* protected_peer_ids */ {0, 4},
+ /* unprotected_peer_ids */ {1, 2, 3},
+ random_context));
+
+ // Combined test: expect having 1 CJDNS, 1 I2P, 1 localhost and 1 onion peer
+ // out of 7 to protect 1 CJDNS, 0, I2P, 0 localhost, 0 onion and 2 other
+ // peers (3 total) sorted by longest uptime; stable sort breaks tie with
+ // array order of CJDNS first.
+ BOOST_CHECK(IsProtected(
+ 7, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = (c.id == 4);
+ if (c.id == 6) {
+ c.m_network = NET_CJDNS;
+ } else if (c.id == 5) {
+ c.m_network = NET_I2P;
+ } else if (c.id == 3) {
+ c.m_network = NET_ONION;
+ } else {
+ c.m_network = NET_IPV4;
+ }
+ },
+ /*protected_peer_ids=*/{0, 1, 6},
+ /*unprotected_peer_ids=*/{2, 3, 4, 5},
+ random_context));
+
+ // Combined test: expect having 1 CJDNS, 1 I2P, 1 localhost and 1 onion peer
+ // out of 8 to protect 1 CJDNS, 1 I2P, 0 localhost, 0 onion and 2 other
+ // peers (4 total) sorted by longest uptime; stable sort breaks tie with
+ // array order of CJDNS first.
+ BOOST_CHECK(IsProtected(
+ 8, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = (c.id == 3);
+ if (c.id == 5) {
+ c.m_network = NET_CJDNS;
+ } else if (c.id == 6) {
+ c.m_network = NET_I2P;
+ } else if (c.id == 3) {
+ c.m_network = NET_ONION;
+ } else {
+ c.m_network = NET_IPV6;
+ }
+ },
+ /*protected_peer_ids=*/{0, 1, 5, 6},
+ /*unprotected_peer_ids=*/{2, 3, 4, 7},
+ random_context));
+
+ // Combined test: expect having 2 CJDNS, 2 I2P, 4 localhost, and 2 onion
+ // peers out of 16 to protect 1 CJDNS, 1 I2P, 1 localhost, 1 onion (4/16
+ // total), plus 4 others for 8 total, sorted by longest uptime.
+ BOOST_CHECK(IsProtected(
+ 16, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = (c.id > 5);
+ if (c.id == 11 || c.id == 15) {
+ c.m_network = NET_CJDNS;
+ } else if (c.id == 10 || c.id == 14) {
+ c.m_network = NET_I2P;
+ } else if (c.id == 8 || c.id == 9) {
+ c.m_network = NET_ONION;
+ } else {
+ c.m_network = NET_IPV4;
+ }
+ },
+ /*protected_peer_ids=*/{0, 1, 2, 3, 6, 8, 10, 11},
+ /*unprotected_peer_ids=*/{4, 5, 7, 9, 12, 13, 14, 15},
+ random_context));
+
+ // Combined test: expect having 6 CJDNS, 1 I2P, 1 localhost, and 4 onion
+ // peers out of 24 to protect 2 CJDNS, 1 I2P, 1 localhost, and 2 onions (6
+ // total), plus 6 others for 12/24 total, sorted by longest uptime.
+ BOOST_CHECK(IsProtected(
+ 24, [](NodeEvictionCandidate& c) {
+ c.m_connected = std::chrono::seconds{c.id};
+ c.m_is_local = (c.id == 13);
+ if (c.id > 17) {
+ c.m_network = NET_CJDNS;
+ } else if (c.id == 17) {
+ c.m_network = NET_I2P;
+ } else if (c.id == 12 || c.id == 14 || c.id == 15 || c.id == 16) {
+ c.m_network = NET_ONION;
+ } else {
+ c.m_network = NET_IPV6;
+ }
+ },
+ /*protected_peer_ids=*/{0, 1, 2, 3, 4, 5, 12, 13, 14, 17, 18, 19},
+ /*unprotected_peer_ids=*/{6, 7, 8, 9, 10, 11, 15, 16, 20, 21, 22, 23},
+ random_context));
}
// Returns true if any of the node ids in node_ids are selected for eviction.
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 908b030eea..fcb1a80765 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -4,17 +4,23 @@
#include <chainparams.h>
#include <clientversion.h>
+#include <compat.h>
#include <cstdint>
#include <net.h>
+#include <net_processing.h>
#include <netaddress.h>
#include <netbase.h>
+#include <netmessagemaker.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
#include <test/util/setup_common.h>
+#include <test/util/validation.h>
+#include <timedata.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
+#include <validation.h>
#include <version.h>
#include <boost/test/unit_test.hpp>
@@ -27,7 +33,7 @@
using namespace std::literals;
-BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(net_tests, RegTestingSetup)
BOOST_AUTO_TEST_CASE(cnode_listen_port)
{
@@ -607,15 +613,15 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
// set up local addresses; all that's necessary to reproduce the bug is
// that a normal IPv4 address is among the entries, but if this address is
// !IsRoutable the undefined behavior is easier to trigger deterministically
+ in_addr raw_addr;
+ raw_addr.s_addr = htonl(0x7f000001);
+ const CNetAddr mapLocalHost_entry = CNetAddr(raw_addr);
{
LOCK(g_maplocalhost_mutex);
- in_addr ipv4AddrLocal;
- ipv4AddrLocal.s_addr = 0x0100007f;
- CNetAddr addr = CNetAddr(ipv4AddrLocal);
LocalServiceInfo lsi;
lsi.nScore = 23;
lsi.nPort = 42;
- mapLocalHost[addr] = lsi;
+ mapLocalHost[mapLocalHost_entry] = lsi;
}
// create a peer with an IPv4 address
@@ -646,8 +652,79 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
// suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
BOOST_CHECK(1);
+
+ // Cleanup, so that we don't confuse other tests.
+ {
+ LOCK(g_maplocalhost_mutex);
+ mapLocalHost.erase(mapLocalHost_entry);
+ }
}
+BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
+{
+ // Test that GetLocalAddrForPeer() properly selects the address to self-advertise:
+ //
+ // 1. GetLocalAddrForPeer() calls GetLocalAddress() which returns an address that is
+ // not routable.
+ // 2. GetLocalAddrForPeer() overrides the address with whatever the peer has told us
+ // he sees us as.
+ // 2.1. For inbound connections we must override both the address and the port.
+ // 2.2. For outbound connections we must override only the address.
+
+ // Pretend that we bound to this port.
+ const uint16_t bind_port = 20001;
+ m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
+
+ // Our address:port as seen from the peer, completely different from the above.
+ in_addr peer_us_addr;
+ peer_us_addr.s_addr = htonl(0x02030405);
+ const CAddress peer_us{CService{peer_us_addr, 20002}, NODE_NETWORK};
+
+ // Create a peer with a routable IPv4 address (outbound).
+ in_addr peer_out_in_addr;
+ peer_out_in_addr.s_addr = htonl(0x01020304);
+ CNode peer_out{/*id=*/0,
+ /*nLocalServicesIn=*/NODE_NETWORK,
+ /*sock=*/nullptr,
+ /*addrIn=*/CAddress{CService{peer_out_in_addr, 8333}, NODE_NETWORK},
+ /*nKeyedNetGroupIn=*/0,
+ /*nLocalHostNonceIn=*/0,
+ /*addrBindIn=*/CAddress{},
+ /*addrNameIn=*/std::string{},
+ /*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
+ /*inbound_onion=*/false};
+ peer_out.fSuccessfullyConnected = true;
+ peer_out.SetAddrLocal(peer_us);
+
+ // Without the fix peer_us:8333 is chosen instead of the proper peer_us:bind_port.
+ auto chosen_local_addr = GetLocalAddrForPeer(&peer_out);
+ BOOST_REQUIRE(chosen_local_addr);
+ const CService expected{peer_us_addr, bind_port};
+ BOOST_CHECK(*chosen_local_addr == expected);
+
+ // Create a peer with a routable IPv4 address (inbound).
+ in_addr peer_in_in_addr;
+ peer_in_in_addr.s_addr = htonl(0x05060708);
+ CNode peer_in{/*id=*/0,
+ /*nLocalServicesIn=*/NODE_NETWORK,
+ /*sock=*/nullptr,
+ /*addrIn=*/CAddress{CService{peer_in_in_addr, 8333}, NODE_NETWORK},
+ /*nKeyedNetGroupIn=*/0,
+ /*nLocalHostNonceIn=*/0,
+ /*addrBindIn=*/CAddress{},
+ /*addrNameIn=*/std::string{},
+ /*conn_type_in=*/ConnectionType::INBOUND,
+ /*inbound_onion=*/false};
+ peer_in.fSuccessfullyConnected = true;
+ peer_in.SetAddrLocal(peer_us);
+
+ // Without the fix peer_us:8333 is chosen instead of the proper peer_us:peer_us.GetPort().
+ chosen_local_addr = GetLocalAddrForPeer(&peer_in);
+ BOOST_REQUIRE(chosen_local_addr);
+ BOOST_CHECK(*chosen_local_addr == peer_us);
+
+ m_node.args->ForceSetArg("-bind", "");
+}
BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
{
@@ -728,4 +805,108 @@ BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
BOOST_CHECK(!IsLocal(addr));
}
+BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)
+{
+ // Tests the following scenario:
+ // * -bind=3.4.5.6:20001 is specified
+ // * we make an outbound connection to a peer
+ // * the peer reports he sees us as 2.3.4.5:20002 in the version message
+ // (20002 is a random port assigned by our OS for the outgoing TCP connection,
+ // we cannot accept connections to it)
+ // * we should self-advertise to that peer as 2.3.4.5:20001
+
+ // Pretend that we bound to this port.
+ const uint16_t bind_port = 20001;
+ m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
+ m_node.args->ForceSetArg("-capturemessages", "1");
+
+ // Our address:port as seen from the peer - 2.3.4.5:20002 (different from the above).
+ in_addr peer_us_addr;
+ peer_us_addr.s_addr = htonl(0x02030405);
+ const CService peer_us{peer_us_addr, 20002};
+
+ // Create a peer with a routable IPv4 address.
+ in_addr peer_in_addr;
+ peer_in_addr.s_addr = htonl(0x01020304);
+ CNode peer{/*id=*/0,
+ /*nLocalServicesIn=*/NODE_NETWORK,
+ /*sock=*/nullptr,
+ /*addrIn=*/CAddress{CService{peer_in_addr, 8333}, NODE_NETWORK},
+ /*nKeyedNetGroupIn=*/0,
+ /*nLocalHostNonceIn=*/0,
+ /*addrBindIn=*/CAddress{},
+ /*addrNameIn=*/std::string{},
+ /*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
+ /*inbound_onion=*/false};
+
+ const uint64_t services{NODE_NETWORK | NODE_WITNESS};
+ const int64_t time{0};
+ const CNetMsgMaker msg_maker{PROTOCOL_VERSION};
+
+ // Force CChainState::IsInitialBlockDownload() to return false.
+ // Otherwise PushAddress() isn't called by PeerManager::ProcessMessage().
+ TestChainState& chainstate =
+ *static_cast<TestChainState*>(&m_node.chainman->ActiveChainstate());
+ chainstate.JumpOutOfIbd();
+
+ m_node.peerman->InitializeNode(&peer);
+
+ std::atomic<bool> interrupt_dummy{false};
+ std::chrono::microseconds time_received_dummy{0};
+
+ const auto msg_version =
+ msg_maker.Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, peer_us);
+ CDataStream msg_version_stream{msg_version.data, SER_NETWORK, PROTOCOL_VERSION};
+
+ m_node.peerman->ProcessMessage(
+ peer, NetMsgType::VERSION, msg_version_stream, time_received_dummy, interrupt_dummy);
+
+ const auto msg_verack = msg_maker.Make(NetMsgType::VERACK);
+ CDataStream msg_verack_stream{msg_verack.data, SER_NETWORK, PROTOCOL_VERSION};
+
+ // Will set peer.fSuccessfullyConnected to true (necessary in SendMessages()).
+ m_node.peerman->ProcessMessage(
+ peer, NetMsgType::VERACK, msg_verack_stream, time_received_dummy, interrupt_dummy);
+
+ // Ensure that peer_us_addr:bind_port is sent to the peer.
+ const CService expected{peer_us_addr, bind_port};
+ bool sent{false};
+
+ const auto CaptureMessageOrig = CaptureMessage;
+ CaptureMessage = [&sent, &expected](const CAddress& addr,
+ const std::string& msg_type,
+ Span<const unsigned char> data,
+ bool is_incoming) -> void {
+ if (!is_incoming && msg_type == "addr") {
+ CDataStream s(data, SER_NETWORK, PROTOCOL_VERSION);
+ std::vector<CAddress> addresses;
+
+ s >> addresses;
+
+ for (const auto& addr : addresses) {
+ if (addr == expected) {
+ sent = true;
+ return;
+ }
+ }
+ }
+ };
+
+ {
+ LOCK(peer.cs_sendProcessing);
+ m_node.peerman->SendMessages(&peer);
+ }
+
+ BOOST_CHECK(sent);
+
+ CaptureMessage = CaptureMessageOrig;
+ chainstate.ResetIbd();
+ m_node.args->ForceSetArg("-capturemessages", "0");
+ m_node.args->ForceSetArg("-bind", "");
+ // PeerManager::ProcessMessage() calls AddTimeData() which changes the internal state
+ // in timedata.cpp and later confuses the test "timedata_tests/addtimedata". Thus reset
+ // that state as it was before our test was run.
+ TestOnlyResetTimeData();
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 6410ac565a..8e6e911ec2 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -576,4 +576,24 @@ BOOST_AUTO_TEST_CASE(caddress_unserialize_v2)
BOOST_CHECK(fixture_addresses == addresses_unserialized);
}
+BOOST_AUTO_TEST_CASE(isbadport)
+{
+ BOOST_CHECK(IsBadPort(1));
+ BOOST_CHECK(IsBadPort(22));
+ BOOST_CHECK(IsBadPort(6000));
+
+ BOOST_CHECK(!IsBadPort(80));
+ BOOST_CHECK(!IsBadPort(443));
+ BOOST_CHECK(!IsBadPort(8333));
+
+ // Check all ports, there must be 80 bad ports in total.
+ size_t total_bad_ports{0};
+ for (uint16_t port = std::numeric_limits<uint16_t>::max(); port > 0; --port) {
+ if (IsBadPort(port)) {
+ ++total_bad_ports;
+ }
+ }
+ BOOST_CHECK_EQUAL(total_bad_ports, 80);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_segwit_tests.cpp b/src/test/script_segwit_tests.cpp
new file mode 100644
index 0000000000..2bad59805f
--- /dev/null
+++ b/src/test/script_segwit_tests.cpp
@@ -0,0 +1,164 @@
+// Copyright (c) 2012-2021 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 <script/script.h>
+#include <test/util/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(script_segwit_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Valid)
+{
+ uint256 dummy;
+ CScript p2wsh;
+ p2wsh << OP_0 << ToByteVector(dummy);
+ BOOST_CHECK(p2wsh.IsPayToWitnessScriptHash());
+
+ std::vector<unsigned char> bytes = {OP_0, 32};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(CScript(bytes.begin(), bytes.end()).IsPayToWitnessScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Invalid_NotOp0)
+{
+ uint256 dummy;
+ CScript notp2wsh;
+ notp2wsh << OP_1 << ToByteVector(dummy);
+ BOOST_CHECK(!notp2wsh.IsPayToWitnessScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Invalid_Size)
+{
+ uint160 dummy;
+ CScript notp2wsh;
+ notp2wsh << OP_0 << ToByteVector(dummy);
+ BOOST_CHECK(!notp2wsh.IsPayToWitnessScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Invalid_Nop)
+{
+ uint256 dummy;
+ CScript notp2wsh;
+ notp2wsh << OP_0 << OP_NOP << ToByteVector(dummy);
+ BOOST_CHECK(!notp2wsh.IsPayToWitnessScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Invalid_EmptyScript)
+{
+ CScript notp2wsh;
+ BOOST_CHECK(!notp2wsh.IsPayToWitnessScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(IsPayToWitnessScriptHash_Invalid_Pushdata)
+{
+ // A script is not P2WSH if OP_PUSHDATA is used to push the hash.
+ std::vector<unsigned char> bytes = {OP_0, OP_PUSHDATA1, 32};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(!CScript(bytes.begin(), bytes.end()).IsPayToWitnessScriptHash());
+
+ bytes = {OP_0, OP_PUSHDATA2, 32, 0};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(!CScript(bytes.begin(), bytes.end()).IsPayToWitnessScriptHash());
+
+ bytes = {OP_0, OP_PUSHDATA4, 32, 0, 0, 0};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(!CScript(bytes.begin(), bytes.end()).IsPayToWitnessScriptHash());
+}
+
+namespace {
+
+bool IsExpectedWitnessProgram(const CScript& script, const int expectedVersion, const std::vector<unsigned char>& expectedProgram)
+{
+ int actualVersion;
+ std::vector<unsigned char> actualProgram;
+ if (!script.IsWitnessProgram(actualVersion, actualProgram)) {
+ return false;
+ }
+ BOOST_CHECK_EQUAL(actualVersion, expectedVersion);
+ BOOST_CHECK(actualProgram == expectedProgram);
+ return true;
+}
+
+bool IsNoWitnessProgram(const CScript& script)
+{
+ int dummyVersion;
+ std::vector<unsigned char> dummyProgram;
+ return !script.IsWitnessProgram(dummyVersion, dummyProgram);
+}
+
+} // anonymous namespace
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Valid)
+{
+ // Witness programs have a minimum data push of 2 bytes.
+ std::vector<unsigned char> program = {42, 18};
+ CScript wit;
+ wit << OP_0 << program;
+ BOOST_CHECK(IsExpectedWitnessProgram(wit, 0, program));
+
+ wit.clear();
+ // Witness programs have a maximum data push of 40 bytes.
+ program.resize(40);
+ wit << OP_16 << program;
+ BOOST_CHECK(IsExpectedWitnessProgram(wit, 16, program));
+
+ program.resize(32);
+ std::vector<unsigned char> bytes = {OP_5, static_cast<unsigned char>(program.size())};
+ bytes.insert(bytes.end(), program.begin(), program.end());
+ BOOST_CHECK(IsExpectedWitnessProgram(CScript(bytes.begin(), bytes.end()), 5, program));
+}
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Invalid_Version)
+{
+ std::vector<unsigned char> program(10);
+ CScript nowit;
+ nowit << OP_1NEGATE << program;
+ BOOST_CHECK(IsNoWitnessProgram(nowit));
+}
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Invalid_Size)
+{
+ std::vector<unsigned char> program(1);
+ CScript nowit;
+ nowit << OP_0 << program;
+ BOOST_CHECK(IsNoWitnessProgram(nowit));
+
+ nowit.clear();
+ program.resize(41);
+ nowit << OP_0 << program;
+ BOOST_CHECK(IsNoWitnessProgram(nowit));
+}
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Invalid_Nop)
+{
+ std::vector<unsigned char> program(10);
+ CScript nowit;
+ nowit << OP_0 << OP_NOP << program;
+ BOOST_CHECK(IsNoWitnessProgram(nowit));
+}
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Invalid_EmptyScript)
+{
+ CScript nowit;
+ BOOST_CHECK(IsNoWitnessProgram(nowit));
+}
+
+BOOST_AUTO_TEST_CASE(IsWitnessProgram_Invalid_Pushdata)
+{
+ // A script is no witness program if OP_PUSHDATA is used to push the hash.
+ std::vector<unsigned char> bytes = {OP_0, OP_PUSHDATA1, 32};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(IsNoWitnessProgram(CScript(bytes.begin(), bytes.end())));
+
+ bytes = {OP_0, OP_PUSHDATA2, 32, 0};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(IsNoWitnessProgram(CScript(bytes.begin(), bytes.end())));
+
+ bytes = {OP_0, OP_PUSHDATA4, 32, 0, 0, 0};
+ bytes.insert(bytes.end(), 32, 0);
+ BOOST_CHECK(IsNoWitnessProgram(CScript(bytes.begin(), bytes.end())));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
index 1dcee23bbb..478d61d5e2 100644
--- a/src/test/timedata_tests.cpp
+++ b/src/test/timedata_tests.cpp
@@ -96,9 +96,10 @@ BOOST_AUTO_TEST_CASE(addtimedata)
// not to fix this because it prevents possible attacks. See the comment in AddTimeData() or issue #4521
// for a more detailed explanation.
MultiAddTimeData(2, 100); // filter median is 100 now, but nTimeOffset will not change
+ // We want this test to end with nTimeOffset==0, otherwise subsequent tests of the suite will fail.
BOOST_CHECK_EQUAL(GetTimeOffset(), 0);
- // We want this test to end with nTimeOffset==0, otherwise subsequent tests of the suite will fail.
+ TestOnlyResetTimeData();
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index c968e4d124..211153f06c 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -180,10 +180,9 @@ ChainTestingSetup::~ChainTestingSetup()
m_node.banman.reset();
m_node.addrman.reset();
m_node.args = nullptr;
- UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman);
+ WITH_LOCK(::cs_main, UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman));
m_node.mempool.reset();
m_node.scheduler.reset();
- m_node.chainman->Reset();
m_node.chainman.reset();
}
diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp
index 1aed492c3c..49535855f9 100644
--- a/src/test/util/validation.cpp
+++ b/src/test/util/validation.cpp
@@ -7,6 +7,7 @@
#include <util/check.h>
#include <util/time.h>
#include <validation.h>
+#include <validationinterface.h>
void TestChainState::ResetIbd()
{
@@ -20,3 +21,8 @@ void TestChainState::JumpOutOfIbd()
m_cached_finished_ibd = true;
Assert(!IsInitialBlockDownload());
}
+
+void ValidationInterfaceTest::BlockConnected(CValidationInterface& obj, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
+{
+ obj.BlockConnected(block, pindex);
+}
diff --git a/src/test/util/validation.h b/src/test/util/validation.h
index b13aa0be60..b0bc717b6c 100644
--- a/src/test/util/validation.h
+++ b/src/test/util/validation.h
@@ -7,6 +7,8 @@
#include <validation.h>
+class CValidationInterface;
+
struct TestChainState : public CChainState {
/** Reset the ibd cache to its initial state */
void ResetIbd();
@@ -14,4 +16,10 @@ struct TestChainState : public CChainState {
void JumpOutOfIbd();
};
+class ValidationInterfaceTest
+{
+public:
+ static void BlockConnected(CValidationInterface& obj, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex);
+};
+
#endif // BITCOIN_TEST_UTIL_VALIDATION_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 9f78215de2..1881573e7a 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -17,6 +17,7 @@
#include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
#include <util/moneystr.h>
#include <util/overflow.h>
+#include <util/readwritefile.h>
#include <util/spanparsing.h>
#include <util/strencodings.h>
#include <util/string.h>
@@ -24,9 +25,10 @@
#include <util/vector.h>
#include <array>
-#include <optional>
+#include <fstream>
#include <limits>
#include <map>
+#include <optional>
#include <stdint.h>
#include <string.h>
#include <thread>
@@ -2592,4 +2594,49 @@ BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
BOOST_CHECK(!ParseByteUnits("1x", noop));
}
+BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
+{
+ fs::path tmpfolder = m_args.GetDataDirBase();
+ fs::path tmpfile = tmpfolder / "read_binary.dat";
+ std::string expected_text;
+ for (int i = 0; i < 30; i++) {
+ expected_text += "0123456789";
+ }
+ {
+ std::ofstream file{tmpfile};
+ file << expected_text;
+ }
+ {
+ // read all contents in file
+ auto [valid, text] = ReadBinaryFile(tmpfile);
+ BOOST_CHECK(valid);
+ BOOST_CHECK_EQUAL(text, expected_text);
+ }
+ {
+ // read half contents in file
+ auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
+ BOOST_CHECK(valid);
+ BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
+ }
+ {
+ // read from non-existent file
+ fs::path invalid_file = tmpfolder / "invalid_binary.dat";
+ auto [valid, text] = ReadBinaryFile(invalid_file);
+ BOOST_CHECK(!valid);
+ BOOST_CHECK(text.empty());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
+{
+ fs::path tmpfolder = m_args.GetDataDirBase();
+ fs::path tmpfile = tmpfolder / "write_binary.dat";
+ std::string expected_text = "bitcoin";
+ auto valid = WriteBinaryFile(tmpfile, expected_text);
+ std::string actual_text;
+ std::ifstream file{tmpfile};
+ file >> actual_text;
+ BOOST_CHECK(valid);
+ BOOST_CHECK_EQUAL(actual_text, expected_text);
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index 1beef5cf04..b0d7389d39 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -72,9 +72,6 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
// The view cache should be empty since we had to destruct to downsize.
BOOST_CHECK(!c1.CoinsTip().HaveCoinInCache(outpoint));
}
-
- // Avoid triggering the address sanitizer.
- WITH_LOCK(::cs_main, manager.Unload());
}
//! Test UpdateTip behavior for both active and background chainstates.
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index 26392e690d..5d0ec593e3 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -99,8 +99,6 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
// Let scheduler events finish running to avoid accessing memory that is going to be unloaded
SyncWithValidationInterfaceQueue();
-
- WITH_LOCK(::cs_main, manager.Unload());
}
//! Test rebalancing the caches associated with each chainstate.