LCOV - code coverage report
Current view: top level - src/test - util_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1246 1249 99.8 %
Date: 2026-06-25 07:23:43 Functions: 396 396 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2021 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 <fs.h>
       9             : #include <hash.h> // For Hash()
      10             : #include <key.h>  // For CKey
      11             : #include <sync.h>
      12             : #include <test/util/random.h>
      13             : #include <test/util/setup_common.h>
      14             : #include <uint256.h>
      15             : #include <util/getuniquepath.h>
      16             : #include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
      17             : #include <util/moneystr.h>
      18             : #include <util/overflow.h>
      19             : #include <util/ranges_set.h>
      20             : #include <util/readwritefile.h>
      21             : #include <util/spanparsing.h>
      22             : #include <util/strencodings.h>
      23             : #include <util/string.h>
      24             : #include <util/time.h>
      25             : #include <util/vector.h>
      26             : 
      27             : #include <array>
      28             : #include <cmath>
      29             : #include <fstream>
      30             : #include <deque>
      31             : #include <optional>
      32             : #include <limits>
      33             : #include <map>
      34             : #include <random>
      35             : #include <stdint.h>
      36             : #include <string.h>
      37             : #include <thread>
      38             : #include <univalue.h>
      39             : #include <unordered_set>
      40             : #include <utility>
      41             : #include <vector>
      42             : 
      43             : #include <sys/types.h>
      44             : 
      45             : #ifndef WIN32
      46             : #include <signal.h>
      47             : #include <sys/wait.h>
      48             : #endif
      49             : 
      50             : #include <boost/test/unit_test.hpp>
      51             : 
      52             : using namespace std::literals;
      53             : 
      54             : static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s};
      55             : 
      56             : /* defined in logging.cpp */
      57             : namespace BCLog {
      58             :     std::string LogEscapeMessage(const std::string& str);
      59             : }
      60             : 
      61         146 : BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
      62             : 
      63             : namespace {
      64             : class NoCopyOrMove
      65             : {
      66             : public:
      67             :     int i;
      68           4 :     explicit NoCopyOrMove(int i) : i{i} { }
      69             : 
      70             :     NoCopyOrMove() = delete;
      71             :     NoCopyOrMove(const NoCopyOrMove&) = delete;
      72             :     NoCopyOrMove(NoCopyOrMove&&) = delete;
      73             :     NoCopyOrMove& operator=(const NoCopyOrMove&) = delete;
      74             :     NoCopyOrMove& operator=(NoCopyOrMove&&) = delete;
      75             : 
      76           6 :     operator bool() const { return i != 0; }
      77             : 
      78           8 :     int get_ip1() { return i + 1; }
      79           4 :     bool test()
      80             :     {
      81             :         // Check that Assume can be used within a lambda and still call methods
      82           8 :         [&]() { Assume(get_ip1()); }();
      83           4 :         return Assume(get_ip1() != 5);
      84             :     }
      85             : };
      86             : } // namespace
      87             : 
      88         152 : BOOST_AUTO_TEST_CASE(util_check)
      89             : {
      90             :     // Check that Assert can forward
      91           2 :     const std::unique_ptr<int> p_two = Assert(std::make_unique<int>(2));
      92             :     // Check that Assert works on lvalues and rvalues
      93           2 :     const int two = *Assert(p_two);
      94           2 :     Assert(two == 2);
      95           2 :     Assert(true);
      96             :     // Check that Assume can be used as unary expression
      97           2 :     const bool result{Assume(two == 2)};
      98           2 :     Assert(result);
      99             : 
     100             :     // Check that Assert doesn't require copy/move
     101           2 :     NoCopyOrMove x{9};
     102           2 :     Assert(x).i += 3;
     103           2 :     Assert(x).test();
     104             : 
     105             :     // Check nested Asserts
     106           2 :     BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3);
     107             : 
     108             :     // Check -Wdangling-gsl does not trigger when copying the int. (It would
     109             :     // trigger on "const int&")
     110           2 :     const int nine{*Assert(std::optional<int>{9})};
     111           2 :     BOOST_CHECK_EQUAL(9, nine);
     112           2 : }
     113             : 
     114         152 : BOOST_AUTO_TEST_CASE(util_criticalsection)
     115             : {
     116           2 :     RecursiveMutex cs;
     117             : 
     118           2 :     do {
     119           2 :         LOCK(cs);
     120             :         break;
     121             : 
     122             :         BOOST_ERROR("break was swallowed!");
     123           2 :     } while(0);
     124             : 
     125           2 :     do {
     126           2 :         TRY_LOCK(cs, lockTest);
     127           2 :         if (lockTest) {
     128           2 :             BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
     129           2 :             break;
     130             :         }
     131             : 
     132           0 :         BOOST_ERROR("break was swallowed!");
     133           2 :     } while(0);
     134           2 : }
     135             : 
     136             : static const unsigned char ParseHex_expected[65] = {
     137             :     0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
     138             :     0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
     139             :     0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
     140             :     0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
     141             :     0x5f
     142             : };
     143         152 : BOOST_AUTO_TEST_CASE(parse_hex)
     144             : {
     145           2 :     std::vector<unsigned char> result;
     146           2 :     std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
     147             :     // Basic test vector
     148           2 :     result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
     149           2 :     BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
     150           2 :     result = TryParseHex<uint8_t>("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").value();
     151           2 :     BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
     152             : 
     153             :     // Spaces between bytes must be supported
     154           2 :     result = ParseHex("12 34 56 78");
     155           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
     156           2 :     result = TryParseHex<uint8_t>("12 34 56 78").value();
     157           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
     158             : 
     159             :     // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
     160           2 :     result = ParseHex(" 89 34 56 78");
     161           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
     162           2 :     result = TryParseHex<uint8_t>(" 89 34 56 78").value();
     163           2 :     BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
     164             : 
     165             :     // Mixed case and spaces are supported
     166           2 :     result = ParseHex("     Ff        aA    ");
     167           2 :     BOOST_CHECK(result.size() == 2 && result[0] == 0xff && result[1] == 0xaa);
     168           2 :     result = TryParseHex<uint8_t>("     Ff        aA    ").value();
     169           2 :     BOOST_CHECK(result.size() == 2 && result[0] == 0xff && result[1] == 0xaa);
     170             : 
     171             :     // Empty string is supported
     172           2 :     result = ParseHex("");
     173           2 :     BOOST_CHECK(result.size() == 0);
     174           2 :     result = TryParseHex<uint8_t>("").value();
     175           2 :     BOOST_CHECK(result.size() == 0);
     176             : 
     177             :     // Spaces between nibbles is treated as invalid
     178           2 :     BOOST_CHECK_EQUAL(ParseHex("AAF F").size(), 0);
     179           2 :     BOOST_CHECK(!TryParseHex("AAF F").has_value());
     180             : 
     181             :     // Embedded null is treated as invalid
     182           2 :     const std::string with_embedded_null{" 11 "s
     183             :                                          " \0 "
     184             :                                          " 22 "s};
     185           2 :     BOOST_CHECK_EQUAL(with_embedded_null.size(), 11);
     186           2 :     BOOST_CHECK_EQUAL(ParseHex(with_embedded_null).size(), 0);
     187           2 :     BOOST_CHECK(!TryParseHex(with_embedded_null).has_value());
     188             : 
     189             :     // Non-hex is treated as invalid
     190           2 :     BOOST_CHECK_EQUAL(ParseHex("1234 invalid 1234").size(), 0);
     191           2 :     BOOST_CHECK(!TryParseHex("1234 invalid 1234").has_value());
     192             : 
     193             :     // Truncated input is treated as invalid
     194           2 :     BOOST_CHECK_EQUAL(ParseHex("12 3").size(), 0);
     195           2 :     BOOST_CHECK(!TryParseHex("12 3").has_value());
     196           2 : }
     197             : 
     198         152 : BOOST_AUTO_TEST_CASE(util_HexStr)
     199             : {
     200           2 :     BOOST_CHECK_EQUAL(
     201             :         HexStr(ParseHex_expected),
     202             :         "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
     203             : 
     204           2 :     BOOST_CHECK_EQUAL(
     205             :         HexStr(Span{ParseHex_expected}.last(0)),
     206             :         "");
     207             : 
     208           2 :     BOOST_CHECK_EQUAL(
     209             :         HexStr(Span{ParseHex_expected}.first(0)),
     210             :         "");
     211             : 
     212             :     {
     213           2 :         const std::vector<char> in_s{ParseHex_expected, ParseHex_expected + 5};
     214           2 :         const Span<const uint8_t> in_u{MakeUCharSpan(in_s)};
     215           2 :         const Span<const std::byte> in_b{MakeByteSpan(in_s)};
     216           2 :         const std::string out_exp{"04678afdb0"};
     217             : 
     218           2 :         BOOST_CHECK_EQUAL(HexStr(in_u), out_exp);
     219           2 :         BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
     220           2 :         BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
     221           2 :     }
     222             : 
     223             :     {
     224           2 :         auto input = std::string();
     225         514 :         for (size_t i=0; i<256; ++i) {
     226         512 :             input.push_back(static_cast<char>(i));
     227         512 :         }
     228             : 
     229           2 :         auto hex = HexStr(input);
     230           2 :         BOOST_TEST_REQUIRE(hex.size() == 512);
     231             :         static constexpr auto hexmap = std::string_view("0123456789abcdef");
     232         514 :         for (size_t i = 0; i < 256; ++i) {
     233         512 :             auto upper = hexmap.find(hex[i * 2]);
     234         512 :             auto lower = hexmap.find(hex[i * 2 + 1]);
     235         512 :             BOOST_TEST_REQUIRE(upper != std::string_view::npos);
     236         512 :             BOOST_TEST_REQUIRE(lower != std::string_view::npos);
     237         512 :             BOOST_TEST_REQUIRE(i == upper*16 + lower);
     238         512 :         }
     239           2 :     }
     240           2 : }
     241             : 
     242         152 : BOOST_AUTO_TEST_CASE(span_write_bytes)
     243             : {
     244           2 :     std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}};
     245           2 :     const auto mut_bytes{MakeWritableByteSpan(mut_arr)};
     246           2 :     mut_bytes[1] = std::byte{0x11};
     247           2 :     BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa);
     248           2 :     BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11);
     249           2 : }
     250             : 
     251         152 : BOOST_AUTO_TEST_CASE(util_Join)
     252             : {
     253             :     // Normal version
     254           2 :     BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
     255           2 :     BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
     256           2 :     BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
     257             : 
     258             :     // Version with unary operator
     259           8 :     const auto op_upper = [](const std::string& s) { return ToUpper(s); };
     260           2 :     BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
     261           2 :     BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
     262           2 :     BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
     263           2 : }
     264             : 
     265         152 : BOOST_AUTO_TEST_CASE(util_ReplaceAll)
     266             : {
     267           2 :     const std::string original("A test \"%s\" string '%s'.");
     268          12 :     auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) {
     269          10 :         auto test = original;
     270          10 :         ReplaceAll(test, search, substitute);
     271          10 :         BOOST_CHECK_EQUAL(test, expected);
     272          10 :     };
     273             : 
     274           2 :     test_replaceall("", "foo", original);
     275           2 :     test_replaceall(original, "foo", "foo");
     276           2 :     test_replaceall("%s", "foo", "A test \"foo\" string 'foo'.");
     277           2 :     test_replaceall("\"", "foo", "A test foo%sfoo string '%s'.");
     278           2 :     test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo.");
     279           2 : }
     280             : 
     281         152 : BOOST_AUTO_TEST_CASE(util_TrimString)
     282             : {
     283           2 :     BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar");
     284           2 :     BOOST_CHECK_EQUAL(TrimStringView("\t \n  \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t  \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar");
     285           2 :     BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar");
     286           2 :     BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
     287           2 :     BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar");
     288           2 :     BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " ");
     289           2 :     BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7));
     290           2 :     BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3));
     291           2 :     BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2));
     292           2 :     BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
     293           2 :     BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01", 5)), std::string("\0", 1));
     294           2 :     BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
     295           2 : }
     296             : 
     297         152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
     298             : {
     299           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890963199), "32767-12-31T23:59:59Z");
     300           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890876800), "32767-12-31T00:00:00Z");
     301           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
     302           2 :     BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z");
     303           2 : }
     304             : 
     305         152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
     306             : {
     307           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(971890963199), "32767-12-31");
     308           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(971890876800), "32767-12-31");
     309           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
     310           2 :     BOOST_CHECK_EQUAL(FormatISO8601Date(0), "1970-01-01");
     311           2 : }
     312             : 
     313         152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
     314             : {
     315           2 :     BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
     316           2 : }
     317             : 
     318         152 : BOOST_AUTO_TEST_CASE(util_FormatMoney)
     319             : {
     320           2 :     BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
     321           2 :     BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
     322           2 :     BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
     323             : 
     324           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
     325           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
     326           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
     327           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
     328           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
     329           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
     330           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
     331           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
     332           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
     333           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
     334           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
     335           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
     336           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
     337           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
     338           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
     339           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
     340           2 :     BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
     341             : 
     342           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max()), "92233720368.54775807");
     343           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 1), "92233720368.54775806");
     344           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 2), "92233720368.54775805");
     345           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 3), "92233720368.54775804");
     346             :     // ...
     347           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 3), "-92233720368.54775805");
     348           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 2), "-92233720368.54775806");
     349           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 1), "-92233720368.54775807");
     350           2 :     BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min()), "-92233720368.54775808");
     351           2 : }
     352             : 
     353         152 : BOOST_AUTO_TEST_CASE(util_ParseMoney)
     354             : {
     355           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.0").value(), 0);
     356           2 :     BOOST_CHECK_EQUAL(ParseMoney(".").value(), 0);
     357           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.").value(), 0);
     358           2 :     BOOST_CHECK_EQUAL(ParseMoney(".0").value(), 0);
     359           2 :     BOOST_CHECK_EQUAL(ParseMoney(".6789").value(), 6789'0000);
     360           2 :     BOOST_CHECK_EQUAL(ParseMoney("12345.").value(), COIN * 12345);
     361             : 
     362           2 :     BOOST_CHECK_EQUAL(ParseMoney("12345.6789").value(), (COIN/10000)*123456789);
     363             : 
     364           2 :     BOOST_CHECK_EQUAL(ParseMoney("10000000.00").value(), COIN*10000000);
     365           2 :     BOOST_CHECK_EQUAL(ParseMoney("1000000.00").value(), COIN*1000000);
     366           2 :     BOOST_CHECK_EQUAL(ParseMoney("100000.00").value(), COIN*100000);
     367           2 :     BOOST_CHECK_EQUAL(ParseMoney("10000.00").value(), COIN*10000);
     368           2 :     BOOST_CHECK_EQUAL(ParseMoney("1000.00").value(), COIN*1000);
     369           2 :     BOOST_CHECK_EQUAL(ParseMoney("100.00").value(), COIN*100);
     370           2 :     BOOST_CHECK_EQUAL(ParseMoney("10.00").value(), COIN*10);
     371           2 :     BOOST_CHECK_EQUAL(ParseMoney("1.00").value(), COIN);
     372           2 :     BOOST_CHECK_EQUAL(ParseMoney("1").value(), COIN);
     373           2 :     BOOST_CHECK_EQUAL(ParseMoney("   1").value(), COIN);
     374           2 :     BOOST_CHECK_EQUAL(ParseMoney("1   ").value(), COIN);
     375           2 :     BOOST_CHECK_EQUAL(ParseMoney("  1 ").value(), COIN);
     376           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.1").value(), COIN/10);
     377           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.01").value(), COIN/100);
     378           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.001").value(), COIN/1000);
     379           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.0001").value(), COIN/10000);
     380           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.00001").value(), COIN/100000);
     381           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.000001").value(), COIN/1000000);
     382           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.0000001").value(), COIN/10000000);
     383           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.00000001").value(), COIN/100000000);
     384           2 :     BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001 ").value(), COIN/100000000);
     385           2 :     BOOST_CHECK_EQUAL(ParseMoney("0.00000001 ").value(), COIN/100000000);
     386           2 :     BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001").value(), COIN/100000000);
     387             : 
     388             :     // Parsing amount that cannot be represented should fail
     389           2 :     BOOST_CHECK(!ParseMoney("100000000.00"));
     390           2 :     BOOST_CHECK(!ParseMoney("0.000000001"));
     391             : 
     392             :     // Parsing empty string should fail
     393           2 :     BOOST_CHECK(!ParseMoney(""));
     394           2 :     BOOST_CHECK(!ParseMoney(" "));
     395           2 :     BOOST_CHECK(!ParseMoney("  "));
     396             : 
     397             :     // Parsing two numbers should fail
     398           2 :     BOOST_CHECK(!ParseMoney(".."));
     399           2 :     BOOST_CHECK(!ParseMoney("0..0"));
     400           2 :     BOOST_CHECK(!ParseMoney("1 2"));
     401           2 :     BOOST_CHECK(!ParseMoney(" 1 2 "));
     402           2 :     BOOST_CHECK(!ParseMoney(" 1.2 3 "));
     403           2 :     BOOST_CHECK(!ParseMoney(" 1 2.3 "));
     404             : 
     405             :     // Embedded whitespace should fail
     406           2 :     BOOST_CHECK(!ParseMoney(" -1 .2  "));
     407           2 :     BOOST_CHECK(!ParseMoney("  1 .2  "));
     408           2 :     BOOST_CHECK(!ParseMoney(" +1 .2  "));
     409             : 
     410             :     // Attempted 63 bit overflow should fail
     411           2 :     BOOST_CHECK(!ParseMoney("92233720368.54775808"));
     412             : 
     413             :     // Parsing negative amounts must fail
     414           2 :     BOOST_CHECK(!ParseMoney("-1"));
     415             : 
     416             :     // Parsing strings with embedded NUL characters should fail
     417           2 :     BOOST_CHECK(!ParseMoney("\0-1"s));
     418           2 :     BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR));
     419           2 :     BOOST_CHECK(!ParseMoney("1\0"s));
     420           2 : }
     421             : 
     422         152 : BOOST_AUTO_TEST_CASE(util_IsHex)
     423             : {
     424           2 :     BOOST_CHECK(IsHex("00"));
     425           2 :     BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
     426           2 :     BOOST_CHECK(IsHex("ff"));
     427           2 :     BOOST_CHECK(IsHex("FF"));
     428             : 
     429           2 :     BOOST_CHECK(!IsHex(""));
     430           2 :     BOOST_CHECK(!IsHex("0"));
     431           2 :     BOOST_CHECK(!IsHex("a"));
     432           2 :     BOOST_CHECK(!IsHex("eleven"));
     433           2 :     BOOST_CHECK(!IsHex("00xx00"));
     434           2 :     BOOST_CHECK(!IsHex("0x0000"));
     435           2 : }
     436             : 
     437         152 : BOOST_AUTO_TEST_CASE(util_IsHexNumber)
     438             : {
     439           2 :     BOOST_CHECK(IsHexNumber("0x0"));
     440           2 :     BOOST_CHECK(IsHexNumber("0"));
     441           2 :     BOOST_CHECK(IsHexNumber("0x10"));
     442           2 :     BOOST_CHECK(IsHexNumber("10"));
     443           2 :     BOOST_CHECK(IsHexNumber("0xff"));
     444           2 :     BOOST_CHECK(IsHexNumber("ff"));
     445           2 :     BOOST_CHECK(IsHexNumber("0xFfa"));
     446           2 :     BOOST_CHECK(IsHexNumber("Ffa"));
     447           2 :     BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
     448           2 :     BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
     449             : 
     450           2 :     BOOST_CHECK(!IsHexNumber(""));   // empty string not allowed
     451           2 :     BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
     452           2 :     BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
     453           2 :     BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
     454           2 :     BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
     455           2 :     BOOST_CHECK(!IsHexNumber(" "));    // etc.
     456           2 :     BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
     457           2 :     BOOST_CHECK(!IsHexNumber("x0"));    // broken prefix
     458           2 :     BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
     459             : 
     460           2 : }
     461             : 
     462         152 : BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
     463             : {
     464           2 :     SeedInsecureRand(SeedRand::ZEROS);
     465          20 :     for (int mod=2;mod<11;mod++)
     466             :     {
     467          18 :         int mask = 1;
     468             :         // Really rough binomial confidence approximation.
     469          18 :         int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
     470             :         //mask is 2^ceil(log2(mod))-1
     471          50 :         while(mask<mod-1)mask=(mask<<1)+1;
     472             : 
     473          18 :         int count = 0;
     474             :         //How often does it get a zero from the uniform range [0,mod)?
     475      180018 :         for (int i = 0; i < 10000; i++) {
     476             :             uint32_t rval;
     477      180000 :             do{
     478      235652 :                 rval=InsecureRand32()&mask;
     479      235652 :             }while(rval>=(uint32_t)mod);
     480      180000 :             count += rval==0;
     481      180000 :         }
     482          18 :         BOOST_CHECK(count<=10000/mod+err);
     483          18 :         BOOST_CHECK(count>=10000/mod-err);
     484          18 :     }
     485           2 : }
     486             : 
     487         152 : BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
     488             : {
     489           2 :     BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
     490           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
     491           2 :     BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
     492           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
     493           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
     494           2 :     BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
     495           2 :     BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
     496           2 : }
     497             : 
     498             : /* Test strprintf formatting directives.
     499             :  * Put a string before and after to ensure sanity of element sizes on stack. */
     500             : #define B "check_prefix"
     501             : #define E "check_postfix"
     502         152 : BOOST_AUTO_TEST_CASE(strprintf_numbers)
     503             : {
     504           2 :     int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
     505           2 :     uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
     506           2 :     BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
     507           2 :     BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
     508           2 :     BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
     509             : 
     510           2 :     size_t st = 12345678; /* unsigned size_t test value */
     511           2 :     ssize_t sst = -12345678; /* signed size_t test value */
     512           2 :     BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
     513           2 :     BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
     514           2 :     BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
     515             : 
     516           2 :     ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
     517           2 :     ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
     518           2 :     BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
     519           2 :     BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
     520           2 :     BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
     521           2 : }
     522             : #undef B
     523             : #undef E
     524             : 
     525             : /* Check for mingw/wine issue #3494
     526             :  * Remove this test before time.ctime(0xffffffff) == 'Sun Feb  7 07:28:15 2106'
     527             :  */
     528         152 : BOOST_AUTO_TEST_CASE(gettime)
     529             : {
     530           2 :     BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
     531           2 : }
     532             : 
     533         152 : BOOST_AUTO_TEST_CASE(util_time_GetTime)
     534             : {
     535           2 :     SetMockTime(111);
     536             :     // Check that mock time does not change after a sleep
     537           6 :     for (const auto& num_sleep : {0ms, 1ms}) {
     538           4 :         UninterruptibleSleep(num_sleep);
     539           4 :         BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
     540           4 :         BOOST_CHECK_EQUAL(111, Now<NodeSeconds>().time_since_epoch().count());
     541           4 :         BOOST_CHECK_EQUAL(111, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()));
     542           4 :         BOOST_CHECK_EQUAL(111, TicksSinceEpoch<SecondsDouble>(Now<NodeSeconds>()));
     543           4 :         BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
     544           4 :         BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
     545           4 :         BOOST_CHECK_EQUAL(111000, TicksSinceEpoch<std::chrono::milliseconds>(NodeClock::now()));
     546           4 :         BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
     547             :     }
     548             : 
     549           2 :     SetMockTime(0);
     550             :     // Check that steady time and system time changes after a sleep
     551           2 :     const auto steady_ms_0 = Now<SteadyMilliseconds>();
     552           2 :     const auto steady_0 = std::chrono::steady_clock::now();
     553           2 :     const auto ms_0 = GetTime<std::chrono::milliseconds>();
     554           2 :     const auto us_0 = GetTime<std::chrono::microseconds>();
     555           2 :     UninterruptibleSleep(1ms);
     556           2 :     BOOST_CHECK(steady_ms_0 < Now<SteadyMilliseconds>());
     557           2 :     BOOST_CHECK(steady_0 + 1ms <= std::chrono::steady_clock::now());
     558           2 :     BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
     559           2 :     BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
     560           2 : }
     561             : 
     562         152 : BOOST_AUTO_TEST_CASE(test_IsDigit)
     563             : {
     564           2 :     BOOST_CHECK_EQUAL(IsDigit('0'), true);
     565           2 :     BOOST_CHECK_EQUAL(IsDigit('1'), true);
     566           2 :     BOOST_CHECK_EQUAL(IsDigit('8'), true);
     567           2 :     BOOST_CHECK_EQUAL(IsDigit('9'), true);
     568             : 
     569           2 :     BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
     570           2 :     BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
     571           2 :     BOOST_CHECK_EQUAL(IsDigit(0), false);
     572           2 :     BOOST_CHECK_EQUAL(IsDigit(1), false);
     573           2 :     BOOST_CHECK_EQUAL(IsDigit(8), false);
     574           2 :     BOOST_CHECK_EQUAL(IsDigit(9), false);
     575           2 : }
     576             : 
     577             : /* Check for overflow */
     578             : template <typename T>
     579           4 : static void TestAddMatrixOverflow()
     580             : {
     581           4 :     constexpr T MAXI{std::numeric_limits<T>::max()};
     582           4 :     BOOST_CHECK(!CheckedAdd(T{1}, MAXI));
     583           4 :     BOOST_CHECK(!CheckedAdd(MAXI, MAXI));
     584           4 :     BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI));
     585           4 :     BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(MAXI, MAXI));
     586             : 
     587           4 :     BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value());
     588           4 :     BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value());
     589           4 :     BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value());
     590           4 :     BOOST_CHECK_EQUAL(MAXI - 1, CheckedAdd(T{1}, MAXI - 2).value());
     591           4 :     BOOST_CHECK_EQUAL(0, SaturatingAdd(T{0}, T{0}));
     592           4 :     BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{0}, MAXI));
     593           4 :     BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI - 1));
     594           4 :     BOOST_CHECK_EQUAL(MAXI - 1, SaturatingAdd(T{1}, MAXI - 2));
     595           4 : }
     596             : 
     597             : /* Check for overflow or underflow */
     598             : template <typename T>
     599           2 : static void TestAddMatrix()
     600             : {
     601           2 :     TestAddMatrixOverflow<T>();
     602           2 :     constexpr T MINI{std::numeric_limits<T>::min()};
     603           2 :     constexpr T MAXI{std::numeric_limits<T>::max()};
     604           2 :     BOOST_CHECK(!CheckedAdd(T{-1}, MINI));
     605           2 :     BOOST_CHECK(!CheckedAdd(MINI, MINI));
     606           2 :     BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI));
     607           2 :     BOOST_CHECK_EQUAL(MINI, SaturatingAdd(MINI, MINI));
     608             : 
     609           2 :     BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value());
     610           2 :     BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value());
     611           2 :     BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value());
     612           2 :     BOOST_CHECK_EQUAL(MINI + 1, CheckedAdd(T{-1}, MINI + 2).value());
     613           2 :     BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{0}, MINI));
     614           2 :     BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI + 1));
     615           2 :     BOOST_CHECK_EQUAL(MINI + 1, SaturatingAdd(T{-1}, MINI + 2));
     616           2 :     BOOST_CHECK_EQUAL(-1, SaturatingAdd(MINI, MAXI));
     617           2 : }
     618             : 
     619         152 : BOOST_AUTO_TEST_CASE(util_overflow)
     620             : {
     621           2 :     TestAddMatrixOverflow<unsigned>();
     622           2 :     TestAddMatrix<signed>();
     623           2 : }
     624             : 
     625         152 : BOOST_AUTO_TEST_CASE(test_ParseInt32)
     626             : {
     627             :     int32_t n;
     628             :     // Valid values
     629           2 :     BOOST_CHECK(ParseInt32("1234", nullptr));
     630           2 :     BOOST_CHECK(ParseInt32("0", &n) && n == 0);
     631           2 :     BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
     632           2 :     BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
     633           2 :     BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
     634           2 :     BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
     635           2 :     BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
     636           2 :     BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
     637           2 :     BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
     638           2 :     BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
     639           2 :     BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
     640             :     // Invalid values
     641           2 :     BOOST_CHECK(!ParseInt32("", &n));
     642           2 :     BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
     643           2 :     BOOST_CHECK(!ParseInt32("1 ", &n));
     644           2 :     BOOST_CHECK(!ParseInt32("++1", &n));
     645           2 :     BOOST_CHECK(!ParseInt32("+-1", &n));
     646           2 :     BOOST_CHECK(!ParseInt32("-+1", &n));
     647           2 :     BOOST_CHECK(!ParseInt32("--1", &n));
     648           2 :     BOOST_CHECK(!ParseInt32("1a", &n));
     649           2 :     BOOST_CHECK(!ParseInt32("aap", &n));
     650           2 :     BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
     651           2 :     BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
     652             :     // Overflow and underflow
     653           2 :     BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
     654           2 :     BOOST_CHECK(!ParseInt32("2147483648", nullptr));
     655           2 :     BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
     656           2 :     BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
     657           2 : }
     658             : 
     659             : template <typename T>
     660          16 : static void RunToIntegralTests()
     661             : {
     662          16 :     BOOST_CHECK(!ToIntegral<T>(STRING_WITH_EMBEDDED_NULL_CHAR));
     663          16 :     BOOST_CHECK(!ToIntegral<T>(" 1"));
     664          16 :     BOOST_CHECK(!ToIntegral<T>("1 "));
     665          16 :     BOOST_CHECK(!ToIntegral<T>("1a"));
     666          16 :     BOOST_CHECK(!ToIntegral<T>("1.1"));
     667          16 :     BOOST_CHECK(!ToIntegral<T>("1.9"));
     668          16 :     BOOST_CHECK(!ToIntegral<T>("+01.9"));
     669          16 :     BOOST_CHECK(!ToIntegral<T>("-"));
     670          16 :     BOOST_CHECK(!ToIntegral<T>("+"));
     671          16 :     BOOST_CHECK(!ToIntegral<T>(" -1"));
     672          16 :     BOOST_CHECK(!ToIntegral<T>("-1 "));
     673          16 :     BOOST_CHECK(!ToIntegral<T>(" -1 "));
     674          16 :     BOOST_CHECK(!ToIntegral<T>("+1"));
     675          16 :     BOOST_CHECK(!ToIntegral<T>(" +1"));
     676          16 :     BOOST_CHECK(!ToIntegral<T>(" +1 "));
     677          16 :     BOOST_CHECK(!ToIntegral<T>("+-1"));
     678          16 :     BOOST_CHECK(!ToIntegral<T>("-+1"));
     679          16 :     BOOST_CHECK(!ToIntegral<T>("++1"));
     680          16 :     BOOST_CHECK(!ToIntegral<T>("--1"));
     681          16 :     BOOST_CHECK(!ToIntegral<T>(""));
     682          16 :     BOOST_CHECK(!ToIntegral<T>("aap"));
     683          16 :     BOOST_CHECK(!ToIntegral<T>("0x1"));
     684          16 :     BOOST_CHECK(!ToIntegral<T>("-32482348723847471234"));
     685          16 :     BOOST_CHECK(!ToIntegral<T>("32482348723847471234"));
     686          16 : }
     687             : 
     688         152 : BOOST_AUTO_TEST_CASE(test_ToIntegral)
     689             : {
     690           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("1234").value(), 1'234);
     691           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("0").value(), 0);
     692           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("01234").value(), 1'234);
     693           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000001234").value(), 1'234);
     694           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000001234").value(), -1'234);
     695           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000000000").value(), 0);
     696           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000000000").value(), 0);
     697           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1234").value(), -1'234);
     698           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1").value(), -1);
     699             : 
     700           2 :     RunToIntegralTests<uint64_t>();
     701           2 :     RunToIntegralTests<int64_t>();
     702           2 :     RunToIntegralTests<uint32_t>();
     703           2 :     RunToIntegralTests<int32_t>();
     704           2 :     RunToIntegralTests<uint16_t>();
     705           2 :     RunToIntegralTests<int16_t>();
     706           2 :     RunToIntegralTests<uint8_t>();
     707           2 :     RunToIntegralTests<int8_t>();
     708             : 
     709           2 :     BOOST_CHECK(!ToIntegral<int64_t>("-9223372036854775809"));
     710           2 :     BOOST_CHECK_EQUAL(ToIntegral<int64_t>("-9223372036854775808").value(), -9'223'372'036'854'775'807LL - 1LL);
     711           2 :     BOOST_CHECK_EQUAL(ToIntegral<int64_t>("9223372036854775807").value(), 9'223'372'036'854'775'807);
     712           2 :     BOOST_CHECK(!ToIntegral<int64_t>("9223372036854775808"));
     713             : 
     714           2 :     BOOST_CHECK(!ToIntegral<uint64_t>("-1"));
     715           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("0").value(), 0U);
     716           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("18446744073709551615").value(), 18'446'744'073'709'551'615ULL);
     717           2 :     BOOST_CHECK(!ToIntegral<uint64_t>("18446744073709551616"));
     718             : 
     719           2 :     BOOST_CHECK(!ToIntegral<int32_t>("-2147483649"));
     720           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-2147483648").value(), -2'147'483'648LL);
     721           2 :     BOOST_CHECK_EQUAL(ToIntegral<int32_t>("2147483647").value(), 2'147'483'647);
     722           2 :     BOOST_CHECK(!ToIntegral<int32_t>("2147483648"));
     723             : 
     724           2 :     BOOST_CHECK(!ToIntegral<uint32_t>("-1"));
     725           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("0").value(), 0U);
     726           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("4294967295").value(), 4'294'967'295U);
     727           2 :     BOOST_CHECK(!ToIntegral<uint32_t>("4294967296"));
     728             : 
     729           2 :     BOOST_CHECK(!ToIntegral<int16_t>("-32769"));
     730           2 :     BOOST_CHECK_EQUAL(ToIntegral<int16_t>("-32768").value(), -32'768);
     731           2 :     BOOST_CHECK_EQUAL(ToIntegral<int16_t>("32767").value(), 32'767);
     732           2 :     BOOST_CHECK(!ToIntegral<int16_t>("32768"));
     733             : 
     734           2 :     BOOST_CHECK(!ToIntegral<uint16_t>("-1"));
     735           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("0").value(), 0U);
     736           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("65535").value(), 65'535U);
     737           2 :     BOOST_CHECK(!ToIntegral<uint16_t>("65536"));
     738             : 
     739           2 :     BOOST_CHECK(!ToIntegral<int8_t>("-129"));
     740           2 :     BOOST_CHECK_EQUAL(ToIntegral<int8_t>("-128").value(), -128);
     741           2 :     BOOST_CHECK_EQUAL(ToIntegral<int8_t>("127").value(), 127);
     742           2 :     BOOST_CHECK(!ToIntegral<int8_t>("128"));
     743             : 
     744           2 :     BOOST_CHECK(!ToIntegral<uint8_t>("-1"));
     745           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("0").value(), 0U);
     746           2 :     BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("255").value(), 255U);
     747           2 :     BOOST_CHECK(!ToIntegral<uint8_t>("256"));
     748           2 : }
     749             : 
     750          16 : int64_t atoi64_legacy(const std::string& str)
     751             : {
     752          16 :     return strtoll(str.c_str(), nullptr, 10);
     753             : }
     754             : 
     755         152 : BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
     756             : {
     757           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1234"), 1'234);
     758           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0"), 0);
     759           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("01234"), 1'234);
     760           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1234"), -1'234);
     761           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" 1"), 1);
     762           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1 "), 1);
     763           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1a"), 1);
     764           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.1"), 1);
     765           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.9"), 1);
     766           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+01.9"), 1);
     767           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1"), -1);
     768           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1"), -1);
     769           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1 "), -1);
     770           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1 "), -1);
     771           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+1"), 1);
     772           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1"), 1);
     773           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1 "), 1);
     774             : 
     775           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+-1"), 0);
     776           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-+1"), 0);
     777           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("++1"), 0);
     778           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("--1"), 0);
     779           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(""), 0);
     780           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("aap"), 0);
     781           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0x1"), 0);
     782           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-32482348723847471234"), -2'147'483'647 - 1);
     783           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("32482348723847471234"), 2'147'483'647);
     784             : 
     785           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775809"), -9'223'372'036'854'775'807LL - 1LL);
     786           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775808"), -9'223'372'036'854'775'807LL - 1LL);
     787           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775807"), 9'223'372'036'854'775'807);
     788           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775808"), 9'223'372'036'854'775'807);
     789             : 
     790           2 :     std::map<std::string, int64_t> atoi64_test_pairs = {
     791           2 :         {"-9223372036854775809", std::numeric_limits<int64_t>::min()},
     792           2 :         {"-9223372036854775808", -9'223'372'036'854'775'807LL - 1LL},
     793           2 :         {"9223372036854775807", 9'223'372'036'854'775'807},
     794           2 :         {"9223372036854775808", std::numeric_limits<int64_t>::max()},
     795           2 :         {"+-", 0},
     796           2 :         {"0x1", 0},
     797           2 :         {"ox1", 0},
     798           2 :         {"", 0},
     799             :     };
     800             : 
     801          18 :     for (const auto& pair : atoi64_test_pairs) {
     802          16 :         BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), pair.second);
     803             :     }
     804             : 
     805             :     // Ensure legacy compatibility with previous versions of Bitcoin Core's atoi64
     806          18 :     for (const auto& pair : atoi64_test_pairs) {
     807          16 :         BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), atoi64_legacy(pair.first));
     808             :     }
     809             : 
     810           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("-1"), 0U);
     811           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("0"), 0U);
     812           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551615"), 18'446'744'073'709'551'615ULL);
     813           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551616"), 18'446'744'073'709'551'615ULL);
     814             : 
     815           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483649"), -2'147'483'648LL);
     816           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483648"), -2'147'483'648LL);
     817           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483647"), 2'147'483'647);
     818           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483648"), 2'147'483'647);
     819             : 
     820           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("-1"), 0U);
     821           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("0"), 0U);
     822           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967295"), 4'294'967'295U);
     823           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967296"), 4'294'967'295U);
     824             : 
     825           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32769"), -32'768);
     826           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32768"), -32'768);
     827           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32767"), 32'767);
     828           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32768"), 32'767);
     829             : 
     830           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("-1"), 0U);
     831           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("0"), 0U);
     832           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65535"), 65'535U);
     833           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65536"), 65'535U);
     834             : 
     835           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-129"), -128);
     836           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-128"), -128);
     837           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("127"), 127);
     838           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("128"), 127);
     839             : 
     840           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("-1"), 0U);
     841           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("0"), 0U);
     842           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("255"), 255U);
     843           2 :     BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
     844           2 : }
     845             : 
     846         152 : BOOST_AUTO_TEST_CASE(test_ParseInt64)
     847             : {
     848             :     int64_t n;
     849             :     // Valid values
     850           2 :     BOOST_CHECK(ParseInt64("1234", nullptr));
     851           2 :     BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
     852           2 :     BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
     853           2 :     BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
     854           2 :     BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
     855           2 :     BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
     856           2 :     BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
     857           2 :     BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
     858           2 :     BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
     859             :     // Invalid values
     860           2 :     BOOST_CHECK(!ParseInt64("", &n));
     861           2 :     BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
     862           2 :     BOOST_CHECK(!ParseInt64("1 ", &n));
     863           2 :     BOOST_CHECK(!ParseInt64("1a", &n));
     864           2 :     BOOST_CHECK(!ParseInt64("aap", &n));
     865           2 :     BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
     866           2 :     BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
     867             :     // Overflow and underflow
     868           2 :     BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
     869           2 :     BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
     870           2 :     BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
     871           2 :     BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
     872           2 : }
     873             : 
     874         152 : BOOST_AUTO_TEST_CASE(test_ParseUInt8)
     875             : {
     876             :     uint8_t n;
     877             :     // Valid values
     878           2 :     BOOST_CHECK(ParseUInt8("255", nullptr));
     879           2 :     BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
     880           2 :     BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
     881           2 :     BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
     882           2 :     BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
     883           2 :     BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
     884           2 :     BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
     885           2 :     BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
     886             :     // Invalid values
     887           2 :     BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
     888           2 :     BOOST_CHECK(!ParseUInt8("", &n));
     889           2 :     BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
     890           2 :     BOOST_CHECK(!ParseUInt8(" -1", &n));
     891           2 :     BOOST_CHECK(!ParseUInt8("++1", &n));
     892           2 :     BOOST_CHECK(!ParseUInt8("+-1", &n));
     893           2 :     BOOST_CHECK(!ParseUInt8("-+1", &n));
     894           2 :     BOOST_CHECK(!ParseUInt8("--1", &n));
     895           2 :     BOOST_CHECK(!ParseUInt8("-1", &n));
     896           2 :     BOOST_CHECK(!ParseUInt8("1 ", &n));
     897           2 :     BOOST_CHECK(!ParseUInt8("1a", &n));
     898           2 :     BOOST_CHECK(!ParseUInt8("aap", &n));
     899           2 :     BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
     900           2 :     BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
     901             :     // Overflow and underflow
     902           2 :     BOOST_CHECK(!ParseUInt8("-255", &n));
     903           2 :     BOOST_CHECK(!ParseUInt8("256", &n));
     904           2 :     BOOST_CHECK(!ParseUInt8("-123", &n));
     905           2 :     BOOST_CHECK(!ParseUInt8("-123", nullptr));
     906           2 :     BOOST_CHECK(!ParseUInt8("256", nullptr));
     907           2 : }
     908             : 
     909         152 : BOOST_AUTO_TEST_CASE(test_ParseUInt16)
     910             : {
     911             :     uint16_t n;
     912             :     // Valid values
     913           2 :     BOOST_CHECK(ParseUInt16("1234", nullptr));
     914           2 :     BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
     915           2 :     BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
     916           2 :     BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
     917           2 :     BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
     918           2 :     BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
     919           2 :     BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
     920           2 :     BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
     921             :     // Invalid values
     922           2 :     BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
     923           2 :     BOOST_CHECK(!ParseUInt16("", &n));
     924           2 :     BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
     925           2 :     BOOST_CHECK(!ParseUInt16(" -1", &n));
     926           2 :     BOOST_CHECK(!ParseUInt16("++1", &n));
     927           2 :     BOOST_CHECK(!ParseUInt16("+-1", &n));
     928           2 :     BOOST_CHECK(!ParseUInt16("-+1", &n));
     929           2 :     BOOST_CHECK(!ParseUInt16("--1", &n));
     930           2 :     BOOST_CHECK(!ParseUInt16("-1", &n));
     931           2 :     BOOST_CHECK(!ParseUInt16("1 ", &n));
     932           2 :     BOOST_CHECK(!ParseUInt16("1a", &n));
     933           2 :     BOOST_CHECK(!ParseUInt16("aap", &n));
     934           2 :     BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
     935           2 :     BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
     936             :     // Overflow and underflow
     937           2 :     BOOST_CHECK(!ParseUInt16("-65535", &n));
     938           2 :     BOOST_CHECK(!ParseUInt16("65536", &n));
     939           2 :     BOOST_CHECK(!ParseUInt16("-123", &n));
     940           2 :     BOOST_CHECK(!ParseUInt16("-123", nullptr));
     941           2 :     BOOST_CHECK(!ParseUInt16("65536", nullptr));
     942           2 : }
     943             : 
     944         152 : BOOST_AUTO_TEST_CASE(test_ParseUInt32)
     945             : {
     946             :     uint32_t n;
     947             :     // Valid values
     948           2 :     BOOST_CHECK(ParseUInt32("1234", nullptr));
     949           2 :     BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
     950           2 :     BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
     951           2 :     BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
     952           2 :     BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
     953           2 :     BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
     954           2 :     BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
     955           2 :     BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
     956           2 :     BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
     957           2 :     BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
     958             :     // Invalid values
     959           2 :     BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
     960           2 :     BOOST_CHECK(!ParseUInt32("", &n));
     961           2 :     BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
     962           2 :     BOOST_CHECK(!ParseUInt32(" -1", &n));
     963           2 :     BOOST_CHECK(!ParseUInt32("++1", &n));
     964           2 :     BOOST_CHECK(!ParseUInt32("+-1", &n));
     965           2 :     BOOST_CHECK(!ParseUInt32("-+1", &n));
     966           2 :     BOOST_CHECK(!ParseUInt32("--1", &n));
     967           2 :     BOOST_CHECK(!ParseUInt32("-1", &n));
     968           2 :     BOOST_CHECK(!ParseUInt32("1 ", &n));
     969           2 :     BOOST_CHECK(!ParseUInt32("1a", &n));
     970           2 :     BOOST_CHECK(!ParseUInt32("aap", &n));
     971           2 :     BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
     972           2 :     BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
     973             :     // Overflow and underflow
     974           2 :     BOOST_CHECK(!ParseUInt32("-2147483648", &n));
     975           2 :     BOOST_CHECK(!ParseUInt32("4294967296", &n));
     976           2 :     BOOST_CHECK(!ParseUInt32("-1234", &n));
     977           2 :     BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
     978           2 :     BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
     979           2 : }
     980             : 
     981         152 : BOOST_AUTO_TEST_CASE(test_ParseUInt64)
     982             : {
     983             :     uint64_t n;
     984             :     // Valid values
     985           2 :     BOOST_CHECK(ParseUInt64("1234", nullptr));
     986           2 :     BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
     987           2 :     BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
     988           2 :     BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
     989           2 :     BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
     990           2 :     BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
     991           2 :     BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
     992           2 :     BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
     993             :     // Invalid values
     994           2 :     BOOST_CHECK(!ParseUInt64("", &n));
     995           2 :     BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
     996           2 :     BOOST_CHECK(!ParseUInt64(" -1", &n));
     997           2 :     BOOST_CHECK(!ParseUInt64("1 ", &n));
     998           2 :     BOOST_CHECK(!ParseUInt64("1a", &n));
     999           2 :     BOOST_CHECK(!ParseUInt64("aap", &n));
    1000           2 :     BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
    1001           2 :     BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
    1002             :     // Overflow and underflow
    1003           2 :     BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
    1004           2 :     BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
    1005           2 :     BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
    1006           2 :     BOOST_CHECK(!ParseUInt64("-2147483648", &n));
    1007           2 :     BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
    1008           2 :     BOOST_CHECK(!ParseUInt64("-1234", &n));
    1009           2 : }
    1010             : 
    1011         152 : BOOST_AUTO_TEST_CASE(test_FormatParagraph)
    1012             : {
    1013           2 :     BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
    1014           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
    1015           2 :     BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
    1016           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
    1017           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
    1018           2 :     BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
    1019           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n    test");
    1020             : 
    1021             :     // Make sure we don't indent a fully-new line following a too-long line ending
    1022           2 :     BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n    test\nabc");
    1023             : 
    1024           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");
    1025             : 
    1026             :     // Test wrap length is exact
    1027           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");
    1028           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");
    1029             :     // Indent should be included in length of lines
    1030           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");
    1031             : 
    1032           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.");
    1033           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.");
    1034           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.");
    1035           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.");
    1036           2 : }
    1037             : 
    1038         152 : BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
    1039             : {
    1040           2 :     std::vector<std::string> comments;
    1041           2 :     comments.emplace_back("comment1");
    1042           2 :     std::vector<std::string> comments2;
    1043           2 :     comments2.emplace_back("comment1");
    1044           2 :     comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
    1045           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/"));
    1046           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
    1047           2 :     BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
    1048           2 : }
    1049             : 
    1050         152 : BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
    1051             : {
    1052           2 :     int64_t amount = 0;
    1053           2 :     BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
    1054           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
    1055           2 :     BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
    1056           2 :     BOOST_CHECK_EQUAL(amount, 100000000LL);
    1057           2 :     BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
    1058           2 :     BOOST_CHECK_EQUAL(amount, 0LL);
    1059           2 :     BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
    1060           2 :     BOOST_CHECK_EQUAL(amount, -10000000LL);
    1061           2 :     BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
    1062           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
    1063           2 :     BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
    1064           2 :     BOOST_CHECK_EQUAL(amount, 110000000LL);
    1065           2 :     BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
    1066           2 :     BOOST_CHECK_EQUAL(amount, 1100000000LL);
    1067           2 :     BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
    1068           2 :     BOOST_CHECK_EQUAL(amount, 11000000LL);
    1069           2 :     BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
    1070           2 :     BOOST_CHECK_EQUAL(amount, 100000000000LL);
    1071           2 :     BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
    1072           2 :     BOOST_CHECK_EQUAL(amount, -100000000000LL);
    1073           2 :     BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
    1074           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
    1075           2 :     BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
    1076           2 :     BOOST_CHECK_EQUAL(amount, 1LL);
    1077           2 :     BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
    1078           2 :     BOOST_CHECK_EQUAL(amount, -1LL);
    1079           2 :     BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
    1080           2 :     BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
    1081           2 :     BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
    1082           2 :     BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
    1083           2 :     BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
    1084           2 :     BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
    1085             : 
    1086           2 :     BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
    1087           2 :     BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
    1088           2 :     BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
    1089           2 :     BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
    1090           2 :     BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
    1091           2 :     BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
    1092           2 :     BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
    1093           2 :     BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
    1094           2 :     BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
    1095           2 :     BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
    1096           2 :     BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
    1097           2 :     BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
    1098           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
    1099           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
    1100           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
    1101           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
    1102           2 :     BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
    1103           2 :     BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
    1104           2 :     BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
    1105           2 :     BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
    1106           2 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
    1107           2 :     BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
    1108           2 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
    1109           2 :     BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
    1110           2 :     BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
    1111           2 :     BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
    1112           2 :     BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
    1113             : 
    1114             :     // Test with 3 decimal places for fee rates in sat/vB.
    1115           2 :     BOOST_CHECK(ParseFixedPoint("0.001", 3, &amount));
    1116           2 :     BOOST_CHECK_EQUAL(amount, CAmount{1});
    1117           2 :     BOOST_CHECK(!ParseFixedPoint("0.0009", 3, &amount));
    1118           2 :     BOOST_CHECK(!ParseFixedPoint("31.00100001", 3, &amount));
    1119           2 :     BOOST_CHECK(!ParseFixedPoint("31.0011", 3, &amount));
    1120           2 :     BOOST_CHECK(!ParseFixedPoint("31.99999999", 3, &amount));
    1121           2 :     BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));
    1122           2 : }
    1123             : 
    1124           1 : static void TestOtherThread(fs::path dirname, fs::path lockname, bool *result)
    1125             : {
    1126           1 :     *result = LockDirectory(dirname, lockname);
    1127           1 : }
    1128             : 
    1129             : #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
    1130             : static constexpr char LockCommand = 'L';
    1131             : static constexpr char UnlockCommand = 'U';
    1132             : static constexpr char ExitCommand = 'X';
    1133             : 
    1134           1 : [[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)
    1135             : {
    1136             :     char ch;
    1137           5 :     while (true) {
    1138           5 :         int rv = read(fd, &ch, 1); // Wait for command
    1139           5 :         assert(rv == 1);
    1140           5 :         switch(ch) {
    1141             :         case LockCommand:
    1142           3 :             ch = LockDirectory(dirname, lockname);
    1143           3 :             rv = write(fd, &ch, 1);
    1144           3 :             assert(rv == 1);
    1145           3 :             break;
    1146             :         case UnlockCommand:
    1147           1 :             ReleaseDirectoryLocks();
    1148           1 :             ch = true; // Always succeeds
    1149           1 :             rv = write(fd, &ch, 1);
    1150           1 :             assert(rv == 1);
    1151           1 :             break;
    1152             :         case ExitCommand:
    1153           1 :             close(fd);
    1154           1 :             exit(0);
    1155             :         default:
    1156           0 :             assert(0);
    1157             :         }
    1158             :     }
    1159             : }
    1160             : #endif
    1161             : 
    1162         152 : BOOST_AUTO_TEST_CASE(test_LockDirectory)
    1163             : {
    1164           2 :     fs::path dirname = m_args.GetDataDirBase() / "lock_dir";
    1165           2 :     const fs::path lockname = ".lock";
    1166             : #ifndef WIN32
    1167             :     // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
    1168             :     // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
    1169             :     // at build-time of the boost library
    1170           2 :     void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
    1171             : 
    1172             :     // Fork another process for testing before creating the lock, so that we
    1173             :     // won't fork while holding the lock (which might be undefined, and is not
    1174             :     // relevant as test case as that is avoided with -daemonize).
    1175             :     int fd[2];
    1176           2 :     BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
    1177           2 :     pid_t pid = fork();
    1178           2 :     if (!pid) {
    1179           1 :         BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
    1180           1 :         TestOtherProcess(dirname, lockname, fd[0]);
    1181             :     }
    1182           1 :     BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
    1183             : #endif
    1184             :     // Lock on non-existent directory should fail
    1185           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
    1186             : 
    1187           1 :     fs::create_directories(dirname);
    1188             : 
    1189             :     // Probing lock on new directory should succeed
    1190           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1191             : 
    1192             :     // Persistent lock on new directory should succeed
    1193           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1194             : 
    1195             :     // Another lock on the directory from the same thread should succeed
    1196           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
    1197             : 
    1198             :     // Another lock on the directory from a different thread within the same process should succeed
    1199             :     bool threadresult;
    1200           1 :     std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
    1201           0 :     thr.join();
    1202           1 :     BOOST_CHECK_EQUAL(threadresult, true);
    1203             : #ifndef WIN32
    1204             :     // Try to acquire lock in child process while we're holding it, this should fail.
    1205             :     char ch;
    1206           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1207           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1208           1 :     BOOST_CHECK_EQUAL((bool)ch, false);
    1209             : 
    1210             :     // Give up our lock
    1211           1 :     ReleaseDirectoryLocks();
    1212             :     // Probing lock from our side now should succeed, but not hold on to the lock.
    1213           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1214             : 
    1215             :     // Try to acquire the lock in the child process, this should be successful.
    1216           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1217           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1218           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1219             : 
    1220             :     // When we try to probe the lock now, it should fail.
    1221           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
    1222             : 
    1223             :     // Unlock the lock in the child process
    1224           1 :     BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
    1225           1 :     BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
    1226           1 :     BOOST_CHECK_EQUAL((bool)ch, true);
    1227             : 
    1228             :     // When we try to probe the lock now, it should succeed.
    1229           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1230             : 
    1231             :     // Re-lock the lock in the child process, then wait for it to exit, check
    1232             :     // successful return. After that, we check that exiting the process
    1233             :     // has released the lock as we would expect by probing it.
    1234             :     int processstatus;
    1235           1 :     BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
    1236           1 :     BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
    1237           1 :     BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
    1238           1 :     BOOST_CHECK_EQUAL(processstatus, 0);
    1239           1 :     BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
    1240             : 
    1241             :     // Restore SIGCHLD
    1242           1 :     signal(SIGCHLD, old_handler);
    1243           1 :     BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
    1244             : #endif
    1245             :     // Clean up
    1246           1 :     ReleaseDirectoryLocks();
    1247           1 :     fs::remove_all(dirname);
    1248           4 : }
    1249             : 
    1250         149 : BOOST_AUTO_TEST_CASE(test_DirIsWritable)
    1251             : {
    1252             :     // Should be able to write to the data dir.
    1253           1 :     fs::path tmpdirname = m_args.GetDataDirBase();
    1254           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1255             : 
    1256             :     // Should not be able to write to a non-existent dir.
    1257           1 :     tmpdirname = GetUniquePath(tmpdirname);
    1258           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
    1259             : 
    1260           1 :     fs::create_directory(tmpdirname);
    1261             :     // Should be able to write to it now.
    1262           1 :     BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
    1263           1 :     fs::remove(tmpdirname);
    1264           1 : }
    1265             : 
    1266             : namespace {
    1267             : 
    1268             : struct Tracker
    1269             : {
    1270             :     //! Points to the original object (possibly itself) we moved/copied from
    1271             :     const Tracker* origin;
    1272             :     //! How many copies where involved between the original object and this one (moves are not counted)
    1273           3 :     int copies{0};
    1274             : 
    1275           9 :     Tracker() noexcept : origin(this) {}
    1276          20 :     Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
    1277          26 :     Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
    1278             :     Tracker& operator=(const Tracker& t) noexcept
    1279             :     {
    1280             :         origin = t.origin;
    1281             :         copies = t.copies + 1;
    1282             :         return *this;
    1283             :     }
    1284             : };
    1285             : 
    1286             : }
    1287             : 
    1288         149 : BOOST_AUTO_TEST_CASE(test_tracked_vector)
    1289             : {
    1290           1 :     Tracker t1;
    1291           1 :     Tracker t2;
    1292           1 :     Tracker t3;
    1293             : 
    1294           1 :     BOOST_CHECK(t1.origin == &t1);
    1295           1 :     BOOST_CHECK(t2.origin == &t2);
    1296           1 :     BOOST_CHECK(t3.origin == &t3);
    1297             : 
    1298           1 :     auto v1 = Vector(t1);
    1299           1 :     BOOST_CHECK_EQUAL(v1.size(), 1U);
    1300           1 :     BOOST_CHECK(v1[0].origin == &t1);
    1301           1 :     BOOST_CHECK_EQUAL(v1[0].copies, 1);
    1302             : 
    1303           1 :     auto v2 = Vector(std::move(t2));
    1304           1 :     BOOST_CHECK_EQUAL(v2.size(), 1U);
    1305           1 :     BOOST_CHECK(v2[0].origin == &t2); // NOLINT(*-use-after-move)
    1306           1 :     BOOST_CHECK_EQUAL(v2[0].copies, 0);
    1307             : 
    1308           1 :     auto v3 = Vector(t1, std::move(t2));
    1309           1 :     BOOST_CHECK_EQUAL(v3.size(), 2U);
    1310           1 :     BOOST_CHECK(v3[0].origin == &t1);
    1311           1 :     BOOST_CHECK(v3[1].origin == &t2); // NOLINT(*-use-after-move)
    1312           1 :     BOOST_CHECK_EQUAL(v3[0].copies, 1);
    1313           1 :     BOOST_CHECK_EQUAL(v3[1].copies, 0);
    1314             : 
    1315           1 :     auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
    1316           1 :     BOOST_CHECK_EQUAL(v4.size(), 3U);
    1317           1 :     BOOST_CHECK(v4[0].origin == &t1);
    1318           1 :     BOOST_CHECK(v4[1].origin == &t2);
    1319           1 :     BOOST_CHECK(v4[2].origin == &t3); // NOLINT(*-use-after-move)
    1320           1 :     BOOST_CHECK_EQUAL(v4[0].copies, 1);
    1321           1 :     BOOST_CHECK_EQUAL(v4[1].copies, 1);
    1322           1 :     BOOST_CHECK_EQUAL(v4[2].copies, 0);
    1323             : 
    1324           1 :     auto v5 = Cat(v1, v4);
    1325           1 :     BOOST_CHECK_EQUAL(v5.size(), 4U);
    1326           1 :     BOOST_CHECK(v5[0].origin == &t1);
    1327           1 :     BOOST_CHECK(v5[1].origin == &t1);
    1328           1 :     BOOST_CHECK(v5[2].origin == &t2);
    1329           1 :     BOOST_CHECK(v5[3].origin == &t3);
    1330           1 :     BOOST_CHECK_EQUAL(v5[0].copies, 2);
    1331           1 :     BOOST_CHECK_EQUAL(v5[1].copies, 2);
    1332           1 :     BOOST_CHECK_EQUAL(v5[2].copies, 2);
    1333           1 :     BOOST_CHECK_EQUAL(v5[3].copies, 1);
    1334             : 
    1335           1 :     auto v6 = Cat(std::move(v1), v3);
    1336           1 :     BOOST_CHECK_EQUAL(v6.size(), 3U);
    1337           1 :     BOOST_CHECK(v6[0].origin == &t1);
    1338           1 :     BOOST_CHECK(v6[1].origin == &t1);
    1339           1 :     BOOST_CHECK(v6[2].origin == &t2);
    1340           1 :     BOOST_CHECK_EQUAL(v6[0].copies, 1);
    1341           1 :     BOOST_CHECK_EQUAL(v6[1].copies, 2);
    1342           1 :     BOOST_CHECK_EQUAL(v6[2].copies, 1);
    1343             : 
    1344           1 :     auto v7 = Cat(v2, std::move(v4));
    1345           1 :     BOOST_CHECK_EQUAL(v7.size(), 4U);
    1346           1 :     BOOST_CHECK(v7[0].origin == &t2);
    1347           1 :     BOOST_CHECK(v7[1].origin == &t1);
    1348           1 :     BOOST_CHECK(v7[2].origin == &t2);
    1349           1 :     BOOST_CHECK(v7[3].origin == &t3);
    1350           1 :     BOOST_CHECK_EQUAL(v7[0].copies, 1);
    1351           1 :     BOOST_CHECK_EQUAL(v7[1].copies, 1);
    1352           1 :     BOOST_CHECK_EQUAL(v7[2].copies, 1);
    1353           1 :     BOOST_CHECK_EQUAL(v7[3].copies, 0);
    1354             : 
    1355           1 :     auto v8 = Cat(std::move(v2), std::move(v3));
    1356           1 :     BOOST_CHECK_EQUAL(v8.size(), 3U);
    1357           1 :     BOOST_CHECK(v8[0].origin == &t2);
    1358           1 :     BOOST_CHECK(v8[1].origin == &t1);
    1359           1 :     BOOST_CHECK(v8[2].origin == &t2);
    1360           1 :     BOOST_CHECK_EQUAL(v8[0].copies, 0);
    1361           1 :     BOOST_CHECK_EQUAL(v8[1].copies, 1);
    1362           1 :     BOOST_CHECK_EQUAL(v8[2].copies, 0);
    1363           1 : }
    1364             : 
    1365         149 : BOOST_AUTO_TEST_CASE(test_ToLower)
    1366             : {
    1367           1 :     BOOST_CHECK_EQUAL(ToLower('@'), '@');
    1368           1 :     BOOST_CHECK_EQUAL(ToLower('A'), 'a');
    1369           1 :     BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
    1370           1 :     BOOST_CHECK_EQUAL(ToLower('['), '[');
    1371           1 :     BOOST_CHECK_EQUAL(ToLower(0), 0);
    1372           1 :     BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
    1373             : 
    1374           1 :     BOOST_CHECK_EQUAL(ToLower(""), "");
    1375           1 :     BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
    1376           1 :     BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
    1377           1 : }
    1378             : 
    1379         149 : BOOST_AUTO_TEST_CASE(test_ToUpper)
    1380             : {
    1381           1 :     BOOST_CHECK_EQUAL(ToUpper('`'), '`');
    1382           1 :     BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
    1383           1 :     BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
    1384           1 :     BOOST_CHECK_EQUAL(ToUpper('{'), '{');
    1385           1 :     BOOST_CHECK_EQUAL(ToUpper(0), 0);
    1386           1 :     BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
    1387             : 
    1388           1 :     BOOST_CHECK_EQUAL(ToUpper(""), "");
    1389           1 :     BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
    1390           1 :     BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
    1391           1 : }
    1392             : 
    1393         149 : BOOST_AUTO_TEST_CASE(test_Capitalize)
    1394             : {
    1395           1 :     BOOST_CHECK_EQUAL(Capitalize(""), "");
    1396           1 :     BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin");
    1397           1 :     BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
    1398           1 : }
    1399             : 
    1400         149 : BOOST_AUTO_TEST_CASE(test_CRanges)
    1401             : {
    1402           1 :     std::mt19937 gen;
    1403          18 :     for (int test = 0; test < 17; ++test) {
    1404          17 :         std::uniform_int_distribution<uint64_t> dist_value(0, (1 << test));
    1405          17 :         CRangesSet ranges;
    1406          17 :         std::unordered_set<uint64_t> set_2;
    1407      262159 :         for (int iter = 0; iter < (1 << test) * 2; ++iter) {
    1408      262142 :             uint64_t value = dist_value(gen);
    1409      262142 :             BOOST_CHECK_EQUAL(ranges.Contains(value), !!set_2.count(value));
    1410      262142 :             if (!ranges.Contains(value)) {
    1411      163304 :                 BOOST_CHECK(ranges.Add(value));
    1412      163304 :                 set_2.insert(value);
    1413      163304 :             } else {
    1414       98838 :                 BOOST_CHECK(ranges.Remove(value));
    1415       98838 :                 set_2.erase(set_2.find(value));
    1416             :             }
    1417      262142 :             BOOST_CHECK_EQUAL(ranges.Contains(value), !!set_2.count(value));
    1418      262142 :             BOOST_CHECK_EQUAL(ranges.Size(), set_2.size());
    1419      262142 :         }
    1420          17 :         if (test > 4) {
    1421          12 :             BOOST_CHECK(ranges.Size() > ((1u << test) / 4));
    1422          12 :         }
    1423          17 :     }
    1424           1 : }
    1425             : 
    1426          28 : static std::string SpanToStr(const Span<const char>& span)
    1427             : {
    1428          28 :     return std::string(span.begin(), span.end());
    1429             : }
    1430             : 
    1431         149 : BOOST_AUTO_TEST_CASE(test_spanparsing)
    1432             : {
    1433             :     using namespace spanparsing;
    1434           1 :     std::string input;
    1435           1 :     Span<const char> sp;
    1436             :     bool success;
    1437             : 
    1438             :     // Const(...): parse a constant, update span to skip it if successful
    1439           1 :     input = "MilkToastHoney";
    1440           1 :     sp = input;
    1441           1 :     success = Const("", sp); // empty
    1442           1 :     BOOST_CHECK(success);
    1443           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");
    1444             : 
    1445           1 :     success = Const("Milk", sp);
    1446           1 :     BOOST_CHECK(success);
    1447           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");
    1448             : 
    1449           1 :     success = Const("Bread", sp);
    1450           1 :     BOOST_CHECK(!success);
    1451             : 
    1452           1 :     success = Const("Toast", sp);
    1453           1 :     BOOST_CHECK(success);
    1454           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");
    1455             : 
    1456           1 :     success = Const("Honeybadger", sp);
    1457           1 :     BOOST_CHECK(!success);
    1458             : 
    1459           1 :     success = Const("Honey", sp);
    1460           1 :     BOOST_CHECK(success);
    1461           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "");
    1462             : 
    1463             :     // Func(...): parse a function call, update span to argument if successful
    1464           1 :     input = "Foo(Bar(xy,z()))";
    1465           1 :     sp = input;
    1466             : 
    1467           1 :     success = Func("FooBar", sp);
    1468           1 :     BOOST_CHECK(!success);
    1469             : 
    1470           1 :     success = Func("Foo(", sp);
    1471           1 :     BOOST_CHECK(!success);
    1472             : 
    1473           1 :     success = Func("Foo", sp);
    1474           1 :     BOOST_CHECK(success);
    1475           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");
    1476             : 
    1477           1 :     success = Func("Bar", sp);
    1478           1 :     BOOST_CHECK(success);
    1479           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()");
    1480             : 
    1481           1 :     success = Func("xy", sp);
    1482           1 :     BOOST_CHECK(!success);
    1483             : 
    1484             :     // Expr(...): return expression that span begins with, update span to skip it
    1485           1 :     Span<const char> result;
    1486             : 
    1487           1 :     input = "(n*(n-1))/2";
    1488           1 :     sp = input;
    1489           1 :     result = Expr(sp);
    1490           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2");
    1491           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), "");
    1492             : 
    1493           1 :     input = "foo,bar";
    1494           1 :     sp = input;
    1495           1 :     result = Expr(sp);
    1496           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "foo");
    1497           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar");
    1498             : 
    1499           1 :     input = "(aaaaa,bbbbb()),c";
    1500           1 :     sp = input;
    1501           1 :     result = Expr(sp);
    1502           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())");
    1503           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",c");
    1504             : 
    1505           1 :     input = "xyz)foo";
    1506           1 :     sp = input;
    1507           1 :     result = Expr(sp);
    1508           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "xyz");
    1509           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo");
    1510             : 
    1511           1 :     input = "((a),(b),(c)),xxx";
    1512           1 :     sp = input;
    1513           1 :     result = Expr(sp);
    1514           1 :     BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))");
    1515           1 :     BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx");
    1516             : 
    1517             :     // Split(...): split a string on every instance of sep, return vector
    1518           1 :     std::vector<Span<const char>> results;
    1519             : 
    1520           1 :     input = "xxx";
    1521           1 :     results = Split(input, 'x');
    1522           1 :     BOOST_CHECK_EQUAL(results.size(), 4);
    1523           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
    1524           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "");
    1525           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "");
    1526           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
    1527             : 
    1528           1 :     input = "one#two#three";
    1529           1 :     results = Split(input, '-');
    1530           1 :     BOOST_CHECK_EQUAL(results.size(), 1);
    1531           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three");
    1532             : 
    1533           1 :     input = "one#two#three";
    1534           1 :     results = Split(input, '#');
    1535           1 :     BOOST_CHECK_EQUAL(results.size(), 3);
    1536           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one");
    1537           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two");
    1538           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three");
    1539             : 
    1540           1 :     input = "*foo*bar*";
    1541           1 :     results = Split(input, '*');
    1542           1 :     BOOST_CHECK_EQUAL(results.size(), 4);
    1543           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
    1544           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo");
    1545           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar");
    1546           1 :     BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
    1547           1 : }
    1548             : 
    1549         149 : BOOST_AUTO_TEST_CASE(test_SplitString)
    1550             : {
    1551             :     // Empty string.
    1552             :     {
    1553           1 :         std::vector<std::string> result = SplitString("", '-');
    1554           1 :         BOOST_CHECK_EQUAL(result.size(), 1);
    1555           1 :         BOOST_CHECK_EQUAL(result[0], "");
    1556           1 :     }
    1557             : 
    1558             :     // Empty items.
    1559             :     {
    1560           1 :         std::vector<std::string> result = SplitString("-", '-');
    1561           1 :         BOOST_CHECK_EQUAL(result.size(), 2);
    1562           1 :         BOOST_CHECK_EQUAL(result[0], "");
    1563           1 :         BOOST_CHECK_EQUAL(result[1], "");
    1564           1 :     }
    1565             : 
    1566             :     // More empty items.
    1567             :     {
    1568           1 :         std::vector<std::string> result = SplitString("--", '-');
    1569           1 :         BOOST_CHECK_EQUAL(result.size(), 3);
    1570           1 :         BOOST_CHECK_EQUAL(result[0], "");
    1571           1 :         BOOST_CHECK_EQUAL(result[1], "");
    1572           1 :         BOOST_CHECK_EQUAL(result[2], "");
    1573           1 :     }
    1574             : 
    1575             :     // Separator is not present.
    1576             :     {
    1577           1 :         std::vector<std::string> result = SplitString("abc", '-');
    1578           1 :         BOOST_CHECK_EQUAL(result.size(), 1);
    1579           1 :         BOOST_CHECK_EQUAL(result[0], "abc");
    1580           1 :     }
    1581             : 
    1582             :     // Basic behavior.
    1583             :     {
    1584           1 :         std::vector<std::string> result = SplitString("a-b", '-');
    1585           1 :         BOOST_CHECK_EQUAL(result.size(), 2);
    1586           1 :         BOOST_CHECK_EQUAL(result[0], "a");
    1587           1 :         BOOST_CHECK_EQUAL(result[1], "b");
    1588           1 :     }
    1589             : 
    1590             :     // Case-sensitivity of the separator.
    1591             :     {
    1592           1 :         std::vector<std::string> result = SplitString("AAA", 'a');
    1593           1 :         BOOST_CHECK_EQUAL(result.size(), 1);
    1594           1 :         BOOST_CHECK_EQUAL(result[0], "AAA");
    1595           1 :     }
    1596             : 
    1597             :     // multiple split characters
    1598             :     {
    1599             :         using V = std::vector<std::string>;
    1600           1 :         BOOST_TEST(SplitString("a,b.c:d;e", ",;") == V({"a", "b.c:d", "e"}));
    1601           1 :         BOOST_TEST(SplitString("a,b.c:d;e", ",;:.") == V({"a", "b", "c", "d", "e"}));
    1602           1 :         BOOST_TEST(SplitString("a,b.c:d;e", "") == V({"a,b.c:d;e"}));
    1603           1 :         BOOST_TEST(SplitString("aaa", "bcdefg") == V({"aaa"}));
    1604           1 :         BOOST_TEST(SplitString("x\0a,b"s, "\0"s) == V({"x", "a,b"}));
    1605           1 :         BOOST_TEST(SplitString("x\0a,b"s, '\0') == V({"x", "a,b"}));
    1606           1 :         BOOST_TEST(SplitString("x\0a,b"s, "\0,"s) == V({"x", "a", "b"}));
    1607           1 :         BOOST_TEST(SplitString("abcdefg", "bcd") == V({"a", "", "", "efg"}));
    1608             :     }
    1609           1 : }
    1610             : 
    1611         149 : BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
    1612             : {
    1613             :     // ASCII and UTF-8 must pass through unaltered.
    1614           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
    1615             :     // Newlines must pass through unaltered.
    1616           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
    1617             :     // Other control characters are escaped in C syntax.
    1618           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
    1619             :     // Embedded NULL characters are escaped too.
    1620           1 :     const std::string NUL("O\x00O", 3);
    1621           1 :     BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
    1622           1 : }
    1623             : 
    1624         149 : BOOST_AUTO_TEST_CASE(message_sign)
    1625             : {
    1626           1 :     const std::array<unsigned char, 32> privkey_bytes = {
    1627             :         // just some random data
    1628             :         // derived address from this private key: XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j
    1629             :         0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
    1630             :         0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
    1631             :         0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
    1632             :         0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
    1633             :     };
    1634             : 
    1635           1 :     const std::string message = "Trust no one";
    1636             : 
    1637             :     const std::string expected_signature =
    1638           1 :         "IIOzMDkvw3GtLWXkeEYRRRH53MOLHM44sJ428Nu4NNacTPJTGcKesMJ+3s3OadYK34tpSQIhu922EviNNWTsiQg=";
    1639             : 
    1640           1 :     CKey privkey;
    1641           1 :     std::string generated_signature;
    1642             : 
    1643           1 :     BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
    1644             :         "Confirm the private key is invalid");
    1645             : 
    1646           1 :     BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
    1647             :         "Sign with an invalid private key");
    1648             : 
    1649           1 :     privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
    1650             : 
    1651           1 :     BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
    1652             :         "Confirm the private key is valid");
    1653             : 
    1654           1 :     BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
    1655             :         "Sign with a valid private key");
    1656             : 
    1657           1 :     BOOST_CHECK_EQUAL(expected_signature, generated_signature);
    1658           1 : }
    1659             : 
    1660         149 : BOOST_AUTO_TEST_CASE(message_verify)
    1661             : {
    1662           1 :     BOOST_CHECK_EQUAL(
    1663             :         MessageVerify(
    1664             :             "invalid address",
    1665             :             "signature should be irrelevant",
    1666             :             "message too"),
    1667             :         MessageVerificationResult::ERR_INVALID_ADDRESS);
    1668             : 
    1669           1 :     BOOST_CHECK_EQUAL(
    1670             :         MessageVerify(
    1671             :             "7iRPy8FEHBzbChrktsG85YbDZ3SuiCxsNq",
    1672             :             "signature should be irrelevant",
    1673             :             "message too"),
    1674             :         MessageVerificationResult::ERR_ADDRESS_NO_KEY);
    1675             : 
    1676           1 :     BOOST_CHECK_EQUAL(
    1677             :         MessageVerify(
    1678             :             "XuXS24zs2xP1vPynvNt14kWLa64csH8Mur",
    1679             :             "invalid signature, not in base64 encoding",
    1680             :             "message should be irrelevant"),
    1681             :         MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
    1682             : 
    1683           1 :     BOOST_CHECK_EQUAL(
    1684             :         MessageVerify(
    1685             :             "XuXS24zs2xP1vPynvNt14kWLa64csH8Mur",
    1686             :             "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
    1687             :             "message should be irrelevant"),
    1688             :         MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED);
    1689             : 
    1690           1 :     BOOST_CHECK_EQUAL(
    1691             :         MessageVerify(
    1692             :             "XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j",
    1693             :             "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
    1694             :             "I never signed this"),
    1695             :         MessageVerificationResult::ERR_NOT_SIGNED);
    1696             : 
    1697           1 :     BOOST_CHECK_EQUAL(
    1698             :         MessageVerify(
    1699             :             "XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j",
    1700             :             "IIOzMDkvw3GtLWXkeEYRRRH53MOLHM44sJ428Nu4NNacTPJTGcKesMJ+3s3OadYK34tpSQIhu922EviNNWTsiQg=",
    1701             :             "Trust no one"),
    1702             :         MessageVerificationResult::OK);
    1703             : 
    1704           1 :     BOOST_CHECK_EQUAL(
    1705             :         MessageVerify(
    1706             :             "XenV77v8QQ3rwjyCb3j2fCwfvgbkC4Vwaj",
    1707             :             "IOACalWiJTLJ2U7wTKICx5mQ2tOAJ3to8dko8FMb2XSYbmvL+yMWedyfSfaK6V8jwoociyYx628nkXXnrOhPFIY=",
    1708             :             "Trust me"),
    1709             :         MessageVerificationResult::OK);
    1710           1 : }
    1711             : 
    1712         149 : BOOST_AUTO_TEST_CASE(message_hash)
    1713             : {
    1714           1 :     const std::string unsigned_tx = "...";
    1715             :     const std::string prefixed_message =
    1716           2 :         std::string(1, (char)MESSAGE_MAGIC.length()) +
    1717           1 :         MESSAGE_MAGIC +
    1718           2 :         std::string(1, (char)unsigned_tx.length()) +
    1719             :         unsigned_tx;
    1720             : 
    1721           1 :     const uint256 signature_hash = Hash(unsigned_tx);
    1722           1 :     const uint256 message_hash1 = Hash(prefixed_message);
    1723           1 :     const uint256 message_hash2 = MessageHash(unsigned_tx);
    1724             : 
    1725           1 :     BOOST_CHECK_EQUAL(message_hash1, message_hash2);
    1726           1 :     BOOST_CHECK_NE(message_hash1, signature_hash);
    1727           1 : }
    1728             : 
    1729         149 : BOOST_AUTO_TEST_CASE(remove_prefix)
    1730             : {
    1731           1 :     BOOST_CHECK_EQUAL(RemovePrefix("./util/system.h", "./"), "util/system.h");
    1732           1 :     BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), "");
    1733           1 :     BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o");
    1734           1 :     BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo");
    1735           1 :     BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo");
    1736           1 :     BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo");
    1737           1 :     BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f");
    1738           1 :     BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), "");
    1739           1 :     BOOST_CHECK_EQUAL(RemovePrefix("", ""), "");
    1740           1 : }
    1741             : 
    1742         149 : BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
    1743             : {
    1744           1 :     auto noop = ByteUnit::NOOP;
    1745             : 
    1746             :     // no multiplier
    1747           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("1", noop).value(), 1);
    1748           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("0", noop).value(), 0);
    1749             : 
    1750           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("1k", noop).value(), 1000ULL);
    1751           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("1K", noop).value(), 1ULL << 10);
    1752             : 
    1753           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("2m", noop).value(), 2'000'000ULL);
    1754           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("2M", noop).value(), 2ULL << 20);
    1755             : 
    1756           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("3g", noop).value(), 3'000'000'000ULL);
    1757           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3ULL << 30);
    1758             : 
    1759           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("4t", noop).value(), 4'000'000'000'000ULL);
    1760           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("4T", noop).value(), 4ULL << 40);
    1761             : 
    1762             :     // check default multiplier
    1763           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("5", ByteUnit::K).value(), 5ULL << 10);
    1764             : 
    1765             :     // NaN
    1766           1 :     BOOST_CHECK(!ParseByteUnits("", noop));
    1767           1 :     BOOST_CHECK(!ParseByteUnits("foo", noop));
    1768             : 
    1769             :     // whitespace
    1770           1 :     BOOST_CHECK(!ParseByteUnits("123m ", noop));
    1771           1 :     BOOST_CHECK(!ParseByteUnits(" 123m", noop));
    1772             : 
    1773             :     // no +-
    1774           1 :     BOOST_CHECK(!ParseByteUnits("-123m", noop));
    1775           1 :     BOOST_CHECK(!ParseByteUnits("+123m", noop));
    1776             : 
    1777             :     // zero padding
    1778           1 :     BOOST_CHECK_EQUAL(ParseByteUnits("020M", noop).value(), 20ULL << 20);
    1779             : 
    1780             :     // fractions not allowed
    1781           1 :     BOOST_CHECK(!ParseByteUnits("0.5T", noop));
    1782             : 
    1783             :     // overflow
    1784           1 :     BOOST_CHECK(!ParseByteUnits("18446744073709551615g", noop));
    1785             : 
    1786             :     // invalid unit
    1787           1 :     BOOST_CHECK(!ParseByteUnits("1x", noop));
    1788           1 : }
    1789             : 
    1790         149 : BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
    1791             : {
    1792           1 :     fs::path tmpfolder = m_args.GetDataDirBase();
    1793           1 :     fs::path tmpfile = tmpfolder / "read_binary.dat";
    1794           1 :     std::string expected_text;
    1795          31 :     for (int i = 0; i < 30; i++) {
    1796          30 :         expected_text += "0123456789";
    1797          30 :     }
    1798             :     {
    1799           1 :         std::ofstream file{tmpfile};
    1800           1 :         file << expected_text;
    1801           1 :     }
    1802             :     {
    1803             :         // read all contents in file
    1804           3 :         auto [valid, text] = ReadBinaryFile(tmpfile);
    1805           1 :         BOOST_CHECK(valid);
    1806           1 :         BOOST_CHECK_EQUAL(text, expected_text);
    1807           1 :     }
    1808             :     {
    1809             :         // read half contents in file
    1810           3 :         auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
    1811           1 :         BOOST_CHECK(valid);
    1812           1 :         BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
    1813           1 :     }
    1814             :     {
    1815             :         // read from non-existent file
    1816           1 :         fs::path invalid_file = tmpfolder / "invalid_binary.dat";
    1817           3 :         auto [valid, text] = ReadBinaryFile(invalid_file);
    1818           1 :         BOOST_CHECK(!valid);
    1819           1 :         BOOST_CHECK(text.empty());
    1820           1 :     }
    1821           1 : }
    1822             : 
    1823         149 : BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
    1824             : {
    1825           1 :     fs::path tmpfolder = m_args.GetDataDirBase();
    1826           1 :     fs::path tmpfile = tmpfolder / "write_binary.dat";
    1827           1 :     std::string expected_text = "bitcoin";
    1828           1 :     auto valid = WriteBinaryFile(tmpfile, expected_text);
    1829           1 :     std::string actual_text;
    1830           1 :     std::ifstream file{tmpfile};
    1831           1 :     file >> actual_text;
    1832           1 :     BOOST_CHECK(valid);
    1833           1 :     BOOST_CHECK_EQUAL(actual_text, expected_text);
    1834           1 : }
    1835             : 
    1836         149 : BOOST_AUTO_TEST_CASE(clearshrink_test)
    1837             : {
    1838             :     {
    1839           1 :         std::vector<uint8_t> v = {1, 2, 3};
    1840           1 :         ClearShrink(v);
    1841           1 :         BOOST_CHECK_EQUAL(v.size(), 0);
    1842           1 :         BOOST_CHECK_EQUAL(v.capacity(), 0);
    1843           1 :     }
    1844             : 
    1845             :     {
    1846           1 :         std::vector<bool> v = {false, true, false, false, true, true};
    1847           1 :         ClearShrink(v);
    1848           1 :         BOOST_CHECK_EQUAL(v.size(), 0);
    1849           1 :         BOOST_CHECK_EQUAL(v.capacity(), 0);
    1850           1 :     }
    1851             : 
    1852             :     {
    1853           1 :         std::deque<int> v = {1, 3, 3, 7};
    1854           1 :         ClearShrink(v);
    1855           1 :         BOOST_CHECK_EQUAL(v.size(), 0);
    1856             :         // std::deque has no capacity() we can observe.
    1857           1 :     }
    1858           1 : }
    1859             : 
    1860         149 : BOOST_AUTO_TEST_CASE(padding_test)
    1861             : {
    1862             :     /* By default strings will be padded to the left */
    1863           1 :     BOOST_CHECK_EQUAL(PadString("example", 8), " example");
    1864             : 
    1865             :     /* Check padding works on the correct side */
    1866           1 :     BOOST_CHECK_EQUAL(PadString("example", 8, /*left=*/true),  " example");
    1867           1 :     BOOST_CHECK_EQUAL(PadString("example", 8, /*left=*/false), "example ");
    1868             : 
    1869             :     /* Padding lesser than the string size should return the string */
    1870           1 :     BOOST_CHECK_EQUAL(PadString("example", 6), "example");
    1871             : 
    1872             :     /* Padding equal to the string size should return the string */
    1873           1 :     BOOST_CHECK_EQUAL(PadString("example", 7), "example");
    1874             : 
    1875             :     /* Padding an empty string with zero length should return an empty string */
    1876           1 :     BOOST_CHECK(PadString("", 0).empty());
    1877             : 
    1878             :     /* An empty string should be padded if non-zero length specified */
    1879           1 :     BOOST_CHECK_EQUAL(PadString("", 1), " ");
    1880           1 : }
    1881             : 
    1882         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16