LCOV - code coverage report
Current view: top level - src/test - util_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 775 778 99.6 %
Date: 2025-02-23 09:33:43 Functions: 77 77 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2014 The Bitcoin Core developers
       2             : // Copyright (c) 2017-2022 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "util/system.h"
       7             : 
       8             : #include "clientversion.h"
       9             : #include "sync.h"
      10             : #include "utilstrencodings.h"
      11             : #include "util/string.h"
      12             : #include "utilmoneystr.h"
      13             : #include "test/test_pivx.h"
      14             : #include "util/vector.h"
      15             : 
      16             : #include <stdint.h>
      17             : #include <vector>
      18             : #ifndef WIN32
      19             : #include <sys/types.h>
      20             : #include <sys/wait.h>
      21             : #endif
      22             : 
      23             : #include <boost/test/unit_test.hpp>
      24             : 
      25             : BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
      26             : 
      27           4 : BOOST_AUTO_TEST_CASE(util_criticalsection)
      28             : {
      29           4 :     RecursiveMutex cs;
      30             : 
      31           2 :     do {
      32           2 :         LOCK(cs);
      33           2 :         break;
      34             : 
      35             :         BOOST_ERROR("break was swallowed!");
      36             :     } while(0);
      37             : 
      38           2 :     do {
      39           2 :         TRY_LOCK(cs, lockTest);
      40           2 :         if (lockTest)
      41             :             break;
      42             : 
      43           0 :         BOOST_ERROR("break was swallowed!");
      44             :     } while(0);
      45           2 : }
      46             : 
      47             : static const unsigned char ParseHex_expected[65] = {
      48             :     0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
      49             :     0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
      50             :     0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
      51             :     0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
      52             :     0x5f
      53             : };
      54           4 : BOOST_AUTO_TEST_CASE(util_ParseHex)
      55             : {
      56           2 :     std::vector<unsigned char> result;
      57           4 :     std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
      58             :     // Basic test vector
      59           2 :     result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
      60           4 :     BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
      61             : 
      62             :     // Spaces between bytes must be supported
      63           4 :     result = ParseHex("12 34 56 78");
      64           4 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
      65             : 
      66             :     // Stop parsing at invalid value
      67           4 :     result = ParseHex("1234 invalid 1234");
      68           4 :     BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34);
      69           2 : }
      70             : 
      71           4 : BOOST_AUTO_TEST_CASE(util_HexStr)
      72             : {
      73           4 :     BOOST_CHECK_EQUAL(
      74             :             HexStr(ParseHex_expected),
      75             :             "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
      76             : 
      77           2 :     BOOST_CHECK_EQUAL(
      78             :             HexStr(Span<const unsigned char>(
      79             :                     ParseHex_expected + sizeof(ParseHex_expected),
      80             :                     ParseHex_expected + sizeof(ParseHex_expected))),
      81             :             "");
      82             : 
      83           4 :     BOOST_CHECK_EQUAL(
      84             :             HexStr(Span<const unsigned char>(ParseHex_expected, ParseHex_expected)),
      85             :             "");
      86             : 
      87           2 :     std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
      88             : 
      89           2 :     BOOST_CHECK_EQUAL(
      90             :             HexStr(ParseHex_vec),
      91             :             "04678afdb0"
      92             :     );
      93           2 : }
      94             : 
      95           4 : BOOST_AUTO_TEST_CASE(util_Join)
      96             : {
      97             :     // Normal version
      98           2 :     BOOST_CHECK_EQUAL(Join({}, ", "), "");
      99           6 :     BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
     100           8 :     BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
     101             : 
     102             :     // Version with unary operator
     103           8 :     const auto op_upper = [](const std::string& s) { return ToUpper(s); };
     104           2 :     BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), "");
     105           4 :     BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO");
     106           6 :     BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR");
     107           2 : }
     108             : 
     109           4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
     110             : {
     111           4 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
     112           2 : }
     113             : 
     114           4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTimeForBackup)
     115             : {
     116           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTimeForBackup(1586310600), ".20200408T0150Z");
     117           2 : }
     118             : 
     119           4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
     120             : {
     121           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
     122           2 : }
     123             : 
     124           4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
     125             : {
     126           2 :     BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
     127           2 : }
     128             : 
     129          10 : struct TestArgsManager : public ArgsManager
     130             : {
     131          12 :     TestArgsManager() { m_network_only_args.clear(); }
     132          12 :     std::map<std::string, std::vector<std::string> >& GetOverrideArgs() { return m_override_args; }
     133           6 :     std::map<std::string, std::vector<std::string> >& GetConfigArgs() { return m_config_args; }
     134          26 :     void ReadConfigString(const std::string str_config)
     135             :     {
     136          52 :         std::istringstream streamConfig(str_config);
     137          26 :         {
     138          26 :             LOCK(cs_args);
     139          26 :             m_config_args.clear();
     140             :         }
     141          26 :         ReadConfigStream(streamConfig);
     142          26 :     }
     143           6 :     void SetNetworkOnlyArg(const std::string arg)
     144             :     {
     145           6 :         LOCK(cs_args);
     146           6 :         m_network_only_args.insert(arg);
     147           6 :     }
     148             : };
     149             : 
     150           4 : BOOST_AUTO_TEST_CASE(util_ParseParameters)
     151             : {
     152           2 :     TestArgsManager testArgs;
     153           2 :     const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
     154             : 
     155           2 :     testArgs.ParseParameters(0, (char**)argv_test);
     156           4 :     BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
     157             : 
     158           2 :     testArgs.ParseParameters(1, (char**)argv_test);
     159           4 :     BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
     160             : 
     161           2 :     testArgs.ParseParameters(5, (char**)argv_test);
     162             :     // expectation: -ignored is ignored (program name argument),
     163             :     // -a, -b and -ccc end up in map, -d ignored because it is after
     164             :     // a non-option argument (non-GNU option parsing)
     165           4 :     BOOST_CHECK(testArgs.GetOverrideArgs().size() == 3 && testArgs.GetConfigArgs().empty());
     166          12 :     BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc")
     167             :                 && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d"));
     168          22 :     BOOST_CHECK(testArgs.GetOverrideArgs().count("-a") && testArgs.GetOverrideArgs().count("-b") && testArgs.GetOverrideArgs().count("-ccc")
     169             :                 && !testArgs.GetOverrideArgs().count("f") && !testArgs.GetOverrideArgs().count("-d"));
     170             : 
     171           4 :     BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].size() == 1);
     172           4 :     BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].front() == "");
     173           4 :     BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].size() == 2);
     174           4 :     BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].front() == "argument");
     175           4 :     BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].back() == "multiple");
     176           2 : }
     177             : 
     178           4 : BOOST_AUTO_TEST_CASE(util_GetBoolArg)
     179             : {
     180           2 :     TestArgsManager testArgs;
     181           2 :     const char *argv_test[] = {
     182             :         "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
     183           2 :     testArgs.ParseParameters(7, (char**)argv_test);
     184             : 
     185             :     // Each letter should be set.
     186          16 :     for (char opt : "abcdef")
     187          42 :         BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
     188             : 
     189             :     // Nothing else should be in the map
     190           4 :     BOOST_CHECK(testArgs.GetOverrideArgs().size() == 6 &&
     191             :                 testArgs.GetConfigArgs().empty());
     192             : 
     193             :     // The -no prefix should get stripped on the way in.
     194           4 :     BOOST_CHECK(!testArgs.IsArgSet("-nob"));
     195             : 
     196             :     // The -b option is flagged as negated, and nothing else is
     197           4 :     BOOST_CHECK(testArgs.IsArgNegated("-b"));
     198           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-a"));
     199             : 
     200             :     // Check expected values.
     201           4 :     BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
     202           4 :     BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
     203           4 :     BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
     204           4 :     BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
     205           4 :     BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
     206           4 :     BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
     207           2 : }
     208             : 
     209           4 : BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
     210             : {
     211             :     // Test some awful edge cases that hopefully no user will ever exercise.
     212           2 :     TestArgsManager testArgs;
     213             : 
     214             :     // Params test
     215           2 :     const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
     216           2 :     testArgs.ParseParameters(4, (char**)argv_test);
     217             : 
     218             :     // This was passed twice, second one overrides the negative setting.
     219           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
     220           6 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
     221             : 
     222             :     // A double negative is a positive, and not marked as negated.
     223           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     224           6 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
     225             : 
     226             :     // Config test
     227           2 :     const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
     228           2 :     testArgs.ParseParameters(1, (char**)argv_test);
     229           2 :     testArgs.ReadConfigString(conf_test);
     230             : 
     231             :     // This was passed twice, second one overrides the negative setting,
     232             :     // and the value.
     233           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
     234           6 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
     235             : 
     236             :     // A double negative is a positive, and does not count as negated.
     237           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     238           6 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
     239             : 
     240             :     // Combined test
     241           2 :     const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
     242           2 :     const char *combo_test_conf = "foo=1\nnobar=1\n";
     243           2 :     testArgs.ParseParameters(3, (char**)combo_test_args);
     244           2 :     testArgs.ReadConfigString(combo_test_conf);
     245             : 
     246             :     // Command line overrides, but doesn't erase old setting
     247           4 :     BOOST_CHECK(testArgs.IsArgNegated("-foo"));
     248           6 :     BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
     249           4 :     BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
     250             : 
     251             :     // Command line overrides, but doesn't erase old setting
     252           4 :     BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
     253           6 :     BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
     254           6 :     BOOST_CHECK(testArgs.GetArgs("-bar").size() == 1
     255             :                 && testArgs.GetArgs("-bar").front() == "");
     256           2 : }
     257             : 
     258           4 : BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
     259             : {
     260           2 :     const char *str_config =
     261             :        "a=\n"
     262             :        "b=1\n"
     263             :        "ccc=argument\n"
     264             :        "ccc=multiple\n"
     265             :        "d=e\n"
     266             :        "nofff=1\n"
     267             :        "noggg=0\n"
     268             :        "h=1\n"
     269             :        "noh=1\n"
     270             :        "noi=1\n"
     271             :        "i=1\n"
     272             :        "sec1.ccc=extend1\n"
     273             :        "\n"
     274             :        "[sec1]\n"
     275             :        "ccc=extend2\n"
     276             :        "d=eee\n"
     277             :        "h=1\n"
     278             :        "[sec2]\n"
     279             :        "ccc=extend3\n"
     280             :        "iii=2\n";
     281             : 
     282           2 :     TestArgsManager test_args;
     283             : 
     284           2 :     test_args.ReadConfigString(str_config);
     285             :     // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
     286             :     // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
     287             : 
     288           4 :     BOOST_CHECK(test_args.GetOverrideArgs().empty());
     289           4 :     BOOST_CHECK(test_args.GetConfigArgs().size() == 13);
     290             : 
     291          34 :     BOOST_CHECK(test_args.GetConfigArgs().count("-a")
     292             :                 && test_args.GetConfigArgs().count("-b")
     293             :                 && test_args.GetConfigArgs().count("-ccc")
     294             :                 && test_args.GetConfigArgs().count("-d")
     295             :                 && test_args.GetConfigArgs().count("-fff")
     296             :                 && test_args.GetConfigArgs().count("-ggg")
     297             :                 && test_args.GetConfigArgs().count("-h")
     298             :                 && test_args.GetConfigArgs().count("-i")
     299             :                );
     300          18 :     BOOST_CHECK(test_args.GetConfigArgs().count("-sec1.ccc")
     301             :                 && test_args.GetConfigArgs().count("-sec1.h")
     302             :                 && test_args.GetConfigArgs().count("-sec2.ccc")
     303             :                 && test_args.GetConfigArgs().count("-sec2.iii")
     304             :                );
     305             : 
     306          22 :     BOOST_CHECK(test_args.IsArgSet("-a")
     307             :                 && test_args.IsArgSet("-b")
     308             :                 && test_args.IsArgSet("-ccc")
     309             :                 && test_args.IsArgSet("-d")
     310             :                 && test_args.IsArgSet("-fff")
     311             :                 && test_args.IsArgSet("-ggg")
     312             :                 && test_args.IsArgSet("-h")
     313             :                 && test_args.IsArgSet("-i")
     314             :                 && !test_args.IsArgSet("-zzz")
     315             :                 && !test_args.IsArgSet("-iii")
     316             :                );
     317             : 
     318          58 :     BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
     319             :                 && test_args.GetArg("-b", "xxx") == "1"
     320             :                 && test_args.GetArg("-ccc", "xxx") == "argument"
     321             :                 && test_args.GetArg("-d", "xxx") == "e"
     322             :                 && test_args.GetArg("-fff", "xxx") == "0"
     323             :                 && test_args.GetArg("-ggg", "xxx") == "1"
     324             :                 && test_args.GetArg("-h", "xxx") == "0"
     325             :                 && test_args.GetArg("-i", "xxx") == "1"
     326             :                 && test_args.GetArg("-zzz", "xxx") == "xxx"
     327             :                 && test_args.GetArg("-iii", "xxx") == "xxx"
     328             :                );
     329             : 
     330           6 :     for (bool def : {false, true}) {
     331          44 :         BOOST_CHECK(test_args.GetBoolArg("-a", def)
     332             :                      && test_args.GetBoolArg("-b", def)
     333             :                      && !test_args.GetBoolArg("-ccc", def)
     334             :                      && !test_args.GetBoolArg("-d", def)
     335             :                      && !test_args.GetBoolArg("-fff", def)
     336             :                      && test_args.GetBoolArg("-ggg", def)
     337             :                      && !test_args.GetBoolArg("-h", def)
     338             :                      && test_args.GetBoolArg("-i", def)
     339             :                      && test_args.GetBoolArg("-zzz", def) == def
     340             :                      && test_args.GetBoolArg("-iii", def) == def
     341             :                    );
     342             :     }
     343             : 
     344           6 :     BOOST_CHECK(test_args.GetArgs("-a").size() == 1
     345             :                 && test_args.GetArgs("-a").front() == "");
     346           6 :     BOOST_CHECK(test_args.GetArgs("-b").size() == 1
     347             :                 && test_args.GetArgs("-b").front() == "1");
     348           8 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
     349             :                 && test_args.GetArgs("-ccc").front() == "argument"
     350             :                 && test_args.GetArgs("-ccc").back() == "multiple");
     351           4 :     BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
     352           4 :     BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
     353           6 :     BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
     354             :                 && test_args.GetArgs("-ggg").front() == "1");
     355           4 :     BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
     356           4 :     BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
     357           4 :     BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
     358           6 :     BOOST_CHECK(test_args.GetArgs("-i").size() == 1
     359             :                 && test_args.GetArgs("-i").front() == "1");
     360           4 :     BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
     361           4 :     BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
     362             : 
     363           4 :     BOOST_CHECK(!test_args.IsArgNegated("-a"));
     364           4 :     BOOST_CHECK(!test_args.IsArgNegated("-b"));
     365           4 :     BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
     366           4 :     BOOST_CHECK(!test_args.IsArgNegated("-d"));
     367           4 :     BOOST_CHECK(test_args.IsArgNegated("-fff"));
     368           4 :     BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
     369           4 :     BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
     370           4 :     BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
     371           4 :     BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
     372             : 
     373             :     // Test sections work
     374           2 :     test_args.SelectConfigNetwork("sec1");
     375             : 
     376             :     // same as original
     377          34 :     BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
     378             :                 && test_args.GetArg("-b", "xxx") == "1"
     379             :                 && test_args.GetArg("-fff", "xxx") == "0"
     380             :                 && test_args.GetArg("-ggg", "xxx") == "1"
     381             :                 && test_args.GetArg("-zzz", "xxx") == "xxx"
     382             :                 && test_args.GetArg("-iii", "xxx") == "xxx"
     383             :                );
     384             :     // d is overridden
     385           6 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
     386             :     // section-specific setting
     387           6 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
     388             :     // section takes priority for multiple values
     389           6 :     BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
     390             :     // check multiple values works
     391          12 :     const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
     392           4 :     const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
     393           4 :     BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
     394             : 
     395           2 :     test_args.SelectConfigNetwork("sec2");
     396             : 
     397             :     // same as original
     398          40 :     BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
     399             :                 && test_args.GetArg("-b", "xxx") == "1"
     400             :                 && test_args.GetArg("-d", "xxx") == "e"
     401             :                 && test_args.GetArg("-fff", "xxx") == "0"
     402             :                 && test_args.GetArg("-ggg", "xxx") == "1"
     403             :                 && test_args.GetArg("-zzz", "xxx") == "xxx"
     404             :                 && test_args.GetArg("-h", "xxx") == "0"
     405             :                );
     406             :     // section-specific setting
     407           6 :     BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
     408             :     // section takes priority for multiple values
     409           6 :     BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
     410             :     // check multiple values works
     411          10 :     const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
     412           4 :     const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
     413           4 :     BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
     414             : 
     415             :     // Test section only options
     416             : 
     417           2 :     test_args.SetNetworkOnlyArg("-d");
     418           2 :     test_args.SetNetworkOnlyArg("-ccc");
     419           2 :     test_args.SetNetworkOnlyArg("-h");
     420             : 
     421           2 :     test_args.SelectConfigNetwork(CBaseChainParams::MAIN);
     422           6 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
     423           4 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
     424           6 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
     425             : 
     426           2 :     test_args.SelectConfigNetwork("sec1");
     427           6 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
     428           4 :     BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
     429           4 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
     430           6 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
     431             : 
     432           2 :     test_args.SelectConfigNetwork("sec2");
     433           6 :     BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
     434           4 :     BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
     435           4 :     BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
     436           6 :     BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
     437           2 : }
     438             : 
     439           4 : BOOST_AUTO_TEST_CASE(util_GetArg)
     440             : {
     441           2 :     TestArgsManager testArgs;
     442           2 :     testArgs.GetOverrideArgs().clear();
     443           4 :     testArgs.GetOverrideArgs()["strtest1"] = {"string..."};
     444             :     // strtest2 undefined on purpose
     445           4 :     testArgs.GetOverrideArgs()["inttest1"] = {"12345"};
     446           4 :     testArgs.GetOverrideArgs()["inttest2"] = {"81985529216486895"};
     447             :     // inttest3 undefined on purpose
     448           4 :     testArgs.GetOverrideArgs()["booltest1"] = {""};
     449             :     // booltest2 undefined on purpose
     450           4 :     testArgs.GetOverrideArgs()["booltest3"] = {"0"};
     451           4 :     testArgs.GetOverrideArgs()["booltest4"] = {"1"};
     452             : 
     453             :     // priorities
     454           6 :     testArgs.GetOverrideArgs()["pritest1"] = {"a", "b"};
     455           6 :     testArgs.GetConfigArgs()["pritest2"] = {"a", "b"};
     456           4 :     testArgs.GetOverrideArgs()["pritest3"] = {"a"};
     457           4 :     testArgs.GetConfigArgs()["pritest3"] = {"b"};
     458           6 :     testArgs.GetOverrideArgs()["pritest4"] = {"a","b"};
     459           6 :     testArgs.GetConfigArgs()["pritest4"] = {"c","d"};
     460             : 
     461           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
     462           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
     463           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest1", -1), 12345);
     464           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest2", -1), 81985529216486895LL);
     465           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("inttest3", -1), -1);
     466           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
     467           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
     468           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
     469           2 :     BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
     470             : 
     471           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
     472           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
     473           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
     474           2 :     BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
     475           2 : }
     476             : 
     477           4 : BOOST_AUTO_TEST_CASE(util_GetChainName)
     478             : {
     479           2 :     TestArgsManager test_args;
     480             : 
     481           2 :     const char* argv_testnet[] = {"cmd", "-testnet"};
     482           2 :     const char* argv_regtest[] = {"cmd", "-regtest"};
     483           2 :     const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
     484           2 :     const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
     485             : 
     486             :     // equivalent to "-testnet"
     487             :     // regtest in testnet section is ignored
     488           2 :     const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
     489             : 
     490           2 :     test_args.ParseParameters(0, (char**)argv_testnet);
     491           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
     492             : 
     493           2 :     test_args.ParseParameters(2, (char**)argv_testnet);
     494           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     495             : 
     496           2 :     test_args.ParseParameters(2, (char**)argv_regtest);
     497           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
     498             : 
     499           2 :     test_args.ParseParameters(3, (char**)argv_test_no_reg);
     500           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     501             : 
     502           2 :     test_args.ParseParameters(3, (char**)argv_both);
     503           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     504             : 
     505           2 :     test_args.ParseParameters(0, (char**)argv_testnet);
     506           2 :     test_args.ReadConfigString(testnetconf);
     507           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     508             : 
     509           2 :     test_args.ParseParameters(2, (char**)argv_testnet);
     510           2 :     test_args.ReadConfigString(testnetconf);
     511           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     512             : 
     513           2 :     test_args.ParseParameters(2, (char**)argv_regtest);
     514           2 :     test_args.ReadConfigString(testnetconf);
     515           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     516             : 
     517           2 :     test_args.ParseParameters(3, (char**)argv_test_no_reg);
     518           2 :     test_args.ReadConfigString(testnetconf);
     519           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     520             : 
     521           2 :     test_args.ParseParameters(3, (char**)argv_both);
     522           2 :     test_args.ReadConfigString(testnetconf);
     523           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     524             : 
     525             :     // check setting the network to test (and thus making
     526             :     // [test] regtest=1 potentially relevant) doesn't break things
     527           2 :     test_args.SelectConfigNetwork("test");
     528             : 
     529           2 :     test_args.ParseParameters(0, (char**)argv_testnet);
     530           2 :     test_args.ReadConfigString(testnetconf);
     531           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     532             : 
     533           2 :     test_args.ParseParameters(2, (char**)argv_testnet);
     534           2 :     test_args.ReadConfigString(testnetconf);
     535           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     536             : 
     537           2 :     test_args.ParseParameters(2, (char**)argv_regtest);
     538           2 :     test_args.ReadConfigString(testnetconf);
     539           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     540             : 
     541           2 :     test_args.ParseParameters(2, (char**)argv_test_no_reg);
     542           2 :     test_args.ReadConfigString(testnetconf);
     543           2 :     BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
     544             : 
     545           2 :     test_args.ParseParameters(3, (char**)argv_both);
     546           2 :     test_args.ReadConfigString(testnetconf);
     547           4 :     BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
     548           2 : }
     549             : 
     550           4 : BOOST_AUTO_TEST_CASE(util_FormatMoney)
     551             : {
     552           2 :     BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00");
     553           2 :     BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789");
     554           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00");
     555           2 :     BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00");
     556           2 :     BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00");
     557             : 
     558           4 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00");
     559           4 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00");
     560           4 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00");
     561           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00");
     562           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00");
     563           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00");
     564           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00");
     565           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00");
     566           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00");
     567           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10");
     568           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01");
     569           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001");
     570           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
     571           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
     572           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
     573           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
     574           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
     575           2 : }
     576             : 
     577           4 : BOOST_AUTO_TEST_CASE(util_ParseMoney)
     578             : {
     579           2 :     CAmount ret = 0;
     580           4 :     BOOST_CHECK(ParseMoney("0.0", ret));
     581           2 :     BOOST_CHECK_EQUAL(ret, 0);
     582             : 
     583           4 :     BOOST_CHECK(ParseMoney("12345.6789", ret));
     584           2 :     BOOST_CHECK_EQUAL(ret, (COIN/10000)*123456789);
     585             : 
     586           4 :     BOOST_CHECK(ParseMoney("100000000.00", ret));
     587           2 :     BOOST_CHECK_EQUAL(ret, COIN*100000000);
     588           4 :     BOOST_CHECK(ParseMoney("10000000.00", ret));
     589           2 :     BOOST_CHECK_EQUAL(ret, COIN*10000000);
     590           4 :     BOOST_CHECK(ParseMoney("1000000.00", ret));
     591           2 :     BOOST_CHECK_EQUAL(ret, COIN*1000000);
     592           4 :     BOOST_CHECK(ParseMoney("100000.00", ret));
     593           2 :     BOOST_CHECK_EQUAL(ret, COIN*100000);
     594           4 :     BOOST_CHECK(ParseMoney("10000.00", ret));
     595           2 :     BOOST_CHECK_EQUAL(ret, COIN*10000);
     596           4 :     BOOST_CHECK(ParseMoney("1000.00", ret));
     597           2 :     BOOST_CHECK_EQUAL(ret, COIN*1000);
     598           4 :     BOOST_CHECK(ParseMoney("100.00", ret));
     599           2 :     BOOST_CHECK_EQUAL(ret, COIN*100);
     600           4 :     BOOST_CHECK(ParseMoney("10.00", ret));
     601           2 :     BOOST_CHECK_EQUAL(ret, COIN*10);
     602           4 :     BOOST_CHECK(ParseMoney("1.00", ret));
     603           2 :     BOOST_CHECK_EQUAL(ret, COIN);
     604           4 :     BOOST_CHECK(ParseMoney("1", ret));
     605           2 :     BOOST_CHECK_EQUAL(ret, COIN);
     606           4 :     BOOST_CHECK(ParseMoney("0.1", ret));
     607           2 :     BOOST_CHECK_EQUAL(ret, COIN/10);
     608           4 :     BOOST_CHECK(ParseMoney("0.01", ret));
     609           2 :     BOOST_CHECK_EQUAL(ret, COIN/100);
     610           4 :     BOOST_CHECK(ParseMoney("0.001", ret));
     611           2 :     BOOST_CHECK_EQUAL(ret, COIN/1000);
     612           4 :     BOOST_CHECK(ParseMoney("0.0001", ret));
     613           2 :     BOOST_CHECK_EQUAL(ret, COIN/10000);
     614           4 :     BOOST_CHECK(ParseMoney("0.00001", ret));
     615           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000);
     616           4 :     BOOST_CHECK(ParseMoney("0.000001", ret));
     617           2 :     BOOST_CHECK_EQUAL(ret, COIN/1000000);
     618           4 :     BOOST_CHECK(ParseMoney("0.0000001", ret));
     619           2 :     BOOST_CHECK_EQUAL(ret, COIN/10000000);
     620           4 :     BOOST_CHECK(ParseMoney("0.00000001", ret));
     621           2 :     BOOST_CHECK_EQUAL(ret, COIN/100000000);
     622             : 
     623             :     // Attempted 63 bit overflow should fail
     624           4 :     BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
     625             : 
     626             :     // Parsing negative amounts must fail
     627           4 :     BOOST_CHECK(!ParseMoney("-1", ret));
     628           2 : }
     629             : 
     630           4 : BOOST_AUTO_TEST_CASE(util_IsHex)
     631             : {
     632           4 :     BOOST_CHECK(IsHex("00"));
     633           6 :     BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
     634           4 :     BOOST_CHECK(IsHex("ff"));
     635           4 :     BOOST_CHECK(IsHex("FF"));
     636             : 
     637           4 :     BOOST_CHECK(!IsHex(""));
     638           4 :     BOOST_CHECK(!IsHex("0"));
     639           4 :     BOOST_CHECK(!IsHex("a"));
     640           4 :     BOOST_CHECK(!IsHex("eleven"));
     641           4 :     BOOST_CHECK(!IsHex("00xx00"));
     642           4 :     BOOST_CHECK(!IsHex("0x0000"));
     643           2 : }
     644             : 
     645           4 : BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
     646             : {
     647           2 :     int i;
     648           2 :     int count=0;
     649             : 
     650           2 :     SeedInsecureRand(SeedRand::ZEROS);
     651             : 
     652          20 :     for (int mod=2;mod<11;mod++)
     653             :     {
     654          18 :         int mask = 1;
     655             :         // Really rough binomal confidence approximation.
     656          18 :         int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
     657             :         //mask is 2^ceil(log2(mod))-1
     658          50 :         while(mask<mod-1)mask=(mask<<1)+1;
     659             : 
     660             :         count = 0;
     661             :         //How often does it get a zero from the uniform range [0,mod)?
     662      180018 :         for (i=0;i<10000;i++)
     663             :         {
     664      235652 :             uint32_t rval;
     665      235652 :             do{
     666      235652 :                 rval=InsecureRand32()&mask;
     667      235652 :             }while(rval>=(uint32_t)mod);
     668      180000 :             count += rval==0;
     669             :         }
     670          36 :         BOOST_CHECK(count<=10000/mod+err);
     671          36 :         BOOST_CHECK(count>=10000/mod-err);
     672             :     }
     673           2 : }
     674             : 
     675           4 : BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
     676             : {
     677           4 :     BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
     678           4 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
     679           4 :     BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
     680           4 :     BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
     681           4 :     BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
     682           4 :     BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
     683           4 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
     684           2 : }
     685             : 
     686             : /* Test strprintf formatting directives.
     687             :  * Put a string before and after to ensure sanity of element sizes on stack. */
     688             : #define B "check_prefix"
     689             : #define E "check_postfix"
     690           4 : BOOST_AUTO_TEST_CASE(strprintf_numbers)
     691             : {
     692           2 :     int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
     693           2 :     uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
     694           8 :     BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
     695           8 :     BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
     696           8 :     BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
     697             : 
     698           2 :     size_t st = 12345678; /* unsigned size_t test value */
     699           2 :     ssize_t sst = -12345678; /* signed size_t test value */
     700           8 :     BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
     701           8 :     BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
     702           8 :     BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
     703             : 
     704           2 :     ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
     705           2 :     ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
     706           8 :     BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
     707           8 :     BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
     708           8 :     BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
     709           2 : }
     710             : #undef B
     711             : #undef E
     712             : 
     713             : /* Check for mingw/wine issue #3494
     714             :  * Remove this test before time.ctime(0xffffffff) == 'Sun Feb  7 07:28:15 2106'
     715             :  */
     716           4 : BOOST_AUTO_TEST_CASE(gettime)
     717             : {
     718           4 :     BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
     719           2 : }
     720             : 
     721           4 : BOOST_AUTO_TEST_CASE(util_time_GetTime)
     722             : {
     723           2 :     SetMockTime(111);
     724             :     // Check that mock time does not change after a sleep
     725           6 :     for (const auto& num_sleep : {0, 1}) {
     726           4 :         MilliSleep(num_sleep);
     727           4 :         BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
     728           4 :         BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
     729           4 :         BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
     730           4 :         BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
     731             :     }
     732             : 
     733           2 :     SetMockTime(0);
     734             :     // Check that system time changes after a sleep
     735           2 :     const auto ms_0 = GetTime<std::chrono::milliseconds>();
     736           2 :     const auto us_0 = GetTime<std::chrono::microseconds>();
     737           2 :     MilliSleep(1);
     738           4 :     BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
     739           4 :     BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
     740           2 : }
     741             : 
     742           4 : BOOST_AUTO_TEST_CASE(test_IsDigit)
     743             : {
     744           2 :     BOOST_CHECK_EQUAL(IsDigit('0'), true);
     745           2 :     BOOST_CHECK_EQUAL(IsDigit('1'), true);
     746           2 :     BOOST_CHECK_EQUAL(IsDigit('8'), true);
     747           2 :     BOOST_CHECK_EQUAL(IsDigit('9'), true);
     748             : 
     749           2 :     BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
     750           2 :     BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
     751           2 :     BOOST_CHECK_EQUAL(IsDigit(0), false);
     752           2 :     BOOST_CHECK_EQUAL(IsDigit(1), false);
     753           2 :     BOOST_CHECK_EQUAL(IsDigit(8), false);
     754           2 :     BOOST_CHECK_EQUAL(IsDigit(9), false);
     755           2 : }
     756             : 
     757           4 : BOOST_AUTO_TEST_CASE(test_ParseInt32)
     758             : {
     759           2 :     int32_t n;
     760             :     // Valid values
     761           4 :     BOOST_CHECK(ParseInt32("1234", nullptr));
     762           4 :     BOOST_CHECK(ParseInt32("0", &n) && n == 0);
     763           4 :     BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
     764           4 :     BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
     765           4 :     BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
     766           4 :     BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648);
     767           4 :     BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
     768             :     // Invalid values
     769           4 :     BOOST_CHECK(!ParseInt32("", &n));
     770           4 :     BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
     771           4 :     BOOST_CHECK(!ParseInt32("1 ", &n));
     772           4 :     BOOST_CHECK(!ParseInt32("1a", &n));
     773           4 :     BOOST_CHECK(!ParseInt32("aap", &n));
     774           4 :     BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
     775           4 :     BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
     776           2 :     const char test_bytes[] = {'1', 0, '1'};
     777           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
     778           4 :     BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
     779             :     // Overflow and underflow
     780           4 :     BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
     781           4 :     BOOST_CHECK(!ParseInt32("2147483648", nullptr));
     782           6 :     BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
     783           6 :     BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
     784           2 : }
     785             : 
     786           4 : BOOST_AUTO_TEST_CASE(test_ParseInt64)
     787             : {
     788           2 :     int64_t n;
     789             :     // Valid values
     790           4 :     BOOST_CHECK(ParseInt64("1234", nullptr));
     791           4 :     BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
     792           4 :     BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
     793           4 :     BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
     794           4 :     BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
     795           4 :     BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
     796           6 :     BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
     797           6 :     BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
     798           4 :     BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
     799             :     // Invalid values
     800           4 :     BOOST_CHECK(!ParseInt64("", &n));
     801           4 :     BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
     802           4 :     BOOST_CHECK(!ParseInt64("1 ", &n));
     803           4 :     BOOST_CHECK(!ParseInt64("1a", &n));
     804           4 :     BOOST_CHECK(!ParseInt64("aap", &n));
     805           4 :     BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
     806           2 :     const char test_bytes[] = {'1', 0, '1'};
     807           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
     808           4 :     BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
     809             :     // Overflow and underflow
     810           6 :     BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
     811           6 :     BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
     812           6 :     BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
     813           6 :     BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
     814           2 : }
     815             : 
     816           4 : BOOST_AUTO_TEST_CASE(test_ParseDouble)
     817             : {
     818           2 :     double n;
     819             :     // Valid values
     820           4 :     BOOST_CHECK(ParseDouble("1234", nullptr));
     821           4 :     BOOST_CHECK(ParseDouble("0", &n) && n == 0.0);
     822           4 :     BOOST_CHECK(ParseDouble("1234", &n) && n == 1234.0);
     823           4 :     BOOST_CHECK(ParseDouble("01234", &n) && n == 1234.0); // no octal
     824           4 :     BOOST_CHECK(ParseDouble("2147483647", &n) && n == 2147483647.0);
     825           4 :     BOOST_CHECK(ParseDouble("-2147483648", &n) && n == -2147483648.0);
     826           4 :     BOOST_CHECK(ParseDouble("-1234", &n) && n == -1234.0);
     827           4 :     BOOST_CHECK(ParseDouble("1e6", &n) && n == 1e6);
     828           4 :     BOOST_CHECK(ParseDouble("-1e6", &n) && n == -1e6);
     829             :     // Invalid values
     830           4 :     BOOST_CHECK(!ParseDouble("", &n));
     831           4 :     BOOST_CHECK(!ParseDouble(" 1", &n)); // no padding inside
     832           4 :     BOOST_CHECK(!ParseDouble("1 ", &n));
     833           4 :     BOOST_CHECK(!ParseDouble("1a", &n));
     834           4 :     BOOST_CHECK(!ParseDouble("aap", &n));
     835           4 :     BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
     836           2 :     const char test_bytes[] = {'1', 0, '1'};
     837           2 :     std::string teststr(test_bytes, sizeof(test_bytes));
     838           4 :     BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
     839             :     // Overflow and underflow
     840           4 :     BOOST_CHECK(!ParseDouble("-1e10000", nullptr));
     841           4 :     BOOST_CHECK(!ParseDouble("1e10000", nullptr));
     842           2 : }
     843             : 
     844           4 : BOOST_AUTO_TEST_CASE(test_FormatParagraph)
     845             : {
     846           2 :     BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
     847           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
     848           2 :     BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), "test");
     849           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
     850           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
     851           2 :     BOOST_CHECK_EQUAL(FormatParagraph("testerde test ", 4, 0), "testerde\ntest");
     852           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n    test");
     853           6 :     BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string."), "This is a very long test string. This is a second sentence in the very long\ntest string.");
     854           2 : }
     855             : 
     856           4 : BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
     857             : {
     858           4 :     std::vector<std::string> comments;
     859           4 :     comments.push_back(std::string("comment1"));
     860           4 :     std::vector<std::string> comments2;
     861           4 :     comments2.push_back(std::string("comment1"));
     862           4 :     comments2.push_back(std::string("comment2"));
     863           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
     864           6 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
     865           6 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/"));
     866           2 : }
     867             : 
     868           4 : BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
     869             : {
     870           2 :     int64_t amount = 0;
     871           4 :     BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
     872           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
     873           4 :     BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
     874           2 :     BOOST_CHECK_EQUAL(amount, 100000000LL);
     875           4 :     BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
     876           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
     877           4 :     BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
     878           2 :     BOOST_CHECK_EQUAL(amount, -10000000LL);
     879           4 :     BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
     880           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
     881           6 :     BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
     882           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
     883           4 :     BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
     884           2 :     BOOST_CHECK_EQUAL(amount, 1100000000LL);
     885           4 :     BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
     886           2 :     BOOST_CHECK_EQUAL(amount, 11000000LL);
     887           4 :     BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
     888           2 :     BOOST_CHECK_EQUAL(amount, 100000000000LL);
     889           4 :     BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
     890           2 :     BOOST_CHECK_EQUAL(amount, -100000000000LL);
     891           4 :     BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
     892           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
     893           6 :     BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
     894           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
     895           4 :     BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
     896           2 :     BOOST_CHECK_EQUAL(amount, -1LL);
     897           6 :     BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
     898           2 :     BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
     899           6 :     BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
     900           2 :     BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
     901           6 :     BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
     902           2 :     BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
     903             : 
     904           4 :     BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
     905           4 :     BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
     906           4 :     BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
     907           4 :     BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
     908           4 :     BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
     909           4 :     BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
     910           4 :     BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
     911           4 :     BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
     912           4 :     BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
     913           4 :     BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
     914           4 :     BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
     915           6 :     BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
     916           6 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
     917           6 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
     918           6 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
     919           6 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
     920           6 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
     921           6 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
     922           6 :     BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
     923           6 :     BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
     924           6 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
     925           6 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
     926           6 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
     927           6 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
     928           4 :     BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
     929           4 :     BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
     930           4 :     BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
     931           2 : }
     932             : 
     933           4 : BOOST_AUTO_TEST_CASE(test_ToLower)
     934             : {
     935           2 :     BOOST_CHECK_EQUAL(ToLower('@'), '@');
     936           2 :     BOOST_CHECK_EQUAL(ToLower('A'), 'a');
     937           2 :     BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
     938           2 :     BOOST_CHECK_EQUAL(ToLower('['), '[');
     939           2 :     BOOST_CHECK_EQUAL(ToLower(0), 0);
     940           2 :     BOOST_CHECK_EQUAL(ToLower(255), 255);
     941             : 
     942           2 :     std::string testVector;
     943           2 :     Downcase(testVector);
     944           2 :     BOOST_CHECK_EQUAL(testVector, "");
     945             : 
     946           2 :     testVector = "#HODL";
     947           2 :     Downcase(testVector);
     948           2 :     BOOST_CHECK_EQUAL(testVector, "#hodl");
     949             : 
     950           2 :     testVector = "\x00\xfe\xff";
     951           2 :     Downcase(testVector);
     952           2 :     BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff");
     953           2 : }
     954             : 
     955           4 : BOOST_AUTO_TEST_CASE(test_ToUpper)
     956             : {
     957           2 :     BOOST_CHECK_EQUAL(ToUpper('`'), '`');
     958           2 :     BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
     959           2 :     BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
     960           2 :     BOOST_CHECK_EQUAL(ToUpper('{'), '{');
     961           2 :     BOOST_CHECK_EQUAL(ToUpper(0), 0);
     962           2 :     BOOST_CHECK_EQUAL(ToUpper(255), 255);
     963           2 : }
     964             : 
     965           4 : BOOST_AUTO_TEST_CASE(test_Capitalize)
     966             : {
     967           2 :     BOOST_CHECK_EQUAL(Capitalize(""), "");
     968           2 :     BOOST_CHECK_EQUAL(Capitalize("pivx"), "Pivx");
     969           2 :     BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
     970           2 : }
     971             : 
     972           4 : BOOST_AUTO_TEST_CASE(test_validateURL)
     973             : {
     974             :     // Must pass
     975           4 :     BOOST_CHECK(validateURL("http://foo.bar"));
     976           4 :     BOOST_CHECK(validateURL("https://foo.bar"));
     977           6 :     BOOST_CHECK(validateURL("https://foo.bar/"));
     978           6 :     BOOST_CHECK(validateURL("http://pivx.foo.bar"));
     979           6 :     BOOST_CHECK(validateURL("https://foo.bar/pivx"));
     980           6 :     BOOST_CHECK(validateURL("https://foo.bar/pivx/more/"));
     981           6 :     BOOST_CHECK(validateURL("https://142.2.3.1"));
     982           6 :     BOOST_CHECK(validateURL("https://foo_bar.pivx.com"));
     983           6 :     BOOST_CHECK(validateURL("http://foo.bar/?baz=some"));
     984           6 :     BOOST_CHECK(validateURL("http://foo.bar/?baz=some&p=364"));
     985             : 
     986             :     // Must fail
     987           4 :     BOOST_CHECK(!validateURL("BlahBlah"));
     988           4 :     BOOST_CHECK(!validateURL("foo.bar"));
     989           4 :     BOOST_CHECK(!validateURL("://foo.bar"));
     990           4 :     BOOST_CHECK(!validateURL("www.foo.bar"));
     991           4 :     BOOST_CHECK(!validateURL("http://foo..bar"));
     992           4 :     BOOST_CHECK(!validateURL("http:///foo.bar"));
     993           4 :     BOOST_CHECK(!validateURL("http:// foo.bar"));
     994           4 :     BOOST_CHECK(!validateURL("http://foo .bar"));
     995           4 :     BOOST_CHECK(!validateURL("http://foo"));
     996           4 :     BOOST_CHECK(!validateURL("http://foo.bar."));
     997           6 :     BOOST_CHECK(!validateURL("http://foo.bar.."));
     998           4 :     BOOST_CHECK(!validateURL("http://"));
     999           6 :     BOOST_CHECK(!validateURL("http://.something.com"));
    1000           6 :     BOOST_CHECK(!validateURL("http://?something.com"));
    1001           6 :     BOOST_CHECK(!validateURL("https://foo.bar/?q=Spaces are not encoded"));
    1002           2 : }
    1003             : 
    1004           1 : static void TestOtherThread(fs::path dirname, std::string lockname, bool *result)
    1005             : {
    1006           1 :     *result = LockDirectory(dirname, lockname);
    1007           1 : }
    1008             : 
    1009             : #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
    1010             : static constexpr char LockCommand = 'L';
    1011             : static constexpr char UnlockCommand = 'U';
    1012             : static constexpr char ExitCommand = 'X';
    1013             : 
    1014           1 : static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
    1015             : {
    1016           5 :     char ch;
    1017           5 :     int rv;
    1018           5 :     while (true) {
    1019          10 :         rv = read(fd, &ch, 1); // Wait for command
    1020           5 :         assert(rv == 1);
    1021           5 :         switch(ch) {
    1022           3 :             case LockCommand:
    1023           3 :                 ch = LockDirectory(dirname, lockname);
    1024           3 :                 rv = write(fd, &ch, 1);
    1025           3 :                 assert(rv == 1);
    1026             :                 break;
    1027           1 :             case UnlockCommand:
    1028           1 :                 ReleaseDirectoryLocks();
    1029           1 :                 ch = true; // Always succeeds
    1030           6 :                 rv = write(fd, &ch, 1);
    1031             :                 break;
    1032           1 :             case ExitCommand:
    1033           1 :                 close(fd);
    1034           1 :                 exit(0);
    1035           0 :             default:
    1036           0 :                 assert(0);
    1037             :         }
    1038             :     }
    1039             : }
    1040             : #endif
    1041             : 
    1042           4 : BOOST_AUTO_TEST_CASE(test_LockDirectory)
    1043             : {
    1044           6 :     fs::path dirname = fs::temp_directory_path() / fs::unique_path();
    1045           3 :     const std::string lockname = ".lock";
    1046             : #ifndef WIN32
    1047             :     // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
    1048             :     // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
    1049             :     // at build-time of the boost library
    1050           2 :     void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
    1051             : 
    1052             :     // Fork another process for testing before creating the lock, so that we
    1053             :     // won't fork while holding the lock (which might be undefined, and is not
    1054             :     // relevant as test case as that is avoided with -daemonize).
    1055           2 :     int fd[2];
    1056           2 :     BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
    1057           2 :     pid_t pid = fork();
    1058           2 :     if (!pid) {
    1059           1 :         BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
    1060           3 :         TestOtherProcess(dirname, lockname, fd[0]);
    1061             :     }
    1062           1 :     BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
    1063             : #endif
    1064             :     // Lock on non-existent directory should fail
    1065           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
    1066             : 
    1067           1 :     fs::create_directories(dirname);
    1068             : 
    1069             :     // Probing lock on new directory should succeed
    1070           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1071             : 
    1072             :     // Persistent lock on new directory should succeed
    1073           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1074             : 
    1075             :     // Another lock on the directory from the same thread should succeed
    1076           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1077             : 
    1078             :     // Another lock on the directory from a different thread within the same process should succeed
    1079           1 :     bool threadresult;
    1080           2 :     std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
    1081           1 :     thr.join();
    1082           1 :     BOOST_CHECK_EQUAL(threadresult, true);
    1083             : #ifndef WIN32
    1084             :     // Try to acquire lock in child process while we're holding it, this should fail.
    1085           1 :     char ch;
    1086           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1087           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1088           1 :     BOOST_CHECK_EQUAL((bool)ch, false);
    1089             : 
    1090             :     // Give up our lock
    1091           1 :     ReleaseDirectoryLocks();
    1092             :     // Probing lock from our side now should succeed, but not hold on to the lock.
    1093           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1094             : 
    1095             :     // Try to acquire the lock in the child process, this should be successful.
    1096           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1097           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1098           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1099             : 
    1100             :     // When we try to probe the lock now, it should fail.
    1101           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
    1102             : 
    1103             :     // Unlock the lock in the child process
    1104           1 :     BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
    1105           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1106           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1107             : 
    1108             :     // When we try to probe the lock now, it should succeed.
    1109           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1110             : 
    1111             :     // Re-lock the lock in the child process, then wait for it to exit, check
    1112             :     // successful return. After that, we check that exiting the process
    1113             :     // has released the lock as we would expect by probing it.
    1114           1 :     int processstatus;
    1115           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1116           1 :     BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
    1117           1 :     BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
    1118           1 :     BOOST_CHECK_EQUAL(processstatus, 0);
    1119           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1120             : 
    1121             :     // Restore SIGCHLD
    1122           1 :     signal(SIGCHLD, old_handler);
    1123           1 :     BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
    1124             : #endif
    1125             :     // Clean up
    1126           1 :     ReleaseDirectoryLocks();
    1127           1 :     fs::remove_all(dirname);
    1128           1 : }
    1129             : 
    1130           2 : BOOST_AUTO_TEST_CASE(test_DirIsWritable)
    1131             : {
    1132             :     // Should be able to write to the system tmp dir.
    1133           1 :     fs::path tmpdirname = fs::temp_directory_path();
    1134           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1135             : 
    1136             :     // Should not be able to write to a non-existent dir.
    1137           3 :     tmpdirname = fs::temp_directory_path() / fs::unique_path();
    1138           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
    1139             : 
    1140           1 :     fs::create_directory(tmpdirname);
    1141             :     // Should be able to write to it now.
    1142           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1143           1 :     fs::remove(tmpdirname);
    1144           1 : }
    1145             : 
    1146             : namespace {
    1147             : 
    1148             :     struct Tracker
    1149             :     {
    1150             :         //! Points to the original object (possibly itself) we moved/copied from
    1151             :         const Tracker* origin;
    1152             :         //! How many copies where involved between the original object and this one (moves are not counted)
    1153             :         int copies;
    1154             : 
    1155           1 :         Tracker() noexcept : origin(this), copies(0) {}
    1156          10 :         Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
    1157          13 :         Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
    1158             :         Tracker& operator=(const Tracker& t) noexcept
    1159             :         {
    1160             :             origin = t.origin;
    1161             :             copies = t.copies + 1;
    1162             :             return *this;
    1163             :         }
    1164             :         Tracker& operator=(Tracker&& t) noexcept
    1165             :         {
    1166             :             origin = t.origin;
    1167             :             copies = t.copies;
    1168             :             return *this;
    1169             :         }
    1170             :     };
    1171             : 
    1172             : }
    1173             : 
    1174           2 : BOOST_AUTO_TEST_CASE(test_tracked_vector)
    1175             : {
    1176           1 :     Tracker t1;
    1177           1 :     Tracker t2;
    1178           1 :     Tracker t3;
    1179             : 
    1180           2 :     BOOST_CHECK(t1.origin == &t1);
    1181           2 :     BOOST_CHECK(t2.origin == &t2);
    1182           2 :     BOOST_CHECK(t3.origin == &t3);
    1183             : 
    1184           1 :     auto v1 = Vector(t1);
    1185           1 :     BOOST_CHECK_EQUAL(v1.size(), 1);
    1186           2 :     BOOST_CHECK(v1[0].origin == &t1);
    1187           1 :     BOOST_CHECK_EQUAL(v1[0].copies, 1);
    1188             : 
    1189           2 :     auto v2 = Vector(std::move(t2));
    1190           1 :     BOOST_CHECK_EQUAL(v2.size(), 1);
    1191           2 :     BOOST_CHECK(v2[0].origin == &t2);
    1192           1 :     BOOST_CHECK_EQUAL(v2[0].copies, 0);
    1193             : 
    1194           2 :     auto v3 = Vector(t1, std::move(t2));
    1195           1 :     BOOST_CHECK_EQUAL(v3.size(), 2);
    1196           2 :     BOOST_CHECK(v3[0].origin == &t1);
    1197           2 :     BOOST_CHECK(v3[1].origin == &t2);
    1198           1 :     BOOST_CHECK_EQUAL(v3[0].copies, 1);
    1199           1 :     BOOST_CHECK_EQUAL(v3[1].copies, 0);
    1200             : 
    1201           2 :     auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
    1202           1 :     BOOST_CHECK_EQUAL(v4.size(), 3);
    1203           2 :     BOOST_CHECK(v4[0].origin == &t1);
    1204           2 :     BOOST_CHECK(v4[1].origin == &t2);
    1205           2 :     BOOST_CHECK(v4[2].origin == &t3);
    1206           1 :     BOOST_CHECK_EQUAL(v4[0].copies, 1);
    1207           1 :     BOOST_CHECK_EQUAL(v4[1].copies, 1);
    1208           1 :     BOOST_CHECK_EQUAL(v4[2].copies, 0);
    1209             : 
    1210           2 :     auto v5 = Cat(v1, v4);
    1211           1 :     BOOST_CHECK_EQUAL(v5.size(), 4);
    1212           2 :     BOOST_CHECK(v5[0].origin == &t1);
    1213           2 :     BOOST_CHECK(v5[1].origin == &t1);
    1214           2 :     BOOST_CHECK(v5[2].origin == &t2);
    1215           2 :     BOOST_CHECK(v5[3].origin == &t3);
    1216           1 :     BOOST_CHECK_EQUAL(v5[0].copies, 2);
    1217           1 :     BOOST_CHECK_EQUAL(v5[1].copies, 2);
    1218           1 :     BOOST_CHECK_EQUAL(v5[2].copies, 2);
    1219           1 :     BOOST_CHECK_EQUAL(v5[3].copies, 1);
    1220             : 
    1221           2 :     auto v6 = Cat(std::move(v1), v3);
    1222           1 :     BOOST_CHECK_EQUAL(v6.size(), 3);
    1223           2 :     BOOST_CHECK(v6[0].origin == &t1);
    1224           2 :     BOOST_CHECK(v6[1].origin == &t1);
    1225           2 :     BOOST_CHECK(v6[2].origin == &t2);
    1226           1 :     BOOST_CHECK_EQUAL(v6[0].copies, 1);
    1227           1 :     BOOST_CHECK_EQUAL(v6[1].copies, 2);
    1228           1 :     BOOST_CHECK_EQUAL(v6[2].copies, 1);
    1229             : 
    1230           2 :     auto v7 = Cat(v2, std::move(v4));
    1231           1 :     BOOST_CHECK_EQUAL(v7.size(), 4);
    1232           2 :     BOOST_CHECK(v7[0].origin == &t2);
    1233           2 :     BOOST_CHECK(v7[1].origin == &t1);
    1234           2 :     BOOST_CHECK(v7[2].origin == &t2);
    1235           2 :     BOOST_CHECK(v7[3].origin == &t3);
    1236           1 :     BOOST_CHECK_EQUAL(v7[0].copies, 1);
    1237           1 :     BOOST_CHECK_EQUAL(v7[1].copies, 1);
    1238           1 :     BOOST_CHECK_EQUAL(v7[2].copies, 1);
    1239           1 :     BOOST_CHECK_EQUAL(v7[3].copies, 0);
    1240             : 
    1241           2 :     auto v8 = Cat(std::move(v2), std::move(v3));
    1242           1 :     BOOST_CHECK_EQUAL(v8.size(), 3);
    1243           2 :     BOOST_CHECK(v8[0].origin == &t2);
    1244           2 :     BOOST_CHECK(v8[1].origin == &t1);
    1245           2 :     BOOST_CHECK(v8[2].origin == &t2);
    1246           1 :     BOOST_CHECK_EQUAL(v8[0].copies, 0);
    1247           1 :     BOOST_CHECK_EQUAL(v8[1].copies, 1);
    1248           1 :     BOOST_CHECK_EQUAL(v8[2].copies, 0);
    1249           1 : }
    1250             : 
    1251             : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14