LCOV - code coverage report
Current view: top level - src/test - util_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1378 1401 98.4 %
Date: 2020-09-26 01:30:44 Functions: 390 390 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2020 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <util/system.h>
       6             : 
       7             : #include <clientversion.h>
       8             : #include <hash.h> // For Hash()
       9             : #include <key.h>  // For CKey
      10             : #include <optional.h>
      11             : #include <sync.h>
      12             : #include <test/util/logging.h>
      13             : #include <test/util/setup_common.h>
      14             : #include <test/util/str.h>
      15             : #include <uint256.h>
      16             : #include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
      17             : #include <util/moneystr.h>
      18             : #include <util/spanparsing.h>
      19             : #include <util/strencodings.h>
      20             : #include <util/string.h>
      21             : #include <util/time.h>
      22             : #include <util/vector.h>
      23             : 
      24             : #include <array>
      25             : #include <stdint.h>
      26             : #include <thread>
      27             : #include <univalue.h>
      28             : #include <utility>
      29             : #include <vector>
      30             : #ifndef WIN32
      31             : #include <signal.h>
      32             : #include <sys/types.h>
      33             : #include <sys/wait.h>
      34             : #endif
      35             : 
      36             : #include <boost/test/unit_test.hpp>
      37             : 
      38             : /* defined in logging.cpp */
      39             : namespace BCLog {
      40             :     std::string LogEscapeMessage(const std::string& str);
      41             : }
      42             : 
      43          89 : BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
      44             : 
      45         101 : BOOST_AUTO_TEST_CASE(util_check)
      46             : {
      47             :     // Check that Assert can forward
      48           4 :     const std::unique_ptr<int> p_two = Assert(MakeUnique<int>(2));
      49             :     // Check that Assert works on lvalues and rvalues
      50           4 :     const int two = *Assert(p_two);
      51           4 :     Assert(two == 2);
      52           4 :     Assert(true);
      53           2 : }
      54             : 
      55         101 : BOOST_AUTO_TEST_CASE(util_criticalsection)
      56             : {
      57           2 :     RecursiveMutex cs;
      58             : 
      59             :     do {
      60           2 :         LOCK(cs);
      61             :         break;
      62             : 
      63             :         BOOST_ERROR("break was swallowed!");
      64           2 :     } while(0);
      65             : 
      66             :     do {
      67           2 :         TRY_LOCK(cs, lockTest);
      68           2 :         if (lockTest) {
      69           2 :             BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
      70           2 :             break;
      71             :         }
      72             : 
      73           0 :         BOOST_ERROR("break was swallowed!");
      74           2 :     } while(0);
      75           2 : }
      76             : 
      77             : static const unsigned char ParseHex_expected[65] = {
      78             :     0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
      79             :     0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
      80             :     0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
      81             :     0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
      82             :     0x5f
      83             : };
      84         101 : BOOST_AUTO_TEST_CASE(util_ParseHex)
      85             : {
      86           2 :     std::vector<unsigned char> result;
      87           2 :     std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
      88             :     // Basic test vector
      89           2 :     result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
      90           2 :     BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
      91             : 
      92             :     // Spaces between bytes must be supported
      93           2 :     result = ParseHex("12 34 56 78");
      94           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
      95             : 
      96             :     // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
      97           2 :     result = ParseHex(" 89 34 56 78");
      98           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
      99             : 
     100             :     // Stop parsing at invalid value
     101           2 :     result = ParseHex("1234 invalid 1234");
     102           2 :     BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34);
     103           2 : }
     104             : 
     105         101 : BOOST_AUTO_TEST_CASE(util_HexStr)
     106             : {
     107           2 :     BOOST_CHECK_EQUAL(
     108             :         HexStr(ParseHex_expected),
     109             :         "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
     110             : 
     111           2 :     BOOST_CHECK_EQUAL(
     112             :         HexStr(Span<const unsigned char>(
     113             :                ParseHex_expected + sizeof(ParseHex_expected),
     114             :                ParseHex_expected + sizeof(ParseHex_expected))),
     115             :         "");
     116             : 
     117           2 :     BOOST_CHECK_EQUAL(
     118             :         HexStr(Span<const unsigned char>(ParseHex_expected, ParseHex_expected)),
     119             :         "");
     120             : 
     121           2 :     std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
     122             : 
     123           2 :     BOOST_CHECK_EQUAL(
     124             :         HexStr(ParseHex_vec),
     125             :         "04678afdb0"
     126             :     );
     127           2 : }
     128             : 
     129         101 : BOOST_AUTO_TEST_CASE(util_Join)
     130             : {
     131             :     // Normal version
     132           2 :     BOOST_CHECK_EQUAL(Join({}, ", "), "");
     133           2 :     BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
     134           4 :     BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
     135             : 
     136             :     // Version with unary operator
     137           6 :     const auto op_upper = [](const std::string& s) { return ToUpper(s); };
     138           2 :     BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), "");
     139           2 :     BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO");
     140           4 :     BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR");
     141           2 : }
     142             : 
     143         101 : BOOST_AUTO_TEST_CASE(util_FormatParseISO8601DateTime)
     144             : {
     145           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
     146           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z");
     147             : 
     148           2 :     BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:00Z"), 0);
     149           2 :     BOOST_CHECK_EQUAL(ParseISO8601DateTime("1960-01-01T00:00:00Z"), 0);
     150           2 :     BOOST_CHECK_EQUAL(ParseISO8601DateTime("2011-09-30T23:36:17Z"), 1317425777);
     151             : 
     152           2 :     auto time = GetSystemTimeInSeconds();
     153           2 :     BOOST_CHECK_EQUAL(ParseISO8601DateTime(FormatISO8601DateTime(time)), time);
     154           2 : }
     155             : 
     156         101 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
     157             : {
     158           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
     159           2 : }
     160             : 
     161       53176 : struct TestArgsManager : public ArgsManager
     162             : {
     163       53176 :     TestArgsManager() { m_network_only_args.clear(); }
     164          26 :     void ReadConfigString(const std::string str_config)
     165             :     {
     166          26 :         std::istringstream streamConfig(str_config);
     167             :         {
     168          26 :             LOCK(cs_args);
     169          26 :             m_settings.ro_config.clear();
     170          26 :             m_config_sections.clear();
     171          26 :         }
     172          26 :         std::string error;
     173          26 :         BOOST_REQUIRE(ReadConfigStream(streamConfig, "", error));
     174          26 :     }
     175       11878 :     void SetNetworkOnlyArg(const std::string arg)
     176             :     {
     177       11878 :         LOCK(cs_args);
     178       11878 :         m_network_only_args.insert(arg);
     179       11878 :     }
     180         100 :     void SetupArgs(const std::vector<std::pair<std::string, unsigned int>>& args)
     181             :     {
     182         238 :         for (const auto& arg : args) {
     183         138 :             AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
     184             :         }
     185         100 :     }
     186             :     using ArgsManager::GetSetting;
     187             :     using ArgsManager::GetSettingsList;
     188             :     using ArgsManager::ReadConfigStream;
     189             :     using ArgsManager::cs_args;
     190             :     using ArgsManager::m_network;
     191             :     using ArgsManager::m_settings;
     192             : };
     193             : 
     194             : //! Test GetSetting and GetArg type coercion, negation, and default value handling.
     195           4 : class CheckValueTest : public TestChain100Setup
     196             : {
     197             : public:
     198          52 :     struct Expect {
     199             :         util::SettingsValue setting;
     200          26 :         bool default_string = false;
     201          26 :         bool default_int = false;
     202          26 :         bool default_bool = false;
     203          26 :         const char* string_value = nullptr;
     204             :         Optional<int64_t> int_value;
     205             :         Optional<bool> bool_value;
     206             :         Optional<std::vector<std::string>> list_value;
     207          26 :         const char* error = nullptr;
     208             : 
     209          52 :         Expect(util::SettingsValue s) : setting(std::move(s)) {}
     210           2 :         Expect& DefaultString() { default_string = true; return *this; }
     211           2 :         Expect& DefaultInt() { default_int = true; return *this; }
     212           2 :         Expect& DefaultBool() { default_bool = true; return *this; }
     213          24 :         Expect& String(const char* s) { string_value = s; return *this; }
     214          24 :         Expect& Int(int64_t i) { int_value = i; return *this; }
     215          24 :         Expect& Bool(bool b) { bool_value = b; return *this; }
     216          26 :         Expect& List(std::vector<std::string> m) { list_value = std::move(m); return *this; }
     217             :         Expect& Error(const char* e) { error = e; return *this; }
     218             :     };
     219             : 
     220          26 :     void CheckValue(unsigned int flags, const char* arg, const Expect& expect)
     221             :     {
     222          26 :         TestArgsManager test;
     223          26 :         test.SetupArgs({{"-value", flags}});
     224          26 :         const char* argv[] = {"ignored", arg};
     225          26 :         std::string error;
     226          26 :         bool success = test.ParseParameters(arg ? 2 : 1, (char**)argv, error);
     227             : 
     228          26 :         BOOST_CHECK_EQUAL(test.GetSetting("-value").write(), expect.setting.write());
     229          26 :         auto settings_list = test.GetSettingsList("-value");
     230          26 :         if (expect.setting.isNull() || expect.setting.isFalse()) {
     231          10 :             BOOST_CHECK_EQUAL(settings_list.size(), 0U);
     232             :         } else {
     233          16 :             BOOST_CHECK_EQUAL(settings_list.size(), 1U);
     234          16 :             BOOST_CHECK_EQUAL(settings_list[0].write(), expect.setting.write());
     235             :         }
     236             : 
     237          26 :         if (expect.error) {
     238           0 :             BOOST_CHECK(!success);
     239           0 :             BOOST_CHECK_NE(error.find(expect.error), std::string::npos);
     240             :         } else {
     241          26 :             BOOST_CHECK(success);
     242          26 :             BOOST_CHECK_EQUAL(error, "");
     243             :         }
     244             : 
     245          26 :         if (expect.default_string) {
     246           2 :             BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), "zzzzz");
     247          24 :         } else if (expect.string_value) {
     248          24 :             BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), expect.string_value);
     249             :         } else {
     250           0 :             BOOST_CHECK(!success);
     251             :         }
     252             : 
     253          26 :         if (expect.default_int) {
     254           2 :             BOOST_CHECK_EQUAL(test.GetArg("-value", 99999), 99999);
     255          24 :         } else if (expect.int_value) {
     256          24 :             BOOST_CHECK_EQUAL(test.GetArg("-value", 99999), *expect.int_value);
     257             :         } else {
     258           0 :             BOOST_CHECK(!success);
     259             :         }
     260             : 
     261          26 :         if (expect.default_bool) {
     262           2 :             BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), false);
     263           2 :             BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), true);
     264          24 :         } else if (expect.bool_value) {
     265          24 :             BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), *expect.bool_value);
     266          24 :             BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), *expect.bool_value);
     267             :         } else {
     268           0 :             BOOST_CHECK(!success);
     269             :         }
     270             : 
     271          26 :         if (expect.list_value) {
     272          26 :             auto l = test.GetArgs("-value");
     273          26 :             BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(), expect.list_value->begin(), expect.list_value->end());
     274          26 :         } else {
     275           0 :             BOOST_CHECK(!success);
     276             :         }
     277          26 :     }
     278             : };
     279             : 
     280         101 : BOOST_FIXTURE_TEST_CASE(util_CheckValue, CheckValueTest)
     281             : {
     282             :     using M = ArgsManager;
     283             : 
     284           2 :     CheckValue(M::ALLOW_ANY, nullptr, Expect{{}}.DefaultString().DefaultInt().DefaultBool().List({}));
     285           2 :     CheckValue(M::ALLOW_ANY, "-novalue", Expect{false}.String("0").Int(0).Bool(false).List({}));
     286           2 :     CheckValue(M::ALLOW_ANY, "-novalue=", Expect{false}.String("0").Int(0).Bool(false).List({}));
     287           2 :     CheckValue(M::ALLOW_ANY, "-novalue=0", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));
     288           2 :     CheckValue(M::ALLOW_ANY, "-novalue=1", Expect{false}.String("0").Int(0).Bool(false).List({}));
     289           2 :     CheckValue(M::ALLOW_ANY, "-novalue=2", Expect{false}.String("0").Int(0).Bool(false).List({}));
     290           2 :     CheckValue(M::ALLOW_ANY, "-novalue=abc", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));
     291           2 :     CheckValue(M::ALLOW_ANY, "-value", Expect{""}.String("").Int(0).Bool(true).List({""}));
     292           2 :     CheckValue(M::ALLOW_ANY, "-value=", Expect{""}.String("").Int(0).Bool(true).List({""}));
     293           2 :     CheckValue(M::ALLOW_ANY, "-value=0", Expect{"0"}.String("0").Int(0).Bool(false).List({"0"}));
     294           2 :     CheckValue(M::ALLOW_ANY, "-value=1", Expect{"1"}.String("1").Int(1).Bool(true).List({"1"}));
     295           2 :     CheckValue(M::ALLOW_ANY, "-value=2", Expect{"2"}.String("2").Int(2).Bool(true).List({"2"}));
     296           2 :     CheckValue(M::ALLOW_ANY, "-value=abc", Expect{"abc"}.String("abc").Int(0).Bool(false).List({"abc"}));
     297           2 : }
     298             : 
     299         101 : BOOST_AUTO_TEST_CASE(util_ParseParameters)
     300             : {
     301           2 :     TestArgsManager testArgs;
     302           2 :     const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
     303           2 :     const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
     304           2 :     const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);
     305           2 :     const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
     306             : 
     307           2 :     const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
     308             : 
     309           2 :     std::string error;
     310           2 :     LOCK(testArgs.cs_args);
     311           8 :     testArgs.SetupArgs({a, b, ccc, d});
     312           2 :     BOOST_CHECK(testArgs.ParseParameters(0, (char**)argv_test, error));
     313           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
     314             : 
     315           2 :     BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error));
     316           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
     317             : 
     318           2 :     BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error));
     319             :     // expectation: -ignored is ignored (program name argument),
     320             :     // -a, -b and -ccc end up in map, -d ignored because it is after
     321             :     // a non-option argument (non-GNU option parsing)
     322           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 3 && testArgs.m_settings.ro_config.empty());
     323           2 :     BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc")
     324             :                 && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d"));
     325           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options.count("a") && testArgs.m_settings.command_line_options.count("b") && testArgs.m_settings.command_line_options.count("ccc")
     326             :                 && !testArgs.m_settings.command_line_options.count("f") && !testArgs.m_settings.command_line_options.count("d"));
     327             : 
     328           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options["a"].size() == 1);
     329           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options["a"].front().get_str() == "");
     330           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options["ccc"].size() == 2);
     331           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options["ccc"].front().get_str() == "argument");
     332           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options["ccc"].back().get_str() == "multiple");
     333           2 :     BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
     334           2 : }
     335             : 
     336         101 : BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)
     337             : {
     338           2 :     TestArgsManager test;
     339           2 :     test.SetupArgs({{"-registered", ArgsManager::ALLOW_ANY}});
     340             : 
     341           2 :     const char* argv[] = {"ignored", "-registered"};
     342           2 :     std::string error;
     343           2 :     BOOST_CHECK(test.ParseParameters(2, (char**)argv, error));
     344           2 :     BOOST_CHECK_EQUAL(error, "");
     345             : 
     346           2 :     argv[1] = "-unregistered";
     347           2 :     BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
     348           2 :     BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered");
     349             : 
     350             :     // Make sure registered parameters prefixed with a chain name trigger errors.
     351             :     // (Previously, they were accepted and ignored.)
     352           2 :     argv[1] = "-test.registered";
     353           2 :     BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
     354           2 :     BOOST_CHECK_EQUAL(error, "Invalid parameter -test.registered");
     355           2 : }
     356             : 
     357          62 : static void TestParse(const std::string& str, bool expected_bool, int64_t expected_int)
     358             : {
     359          62 :     TestArgsManager test;
     360          62 :     test.SetupArgs({{"-value", ArgsManager::ALLOW_ANY}});
     361          62 :     std::string arg = "-value=" + str;
     362          62 :     const char* argv[] = {"ignored", arg.c_str()};
     363          62 :     std::string error;
     364          62 :     BOOST_CHECK(test.ParseParameters(2, (char**)argv, error));
     365          62 :     BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), expected_bool);
     366          62 :     BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), expected_bool);
     367          62 :     BOOST_CHECK_EQUAL(test.GetArg("-value", 99998), expected_int);
     368          62 :     BOOST_CHECK_EQUAL(test.GetArg("-value", 99999), expected_int);
     369          62 : }
     370             : 
     371             : // Test bool and int parsing.
     372         101 : BOOST_AUTO_TEST_CASE(util_ArgParsing)
     373             : {
     374             :     // Some of these cases could be ambiguous or surprising to users, and might
     375             :     // be worth triggering errors or warnings in the future. But for now basic
     376             :     // test coverage is useful to avoid breaking backwards compatibility
     377             :     // unintentionally.
     378           2 :     TestParse("", true, 0);
     379           2 :     TestParse(" ", false, 0);
     380           2 :     TestParse("0", false, 0);
     381           2 :     TestParse("0 ", false, 0);
     382           2 :     TestParse(" 0", false, 0);
     383           2 :     TestParse("+0", false, 0);
     384           2 :     TestParse("-0", false, 0);
     385           2 :     TestParse("5", true, 5);
     386           2 :     TestParse("5 ", true, 5);
     387           2 :     TestParse(" 5", true, 5);
     388           2 :     TestParse("+5", true, 5);
     389           2 :     TestParse("-5", true, -5);
     390           2 :     TestParse("0 5", false, 0);
     391           2 :     TestParse("5 0", true, 5);
     392           2 :     TestParse("050", true, 50);
     393           2 :     TestParse("0.", false, 0);
     394           2 :     TestParse("5.", true, 5);
     395           2 :     TestParse("0.0", false, 0);
     396           2 :     TestParse("0.5", false, 0);
     397           2 :     TestParse("5.0", true, 5);
     398           2 :     TestParse("5.5", true, 5);
     399           2 :     TestParse("x", false, 0);
     400           2 :     TestParse("x0", false, 0);
     401           2 :     TestParse("x5", false, 0);
     402           2 :     TestParse("0x", false, 0);
     403           2 :     TestParse("5x", true, 5);
     404           2 :     TestParse("0x5", false, 0);
     405           2 :     TestParse("false", false, 0);
     406           2 :     TestParse("true", false, 0);
     407           2 :     TestParse("yes", false, 0);
     408           2 :     TestParse("no", false, 0);
     409           2 : }
     410             : 
     411         101 : BOOST_AUTO_TEST_CASE(util_GetBoolArg)
     412             : {
     413           2 :     TestArgsManager testArgs;
     414           2 :     const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
     415           2 :     const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
     416           2 :     const auto c = std::make_pair("-c", ArgsManager::ALLOW_ANY);
     417           2 :     const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
     418           2 :     const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
     419           2 :     const auto f = std::make_pair("-f", ArgsManager::ALLOW_ANY);
     420             : 
     421           2 :     const char *argv_test[] = {
     422             :         "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
     423           2 :     std::string error;
     424           2 :     LOCK(testArgs.cs_args);
     425          12 :     testArgs.SetupArgs({a, b, c, d, e, f});
     426           2 :     BOOST_CHECK(testArgs.ParseParameters(7, (char**)argv_test, error));
     427             : 
     428             :     // Each letter should be set.
     429          16 :     for (const char opt : "abcdef")
     430          14 :         BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
     431             : 
     432             :     // Nothing else should be in the map
     433           2 :     BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 6 &&
     434             :                 testArgs.m_settings.ro_config.empty());
     435             : 
     436             :     // The -no prefix should get stripped on the way in.
     437           2 :     BOOST_CHECK(!testArgs.IsArgSet("-nob"));
     438             : 
     439             :     // The -b option is flagged as negated, and nothing else is
     440           2 :     BOOST_CHECK(testArgs.IsArgNegated("-b"));
     441           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-a"));
     442             : 
     443             :     // Check expected values.
     444           2 :     BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
     445           2 :     BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
     446           2 :     BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
     447           2 :     BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
     448           2 :     BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
     449           2 :     BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
     450           2 : }
     451             : 
     452         101 : BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
     453             : {
     454             :     // Test some awful edge cases that hopefully no user will ever exercise.
     455           2 :     TestArgsManager testArgs;
     456             : 
     457             :     // Params test
     458           2 :     const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
     459           2 :     const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
     460           2 :     const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
     461           4 :     testArgs.SetupArgs({foo, bar});
     462           2 :     std::string error;
     463           2 :     BOOST_CHECK(testArgs.ParseParameters(4, (char**)argv_test, error));
     464             : 
     465             :     // This was passed twice, second one overrides the negative setting.
     466           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
     467           2 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
     468             : 
     469             :     // A double negative is a positive, and not marked as negated.
     470           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     471           2 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
     472             : 
     473             :     // Config test
     474             :     const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
     475           2 :     BOOST_CHECK(testArgs.ParseParameters(1, (char**)argv_test, error));
     476           2 :     testArgs.ReadConfigString(conf_test);
     477             : 
     478             :     // This was passed twice, second one overrides the negative setting,
     479             :     // and the value.
     480           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
     481           2 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
     482             : 
     483             :     // A double negative is a positive, and does not count as negated.
     484           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     485           2 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
     486             : 
     487             :     // Combined test
     488           2 :     const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
     489             :     const char *combo_test_conf = "foo=1\nnobar=1\n";
     490           2 :     BOOST_CHECK(testArgs.ParseParameters(3, (char**)combo_test_args, error));
     491           2 :     testArgs.ReadConfigString(combo_test_conf);
     492             : 
     493             :     // Command line overrides, but doesn't erase old setting
     494           2 :     BOOST_CHECK(testArgs.IsArgNegated("-foo"));
     495           2 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
     496           2 :     BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
     497             : 
     498             :     // Command line overrides, but doesn't erase old setting
     499           2 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     500           2 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
     501           2 :     BOOST_CHECK(testArgs.GetArgs("-bar").size() == 1
     502             :                 && testArgs.GetArgs("-bar").front() == "");
     503           2 : }
     504             : 
     505         101 : BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
     506             : {
     507             :     const char *str_config =
     508             :        "a=\n"
     509             :        "b=1\n"
     510             :        "ccc=argument\n"
     511             :        "ccc=multiple\n"
     512             :        "d=e\n"
     513             :        "nofff=1\n"
     514             :        "noggg=0\n"
     515             :        "h=1\n"
     516             :        "noh=1\n"
     517             :        "noi=1\n"
     518             :        "i=1\n"
     519             :        "sec1.ccc=extend1\n"
     520             :        "\n"
     521             :        "[sec1]\n"
     522             :        "ccc=extend2\n"
     523             :        "d=eee\n"
     524             :        "h=1\n"
     525             :        "[sec2]\n"
     526             :        "ccc=extend3\n"
     527             :        "iii=2\n";
     528             : 
     529           2 :     TestArgsManager test_args;
     530           2 :     LOCK(test_args.cs_args);
     531           2 :     const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
     532           2 :     const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
     533           2 :     const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);
     534           2 :     const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
     535           2 :     const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
     536           2 :     const auto fff = std::make_pair("-fff", ArgsManager::ALLOW_ANY);
     537           2 :     const auto ggg = std::make_pair("-ggg", ArgsManager::ALLOW_ANY);
     538           2 :     const auto h = std::make_pair("-h", ArgsManager::ALLOW_ANY);
     539           2 :     const auto i = std::make_pair("-i", ArgsManager::ALLOW_ANY);
     540           2 :     const auto iii = std::make_pair("-iii", ArgsManager::ALLOW_ANY);
     541          20 :     test_args.SetupArgs({a, b, ccc, d, e, fff, ggg, h, i, iii});
     542             : 
     543           2 :     test_args.ReadConfigString(str_config);
     544             :     // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
     545             :     // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
     546             : 
     547           2 :     BOOST_CHECK(test_args.m_settings.command_line_options.empty());
     548           2 :     BOOST_CHECK(test_args.m_settings.ro_config.size() == 3);
     549           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].size() == 8);
     550           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec1"].size() == 3);
     551           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec2"].size() == 2);
     552             : 
     553           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("a"));
     554           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("b"));
     555           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("ccc"));
     556           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("d"));
     557           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("fff"));
     558           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("ggg"));
     559           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("h"));
     560           2 :     BOOST_CHECK(test_args.m_settings.ro_config[""].count("i"));
     561           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("ccc"));
     562           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("h"));
     563           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec2"].count("ccc"));
     564           2 :     BOOST_CHECK(test_args.m_settings.ro_config["sec2"].count("iii"));
     565             : 
     566           2 :     BOOST_CHECK(test_args.IsArgSet("-a"));
     567           2 :     BOOST_CHECK(test_args.IsArgSet("-b"));
     568           2 :     BOOST_CHECK(test_args.IsArgSet("-ccc"));
     569           2 :     BOOST_CHECK(test_args.IsArgSet("-d"));
     570           2 :     BOOST_CHECK(test_args.IsArgSet("-fff"));
     571           2 :     BOOST_CHECK(test_args.IsArgSet("-ggg"));
     572           2 :     BOOST_CHECK(test_args.IsArgSet("-h"));
     573           2 :     BOOST_CHECK(test_args.IsArgSet("-i"));
     574           2 :     BOOST_CHECK(!test_args.IsArgSet("-zzz"));
     575           2 :     BOOST_CHECK(!test_args.IsArgSet("-iii"));
     576             : 
     577           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
     578           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
     579           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-ccc", "xxx"), "argument");
     580           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-d", "xxx"), "e");
     581           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
     582           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
     583           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-h", "xxx"), "0");
     584           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-i", "xxx"), "1");
     585           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
     586           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
     587             : 
     588           6 :     for (const bool def : {false, true}) {
     589           4 :         BOOST_CHECK(test_args.GetBoolArg("-a", def));
     590           4 :         BOOST_CHECK(test_args.GetBoolArg("-b", def));
     591           4 :         BOOST_CHECK(!test_args.GetBoolArg("-ccc", def));
     592           4 :         BOOST_CHECK(!test_args.GetBoolArg("-d", def));
     593           4 :         BOOST_CHECK(!test_args.GetBoolArg("-fff", def));
     594           4 :         BOOST_CHECK(test_args.GetBoolArg("-ggg", def));
     595           4 :         BOOST_CHECK(!test_args.GetBoolArg("-h", def));
     596           4 :         BOOST_CHECK(test_args.GetBoolArg("-i", def));
     597           4 :         BOOST_CHECK(test_args.GetBoolArg("-zzz", def) == def);
     598           4 :         BOOST_CHECK(test_args.GetBoolArg("-iii", def) == def);
     599             :     }
     600             : 
     601           2 :     BOOST_CHECK(test_args.GetArgs("-a").size() == 1
     602             :                 && test_args.GetArgs("-a").front() == "");
     603           2 :     BOOST_CHECK(test_args.GetArgs("-b").size() == 1
     604             :                 && test_args.GetArgs("-b").front() == "1");
     605           2 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
     606             :                 && test_args.GetArgs("-ccc").front() == "argument"
     607             :                 && test_args.GetArgs("-ccc").back() == "multiple");
     608           2 :     BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
     609           2 :     BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
     610           2 :     BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
     611             :                 && test_args.GetArgs("-ggg").front() == "1");
     612           2 :     BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
     613           2 :     BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
     614           2 :     BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
     615           2 :     BOOST_CHECK(test_args.GetArgs("-i").size() == 1
     616             :                 && test_args.GetArgs("-i").front() == "1");
     617           2 :     BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
     618           2 :     BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
     619             : 
     620           2 :     BOOST_CHECK(!test_args.IsArgNegated("-a"));
     621           2 :     BOOST_CHECK(!test_args.IsArgNegated("-b"));
     622           2 :     BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
     623           2 :     BOOST_CHECK(!test_args.IsArgNegated("-d"));
     624           2 :     BOOST_CHECK(test_args.IsArgNegated("-fff"));
     625           2 :     BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
     626           2 :     BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
     627           2 :     BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
     628           2 :     BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
     629             : 
     630             :     // Test sections work
     631           2 :     test_args.SelectConfigNetwork("sec1");
     632             : 
     633             :     // same as original
     634           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
     635           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
     636           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
     637           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
     638           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
     639           2 :     BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
     640             :     // d is overridden
     641           2 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
     642             :     // section-specific setting
     643           2 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
     644             :     // section takes priority for multiple values
     645           2 :     BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
     646             :     // check multiple values works
     647           8 :     const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
     648           2 :     const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
     649           2 :     BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
     650             : 
     651           2 :     test_args.SelectConfigNetwork("sec2");
     652             : 
     653             :     // same as original
     654           2 :     BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");
     655           2 :     BOOST_CHECK(test_args.GetArg("-b", "xxx") == "1");
     656           2 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
     657           2 :     BOOST_CHECK(test_args.GetArg("-fff", "xxx") == "0");
     658           2 :     BOOST_CHECK(test_args.GetArg("-ggg", "xxx") == "1");
     659           2 :     BOOST_CHECK(test_args.GetArg("-zzz", "xxx") == "xxx");
     660           2 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
     661             :     // section-specific setting
     662           2 :     BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
     663             :     // section takes priority for multiple values
     664           2 :     BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
     665             :     // check multiple values works
     666           6 :     const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
     667           2 :     const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
     668           2 :     BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
     669             : 
     670             :     // Test section only options
     671             : 
     672           2 :     test_args.SetNetworkOnlyArg("-d");
     673           2 :     test_args.SetNetworkOnlyArg("-ccc");
     674           2 :     test_args.SetNetworkOnlyArg("-h");
     675             : 
     676           2 :     test_args.SelectConfigNetwork(CBaseChainParams::MAIN);
     677           2 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
     678           2 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
     679           2 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
     680             : 
     681           2 :     test_args.SelectConfigNetwork("sec1");
     682           2 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
     683           2 :     BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
     684           2 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
     685           2 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
     686             : 
     687           2 :     test_args.SelectConfigNetwork("sec2");
     688           2 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
     689           2 :     BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
     690           2 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
     691           2 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
     692           2 : }
     693             : 
     694         101 : BOOST_AUTO_TEST_CASE(util_GetArg)
     695             : {
     696           2 :     TestArgsManager testArgs;
     697           2 :     LOCK(testArgs.cs_args);
     698           2 :     testArgs.m_settings.command_line_options.clear();
     699           2 :     testArgs.m_settings.command_line_options["strtest1"] = {"string..."};
     700             :     // strtest2 undefined on purpose
     701           2 :     testArgs.m_settings.command_line_options["inttest1"] = {"12345"};
     702           2 :     testArgs.m_settings.command_line_options["inttest2"] = {"81985529216486895"};
     703             :     // inttest3 undefined on purpose
     704           2 :     testArgs.m_settings.command_line_options["booltest1"] = {""};
     705             :     // booltest2 undefined on purpose
     706           2 :     testArgs.m_settings.command_line_options["booltest3"] = {"0"};
     707           2 :     testArgs.m_settings.command_line_options["booltest4"] = {"1"};
     708             : 
     709             :     // priorities
     710           4 :     testArgs.m_settings.command_line_options["pritest1"] = {"a", "b"};
     711           4 :     testArgs.m_settings.ro_config[""]["pritest2"] = {"a", "b"};
     712           2 :     testArgs.m_settings.command_line_options["pritest3"] = {"a"};
     713           2 :     testArgs.m_settings.ro_config[""]["pritest3"] = {"b"};
     714           4 :     testArgs.m_settings.command_line_options["pritest4"] = {"a","b"};
     715           4 :     testArgs.m_settings.ro_config[""]["pritest4"] = {"c","d"};
     716             : 
     717           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
     718           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
     719           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest1", -1), 12345);
     720           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest2", -1), 81985529216486895LL);
     721           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest3", -1), -1);
     722           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
     723           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
     724           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
     725           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
     726             : 
     727           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
     728           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
     729           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
     730           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
     731           2 : }
     732             : 
     733         101 : BOOST_AUTO_TEST_CASE(util_GetChainName)
     734             : {
     735           2 :     TestArgsManager test_args;
     736           2 :     const auto testnet = std::make_pair("-testnet", ArgsManager::ALLOW_ANY);
     737           2 :     const auto regtest = std::make_pair("-regtest", ArgsManager::ALLOW_ANY);
     738           4 :     test_args.SetupArgs({testnet, regtest});
     739             : 
     740           2 :     const char* argv_testnet[] = {"cmd", "-testnet"};
     741           2 :     const char* argv_regtest[] = {"cmd", "-regtest"};
     742           2 :     const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
     743           2 :     const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
     744             : 
     745             :     // equivalent to "-testnet"
     746             :     // regtest in testnet section is ignored
     747             :     const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
     748           2 :     std::string error;
     749             : 
     750           2 :     BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
     751           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
     752             : 
     753           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
     754           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     755             : 
     756           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
     757           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
     758             : 
     759           2 :     BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
     760           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     761             : 
     762           2 :     BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
     763           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     764             : 
     765           2 :     BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
     766           2 :     test_args.ReadConfigString(testnetconf);
     767           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     768             : 
     769           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
     770           2 :     test_args.ReadConfigString(testnetconf);
     771           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     772             : 
     773           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
     774           2 :     test_args.ReadConfigString(testnetconf);
     775           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     776             : 
     777           2 :     BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
     778           2 :     test_args.ReadConfigString(testnetconf);
     779           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     780             : 
     781           2 :     BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
     782           2 :     test_args.ReadConfigString(testnetconf);
     783           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     784             : 
     785             :     // check setting the network to test (and thus making
     786             :     // [test] regtest=1 potentially relevant) doesn't break things
     787           2 :     test_args.SelectConfigNetwork("test");
     788             : 
     789           2 :     BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
     790           2 :     test_args.ReadConfigString(testnetconf);
     791           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     792             : 
     793           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
     794           2 :     test_args.ReadConfigString(testnetconf);
     795           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     796             : 
     797           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
     798           2 :     test_args.ReadConfigString(testnetconf);
     799           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     800             : 
     801           2 :     BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_test_no_reg, error));
     802           2 :     test_args.ReadConfigString(testnetconf);
     803           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     804             : 
     805           2 :     BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
     806           2 :     test_args.ReadConfigString(testnetconf);
     807           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     808          12 : }
     809             : 
     810             : // Test different ways settings can be merged, and verify results. This test can
     811             : // be used to confirm that updates to settings code don't change behavior
     812             : // unintentionally.
     813             : //
     814             : // The test covers:
     815             : //
     816             : // - Combining different setting actions. Possible actions are: configuring a
     817             : //   setting, negating a setting (adding "-no" prefix), and configuring/negating
     818             : //   settings in a network section (adding "main." or "test." prefixes).
     819             : //
     820             : // - Combining settings from command line arguments and a config file.
     821             : //
     822             : // - Combining SoftSet and ForceSet calls.
     823             : //
     824             : // - Testing "main" and "test" network values to make sure settings from network
     825             : //   sections are applied and to check for mainnet-specific behaviors like
     826             : //   inheriting settings from the default section.
     827             : //
     828             : // - Testing network-specific settings like "-wallet", that may be ignored
     829             : //   outside a network section, and non-network specific settings like "-server"
     830             : //   that aren't sensitive to the network.
     831             : //
     832           4 : struct ArgsMergeTestingSetup : public BasicTestingSetup {
     833             :     //! Max number of actions to sequence together. Can decrease this when
     834             :     //! debugging to make test results easier to understand.
     835             :     static constexpr int MAX_ACTIONS = 3;
     836             : 
     837             :     enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE };
     838             :     using ActionList = Action[MAX_ACTIONS];
     839             : 
     840             :     //! Enumerate all possible test configurations.
     841             :     template <typename Fn>
     842           2 :     void ForEachMergeSetup(Fn&& fn)
     843             :     {
     844           2 :         ActionList arg_actions = {};
     845             :         // command_line_options do not have sections. Only iterate over SET and NEGATE
     846          16 :         ForEachNoDup(arg_actions, SET, NEGATE, [&] {
     847          14 :             ActionList conf_actions = {};
     848         756 :             ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
     849        2226 :                 for (bool soft_set : {false, true}) {
     850        4452 :                     for (bool force_set : {false, true}) {
     851       11872 :                         for (const std::string& section : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) {
     852       23744 :                             for (const std::string& network : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET}) {
     853       35616 :                                 for (bool net_specific : {false, true}) {
     854       23744 :                                     fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
     855             :                                 }
     856             :                             }
     857             :                         }
     858             :                     }
     859             :                 }
     860         742 :             });
     861          14 :         });
     862           2 :     }
     863             : 
     864             :     //! Translate actions into a list of <key>=<value> setting strings.
     865       47488 :     std::vector<std::string> GetValues(const ActionList& actions,
     866             :         const std::string& section,
     867             :         const std::string& name,
     868             :         const std::string& value_prefix)
     869             :     {
     870       47488 :         std::vector<std::string> values;
     871       47488 :         int suffix = 0;
     872      149120 :         for (Action action : actions) {
     873      126208 :             if (action == NONE) break;
     874      101632 :             std::string prefix;
     875      101632 :             if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";
     876      101632 :             if (action == SET || action == SECTION_SET) {
     877      152448 :                 for (int i = 0; i < 2; ++i) {
     878      101632 :                     values.push_back(prefix + name + "=" + value_prefix + ToString(++suffix));
     879             :                 }
     880       50816 :             }
     881      101632 :             if (action == NEGATE || action == SECTION_NEGATE) {
     882       50816 :                 values.push_back(prefix + "no" + name + "=1");
     883       50816 :             }
     884      101632 :         }
     885             :         return values;
     886       47488 :     }
     887             : };
     888             : 
     889             : // Regression test covering different ways config settings can be merged. The
     890             : // test parses and merges settings, representing the results as strings that get
     891             : // compared against an expected hash. To debug, the result strings can be dumped
     892             : // to a file (see comments below).
     893         101 : BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
     894             : {
     895           2 :     CHash256 out_sha;
     896           2 :     FILE* out_file = nullptr;
     897           2 :     if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) {
     898           0 :         out_file = fsbridge::fopen(out_path, "w");
     899           0 :         if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
     900             :     }
     901             : 
     902       23746 :     ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool soft_set, bool force_set,
     903             :                           const std::string& section, const std::string& network, bool net_specific) {
     904       23744 :         TestArgsManager parser;
     905       23744 :         LOCK(parser.cs_args);
     906             : 
     907       23744 :         std::string desc = "net=";
     908       23744 :         desc += network;
     909       23744 :         parser.m_network = network;
     910             : 
     911       23744 :         const std::string& name = net_specific ? "wallet" : "server";
     912       23744 :         const std::string key = "-" + name;
     913       23744 :         parser.AddArg(key, name, ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
     914       23744 :         if (net_specific) parser.SetNetworkOnlyArg(key);
     915             : 
     916       23744 :         auto args = GetValues(arg_actions, section, name, "a");
     917       23744 :         std::vector<const char*> argv = {"ignored"};
     918       84800 :         for (auto& arg : args) {
     919       61056 :             arg.insert(0, "-");
     920       61056 :             desc += " ";
     921       61056 :             desc += arg;
     922       61056 :             argv.push_back(arg.c_str());
     923             :         }
     924       23744 :         std::string error;
     925       23744 :         BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
     926       23744 :         BOOST_CHECK_EQUAL(error, "");
     927             : 
     928       23744 :         std::string conf;
     929      115136 :         for (auto& conf_val : GetValues(conf_actions, section, name, "c")) {
     930       91392 :             desc += " ";
     931       91392 :             desc += conf_val;
     932       91392 :             conf += conf_val;
     933       91392 :             conf += "\n";
     934             :         }
     935       23744 :         std::istringstream conf_stream(conf);
     936       23744 :         BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
     937       23744 :         BOOST_CHECK_EQUAL(error, "");
     938             : 
     939       23744 :         if (soft_set) {
     940       11872 :             desc += " soft";
     941       11872 :             parser.SoftSetArg(key, "soft1");
     942       11872 :             parser.SoftSetArg(key, "soft2");
     943       11872 :         }
     944             : 
     945       23744 :         if (force_set) {
     946       11872 :             desc += " force";
     947       11872 :             parser.ForceSetArg(key, "force1");
     948       11872 :             parser.ForceSetArg(key, "force2");
     949       11872 :         }
     950             : 
     951       23744 :         desc += " || ";
     952             : 
     953       23744 :         if (!parser.IsArgSet(key)) {
     954         116 :             desc += "unset";
     955         116 :             BOOST_CHECK(!parser.IsArgNegated(key));
     956         116 :             BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default");
     957         116 :             BOOST_CHECK(parser.GetArgs(key).empty());
     958       23628 :         } else if (parser.IsArgNegated(key)) {
     959        5872 :             desc += "negated";
     960        5872 :             BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0");
     961        5872 :             BOOST_CHECK(parser.GetArgs(key).empty());
     962             :         } else {
     963       17756 :             desc += parser.GetArg(key, "default");
     964       17756 :             desc += " |";
     965       61656 :             for (const auto& arg : parser.GetArgs(key)) {
     966       43900 :                 desc += " ";
     967       43900 :                 desc += arg;
     968             :             }
     969             :         }
     970             : 
     971       23744 :         std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs();
     972       23744 :         if (!ignored.empty()) {
     973         524 :             desc += " | ignored";
     974        1048 :             for (const auto& arg : ignored) {
     975         524 :                 desc += " ";
     976         524 :                 desc += arg;
     977           0 :             }
     978         524 :         }
     979             : 
     980       23744 :         desc += "\n";
     981             : 
     982       23744 :         out_sha.Write(MakeUCharSpan(desc));
     983       23744 :         if (out_file) {
     984           0 :             BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
     985             :         }
     986       23744 :     });
     987             : 
     988           2 :     if (out_file) {
     989           0 :         if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
     990           0 :         out_file = nullptr;
     991           0 :     }
     992             : 
     993           2 :     unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
     994           2 :     out_sha.Finalize(out_sha_bytes);
     995           2 :     std::string out_sha_hex = HexStr(out_sha_bytes);
     996             : 
     997             :     // If check below fails, should manually dump the results with:
     998             :     //
     999             :     //   ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ArgsMerge
    1000             :     //
    1001             :     // And verify diff against previous results to make sure the changes are expected.
    1002             :     //
    1003             :     // Results file is formatted like:
    1004             :     //
    1005             :     //   <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
    1006           2 :     BOOST_CHECK_EQUAL(out_sha_hex, "8fd4877bb8bf337badca950ede6c917441901962f160e52514e06a60dea46cde");
    1007           2 : }
    1008             : 
    1009             : // Similar test as above, but for ArgsManager::GetChainName function.
    1010           4 : struct ChainMergeTestingSetup : public BasicTestingSetup {
    1011             :     static constexpr int MAX_ACTIONS = 2;
    1012             : 
    1013             :     enum Action { NONE, ENABLE_TEST, DISABLE_TEST, NEGATE_TEST, ENABLE_REG, DISABLE_REG, NEGATE_REG };
    1014             :     using ActionList = Action[MAX_ACTIONS];
    1015             : 
    1016             :     //! Enumerate all possible test configurations.
    1017             :     template <typename Fn>
    1018           2 :     void ForEachMergeSetup(Fn&& fn)
    1019             :     {
    1020           2 :         ActionList arg_actions = {};
    1021          76 :         ForEachNoDup(arg_actions, ENABLE_TEST, NEGATE_REG, [&] {
    1022          74 :             ActionList conf_actions = {};
    1023        2812 :             ForEachNoDup(conf_actions, ENABLE_TEST, NEGATE_REG, [&] { fn(arg_actions, conf_actions); });
    1024          74 :         });
    1025           2 :     }
    1026             : };
    1027             : 
    1028         101 : BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
    1029             : {
    1030           2 :     CHash256 out_sha;
    1031           2 :     FILE* out_file = nullptr;
    1032           2 :     if (const char* out_path = getenv("CHAIN_MERGE_TEST_OUT")) {
    1033           0 :         out_file = fsbridge::fopen(out_path, "w");
    1034           0 :         if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
    1035             :     }
    1036             : 
    1037        2740 :     ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions) {
    1038        2738 :         TestArgsManager parser;
    1039        2738 :         LOCK(parser.cs_args);
    1040        2738 :         parser.AddArg("-regtest", "regtest", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    1041        2738 :         parser.AddArg("-testnet", "testnet", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    1042             : 
    1043       22718 :         auto arg = [](Action action) { return action == ENABLE_TEST  ? "-testnet=1"   :
    1044        9176 :                                               action == DISABLE_TEST ? "-testnet=0"   :
    1045        7548 :                                               action == NEGATE_TEST  ? "-notestnet=1" :
    1046        5920 :                                               action == ENABLE_REG   ? "-regtest=1"   :
    1047        4292 :                                               action == DISABLE_REG  ? "-regtest=0"   :
    1048        2664 :                                               action == NEGATE_REG   ? "-noregtest=1" : nullptr; };
    1049             : 
    1050        2738 :         std::string desc;
    1051        2738 :         std::vector<const char*> argv = {"ignored"};
    1052        7622 :         for (Action action : arg_actions) {
    1053        5402 :             const char* argstr = arg(action);
    1054        5402 :             if (!argstr) break;
    1055        4884 :             argv.push_back(argstr);
    1056        4884 :             desc += " ";
    1057        4884 :             desc += argv.back();
    1058        5402 :         }
    1059        2738 :         std::string error;
    1060        2738 :         BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
    1061        2738 :         BOOST_CHECK_EQUAL(error, "");
    1062             : 
    1063        2738 :         std::string conf;
    1064        7622 :         for (Action action : conf_actions) {
    1065        5402 :             const char* argstr = arg(action);
    1066        5402 :             if (!argstr) break;
    1067        4884 :             desc += " ";
    1068        4884 :             desc += argstr + 1;
    1069        4884 :             conf += argstr + 1;
    1070        4884 :             conf += "\n";
    1071        9768 :         }
    1072        2738 :         std::istringstream conf_stream(conf);
    1073        2738 :         BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
    1074        2738 :         BOOST_CHECK_EQUAL(error, "");
    1075             : 
    1076        2738 :         desc += " || ";
    1077             :         try {
    1078        3102 :             desc += parser.GetChainName();
    1079        2738 :         } catch (const std::runtime_error& e) {
    1080         364 :             desc += "error: ";
    1081         364 :             desc += e.what();
    1082         364 :         }
    1083        2738 :         desc += "\n";
    1084             : 
    1085        2738 :         out_sha.Write(MakeUCharSpan(desc));
    1086        2738 :         if (out_file) {
    1087           0 :             BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
    1088             :         }
    1089        3102 :     });
    1090             : 
    1091           2 :     if (out_file) {
    1092           0 :         if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
    1093           0 :         out_file = nullptr;
    1094           0 :     }
    1095             : 
    1096           2 :     unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
    1097           2 :     out_sha.Finalize(out_sha_bytes);
    1098           2 :     std::string out_sha_hex = HexStr(out_sha_bytes);
    1099             : 
    1100             :     // If check below fails, should manually dump the results with:
    1101             :     //
    1102             :     //   CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=util_tests/util_ChainMerge
    1103             :     //
    1104             :     // And verify diff against previous results to make sure the changes are expected.
    1105             :     //
    1106             :     // Results file is formatted like:
    1107             :     //
    1108             :     //   <input> || <output>
    1109           2 :     BOOST_CHECK_EQUAL(out_sha_hex, "f0b3a3c29869edc765d579c928f7f1690a71fbb673b49ccf39cbc4de18156a0d");
    1110           2 : }
    1111             : 
    1112         101 : BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
    1113             : {
    1114             :     // Test writing setting.
    1115           2 :     TestArgsManager args1;
    1116           4 :     args1.LockSettings([&](util::Settings& settings) { settings.rw_settings["name"] = "value"; });
    1117           2 :     args1.WriteSettingsFile();
    1118             : 
    1119             :     // Test reading setting.
    1120           2 :     TestArgsManager args2;
    1121           2 :     args2.ReadSettingsFile();
    1122           4 :     args2.LockSettings([&](util::Settings& settings) { BOOST_CHECK_EQUAL(settings.rw_settings["name"].get_str(), "value"); });
    1123             : 
    1124             :     // Test error logging, and remove previously written setting.
    1125             :     {
    1126           2 :         ASSERT_DEBUG_LOG("Failed renaming settings file");
    1127           2 :         fs::remove(GetDataDir() / "settings.json");
    1128           2 :         fs::create_directory(GetDataDir() / "settings.json");
    1129           2 :         args2.WriteSettingsFile();
    1130           2 :         fs::remove(GetDataDir() / "settings.json");
    1131           2 :     }
    1132           2 : }
    1133             : 
    1134         101 : BOOST_AUTO_TEST_CASE(util_FormatMoney)
    1135             : {
    1136           2 :     BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
    1137           2 :     BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
    1138           2 :     BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
    1139             : 
    1140           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
    1141           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
    1142           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
    1143           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
    1144           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
    1145           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
    1146           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
    1147           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
    1148           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
    1149           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
    1150           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
    1151           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
    1152           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
    1153           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
    1154           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
    1155           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
    1156           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
    1157           2 : }
    1158             : 
    1159         101 : BOOST_AUTO_TEST_CASE(util_ParseMoney)
    1160             : {
    1161           2 :     CAmount ret = 0;
    1162           2 :     BOOST_CHECK(ParseMoney("0.0", ret));
    1163           2 :     BOOST_CHECK_EQUAL(ret, 0);
    1164             : 
    1165           2 :     BOOST_CHECK(ParseMoney("12345.6789", ret));
    1166           2 :     BOOST_CHECK_EQUAL(ret, (COIN/10000)*123456789);
    1167             : 
    1168           2 :     BOOST_CHECK(ParseMoney("100000000.00", ret));
    1169           2 :     BOOST_CHECK_EQUAL(ret, COIN*100000000);
    1170           2 :     BOOST_CHECK(ParseMoney("10000000.00", ret));
    1171           2 :     BOOST_CHECK_EQUAL(ret, COIN*10000000);
    1172           2 :     BOOST_CHECK(ParseMoney("1000000.00", ret));
    1173           2 :     BOOST_CHECK_EQUAL(ret, COIN*1000000);
    1174           2 :     BOOST_CHECK(ParseMoney("100000.00", ret));
    1175           2 :     BOOST_CHECK_EQUAL(ret, COIN*100000);
    1176           2 :     BOOST_CHECK(ParseMoney("10000.00", ret));
    1177           2 :     BOOST_CHECK_EQUAL(ret, COIN*10000);
    1178           2 :     BOOST_CHECK(ParseMoney("1000.00", ret));
    1179           2 :     BOOST_CHECK_EQUAL(ret, COIN*1000);
    1180           2 :     BOOST_CHECK(ParseMoney("100.00", ret));
    1181           2 :     BOOST_CHECK_EQUAL(ret, COIN*100);
    1182           2 :     BOOST_CHECK(ParseMoney("10.00", ret));
    1183           2 :     BOOST_CHECK_EQUAL(ret, COIN*10);
    1184           2 :     BOOST_CHECK(ParseMoney("1.00", ret));
    1185           2 :     BOOST_CHECK_EQUAL(ret, COIN);
    1186           2 :     BOOST_CHECK(ParseMoney("1", ret));
    1187           2 :     BOOST_CHECK_EQUAL(ret, COIN);
    1188           2 :     BOOST_CHECK(ParseMoney("   1", ret));
    1189           2 :     BOOST_CHECK_EQUAL(ret, COIN);
    1190           2 :     BOOST_CHECK(ParseMoney("1   ", ret));
    1191           2 :     BOOST_CHECK_EQUAL(ret, COIN);
    1192           2 :     BOOST_CHECK(ParseMoney("  1 ", ret));
    1193           2 :     BOOST_CHECK_EQUAL(ret, COIN);
    1194           2 :     BOOST_CHECK(ParseMoney("0.1", ret));
    1195           2 :     BOOST_CHECK_EQUAL(ret, COIN/10);
    1196           2 :     BOOST_CHECK(ParseMoney("0.01", ret));
    1197           2 :     BOOST_CHECK_EQUAL(ret, COIN/100);
    1198           2 :     BOOST_CHECK(ParseMoney("0.001", ret));
    1199           2 :     BOOST_CHECK_EQUAL(ret, COIN/1000);
    1200           2 :     BOOST_CHECK(ParseMoney("0.0001", ret));
    1201           2 :     BOOST_CHECK_EQUAL(ret, COIN/10000);
    1202           2 :     BOOST_CHECK(ParseMoney("0.00001", ret));
    1203           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000);
    1204           2 :     BOOST_CHECK(ParseMoney("0.000001", ret));
    1205           2 :     BOOST_CHECK_EQUAL(ret, COIN/1000000);
    1206           2 :     BOOST_CHECK(ParseMoney("0.0000001", ret));
    1207           2 :     BOOST_CHECK_EQUAL(ret, COIN/10000000);
    1208           2 :     BOOST_CHECK(ParseMoney("0.00000001", ret));
    1209           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000000);
    1210           2 :     BOOST_CHECK(ParseMoney(" 0.00000001 ", ret));
    1211           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000000);
    1212           2 :     BOOST_CHECK(ParseMoney("0.00000001 ", ret));
    1213           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000000);
    1214           2 :     BOOST_CHECK(ParseMoney(" 0.00000001", ret));
    1215           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000000);
    1216             : 
    1217             :     // Parsing amount that can not be represented in ret should fail
    1218           2 :     BOOST_CHECK(!ParseMoney("0.000000001", ret));
    1219             : 
    1220             :     // Parsing empty string should fail
    1221           2 :     BOOST_CHECK(!ParseMoney("", ret));
    1222           2 :     BOOST_CHECK(!ParseMoney(" ", ret));
    1223           2 :     BOOST_CHECK(!ParseMoney("  ", ret));
    1224             : 
    1225             :     // Parsing two numbers should fail
    1226           2 :     BOOST_CHECK(!ParseMoney("1 2", ret));
    1227           2 :     BOOST_CHECK(!ParseMoney(" 1 2 ", ret));
    1228           2 :     BOOST_CHECK(!ParseMoney(" 1.2 3 ", ret));
    1229           2 :     BOOST_CHECK(!ParseMoney(" 1 2.3 ", ret));
    1230             : 
    1231             :     // Attempted 63 bit overflow should fail
    1232           2 :     BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
    1233             : 
    1234             :     // Parsing negative amounts must fail
    1235           2 :     BOOST_CHECK(!ParseMoney("-1", ret));
    1236             : 
    1237             :     // Parsing strings with embedded NUL characters should fail
    1238           2 :     BOOST_CHECK(!ParseMoney(std::string("\0-1", 3), ret));
    1239           2 :     BOOST_CHECK(!ParseMoney(std::string("\01", 2), ret));
    1240           2 :     BOOST_CHECK(!ParseMoney(std::string("1\0", 2), ret));
    1241           2 : }
    1242             : 
    1243         101 : BOOST_AUTO_TEST_CASE(util_IsHex)
    1244             : {
    1245           2 :     BOOST_CHECK(IsHex("00"));
    1246           2 :     BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
    1247           2 :     BOOST_CHECK(IsHex("ff"));
    1248           2 :     BOOST_CHECK(IsHex("FF"));
    1249             : 
    1250           2 :     BOOST_CHECK(!IsHex(""));
    1251           2 :     BOOST_CHECK(!IsHex("0"));
    1252           2 :     BOOST_CHECK(!IsHex("a"));
    1253           2 :     BOOST_CHECK(!IsHex("eleven"));
    1254           2 :     BOOST_CHECK(!IsHex("00xx00"));
    1255           2 :     BOOST_CHECK(!IsHex("0x0000"));
    1256           2 : }
    1257             : 
    1258         101 : BOOST_AUTO_TEST_CASE(util_IsHexNumber)
    1259             : {
    1260           2 :     BOOST_CHECK(IsHexNumber("0x0"));
    1261           2 :     BOOST_CHECK(IsHexNumber("0"));
    1262           2 :     BOOST_CHECK(IsHexNumber("0x10"));
    1263           2 :     BOOST_CHECK(IsHexNumber("10"));
    1264           2 :     BOOST_CHECK(IsHexNumber("0xff"));
    1265           2 :     BOOST_CHECK(IsHexNumber("ff"));
    1266           2 :     BOOST_CHECK(IsHexNumber("0xFfa"));
    1267           2 :     BOOST_CHECK(IsHexNumber("Ffa"));
    1268           2 :     BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
    1269           2 :     BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
    1270             : 
    1271           2 :     BOOST_CHECK(!IsHexNumber(""));   // empty string not allowed
    1272           2 :     BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
    1273           2 :     BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
    1274           2 :     BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
    1275           2 :     BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
    1276           2 :     BOOST_CHECK(!IsHexNumber(" "));    // etc.
    1277           2 :     BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
    1278           2 :     BOOST_CHECK(!IsHexNumber("x0"));    // broken prefix
    1279           2 :     BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
    1280             : 
    1281           2 : }
    1282             : 
    1283         101 : BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
    1284             : {
    1285           2 :     SeedInsecureRand(SeedRand::ZEROS);
    1286          20 :     for (int mod=2;mod<11;mod++)
    1287             :     {
    1288             :         int mask = 1;
    1289             :         // Really rough binomial confidence approximation.
    1290          18 :         int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
    1291             :         //mask is 2^ceil(log2(mod))-1
    1292          50 :         while(mask<mod-1)mask=(mask<<1)+1;
    1293             : 
    1294             :         int count = 0;
    1295             :         //How often does it get a zero from the uniform range [0,mod)?
    1296      180018 :         for (int i = 0; i < 10000; i++) {
    1297             :             uint32_t rval;
    1298      180000 :             do{
    1299      235652 :                 rval=InsecureRand32()&mask;
    1300      235652 :             }while(rval>=(uint32_t)mod);
    1301      180000 :             count += rval==0;
    1302             :         }
    1303          18 :         BOOST_CHECK(count<=10000/mod+err);
    1304          18 :         BOOST_CHECK(count>=10000/mod-err);
    1305             :     }
    1306           2 : }
    1307             : 
    1308         101 : BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
    1309             : {
    1310           2 :     BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
    1311           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
    1312           2 :     BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
    1313           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
    1314           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
    1315           2 :     BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
    1316           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
    1317           2 : }
    1318             : 
    1319             : /* Test strprintf formatting directives.
    1320             :  * Put a string before and after to ensure sanity of element sizes on stack. */
    1321             : #define B "check_prefix"
    1322             : #define E "check_postfix"
    1323         101 : BOOST_AUTO_TEST_CASE(strprintf_numbers)
    1324             : {
    1325           2 :     int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
    1326           2 :     uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
    1327           2 :     BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
    1328           2 :     BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
    1329           2 :     BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
    1330             : 
    1331           2 :     size_t st = 12345678; /* unsigned size_t test value */
    1332           2 :     ssize_t sst = -12345678; /* signed size_t test value */
    1333           2 :     BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
    1334           2 :     BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
    1335           2 :     BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
    1336             : 
    1337           2 :     ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
    1338           2 :     ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
    1339           2 :     BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
    1340           2 :     BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
    1341           2 :     BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
    1342           2 : }
    1343             : #undef B
    1344             : #undef E
    1345             : 
    1346             : /* Check for mingw/wine issue #3494
    1347             :  * Remove this test before time.ctime(0xffffffff) == 'Sun Feb  7 07:28:15 2106'
    1348             :  */
    1349         101 : BOOST_AUTO_TEST_CASE(gettime)
    1350             : {
    1351           2 :     BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
    1352           2 : }
    1353             : 
    1354         101 : BOOST_AUTO_TEST_CASE(util_time_GetTime)
    1355             : {
    1356           2 :     SetMockTime(111);
    1357             :     // Check that mock time does not change after a sleep
    1358           6 :     for (const auto& num_sleep : {0, 1}) {
    1359           4 :         UninterruptibleSleep(std::chrono::milliseconds{num_sleep});
    1360           4 :         BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
    1361           4 :         BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
    1362           4 :         BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
    1363           4 :         BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
    1364             :     }
    1365             : 
    1366           2 :     SetMockTime(0);
    1367             :     // Check that system time changes after a sleep
    1368           2 :     const auto ms_0 = GetTime<std::chrono::milliseconds>();
    1369           2 :     const auto us_0 = GetTime<std::chrono::microseconds>();
    1370           2 :     UninterruptibleSleep(std::chrono::milliseconds{1});
    1371           2 :     BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
    1372           2 :     BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
    1373           2 : }
    1374             : 
    1375         101 : BOOST_AUTO_TEST_CASE(test_IsDigit)
    1376             : {
    1377           2 :     BOOST_CHECK_EQUAL(IsDigit('0'), true);
    1378           2 :     BOOST_CHECK_EQUAL(IsDigit('1'), true);
    1379           2 :     BOOST_CHECK_EQUAL(IsDigit('8'), true);
    1380           2 :     BOOST_CHECK_EQUAL(IsDigit('9'), true);
    1381             : 
    1382           2 :     BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
    1383           2 :     BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
    1384           2 :     BOOST_CHECK_EQUAL(IsDigit(0), false);
    1385           2 :     BOOST_CHECK_EQUAL(IsDigit(1), false);
    1386           2 :     BOOST_CHECK_EQUAL(IsDigit(8), false);
    1387           2 :     BOOST_CHECK_EQUAL(IsDigit(9), false);
    1388           2 : }
    1389             : 
    1390         101 : BOOST_AUTO_TEST_CASE(test_ParseInt32)
    1391             : {
    1392           2 :     int32_t n;
    1393             :     // Valid values
    1394           2 :     BOOST_CHECK(ParseInt32("1234", nullptr));
    1395           2 :     BOOST_CHECK(ParseInt32("0", &n) && n == 0);
    1396           2 :     BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
    1397           2 :     BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
    1398           2 :     BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
    1399           2 :     BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
    1400           2 :     BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
    1401             :     // Invalid values
    1402           2 :     BOOST_CHECK(!ParseInt32("", &n));
    1403           2 :     BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
    1404           2 :     BOOST_CHECK(!ParseInt32("1 ", &n));
    1405           2 :     BOOST_CHECK(!ParseInt32("1a", &n));
    1406           2 :     BOOST_CHECK(!ParseInt32("aap", &n));
    1407           2 :     BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
    1408           2 :     BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
    1409           2 :     const char test_bytes[] = {'1', 0, '1'};
    1410           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
    1411           2 :     BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
    1412             :     // Overflow and underflow
    1413           2 :     BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
    1414           2 :     BOOST_CHECK(!ParseInt32("2147483648", nullptr));
    1415           2 :     BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
    1416           2 :     BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
    1417           2 : }
    1418             : 
    1419         101 : BOOST_AUTO_TEST_CASE(test_ParseInt64)
    1420             : {
    1421           2 :     int64_t n;
    1422             :     // Valid values
    1423           2 :     BOOST_CHECK(ParseInt64("1234", nullptr));
    1424           2 :     BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
    1425           2 :     BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
    1426           2 :     BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
    1427           2 :     BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
    1428           2 :     BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
    1429           2 :     BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
    1430           2 :     BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
    1431           2 :     BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
    1432             :     // Invalid values
    1433           2 :     BOOST_CHECK(!ParseInt64("", &n));
    1434           2 :     BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
    1435           2 :     BOOST_CHECK(!ParseInt64("1 ", &n));
    1436           2 :     BOOST_CHECK(!ParseInt64("1a", &n));
    1437           2 :     BOOST_CHECK(!ParseInt64("aap", &n));
    1438           2 :     BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
    1439           2 :     const char test_bytes[] = {'1', 0, '1'};
    1440           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
    1441           2 :     BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
    1442             :     // Overflow and underflow
    1443           2 :     BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
    1444           2 :     BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
    1445           2 :     BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
    1446           2 :     BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
    1447           2 : }
    1448             : 
    1449         101 : BOOST_AUTO_TEST_CASE(test_ParseUInt32)
    1450             : {
    1451           2 :     uint32_t n;
    1452             :     // Valid values
    1453           2 :     BOOST_CHECK(ParseUInt32("1234", nullptr));
    1454           2 :     BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
    1455           2 :     BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
    1456           2 :     BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
    1457           2 :     BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
    1458           2 :     BOOST_CHECK(ParseUInt32("2147483648", &n) && n == (uint32_t)2147483648);
    1459           2 :     BOOST_CHECK(ParseUInt32("4294967295", &n) && n == (uint32_t)4294967295);
    1460             :     // Invalid values
    1461           2 :     BOOST_CHECK(!ParseUInt32("", &n));
    1462           2 :     BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
    1463           2 :     BOOST_CHECK(!ParseUInt32(" -1", &n));
    1464           2 :     BOOST_CHECK(!ParseUInt32("1 ", &n));
    1465           2 :     BOOST_CHECK(!ParseUInt32("1a", &n));
    1466           2 :     BOOST_CHECK(!ParseUInt32("aap", &n));
    1467           2 :     BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
    1468           2 :     BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
    1469           2 :     const char test_bytes[] = {'1', 0, '1'};
    1470           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
    1471           2 :     BOOST_CHECK(!ParseUInt32(teststr, &n)); // no embedded NULs
    1472             :     // Overflow and underflow
    1473           2 :     BOOST_CHECK(!ParseUInt32("-2147483648", &n));
    1474           2 :     BOOST_CHECK(!ParseUInt32("4294967296", &n));
    1475           2 :     BOOST_CHECK(!ParseUInt32("-1234", &n));
    1476           2 :     BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
    1477           2 :     BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
    1478           2 : }
    1479             : 
    1480         101 : BOOST_AUTO_TEST_CASE(test_ParseUInt64)
    1481             : {
    1482           2 :     uint64_t n;
    1483             :     // Valid values
    1484           2 :     BOOST_CHECK(ParseUInt64("1234", nullptr));
    1485           2 :     BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
    1486           2 :     BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
    1487           2 :     BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
    1488           2 :     BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
    1489           2 :     BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
    1490           2 :     BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
    1491           2 :     BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
    1492             :     // Invalid values
    1493           2 :     BOOST_CHECK(!ParseUInt64("", &n));
    1494           2 :     BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
    1495           2 :     BOOST_CHECK(!ParseUInt64(" -1", &n));
    1496           2 :     BOOST_CHECK(!ParseUInt64("1 ", &n));
    1497           2 :     BOOST_CHECK(!ParseUInt64("1a", &n));
    1498           2 :     BOOST_CHECK(!ParseUInt64("aap", &n));
    1499           2 :     BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
    1500           2 :     const char test_bytes[] = {'1', 0, '1'};
    1501           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
    1502           2 :     BOOST_CHECK(!ParseUInt64(teststr, &n)); // no embedded NULs
    1503             :     // Overflow and underflow
    1504           2 :     BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
    1505           2 :     BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
    1506           2 :     BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
    1507           2 :     BOOST_CHECK(!ParseUInt64("-2147483648", &n));
    1508           2 :     BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
    1509           2 :     BOOST_CHECK(!ParseUInt64("-1234", &n));
    1510           2 : }
    1511             : 
    1512         101 : BOOST_AUTO_TEST_CASE(test_ParseDouble)
    1513             : {
    1514           2 :     double n;
    1515             :     // Valid values
    1516           2 :     BOOST_CHECK(ParseDouble("1234", nullptr));
    1517           2 :     BOOST_CHECK(ParseDouble("0", &n) && n == 0.0);
    1518           2 :     BOOST_CHECK(ParseDouble("1234", &n) && n == 1234.0);
    1519           2 :     BOOST_CHECK(ParseDouble("01234", &n) && n == 1234.0); // no octal
    1520           2 :     BOOST_CHECK(ParseDouble("2147483647", &n) && n == 2147483647.0);
    1521           2 :     BOOST_CHECK(ParseDouble("-2147483648", &n) && n == -2147483648.0);
    1522           2 :     BOOST_CHECK(ParseDouble("-1234", &n) && n == -1234.0);
    1523           2 :     BOOST_CHECK(ParseDouble("1e6", &n) && n == 1e6);
    1524           2 :     BOOST_CHECK(ParseDouble("-1e6", &n) && n == -1e6);
    1525             :     // Invalid values
    1526           2 :     BOOST_CHECK(!ParseDouble("", &n));
    1527           2 :     BOOST_CHECK(!ParseDouble(" 1", &n)); // no padding inside
    1528           2 :     BOOST_CHECK(!ParseDouble("1 ", &n));
    1529           2 :     BOOST_CHECK(!ParseDouble("1a", &n));
    1530           2 :     BOOST_CHECK(!ParseDouble("aap", &n));
    1531           2 :     BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
    1532           2 :     const char test_bytes[] = {'1', 0, '1'};
    1533           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
    1534           2 :     BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
    1535             :     // Overflow and underflow
    1536           2 :     BOOST_CHECK(!ParseDouble("-1e10000", nullptr));
    1537           2 :     BOOST_CHECK(!ParseDouble("1e10000", nullptr));
    1538           2 : }
    1539             : 
    1540         101 : BOOST_AUTO_TEST_CASE(test_FormatParagraph)
    1541             : {
    1542           2 :     BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
    1543           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
    1544           2 :     BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
    1545           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
    1546           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
    1547           2 :     BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
    1548           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n    test");
    1549             : 
    1550             :     // Make sure we don't indent a fully-new line following a too-long line ending
    1551           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n    test\nabc");
    1552             : 
    1553           2 :     BOOST_CHECK_EQUAL(FormatParagraph("This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length until it gets here", 79), "This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length\nuntil it gets here");
    1554             : 
    1555             :     // Test wrap length is exact
    1556           2 :     BOOST_CHECK_EQUAL(FormatParagraph("a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
    1557           2 :     BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
    1558             :     // Indent should be included in length of lines
    1559           2 :     BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg h i j k", 79, 4), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\n    f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg\n    h i j k");
    1560             : 
    1561           2 :     BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string.", 79), "This is a very long test string. This is a second sentence in the very long\ntest string.");
    1562           2 :     BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
    1563           2 :     BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
    1564           2 :     BOOST_CHECK_EQUAL(FormatParagraph("Testing that normal newlines do not get indented.\nLike here.", 79), "Testing that normal newlines do not get indented.\nLike here.");
    1565           2 : }
    1566             : 
    1567         101 : BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
    1568             : {
    1569           2 :     std::vector<std::string> comments;
    1570           2 :     comments.push_back(std::string("comment1"));
    1571           2 :     std::vector<std::string> comments2;
    1572           2 :     comments2.push_back(std::string("comment1"));
    1573           2 :     comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
    1574           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
    1575           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
    1576           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/"));
    1577           2 : }
    1578             : 
    1579         101 : BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
    1580             : {
    1581           2 :     int64_t amount = 0;
    1582           2 :     BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
    1583           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
    1584           2 :     BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
    1585           2 :     BOOST_CHECK_EQUAL(amount, 100000000LL);
    1586           2 :     BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
    1587           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
    1588           2 :     BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
    1589           2 :     BOOST_CHECK_EQUAL(amount, -10000000LL);
    1590           2 :     BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
    1591           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
    1592           2 :     BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
    1593           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
    1594           2 :     BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
    1595           2 :     BOOST_CHECK_EQUAL(amount, 1100000000LL);
    1596           2 :     BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
    1597           2 :     BOOST_CHECK_EQUAL(amount, 11000000LL);
    1598           2 :     BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
    1599           2 :     BOOST_CHECK_EQUAL(amount, 100000000000LL);
    1600           2 :     BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
    1601           2 :     BOOST_CHECK_EQUAL(amount, -100000000000LL);
    1602           2 :     BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
    1603           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
    1604           2 :     BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
    1605           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
    1606           2 :     BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
    1607           2 :     BOOST_CHECK_EQUAL(amount, -1LL);
    1608           2 :     BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
    1609           2 :     BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
    1610           2 :     BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
    1611           2 :     BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
    1612           2 :     BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
    1613           2 :     BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
    1614             : 
    1615           2 :     BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
    1616           2 :     BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
    1617           2 :     BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
    1618           2 :     BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
    1619           2 :     BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
    1620           2 :     BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
    1621           2 :     BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
    1622           2 :     BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
    1623           2 :     BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
    1624           2 :     BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
    1625           2 :     BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
    1626           2 :     BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
    1627           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
    1628           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
    1629           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
    1630           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
    1631           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
    1632           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
    1633           2 :     BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
    1634           2 :     BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
    1635           2 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
    1636           2 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
    1637           2 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
    1638           2 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
    1639           2 :     BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
    1640           2 :     BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
    1641           2 :     BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
    1642           2 : }
    1643             : 
    1644           1 : static void TestOtherThread(fs::path dirname, std::string lockname, bool *result)
    1645             : {
    1646           1 :     *result = LockDirectory(dirname, lockname);
    1647           1 : }
    1648             : 
    1649             : #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
    1650             : static constexpr char LockCommand = 'L';
    1651             : static constexpr char UnlockCommand = 'U';
    1652             : static constexpr char ExitCommand = 'X';
    1653             : 
    1654           1 : static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
    1655             : {
    1656           1 :     char ch;
    1657           5 :     while (true) {
    1658           5 :         int rv = read(fd, &ch, 1); // Wait for command
    1659           5 :         assert(rv == 1);
    1660           5 :         switch(ch) {
    1661             :         case LockCommand:
    1662           3 :             ch = LockDirectory(dirname, lockname);
    1663           3 :             rv = write(fd, &ch, 1);
    1664           3 :             assert(rv == 1);
    1665             :             break;
    1666             :         case UnlockCommand:
    1667           1 :             ReleaseDirectoryLocks();
    1668           1 :             ch = true; // Always succeeds
    1669           1 :             rv = write(fd, &ch, 1);
    1670           1 :             assert(rv == 1);
    1671             :             break;
    1672             :         case ExitCommand:
    1673           1 :             close(fd);
    1674           1 :             exit(0);
    1675             :         default:
    1676           0 :             assert(0);
    1677             :         }
    1678             :     }
    1679           0 : }
    1680             : #endif
    1681             : 
    1682          99 : BOOST_AUTO_TEST_CASE(test_LockDirectory)
    1683             : {
    1684           2 :     fs::path dirname = GetDataDir() / "lock_dir";
    1685           2 :     const std::string lockname = ".lock";
    1686             : #ifndef WIN32
    1687             :     // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
    1688             :     // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
    1689             :     // at build-time of the boost library
    1690           2 :     void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
    1691             : 
    1692             :     // Fork another process for testing before creating the lock, so that we
    1693             :     // won't fork while holding the lock (which might be undefined, and is not
    1694             :     // relevant as test case as that is avoided with -daemonize).
    1695           2 :     int fd[2];
    1696           2 :     BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
    1697           2 :     pid_t pid = fork();
    1698           2 :     if (!pid) {
    1699           1 :         BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
    1700           1 :         TestOtherProcess(dirname, lockname, fd[0]);
    1701           0 :     }
    1702           1 :     BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
    1703             : #endif
    1704             :     // Lock on non-existent directory should fail
    1705           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
    1706             : 
    1707           1 :     fs::create_directories(dirname);
    1708             : 
    1709             :     // Probing lock on new directory should succeed
    1710           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1711             : 
    1712             :     // Persistent lock on new directory should succeed
    1713           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1714             : 
    1715             :     // Another lock on the directory from the same thread should succeed
    1716           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1717             : 
    1718             :     // Another lock on the directory from a different thread within the same process should succeed
    1719           1 :     bool threadresult;
    1720           1 :     std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
    1721           1 :     thr.join();
    1722           1 :     BOOST_CHECK_EQUAL(threadresult, true);
    1723             : #ifndef WIN32
    1724             :     // Try to acquire lock in child process while we're holding it, this should fail.
    1725           1 :     char ch;
    1726           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1727           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1728           1 :     BOOST_CHECK_EQUAL((bool)ch, false);
    1729             : 
    1730             :     // Give up our lock
    1731           1 :     ReleaseDirectoryLocks();
    1732             :     // Probing lock from our side now should succeed, but not hold on to the lock.
    1733           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1734             : 
    1735             :     // Try to acquire the lock in the child process, this should be successful.
    1736           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1737           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1738           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1739             : 
    1740             :     // When we try to probe the lock now, it should fail.
    1741           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
    1742             : 
    1743             :     // Unlock the lock in the child process
    1744           1 :     BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
    1745           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1746           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1747             : 
    1748             :     // When we try to probe the lock now, it should succeed.
    1749           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1750             : 
    1751             :     // Re-lock the lock in the child process, then wait for it to exit, check
    1752             :     // successful return. After that, we check that exiting the process
    1753             :     // has released the lock as we would expect by probing it.
    1754           1 :     int processstatus;
    1755           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1756           1 :     BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
    1757           1 :     BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
    1758           1 :     BOOST_CHECK_EQUAL(processstatus, 0);
    1759           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1760             : 
    1761             :     // Restore SIGCHLD
    1762           1 :     signal(SIGCHLD, old_handler);
    1763           1 :     BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
    1764             : #endif
    1765             :     // Clean up
    1766           1 :     ReleaseDirectoryLocks();
    1767           1 :     fs::remove_all(dirname);
    1768           1 : }
    1769             : 
    1770          95 : BOOST_AUTO_TEST_CASE(test_DirIsWritable)
    1771             : {
    1772             :     // Should be able to write to the data dir.
    1773           1 :     fs::path tmpdirname = GetDataDir();
    1774           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1775             : 
    1776             :     // Should not be able to write to a non-existent dir.
    1777           1 :     tmpdirname = tmpdirname / fs::unique_path();
    1778           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
    1779             : 
    1780           1 :     fs::create_directory(tmpdirname);
    1781             :     // Should be able to write to it now.
    1782           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1783           1 :     fs::remove(tmpdirname);
    1784           1 : }
    1785             : 
    1786          95 : BOOST_AUTO_TEST_CASE(test_ToLower)
    1787             : {
    1788           1 :     BOOST_CHECK_EQUAL(ToLower('@'), '@');
    1789           1 :     BOOST_CHECK_EQUAL(ToLower('A'), 'a');
    1790           1 :     BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
    1791           1 :     BOOST_CHECK_EQUAL(ToLower('['), '[');
    1792           1 :     BOOST_CHECK_EQUAL(ToLower(0), 0);
    1793           1 :     BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
    1794             : 
    1795           1 :     BOOST_CHECK_EQUAL(ToLower(""), "");
    1796           1 :     BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
    1797           1 :     BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
    1798           1 : }
    1799             : 
    1800          95 : BOOST_AUTO_TEST_CASE(test_ToUpper)
    1801             : {
    1802           1 :     BOOST_CHECK_EQUAL(ToUpper('`'), '`');
    1803           1 :     BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
    1804           1 :     BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
    1805           1 :     BOOST_CHECK_EQUAL(ToUpper('{'), '{');
    1806           1 :     BOOST_CHECK_EQUAL(ToUpper(0), 0);
    1807           1 :     BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
    1808             : 
    1809           1 :     BOOST_CHECK_EQUAL(ToUpper(""), "");
    1810           1 :     BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
    1811           1 :     BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
    1812           1 : }
    1813             : 
    1814          95 : BOOST_AUTO_TEST_CASE(test_Capitalize)
    1815             : {
    1816           1 :     BOOST_CHECK_EQUAL(Capitalize(""), "");
    1817           1 :     BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin");
    1818           1 :     BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
    1819           1 : }
    1820             : 
    1821          28 : static std::string SpanToStr(Span<const char>& span)
    1822             : {
    1823          28 :     return std::string(span.begin(), span.end());
    1824             : }
    1825             : 
    1826          95 : BOOST_AUTO_TEST_CASE(test_spanparsing)
    1827             : {
    1828             :     using namespace spanparsing;
    1829           1 :     std::string input;
    1830           1 :     Span<const char> sp;
    1831             :     bool success;
    1832             : 
    1833             :     // Const(...): parse a constant, update span to skip it if successful
    1834           1 :     input = "MilkToastHoney";
    1835           1 :     sp = input;
    1836           1 :     success = Const("", sp); // empty
    1837           1 :     BOOST_CHECK(success);
    1838           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");
    1839             : 
    1840           1 :     success = Const("Milk", sp);
    1841           1 :     BOOST_CHECK(success);
    1842           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");
    1843             : 
    1844           1 :     success = Const("Bread", sp);
    1845           1 :     BOOST_CHECK(!success);
    1846             : 
    1847           1 :     success = Const("Toast", sp);
    1848           1 :     BOOST_CHECK(success);
    1849           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");
    1850             : 
    1851           1 :     success = Const("Honeybadger", sp);
    1852           1 :     BOOST_CHECK(!success);
    1853             : 
    1854           1 :     success = Const("Honey", sp);
    1855           1 :     BOOST_CHECK(success);
    1856           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "");
    1857             : 
    1858             :     // Func(...): parse a function call, update span to argument if successful
    1859           1 :     input = "Foo(Bar(xy,z()))";
    1860           1 :     sp = input;
    1861             : 
    1862           1 :     success = Func("FooBar", sp);
    1863           1 :     BOOST_CHECK(!success);
    1864             : 
    1865           1 :     success = Func("Foo(", sp);
    1866           1 :     BOOST_CHECK(!success);
    1867             : 
    1868           1 :     success = Func("Foo", sp);
    1869           1 :     BOOST_CHECK(success);
    1870           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");
    1871             : 
    1872           1 :     success = Func("Bar", sp);
    1873           1 :     BOOST_CHECK(success);
    1874           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()");
    1875             : 
    1876           1 :     success = Func("xy", sp);
    1877           1 :     BOOST_CHECK(!success);
    1878             : 
    1879             :     // Expr(...): return expression that span begins with, update span to skip it
    1880           1 :     Span<const char> result;
    1881             : 
    1882           1 :     input = "(n*(n-1))/2";
    1883           1 :     sp = input;
    1884           1 :     result = Expr(sp);
    1885           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2");
    1886           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "");
    1887             : 
    1888           1 :     input = "foo,bar";
    1889           1 :     sp = input;
    1890           1 :     result = Expr(sp);
    1891           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "foo");
    1892           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar");
    1893             : 
    1894           1 :     input = "(aaaaa,bbbbb()),c";
    1895           1 :     sp = input;
    1896           1 :     result = Expr(sp);
    1897           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())");
    1898           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",c");
    1899             : 
    1900           1 :     input = "xyz)foo";
    1901           1 :     sp = input;
    1902           1 :     result = Expr(sp);
    1903           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "xyz");
    1904           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo");
    1905             : 
    1906           1 :     input = "((a),(b),(c)),xxx";
    1907           1 :     sp = input;
    1908           1 :     result = Expr(sp);
    1909           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))");
    1910           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx");
    1911             : 
    1912             :     // Split(...): split a string on every instance of sep, return vector
    1913           1 :     std::vector<Span<const char>> results;
    1914             : 
    1915           1 :     input = "xxx";
    1916           1 :     results = Split(input, 'x');
    1917           1 :     BOOST_CHECK_EQUAL(results.size(), 4U);
    1918           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
    1919           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "");
    1920           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "");
    1921           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
    1922             : 
    1923           1 :     input = "one#two#three";
    1924           1 :     results = Split(input, '-');
    1925           1 :     BOOST_CHECK_EQUAL(results.size(), 1U);
    1926           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three");
    1927             : 
    1928           1 :     input = "one#two#three";
    1929           1 :     results = Split(input, '#');
    1930           1 :     BOOST_CHECK_EQUAL(results.size(), 3U);
    1931           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one");
    1932           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two");
    1933           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three");
    1934             : 
    1935           1 :     input = "*foo*bar*";
    1936           1 :     results = Split(input, '*');
    1937           1 :     BOOST_CHECK_EQUAL(results.size(), 4U);
    1938           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
    1939           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo");
    1940           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar");
    1941           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
    1942           1 : }
    1943             : 
    1944          95 : BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
    1945             : {
    1946             :     // ASCII and UTF-8 must pass through unaltered.
    1947           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
    1948             :     // Newlines must pass through unaltered.
    1949           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
    1950             :     // Other control characters are escaped in C syntax.
    1951           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
    1952             :     // Embedded NULL characters are escaped too.
    1953           1 :     const std::string NUL("O\x00O", 3);
    1954           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
    1955           1 : }
    1956             : 
    1957             : namespace {
    1958             : 
    1959             : struct Tracker
    1960             : {
    1961             :     //! Points to the original object (possibly itself) we moved/copied from
    1962             :     const Tracker* origin;
    1963             :     //! How many copies where involved between the original object and this one (moves are not counted)
    1964             :     int copies;
    1965             : 
    1966           6 :     Tracker() noexcept : origin(this), copies(0) {}
    1967          20 :     Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
    1968          26 :     Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
    1969             :     Tracker& operator=(const Tracker& t) noexcept
    1970             :     {
    1971             :         origin = t.origin;
    1972             :         copies = t.copies + 1;
    1973             :         return *this;
    1974             :     }
    1975             :     Tracker& operator=(Tracker&& t) noexcept
    1976             :     {
    1977             :         origin = t.origin;
    1978             :         copies = t.copies;
    1979             :         return *this;
    1980             :     }
    1981             : };
    1982             : 
    1983             : }
    1984             : 
    1985          95 : BOOST_AUTO_TEST_CASE(test_tracked_vector)
    1986             : {
    1987           1 :     Tracker t1;
    1988           1 :     Tracker t2;
    1989           1 :     Tracker t3;
    1990             : 
    1991           1 :     BOOST_CHECK(t1.origin == &t1);
    1992           1 :     BOOST_CHECK(t2.origin == &t2);
    1993           1 :     BOOST_CHECK(t3.origin == &t3);
    1994             : 
    1995           1 :     auto v1 = Vector(t1);
    1996           1 :     BOOST_CHECK_EQUAL(v1.size(), 1U);
    1997           1 :     BOOST_CHECK(v1[0].origin == &t1);
    1998           1 :     BOOST_CHECK_EQUAL(v1[0].copies, 1);
    1999             : 
    2000           1 :     auto v2 = Vector(std::move(t2));
    2001           1 :     BOOST_CHECK_EQUAL(v2.size(), 1U);
    2002           1 :     BOOST_CHECK(v2[0].origin == &t2);
    2003           1 :     BOOST_CHECK_EQUAL(v2[0].copies, 0);
    2004             : 
    2005           1 :     auto v3 = Vector(t1, std::move(t2));
    2006           1 :     BOOST_CHECK_EQUAL(v3.size(), 2U);
    2007           1 :     BOOST_CHECK(v3[0].origin == &t1);
    2008           1 :     BOOST_CHECK(v3[1].origin == &t2);
    2009           1 :     BOOST_CHECK_EQUAL(v3[0].copies, 1);
    2010           1 :     BOOST_CHECK_EQUAL(v3[1].copies, 0);
    2011             : 
    2012           1 :     auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
    2013           1 :     BOOST_CHECK_EQUAL(v4.size(), 3U);
    2014           1 :     BOOST_CHECK(v4[0].origin == &t1);
    2015           1 :     BOOST_CHECK(v4[1].origin == &t2);
    2016           1 :     BOOST_CHECK(v4[2].origin == &t3);
    2017           1 :     BOOST_CHECK_EQUAL(v4[0].copies, 1);
    2018           1 :     BOOST_CHECK_EQUAL(v4[1].copies, 1);
    2019           1 :     BOOST_CHECK_EQUAL(v4[2].copies, 0);
    2020             : 
    2021           1 :     auto v5 = Cat(v1, v4);
    2022           1 :     BOOST_CHECK_EQUAL(v5.size(), 4U);
    2023           1 :     BOOST_CHECK(v5[0].origin == &t1);
    2024           1 :     BOOST_CHECK(v5[1].origin == &t1);
    2025           1 :     BOOST_CHECK(v5[2].origin == &t2);
    2026           1 :     BOOST_CHECK(v5[3].origin == &t3);
    2027           1 :     BOOST_CHECK_EQUAL(v5[0].copies, 2);
    2028           1 :     BOOST_CHECK_EQUAL(v5[1].copies, 2);
    2029           1 :     BOOST_CHECK_EQUAL(v5[2].copies, 2);
    2030           1 :     BOOST_CHECK_EQUAL(v5[3].copies, 1);
    2031             : 
    2032           1 :     auto v6 = Cat(std::move(v1), v3);
    2033           1 :     BOOST_CHECK_EQUAL(v6.size(), 3U);
    2034           1 :     BOOST_CHECK(v6[0].origin == &t1);
    2035           1 :     BOOST_CHECK(v6[1].origin == &t1);
    2036           1 :     BOOST_CHECK(v6[2].origin == &t2);
    2037           1 :     BOOST_CHECK_EQUAL(v6[0].copies, 1);
    2038           1 :     BOOST_CHECK_EQUAL(v6[1].copies, 2);
    2039           1 :     BOOST_CHECK_EQUAL(v6[2].copies, 1);
    2040             : 
    2041           1 :     auto v7 = Cat(v2, std::move(v4));
    2042           1 :     BOOST_CHECK_EQUAL(v7.size(), 4U);
    2043           1 :     BOOST_CHECK(v7[0].origin == &t2);
    2044           1 :     BOOST_CHECK(v7[1].origin == &t1);
    2045           1 :     BOOST_CHECK(v7[2].origin == &t2);
    2046           1 :     BOOST_CHECK(v7[3].origin == &t3);
    2047           1 :     BOOST_CHECK_EQUAL(v7[0].copies, 1);
    2048           1 :     BOOST_CHECK_EQUAL(v7[1].copies, 1);
    2049           1 :     BOOST_CHECK_EQUAL(v7[2].copies, 1);
    2050           1 :     BOOST_CHECK_EQUAL(v7[3].copies, 0);
    2051             : 
    2052           1 :     auto v8 = Cat(std::move(v2), std::move(v3));
    2053           1 :     BOOST_CHECK_EQUAL(v8.size(), 3U);
    2054           1 :     BOOST_CHECK(v8[0].origin == &t2);
    2055           1 :     BOOST_CHECK(v8[1].origin == &t1);
    2056           1 :     BOOST_CHECK(v8[2].origin == &t2);
    2057           1 :     BOOST_CHECK_EQUAL(v8[0].copies, 0);
    2058           1 :     BOOST_CHECK_EQUAL(v8[1].copies, 1);
    2059           1 :     BOOST_CHECK_EQUAL(v8[2].copies, 0);
    2060           1 : }
    2061             : 
    2062          95 : BOOST_AUTO_TEST_CASE(message_sign)
    2063             : {
    2064           1 :     const std::array<unsigned char, 32> privkey_bytes = {
    2065             :         // just some random data
    2066             :         // derived address from this private key: 15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs
    2067             :         0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
    2068             :         0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
    2069             :         0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
    2070             :         0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
    2071             :     };
    2072             : 
    2073           1 :     const std::string message = "Trust no one";
    2074             : 
    2075           1 :     const std::string expected_signature =
    2076           1 :         "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=";
    2077             : 
    2078           1 :     CKey privkey;
    2079           1 :     std::string generated_signature;
    2080             : 
    2081           1 :     BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
    2082             :         "Confirm the private key is invalid");
    2083             : 
    2084           1 :     BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
    2085             :         "Sign with an invalid private key");
    2086             : 
    2087           1 :     privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
    2088             : 
    2089           1 :     BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
    2090             :         "Confirm the private key is valid");
    2091             : 
    2092           1 :     BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
    2093             :         "Sign with a valid private key");
    2094             : 
    2095           1 :     BOOST_CHECK_EQUAL(expected_signature, generated_signature);
    2096           1 : }
    2097             : 
    2098          95 : BOOST_AUTO_TEST_CASE(message_verify)
    2099             : {
    2100           1 :     BOOST_CHECK_EQUAL(
    2101             :         MessageVerify(
    2102             :             "invalid address",
    2103             :             "signature should be irrelevant",
    2104             :             "message too"),
    2105             :         MessageVerificationResult::ERR_INVALID_ADDRESS);
    2106             : 
    2107           1 :     BOOST_CHECK_EQUAL(
    2108             :         MessageVerify(
    2109             :             "3B5fQsEXEaV8v6U3ejYc8XaKXAkyQj2MjV",
    2110             :             "signature should be irrelevant",
    2111             :             "message too"),
    2112             :         MessageVerificationResult::ERR_ADDRESS_NO_KEY);
    2113             : 
    2114           1 :     BOOST_CHECK_EQUAL(
    2115             :         MessageVerify(
    2116             :             "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
    2117             :             "invalid signature, not in base64 encoding",
    2118             :             "message should be irrelevant"),
    2119             :         MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
    2120             : 
    2121           1 :     BOOST_CHECK_EQUAL(
    2122             :         MessageVerify(
    2123             :             "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
    2124             :             "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
    2125             :             "message should be irrelevant"),
    2126             :         MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED);
    2127             : 
    2128           1 :     BOOST_CHECK_EQUAL(
    2129             :         MessageVerify(
    2130             :             "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
    2131             :             "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
    2132             :             "I never signed this"),
    2133             :         MessageVerificationResult::ERR_NOT_SIGNED);
    2134             : 
    2135           1 :     BOOST_CHECK_EQUAL(
    2136             :         MessageVerify(
    2137             :             "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
    2138             :             "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
    2139             :             "Trust no one"),
    2140             :         MessageVerificationResult::OK);
    2141             : 
    2142           1 :     BOOST_CHECK_EQUAL(
    2143             :         MessageVerify(
    2144             :             "11canuhp9X2NocwCq7xNrQYTmUgZAnLK3",
    2145             :             "IIcaIENoYW5jZWxsb3Igb24gYnJpbmsgb2Ygc2Vjb25kIGJhaWxvdXQgZm9yIGJhbmtzIAaHRtbCeDZINyavx14=",
    2146             :             "Trust me"),
    2147             :         MessageVerificationResult::OK);
    2148           1 : }
    2149             : 
    2150          95 : BOOST_AUTO_TEST_CASE(message_hash)
    2151             : {
    2152           1 :     const std::string unsigned_tx = "...";
    2153           1 :     const std::string prefixed_message =
    2154           2 :         std::string(1, (char)MESSAGE_MAGIC.length()) +
    2155           1 :         MESSAGE_MAGIC +
    2156           2 :         std::string(1, (char)unsigned_tx.length()) +
    2157             :         unsigned_tx;
    2158             : 
    2159           1 :     const uint256 signature_hash = Hash(unsigned_tx);
    2160           1 :     const uint256 message_hash1 = Hash(prefixed_message);
    2161           1 :     const uint256 message_hash2 = MessageHash(unsigned_tx);
    2162             : 
    2163           1 :     BOOST_CHECK_EQUAL(message_hash1, message_hash2);
    2164           1 :     BOOST_CHECK_NE(message_hash1, signature_hash);
    2165           1 : }
    2166             : 
    2167          89 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.15