util_tests.cpp raw

   1  // Copyright (c) 2011-present The Limenka 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 <clientversion.h>
   6  #include <common/signmessage.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
   7  #include <hash.h> // For Hash()
   8  #include <key.h>  // For CKey
   9  #include <key_io.h> // EncodeDestination
  10  #include <outputtype.h> // For BIP-322 tests
  11  #include <script/parsing.h>
  12  #include <span.h>
  13  #include <sync.h>
  14  #include <test/util/random.h>
  15  #include <test/util/setup_common.h>
  16  #include <uint256.h>
  17  #include <util/bitdeque.h>
  18  #include <util/byte_units.h>
  19  #include <util/fs.h>
  20  #include <util/fs_helpers.h>
  21  #include <util/moneystr.h>
  22  #include <util/overflow.h>
  23  #include <util/readwritefile.h>
  24  #include <util/strencodings.h>
  25  #include <util/string.h>
  26  #include <util/time.h>
  27  #include <util/vector.h>
  28  
  29  #include <array>
  30  #include <cmath>
  31  #include <fstream>
  32  #include <limits>
  33  #include <map>
  34  #include <optional>
  35  #include <stdint.h>
  36  #include <string.h>
  37  #include <thread>
  38  #include <univalue.h>
  39  #include <type_traits>
  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  using namespace util::hex_literals;
  54  using util::ConstevalHexDigit;
  55  using util::Join;
  56  using util::RemovePrefix;
  57  using util::RemovePrefixView;
  58  using util::ReplaceAll;
  59  using util::Split;
  60  using util::SplitString;
  61  using util::TrimString;
  62  using util::TrimStringView;
  63  
  64  static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s};
  65  
  66  /* defined in logging.cpp */
  67  namespace BCLog {
  68      std::string LogEscapeMessage(std::string_view str);
  69  }
  70  
  71  BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
  72  
  73  namespace {
  74  class NoCopyOrMove
  75  {
  76  public:
  77      int i;
  78      explicit NoCopyOrMove(int i) : i{i} { }
  79  
  80      NoCopyOrMove() = delete;
  81      NoCopyOrMove(const NoCopyOrMove&) = delete;
  82      NoCopyOrMove(NoCopyOrMove&&) = delete;
  83      NoCopyOrMove& operator=(const NoCopyOrMove&) = delete;
  84      NoCopyOrMove& operator=(NoCopyOrMove&&) = delete;
  85  
  86      operator bool() const { return i != 0; }
  87  
  88      int get_ip1() { return i + 1; }
  89      bool test()
  90      {
  91          // Check that Assume can be used within a lambda and still call methods
  92          [&]() { Assume(get_ip1()); }();
  93          return Assume(get_ip1() != 5);
  94      }
  95  };
  96  } // namespace
  97  
  98  BOOST_AUTO_TEST_CASE(util_check)
  99  {
 100      // Check that Assert can forward
 101      const std::unique_ptr<int> p_two = Assert(std::make_unique<int>(2));
 102      // Check that Assert works on lvalues and rvalues
 103      const int two = *Assert(p_two);
 104      Assert(two == 2);
 105      Assert(true);
 106      // Check that Assume can be used as unary expression
 107      const bool result{Assume(two == 2)};
 108      Assert(result);
 109  
 110      // Check that Assert doesn't require copy/move
 111      NoCopyOrMove x{9};
 112      Assert(x).i += 3;
 113      Assert(x).test();
 114  
 115      // Check nested Asserts
 116      BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3);
 117  
 118      // Check -Wdangling-gsl does not trigger when copying the int. (It would
 119      // trigger on "const int&")
 120      const int nine{*Assert(std::optional<int>{9})};
 121      BOOST_CHECK_EQUAL(9, nine);
 122  }
 123  
 124  BOOST_AUTO_TEST_CASE(util_criticalsection)
 125  {
 126      RecursiveMutex cs;
 127  
 128      do {
 129          LOCK(cs);
 130          break;
 131  
 132          BOOST_ERROR("break was swallowed!");
 133      } while(0);
 134  
 135      do {
 136          TRY_LOCK(cs, lockTest);
 137          if (lockTest) {
 138              BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
 139              break;
 140          }
 141  
 142          BOOST_ERROR("break was swallowed!");
 143      } while(0);
 144  }
 145  
 146  constexpr char HEX_PARSE_INPUT[] = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
 147  constexpr uint8_t HEX_PARSE_OUTPUT[] = {
 148      0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
 149      0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
 150      0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
 151      0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
 152      0x5f
 153  };
 154  static_assert((sizeof(HEX_PARSE_INPUT) - 1) == 2 * sizeof(HEX_PARSE_OUTPUT));
 155  BOOST_AUTO_TEST_CASE(parse_hex)
 156  {
 157      std::vector<unsigned char> result;
 158  
 159      // Basic test vector
 160      std::vector<unsigned char> expected(std::begin(HEX_PARSE_OUTPUT), std::end(HEX_PARSE_OUTPUT));
 161      constexpr std::array<std::byte, 65> hex_literal_array{operator""_hex<util::detail::Hex(HEX_PARSE_INPUT)>()};
 162      auto hex_literal_span{MakeUCharSpan(hex_literal_array)};
 163      BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
 164  
 165      const std::vector<std::byte> hex_literal_vector{operator""_hex_v<util::detail::Hex(HEX_PARSE_INPUT)>()};
 166      hex_literal_span = MakeUCharSpan(hex_literal_vector);
 167      BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
 168  
 169      constexpr std::array<uint8_t, 65> hex_literal_array_uint8{operator""_hex_u8<util::detail::Hex(HEX_PARSE_INPUT)>()};
 170      BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_array_uint8.begin(), hex_literal_array_uint8.end(), expected.begin(), expected.end());
 171  
 172      result = operator""_hex_v_u8<util::detail::Hex(HEX_PARSE_INPUT)>();
 173      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 174  
 175      result = ParseHex(HEX_PARSE_INPUT);
 176      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 177  
 178      result = TryParseHex<uint8_t>(HEX_PARSE_INPUT).value();
 179      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 180  
 181      // Spaces between bytes must be supported
 182      expected = {0x12, 0x34, 0x56, 0x78};
 183      result = ParseHex("12 34 56 78");
 184      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 185      result = TryParseHex<uint8_t>("12 34 56 78").value();
 186      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 187  
 188      // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
 189      expected = {0x89, 0x34, 0x56, 0x78};
 190      result = ParseHex(" 89 34 56 78");
 191      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 192      result = TryParseHex<uint8_t>(" 89 34 56 78").value();
 193      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 194  
 195      // Mixed case and spaces are supported
 196      expected = {0xff, 0xaa};
 197      result = ParseHex("     Ff        aA    ");
 198      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 199      result = TryParseHex<uint8_t>("     Ff        aA    ").value();
 200      BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
 201  
 202      // Empty string is supported
 203      static_assert(""_hex.empty());
 204      static_assert(""_hex_u8.empty());
 205      BOOST_CHECK_EQUAL(""_hex_v.size(), 0);
 206      BOOST_CHECK_EQUAL(""_hex_v_u8.size(), 0);
 207      BOOST_CHECK_EQUAL(ParseHex("").size(), 0);
 208      BOOST_CHECK_EQUAL(TryParseHex<uint8_t>("").value().size(), 0);
 209  
 210      // Spaces between nibbles is treated as invalid
 211      BOOST_CHECK_EQUAL(ParseHex("AAF F").size(), 0);
 212      BOOST_CHECK(!TryParseHex("AAF F").has_value());
 213  
 214      // Embedded null is treated as invalid
 215      const std::string with_embedded_null{" 11 "s
 216                                           " \0 "
 217                                           " 22 "s};
 218      BOOST_CHECK_EQUAL(with_embedded_null.size(), 11);
 219      BOOST_CHECK_EQUAL(ParseHex(with_embedded_null).size(), 0);
 220      BOOST_CHECK(!TryParseHex(with_embedded_null).has_value());
 221  
 222      // Non-hex is treated as invalid
 223      BOOST_CHECK_EQUAL(ParseHex("1234 invalid 1234").size(), 0);
 224      BOOST_CHECK(!TryParseHex("1234 invalid 1234").has_value());
 225  
 226      // Truncated input is treated as invalid
 227      BOOST_CHECK_EQUAL(ParseHex("12 3").size(), 0);
 228      BOOST_CHECK(!TryParseHex("12 3").has_value());
 229  }
 230  
 231  BOOST_AUTO_TEST_CASE(consteval_hex_digit)
 232  {
 233      BOOST_CHECK_EQUAL(ConstevalHexDigit('0'), 0);
 234      BOOST_CHECK_EQUAL(ConstevalHexDigit('9'), 9);
 235      BOOST_CHECK_EQUAL(ConstevalHexDigit('a'), 0xa);
 236      BOOST_CHECK_EQUAL(ConstevalHexDigit('f'), 0xf);
 237  }
 238  
 239  BOOST_AUTO_TEST_CASE(util_HexStr)
 240  {
 241      BOOST_CHECK_EQUAL(HexStr(HEX_PARSE_OUTPUT), HEX_PARSE_INPUT);
 242      BOOST_CHECK_EQUAL(HexStr(Span{HEX_PARSE_OUTPUT}.last(0)), "");
 243      BOOST_CHECK_EQUAL(HexStr(Span{HEX_PARSE_OUTPUT}.first(0)), "");
 244  
 245      {
 246          constexpr std::string_view out_exp{"04678afdb0"};
 247          constexpr std::span in_s{HEX_PARSE_OUTPUT, out_exp.size() / 2};
 248          const Span<const uint8_t> in_u{MakeUCharSpan(in_s)};
 249          const Span<const std::byte> in_b{MakeByteSpan(in_s)};
 250  
 251          BOOST_CHECK_EQUAL(HexStr(in_u), out_exp);
 252          BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
 253          BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
 254      }
 255  
 256      {
 257          auto input = std::string();
 258          for (size_t i=0; i<256; ++i) {
 259              input.push_back(static_cast<char>(i));
 260          }
 261  
 262          auto hex = HexStr(input);
 263          BOOST_TEST_REQUIRE(hex.size() == 512);
 264          static constexpr auto hexmap = std::string_view("0123456789abcdef");
 265          for (size_t i = 0; i < 256; ++i) {
 266              auto upper = hexmap.find(hex[i * 2]);
 267              auto lower = hexmap.find(hex[i * 2 + 1]);
 268              BOOST_TEST_REQUIRE(upper != std::string_view::npos);
 269              BOOST_TEST_REQUIRE(lower != std::string_view::npos);
 270              BOOST_TEST_REQUIRE(i == upper*16 + lower);
 271          }
 272      }
 273  }
 274  
 275  BOOST_AUTO_TEST_CASE(span_write_bytes)
 276  {
 277      std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}};
 278      const auto mut_bytes{MakeWritableByteSpan(mut_arr)};
 279      mut_bytes[1] = std::byte{0x11};
 280      BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa);
 281      BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11);
 282  }
 283  
 284  BOOST_AUTO_TEST_CASE(util_Join)
 285  {
 286      // Normal version
 287      BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
 288      BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
 289      BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
 290  
 291      // Version with unary operator
 292      const auto op_upper = [](const std::string& s) { return ToUpper(s); };
 293      BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
 294      BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
 295      BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
 296  }
 297  
 298  BOOST_AUTO_TEST_CASE(util_ReplaceAll)
 299  {
 300      const std::string original("A test \"%s\" string '%s'.");
 301      auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) {
 302          auto test = original;
 303          ReplaceAll(test, search, substitute);
 304          BOOST_CHECK_EQUAL(test, expected);
 305      };
 306  
 307      test_replaceall("", "foo", original);
 308      test_replaceall(original, "foo", "foo");
 309      test_replaceall("%s", "foo", "A test \"foo\" string 'foo'.");
 310      test_replaceall("\"", "foo", "A test foo%sfoo string '%s'.");
 311      test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo.");
 312  }
 313  
 314  BOOST_AUTO_TEST_CASE(util_TrimString)
 315  {
 316      BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar");
 317      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");
 318      BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar");
 319      BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
 320      BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar");
 321      BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " ");
 322      BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7));
 323      BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3));
 324      BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2));
 325      BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
 326      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));
 327      BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
 328  }
 329  
 330  BOOST_AUTO_TEST_CASE(util_ParseISO8601DateTime)
 331  {
 332      BOOST_CHECK_EQUAL(ParseISO8601DateTime("1969-12-31T23:59:59Z").value(), -1);
 333      BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:00Z").value(), 0);
 334      BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:01Z").value(), 1);
 335      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:00:01Z").value(), 946684801);
 336      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2011-09-30T23:36:17Z").value(), 1317425777);
 337      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2100-12-31T23:59:59Z").value(), 4133980799);
 338      BOOST_CHECK_EQUAL(ParseISO8601DateTime("9999-12-31T23:59:59Z").value(), 253402300799);
 339  
 340      // Accept edge-cases, where the time overflows. They are not produced by
 341      // FormatISO8601DateTime, so this can be changed in the future, if needed.
 342      // For now, keep compatibility with the previous implementation.
 343      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T99:00:00Z").value(), 947041200);
 344      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:99:00Z").value(), 946690740);
 345      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:00:99Z").value(), 946684899);
 346      BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T99:99:99Z").value(), 947047239);
 347  
 348      // Reject date overflows.
 349      BOOST_CHECK(!ParseISO8601DateTime("2000-99-01T00:00:00Z"));
 350      BOOST_CHECK(!ParseISO8601DateTime("2000-01-99T00:00:00Z"));
 351  
 352      // Reject out-of-range years
 353      BOOST_CHECK(!ParseISO8601DateTime("32768-12-31T23:59:59Z"));
 354      BOOST_CHECK(!ParseISO8601DateTime("32767-12-31T23:59:59Z"));
 355      BOOST_CHECK(!ParseISO8601DateTime("32767-12-31T00:00:00Z"));
 356      BOOST_CHECK(!ParseISO8601DateTime("999-12-31T00:00:00Z"));
 357  
 358      // Reject invalid format
 359      const std::string valid{"2000-01-01T00:00:01Z"};
 360      BOOST_CHECK(ParseISO8601DateTime(valid).has_value());
 361      for (auto mut{0U}; mut < valid.size(); ++mut) {
 362          std::string invalid{valid};
 363          invalid[mut] = 'a';
 364          BOOST_CHECK(!ParseISO8601DateTime(invalid));
 365      }
 366  }
 367  
 368  BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
 369  {
 370      BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890963199), "32767-12-31T23:59:59Z");
 371      BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890876800), "32767-12-31T00:00:00Z");
 372  
 373      BOOST_CHECK_EQUAL(FormatISO8601DateTime(-1), "1969-12-31T23:59:59Z");
 374      BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z");
 375      BOOST_CHECK_EQUAL(FormatISO8601DateTime(1), "1970-01-01T00:00:01Z");
 376      BOOST_CHECK_EQUAL(FormatISO8601DateTime(946684801), "2000-01-01T00:00:01Z");
 377      BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
 378      BOOST_CHECK_EQUAL(FormatISO8601DateTime(4133980799), "2100-12-31T23:59:59Z");
 379      BOOST_CHECK_EQUAL(FormatISO8601DateTime(253402300799), "9999-12-31T23:59:59Z");
 380  }
 381  
 382  BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
 383  {
 384      BOOST_CHECK_EQUAL(FormatISO8601Date(971890963199), "32767-12-31");
 385      BOOST_CHECK_EQUAL(FormatISO8601Date(971890876800), "32767-12-31");
 386  
 387      BOOST_CHECK_EQUAL(FormatISO8601Date(0), "1970-01-01");
 388      BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
 389  }
 390  
 391  BOOST_AUTO_TEST_CASE(util_FormatMoney)
 392  {
 393      BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
 394      BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
 395      BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
 396  
 397      BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
 398      BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
 399      BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
 400      BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
 401      BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
 402      BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
 403      BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
 404      BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
 405      BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
 406      BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
 407      BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
 408      BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
 409      BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
 410      BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
 411      BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
 412      BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
 413      BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
 414  
 415      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max()), "92233720368.54775807");
 416      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 1), "92233720368.54775806");
 417      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 2), "92233720368.54775805");
 418      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 3), "92233720368.54775804");
 419      // ...
 420      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 3), "-92233720368.54775805");
 421      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 2), "-92233720368.54775806");
 422      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 1), "-92233720368.54775807");
 423      BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min()), "-92233720368.54775808");
 424  }
 425  
 426  BOOST_AUTO_TEST_CASE(util_ParseMoney)
 427  {
 428      BOOST_CHECK_EQUAL(ParseMoney("0.0").value(), 0);
 429      BOOST_CHECK_EQUAL(ParseMoney(".").value(), 0);
 430      BOOST_CHECK_EQUAL(ParseMoney("0.").value(), 0);
 431      BOOST_CHECK_EQUAL(ParseMoney(".0").value(), 0);
 432      BOOST_CHECK_EQUAL(ParseMoney(".6789").value(), 6789'0000);
 433      BOOST_CHECK_EQUAL(ParseMoney("12345.").value(), COIN * 12345);
 434  
 435      BOOST_CHECK_EQUAL(ParseMoney("12345.6789").value(), (COIN/10000)*123456789);
 436  
 437      BOOST_CHECK_EQUAL(ParseMoney("10000000.00").value(), COIN*10000000);
 438      BOOST_CHECK_EQUAL(ParseMoney("1000000.00").value(), COIN*1000000);
 439      BOOST_CHECK_EQUAL(ParseMoney("100000.00").value(), COIN*100000);
 440      BOOST_CHECK_EQUAL(ParseMoney("10000.00").value(), COIN*10000);
 441      BOOST_CHECK_EQUAL(ParseMoney("1000.00").value(), COIN*1000);
 442      BOOST_CHECK_EQUAL(ParseMoney("100.00").value(), COIN*100);
 443      BOOST_CHECK_EQUAL(ParseMoney("10.00").value(), COIN*10);
 444      BOOST_CHECK_EQUAL(ParseMoney("1.00").value(), COIN);
 445      BOOST_CHECK_EQUAL(ParseMoney("1").value(), COIN);
 446      BOOST_CHECK_EQUAL(ParseMoney("   1").value(), COIN);
 447      BOOST_CHECK_EQUAL(ParseMoney("1   ").value(), COIN);
 448      BOOST_CHECK_EQUAL(ParseMoney("  1 ").value(), COIN);
 449      BOOST_CHECK_EQUAL(ParseMoney("0.1").value(), COIN/10);
 450      BOOST_CHECK_EQUAL(ParseMoney("0.01").value(), COIN/100);
 451      BOOST_CHECK_EQUAL(ParseMoney("0.001").value(), COIN/1000);
 452      BOOST_CHECK_EQUAL(ParseMoney("0.0001").value(), COIN/10000);
 453      BOOST_CHECK_EQUAL(ParseMoney("0.00001").value(), COIN/100000);
 454      BOOST_CHECK_EQUAL(ParseMoney("0.000001").value(), COIN/1000000);
 455      BOOST_CHECK_EQUAL(ParseMoney("0.0000001").value(), COIN/10000000);
 456      BOOST_CHECK_EQUAL(ParseMoney("0.00000001").value(), COIN/100000000);
 457      BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001 ").value(), COIN/100000000);
 458      BOOST_CHECK_EQUAL(ParseMoney("0.00000001 ").value(), COIN/100000000);
 459      BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001").value(), COIN/100000000);
 460  
 461      // Parsing amount that cannot be represented should fail
 462      BOOST_CHECK(!ParseMoney("100000000.00"));
 463      BOOST_CHECK(!ParseMoney("0.000000001"));
 464  
 465      // Parsing empty string should fail
 466      BOOST_CHECK(!ParseMoney(""));
 467      BOOST_CHECK(!ParseMoney(" "));
 468      BOOST_CHECK(!ParseMoney("  "));
 469  
 470      // Parsing two numbers should fail
 471      BOOST_CHECK(!ParseMoney(".."));
 472      BOOST_CHECK(!ParseMoney("0..0"));
 473      BOOST_CHECK(!ParseMoney("1 2"));
 474      BOOST_CHECK(!ParseMoney(" 1 2 "));
 475      BOOST_CHECK(!ParseMoney(" 1.2 3 "));
 476      BOOST_CHECK(!ParseMoney(" 1 2.3 "));
 477  
 478      // Embedded whitespace should fail
 479      BOOST_CHECK(!ParseMoney(" -1 .2  "));
 480      BOOST_CHECK(!ParseMoney("  1 .2  "));
 481      BOOST_CHECK(!ParseMoney(" +1 .2  "));
 482  
 483      // Attempted 63 bit overflow should fail
 484      BOOST_CHECK(!ParseMoney("92233720368.54775808"));
 485  
 486      // Parsing negative amounts must fail
 487      BOOST_CHECK(!ParseMoney("-1"));
 488  
 489      // Parsing strings with embedded NUL characters should fail
 490      BOOST_CHECK(!ParseMoney("\0-1"s));
 491      BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR));
 492      BOOST_CHECK(!ParseMoney("1\0"s));
 493  }
 494  
 495  BOOST_AUTO_TEST_CASE(util_IsHex)
 496  {
 497      BOOST_CHECK(IsHex("00"));
 498      BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
 499      BOOST_CHECK(IsHex("ff"));
 500      BOOST_CHECK(IsHex("FF"));
 501  
 502      BOOST_CHECK(!IsHex(""));
 503      BOOST_CHECK(!IsHex("0"));
 504      BOOST_CHECK(!IsHex("a"));
 505      BOOST_CHECK(!IsHex("eleven"));
 506      BOOST_CHECK(!IsHex("00xx00"));
 507      BOOST_CHECK(!IsHex("0x0000"));
 508  }
 509  
 510  BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
 511  {
 512      SeedRandomForTest(SeedRand::ZEROS);
 513      for (int mod=2;mod<11;mod++)
 514      {
 515          int mask = 1;
 516          // Really rough binomial confidence approximation.
 517          int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
 518          //mask is 2^ceil(log2(mod))-1
 519          while(mask<mod-1)mask=(mask<<1)+1;
 520  
 521          int count = 0;
 522          //How often does it get a zero from the uniform range [0,mod)?
 523          for (int i = 0; i < 10000; i++) {
 524              uint32_t rval;
 525              do{
 526                  rval=m_rng.rand32()&mask;
 527              }while(rval>=(uint32_t)mod);
 528              count += rval==0;
 529          }
 530          BOOST_CHECK(count<=10000/mod+err);
 531          BOOST_CHECK(count>=10000/mod-err);
 532      }
 533  }
 534  
 535  BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
 536  {
 537      BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
 538      BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
 539      BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
 540      BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
 541      BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
 542      BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
 543      BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
 544  }
 545  
 546  /* Test strprintf formatting directives.
 547   * Put a string before and after to ensure sanity of element sizes on stack. */
 548  #define B "check_prefix"
 549  #define E "check_postfix"
 550  BOOST_AUTO_TEST_CASE(strprintf_numbers)
 551  {
 552      int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
 553      uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
 554      BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
 555      BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
 556      BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
 557  
 558      size_t st = 12345678; /* unsigned size_t test value */
 559      ssize_t sst = -12345678; /* signed size_t test value */
 560      BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
 561      BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
 562      BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
 563  
 564      ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
 565      ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
 566      BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
 567      BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
 568      BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
 569  }
 570  #undef B
 571  #undef E
 572  
 573  BOOST_AUTO_TEST_CASE(util_time_GetTime)
 574  {
 575      SetMockTime(111);
 576      // Check that mock time does not change after a sleep
 577      for (const auto& num_sleep : {0ms, 1ms}) {
 578          UninterruptibleSleep(num_sleep);
 579          BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
 580          BOOST_CHECK_EQUAL(111, Now<NodeSeconds>().time_since_epoch().count());
 581          BOOST_CHECK_EQUAL(111, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()));
 582          BOOST_CHECK_EQUAL(111, TicksSinceEpoch<SecondsDouble>(Now<NodeSeconds>()));
 583          BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
 584          BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
 585          BOOST_CHECK_EQUAL(111000, TicksSinceEpoch<std::chrono::milliseconds>(NodeClock::now()));
 586          BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
 587      }
 588  
 589      SetMockTime(0);
 590      // Check that steady time and system time changes after a sleep
 591      const auto steady_ms_0 = Now<SteadyMilliseconds>();
 592      const auto steady_0 = std::chrono::steady_clock::now();
 593      const auto ms_0 = GetTime<std::chrono::milliseconds>();
 594      const auto us_0 = GetTime<std::chrono::microseconds>();
 595      UninterruptibleSleep(1ms);
 596      BOOST_CHECK(steady_ms_0 < Now<SteadyMilliseconds>());
 597      BOOST_CHECK(steady_0 + 1ms <= std::chrono::steady_clock::now());
 598      BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
 599      BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
 600  }
 601  
 602  BOOST_AUTO_TEST_CASE(util_ticksseconds)
 603  {
 604      BOOST_CHECK_EQUAL(TicksSeconds(0s), 0);
 605      BOOST_CHECK_EQUAL(TicksSeconds(1s), 1);
 606      BOOST_CHECK_EQUAL(TicksSeconds(999ms), 0);
 607      BOOST_CHECK_EQUAL(TicksSeconds(1000ms), 1);
 608      BOOST_CHECK_EQUAL(TicksSeconds(1500ms), 1);
 609  }
 610  
 611  BOOST_AUTO_TEST_CASE(test_IsDigit)
 612  {
 613      BOOST_CHECK_EQUAL(IsDigit('0'), true);
 614      BOOST_CHECK_EQUAL(IsDigit('1'), true);
 615      BOOST_CHECK_EQUAL(IsDigit('8'), true);
 616      BOOST_CHECK_EQUAL(IsDigit('9'), true);
 617  
 618      BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
 619      BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
 620      BOOST_CHECK_EQUAL(IsDigit(0), false);
 621      BOOST_CHECK_EQUAL(IsDigit(1), false);
 622      BOOST_CHECK_EQUAL(IsDigit(8), false);
 623      BOOST_CHECK_EQUAL(IsDigit(9), false);
 624  }
 625  
 626  /* Check for overflow */
 627  template <typename T>
 628  static void TestAddMatrixOverflow()
 629  {
 630      constexpr T MAXI{std::numeric_limits<T>::max()};
 631      BOOST_CHECK(!CheckedAdd(T{1}, MAXI));
 632      BOOST_CHECK(!CheckedAdd(MAXI, MAXI));
 633      BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI));
 634      BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(MAXI, MAXI));
 635  
 636      BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value());
 637      BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value());
 638      BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value());
 639      BOOST_CHECK_EQUAL(MAXI - 1, CheckedAdd(T{1}, MAXI - 2).value());
 640      BOOST_CHECK_EQUAL(0, SaturatingAdd(T{0}, T{0}));
 641      BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{0}, MAXI));
 642      BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI - 1));
 643      BOOST_CHECK_EQUAL(MAXI - 1, SaturatingAdd(T{1}, MAXI - 2));
 644  }
 645  
 646  /* Check for overflow or underflow */
 647  template <typename T>
 648  static void TestAddMatrix()
 649  {
 650      TestAddMatrixOverflow<T>();
 651      constexpr T MINI{std::numeric_limits<T>::min()};
 652      constexpr T MAXI{std::numeric_limits<T>::max()};
 653      BOOST_CHECK(!CheckedAdd(T{-1}, MINI));
 654      BOOST_CHECK(!CheckedAdd(MINI, MINI));
 655      BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI));
 656      BOOST_CHECK_EQUAL(MINI, SaturatingAdd(MINI, MINI));
 657  
 658      BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value());
 659      BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value());
 660      BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value());
 661      BOOST_CHECK_EQUAL(MINI + 1, CheckedAdd(T{-1}, MINI + 2).value());
 662      BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{0}, MINI));
 663      BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI + 1));
 664      BOOST_CHECK_EQUAL(MINI + 1, SaturatingAdd(T{-1}, MINI + 2));
 665      BOOST_CHECK_EQUAL(-1, SaturatingAdd(MINI, MAXI));
 666  }
 667  
 668  BOOST_AUTO_TEST_CASE(util_overflow)
 669  {
 670      TestAddMatrixOverflow<unsigned>();
 671      TestAddMatrix<signed>();
 672  }
 673  
 674  BOOST_AUTO_TEST_CASE(test_ParseInt32)
 675  {
 676      int32_t n;
 677      // Valid values
 678      BOOST_CHECK(ParseInt32("1234", nullptr));
 679      BOOST_CHECK(ParseInt32("0", &n) && n == 0);
 680      BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
 681      BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
 682      BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
 683      BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
 684      BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
 685      BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
 686      BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
 687      BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
 688      BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
 689      // Invalid values
 690      BOOST_CHECK(!ParseInt32("", &n));
 691      BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
 692      BOOST_CHECK(!ParseInt32("1 ", &n));
 693      BOOST_CHECK(!ParseInt32("++1", &n));
 694      BOOST_CHECK(!ParseInt32("+-1", &n));
 695      BOOST_CHECK(!ParseInt32("-+1", &n));
 696      BOOST_CHECK(!ParseInt32("--1", &n));
 697      BOOST_CHECK(!ParseInt32("1a", &n));
 698      BOOST_CHECK(!ParseInt32("aap", &n));
 699      BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
 700      BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
 701      // Overflow and underflow
 702      BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
 703      BOOST_CHECK(!ParseInt32("2147483648", nullptr));
 704      BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
 705      BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
 706  }
 707  
 708  template <typename T>
 709  static void RunToIntegralTests()
 710  {
 711      BOOST_CHECK(!ToIntegral<T>(STRING_WITH_EMBEDDED_NULL_CHAR));
 712      BOOST_CHECK(!ToIntegral<T>(" 1"));
 713      BOOST_CHECK(!ToIntegral<T>("1 "));
 714      BOOST_CHECK(!ToIntegral<T>("1a"));
 715      BOOST_CHECK(!ToIntegral<T>("1.1"));
 716      BOOST_CHECK(!ToIntegral<T>("1.9"));
 717      BOOST_CHECK(!ToIntegral<T>("+01.9"));
 718      BOOST_CHECK(!ToIntegral<T>("-"));
 719      BOOST_CHECK(!ToIntegral<T>("+"));
 720      BOOST_CHECK(!ToIntegral<T>(" -1"));
 721      BOOST_CHECK(!ToIntegral<T>("-1 "));
 722      BOOST_CHECK(!ToIntegral<T>(" -1 "));
 723      BOOST_CHECK(!ToIntegral<T>("+1"));
 724      BOOST_CHECK(!ToIntegral<T>(" +1"));
 725      BOOST_CHECK(!ToIntegral<T>(" +1 "));
 726      BOOST_CHECK(!ToIntegral<T>("+-1"));
 727      BOOST_CHECK(!ToIntegral<T>("-+1"));
 728      BOOST_CHECK(!ToIntegral<T>("++1"));
 729      BOOST_CHECK(!ToIntegral<T>("--1"));
 730      BOOST_CHECK(!ToIntegral<T>(""));
 731      BOOST_CHECK(!ToIntegral<T>("aap"));
 732      BOOST_CHECK(!ToIntegral<T>("0x1"));
 733      BOOST_CHECK(!ToIntegral<T>("-32482348723847471234"));
 734      BOOST_CHECK(!ToIntegral<T>("32482348723847471234"));
 735  }
 736  
 737  BOOST_AUTO_TEST_CASE(test_ToIntegral)
 738  {
 739      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("1234").value(), 1'234);
 740      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("0").value(), 0);
 741      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("01234").value(), 1'234);
 742      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000001234").value(), 1'234);
 743      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000001234").value(), -1'234);
 744      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000000000").value(), 0);
 745      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000000000").value(), 0);
 746      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1234").value(), -1'234);
 747      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1").value(), -1);
 748  
 749      RunToIntegralTests<uint64_t>();
 750      RunToIntegralTests<int64_t>();
 751      RunToIntegralTests<uint32_t>();
 752      RunToIntegralTests<int32_t>();
 753      RunToIntegralTests<uint16_t>();
 754      RunToIntegralTests<int16_t>();
 755      RunToIntegralTests<uint8_t>();
 756      RunToIntegralTests<int8_t>();
 757  
 758      BOOST_CHECK(!ToIntegral<int64_t>("-9223372036854775809"));
 759      BOOST_CHECK_EQUAL(ToIntegral<int64_t>("-9223372036854775808").value(), -9'223'372'036'854'775'807LL - 1LL);
 760      BOOST_CHECK_EQUAL(ToIntegral<int64_t>("9223372036854775807").value(), 9'223'372'036'854'775'807);
 761      BOOST_CHECK(!ToIntegral<int64_t>("9223372036854775808"));
 762  
 763      BOOST_CHECK(!ToIntegral<uint64_t>("-1"));
 764      BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("0").value(), 0U);
 765      BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("18446744073709551615").value(), 18'446'744'073'709'551'615ULL);
 766      BOOST_CHECK(!ToIntegral<uint64_t>("18446744073709551616"));
 767  
 768      BOOST_CHECK(!ToIntegral<int32_t>("-2147483649"));
 769      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-2147483648").value(), -2'147'483'648LL);
 770      BOOST_CHECK_EQUAL(ToIntegral<int32_t>("2147483647").value(), 2'147'483'647);
 771      BOOST_CHECK(!ToIntegral<int32_t>("2147483648"));
 772  
 773      BOOST_CHECK(!ToIntegral<uint32_t>("-1"));
 774      BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("0").value(), 0U);
 775      BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("4294967295").value(), 4'294'967'295U);
 776      BOOST_CHECK(!ToIntegral<uint32_t>("4294967296"));
 777  
 778      BOOST_CHECK(!ToIntegral<int16_t>("-32769"));
 779      BOOST_CHECK_EQUAL(ToIntegral<int16_t>("-32768").value(), -32'768);
 780      BOOST_CHECK_EQUAL(ToIntegral<int16_t>("32767").value(), 32'767);
 781      BOOST_CHECK(!ToIntegral<int16_t>("32768"));
 782  
 783      BOOST_CHECK(!ToIntegral<uint16_t>("-1"));
 784      BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("0").value(), 0U);
 785      BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("65535").value(), 65'535U);
 786      BOOST_CHECK(!ToIntegral<uint16_t>("65536"));
 787  
 788      BOOST_CHECK(!ToIntegral<int8_t>("-129"));
 789      BOOST_CHECK_EQUAL(ToIntegral<int8_t>("-128").value(), -128);
 790      BOOST_CHECK_EQUAL(ToIntegral<int8_t>("127").value(), 127);
 791      BOOST_CHECK(!ToIntegral<int8_t>("128"));
 792  
 793      BOOST_CHECK(!ToIntegral<uint8_t>("-1"));
 794      BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("0").value(), 0U);
 795      BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("255").value(), 255U);
 796      BOOST_CHECK(!ToIntegral<uint8_t>("256"));
 797  }
 798  
 799  int64_t atoi64_legacy(const std::string& str)
 800  {
 801      return strtoll(str.c_str(), nullptr, 10);
 802  }
 803  
 804  BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
 805  {
 806      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1234"), 1'234);
 807      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0"), 0);
 808      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("01234"), 1'234);
 809      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1234"), -1'234);
 810      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" 1"), 1);
 811      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1 "), 1);
 812      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1a"), 1);
 813      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.1"), 1);
 814      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.9"), 1);
 815      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+01.9"), 1);
 816      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1"), -1);
 817      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1"), -1);
 818      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1 "), -1);
 819      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1 "), -1);
 820      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+1"), 1);
 821      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1"), 1);
 822      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1 "), 1);
 823  
 824      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+-1"), 0);
 825      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-+1"), 0);
 826      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("++1"), 0);
 827      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("--1"), 0);
 828      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(""), 0);
 829      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("aap"), 0);
 830      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0x1"), 0);
 831      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-32482348723847471234"), -2'147'483'647 - 1);
 832      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("32482348723847471234"), 2'147'483'647);
 833  
 834      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775809"), -9'223'372'036'854'775'807LL - 1LL);
 835      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775808"), -9'223'372'036'854'775'807LL - 1LL);
 836      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775807"), 9'223'372'036'854'775'807);
 837      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775808"), 9'223'372'036'854'775'807);
 838  
 839      std::map<std::string, int64_t> atoi64_test_pairs = {
 840          {"-9223372036854775809", std::numeric_limits<int64_t>::min()},
 841          {"-9223372036854775808", -9'223'372'036'854'775'807LL - 1LL},
 842          {"9223372036854775807", 9'223'372'036'854'775'807},
 843          {"9223372036854775808", std::numeric_limits<int64_t>::max()},
 844          {"+-", 0},
 845          {"0x1", 0},
 846          {"ox1", 0},
 847          {"", 0},
 848      };
 849  
 850      for (const auto& pair : atoi64_test_pairs) {
 851          BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), pair.second);
 852      }
 853  
 854      // Ensure legacy compatibility with previous versions of Limenka's atoi64
 855      for (const auto& pair : atoi64_test_pairs) {
 856          BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), atoi64_legacy(pair.first));
 857      }
 858  
 859      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("-1"), 0U);
 860      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("0"), 0U);
 861      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551615"), 18'446'744'073'709'551'615ULL);
 862      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551616"), 18'446'744'073'709'551'615ULL);
 863  
 864      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483649"), -2'147'483'648LL);
 865      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483648"), -2'147'483'648LL);
 866      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483647"), 2'147'483'647);
 867      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483648"), 2'147'483'647);
 868  
 869      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("-1"), 0U);
 870      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("0"), 0U);
 871      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967295"), 4'294'967'295U);
 872      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967296"), 4'294'967'295U);
 873  
 874      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32769"), -32'768);
 875      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32768"), -32'768);
 876      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32767"), 32'767);
 877      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32768"), 32'767);
 878  
 879      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("-1"), 0U);
 880      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("0"), 0U);
 881      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65535"), 65'535U);
 882      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65536"), 65'535U);
 883  
 884      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-129"), -128);
 885      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-128"), -128);
 886      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("127"), 127);
 887      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("128"), 127);
 888  
 889      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("-1"), 0U);
 890      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("0"), 0U);
 891      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("255"), 255U);
 892      BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
 893  }
 894  
 895  BOOST_AUTO_TEST_CASE(test_ParseInt64)
 896  {
 897      int64_t n;
 898      // Valid values
 899      BOOST_CHECK(ParseInt64("1234", nullptr));
 900      BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
 901      BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
 902      BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
 903      BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
 904      BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
 905      BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
 906      BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
 907      BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
 908      // Invalid values
 909      BOOST_CHECK(!ParseInt64("", &n));
 910      BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
 911      BOOST_CHECK(!ParseInt64("1 ", &n));
 912      BOOST_CHECK(!ParseInt64("1a", &n));
 913      BOOST_CHECK(!ParseInt64("aap", &n));
 914      BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
 915      BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
 916      // Overflow and underflow
 917      BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
 918      BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
 919      BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
 920      BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
 921  }
 922  
 923  BOOST_AUTO_TEST_CASE(test_ParseUInt8)
 924  {
 925      uint8_t n;
 926      // Valid values
 927      BOOST_CHECK(ParseUInt8("255", nullptr));
 928      BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
 929      BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
 930      BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
 931      BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
 932      BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
 933      BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
 934      BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
 935      // Invalid values
 936      BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
 937      BOOST_CHECK(!ParseUInt8("", &n));
 938      BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
 939      BOOST_CHECK(!ParseUInt8(" -1", &n));
 940      BOOST_CHECK(!ParseUInt8("++1", &n));
 941      BOOST_CHECK(!ParseUInt8("+-1", &n));
 942      BOOST_CHECK(!ParseUInt8("-+1", &n));
 943      BOOST_CHECK(!ParseUInt8("--1", &n));
 944      BOOST_CHECK(!ParseUInt8("-1", &n));
 945      BOOST_CHECK(!ParseUInt8("1 ", &n));
 946      BOOST_CHECK(!ParseUInt8("1a", &n));
 947      BOOST_CHECK(!ParseUInt8("aap", &n));
 948      BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
 949      BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
 950      // Overflow and underflow
 951      BOOST_CHECK(!ParseUInt8("-255", &n));
 952      BOOST_CHECK(!ParseUInt8("256", &n));
 953      BOOST_CHECK(!ParseUInt8("-123", &n));
 954      BOOST_CHECK(!ParseUInt8("-123", nullptr));
 955      BOOST_CHECK(!ParseUInt8("256", nullptr));
 956  }
 957  
 958  BOOST_AUTO_TEST_CASE(test_ParseUInt16)
 959  {
 960      uint16_t n;
 961      // Valid values
 962      BOOST_CHECK(ParseUInt16("1234", nullptr));
 963      BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
 964      BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
 965      BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
 966      BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
 967      BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
 968      BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
 969      BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
 970      // Invalid values
 971      BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
 972      BOOST_CHECK(!ParseUInt16("", &n));
 973      BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
 974      BOOST_CHECK(!ParseUInt16(" -1", &n));
 975      BOOST_CHECK(!ParseUInt16("++1", &n));
 976      BOOST_CHECK(!ParseUInt16("+-1", &n));
 977      BOOST_CHECK(!ParseUInt16("-+1", &n));
 978      BOOST_CHECK(!ParseUInt16("--1", &n));
 979      BOOST_CHECK(!ParseUInt16("-1", &n));
 980      BOOST_CHECK(!ParseUInt16("1 ", &n));
 981      BOOST_CHECK(!ParseUInt16("1a", &n));
 982      BOOST_CHECK(!ParseUInt16("aap", &n));
 983      BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
 984      BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
 985      // Overflow and underflow
 986      BOOST_CHECK(!ParseUInt16("-65535", &n));
 987      BOOST_CHECK(!ParseUInt16("65536", &n));
 988      BOOST_CHECK(!ParseUInt16("-123", &n));
 989      BOOST_CHECK(!ParseUInt16("-123", nullptr));
 990      BOOST_CHECK(!ParseUInt16("65536", nullptr));
 991  }
 992  
 993  BOOST_AUTO_TEST_CASE(test_ParseUInt32)
 994  {
 995      uint32_t n;
 996      // Valid values
 997      BOOST_CHECK(ParseUInt32("1234", nullptr));
 998      BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
 999      BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
1000      BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
1001      BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
1002      BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
1003      BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
1004      BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
1005      BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
1006      BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
1007      // Invalid values
1008      BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
1009      BOOST_CHECK(!ParseUInt32("", &n));
1010      BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
1011      BOOST_CHECK(!ParseUInt32(" -1", &n));
1012      BOOST_CHECK(!ParseUInt32("++1", &n));
1013      BOOST_CHECK(!ParseUInt32("+-1", &n));
1014      BOOST_CHECK(!ParseUInt32("-+1", &n));
1015      BOOST_CHECK(!ParseUInt32("--1", &n));
1016      BOOST_CHECK(!ParseUInt32("-1", &n));
1017      BOOST_CHECK(!ParseUInt32("1 ", &n));
1018      BOOST_CHECK(!ParseUInt32("1a", &n));
1019      BOOST_CHECK(!ParseUInt32("aap", &n));
1020      BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
1021      BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
1022      // Overflow and underflow
1023      BOOST_CHECK(!ParseUInt32("-2147483648", &n));
1024      BOOST_CHECK(!ParseUInt32("4294967296", &n));
1025      BOOST_CHECK(!ParseUInt32("-1234", &n));
1026      BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
1027      BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
1028  }
1029  
1030  BOOST_AUTO_TEST_CASE(test_ParseUInt64)
1031  {
1032      uint64_t n;
1033      // Valid values
1034      BOOST_CHECK(ParseUInt64("1234", nullptr));
1035      BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
1036      BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
1037      BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
1038      BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
1039      BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
1040      BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
1041      BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
1042      // Invalid values
1043      BOOST_CHECK(!ParseUInt64("", &n));
1044      BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
1045      BOOST_CHECK(!ParseUInt64(" -1", &n));
1046      BOOST_CHECK(!ParseUInt64("1 ", &n));
1047      BOOST_CHECK(!ParseUInt64("1a", &n));
1048      BOOST_CHECK(!ParseUInt64("aap", &n));
1049      BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
1050      BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
1051      // Overflow and underflow
1052      BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
1053      BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
1054      BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
1055      BOOST_CHECK(!ParseUInt64("-2147483648", &n));
1056      BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
1057      BOOST_CHECK(!ParseUInt64("-1234", &n));
1058  }
1059  
1060  BOOST_AUTO_TEST_CASE(test_FormatParagraph)
1061  {
1062      BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
1063      BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
1064      BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
1065      BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
1066      BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
1067      BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
1068      BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n    test");
1069  
1070      // Make sure we don't indent a fully-new line following a too-long line ending
1071      BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n    test\nabc");
1072  
1073      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");
1074  
1075      // Test wrap length is exact
1076      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");
1077      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");
1078      // Indent should be included in length of lines
1079      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");
1080  
1081      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.");
1082      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.");
1083      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.");
1084      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.");
1085  }
1086  
1087  BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
1088  {
1089      std::vector<std::string> comments;
1090      comments.emplace_back("comment1");
1091      std::vector<std::string> comments2;
1092      comments2.emplace_back("comment1");
1093      comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
1094      BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>(), true),std::string("/Test:9.99.0/"));
1095      BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments, true),std::string("/Test:9.99.0(comment1)/"));
1096      BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2, true),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
1097  }
1098  
1099  BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
1100  {
1101      int64_t amount = 0;
1102      BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
1103      BOOST_CHECK_EQUAL(amount, 0LL);
1104      BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
1105      BOOST_CHECK_EQUAL(amount, 100000000LL);
1106      BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
1107      BOOST_CHECK_EQUAL(amount, 0LL);
1108      BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
1109      BOOST_CHECK_EQUAL(amount, -10000000LL);
1110      BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
1111      BOOST_CHECK_EQUAL(amount, 110000000LL);
1112      BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
1113      BOOST_CHECK_EQUAL(amount, 110000000LL);
1114      BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
1115      BOOST_CHECK_EQUAL(amount, 1100000000LL);
1116      BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
1117      BOOST_CHECK_EQUAL(amount, 11000000LL);
1118      BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
1119      BOOST_CHECK_EQUAL(amount, 100000000000LL);
1120      BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
1121      BOOST_CHECK_EQUAL(amount, -100000000000LL);
1122      BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
1123      BOOST_CHECK_EQUAL(amount, 1LL);
1124      BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
1125      BOOST_CHECK_EQUAL(amount, 1LL);
1126      BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
1127      BOOST_CHECK_EQUAL(amount, -1LL);
1128      BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
1129      BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
1130      BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
1131      BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
1132      BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
1133      BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
1134  
1135      BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
1136      BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
1137      BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
1138      BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
1139      BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
1140      BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
1141      BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
1142      BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
1143      BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
1144      BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
1145      BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
1146      BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
1147      BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
1148      BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
1149      BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
1150      BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
1151      BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
1152      BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
1153      BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
1154      BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
1155      BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
1156      BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
1157      BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
1158      BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
1159      BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
1160      BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
1161      BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
1162  
1163      // Test with 3 decimal places for fee rates in sat/vB.
1164      BOOST_CHECK(ParseFixedPoint("0.001", 3, &amount));
1165      BOOST_CHECK_EQUAL(amount, CAmount{1});
1166      BOOST_CHECK(!ParseFixedPoint("0.0009", 3, &amount));
1167      BOOST_CHECK(!ParseFixedPoint("31.00100001", 3, &amount));
1168      BOOST_CHECK(!ParseFixedPoint("31.0011", 3, &amount));
1169      BOOST_CHECK(!ParseFixedPoint("31.99999999", 3, &amount));
1170      BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));
1171  }
1172  
1173  #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
1174  static constexpr char LockCommand = 'L';
1175  static constexpr char UnlockCommand = 'U';
1176  static constexpr char ExitCommand = 'X';
1177  enum : char {
1178      ResSuccess = 2, // Start with 2 to avoid accidental collision with common values 0 and 1
1179      ResErrorWrite,
1180      ResErrorLock,
1181      ResUnlockSuccess,
1182  };
1183  
1184  [[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)
1185  {
1186      char ch;
1187      while (true) {
1188          int rv = read(fd, &ch, 1); // Wait for command
1189          assert(rv == 1);
1190          switch (ch) {
1191          case LockCommand:
1192              ch = [&] {
1193                  switch (util::LockDirectory(dirname, lockname)) {
1194                  case util::LockResult::Success: return ResSuccess;
1195                  case util::LockResult::ErrorWrite: return ResErrorWrite;
1196                  case util::LockResult::ErrorLock: return ResErrorLock;
1197                  } // no default case, so the compiler can warn about missing cases
1198                  assert(false);
1199              }();
1200              rv = write(fd, &ch, 1);
1201              assert(rv == 1);
1202              break;
1203          case UnlockCommand:
1204              ReleaseDirectoryLocks();
1205              ch = ResUnlockSuccess; // Always succeeds
1206              rv = write(fd, &ch, 1);
1207              assert(rv == 1);
1208              break;
1209          case ExitCommand:
1210              close(fd);
1211              exit(0);
1212          default:
1213              assert(0);
1214          }
1215      }
1216  }
1217  #endif
1218  
1219  BOOST_AUTO_TEST_CASE(test_LockDirectory)
1220  {
1221      fs::path dirname = m_args.GetDataDirBase() / "lock_dir";
1222      const fs::path lockname = ".lock";
1223  #ifndef WIN32
1224      // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
1225      // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
1226      // at build-time of the boost library
1227      void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
1228  
1229      // Fork another process for testing before creating the lock, so that we
1230      // won't fork while holding the lock (which might be undefined, and is not
1231      // relevant as test case as that is avoided with -daemonize).
1232      int fd[2];
1233      BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
1234      pid_t pid = fork();
1235      if (!pid) {
1236          BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
1237          TestOtherProcess(dirname, lockname, fd[0]);
1238      }
1239      BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
1240  
1241      char ch;
1242      // Lock on non-existent directory should fail
1243      BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1244      BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1245      BOOST_CHECK_EQUAL(ch, ResErrorWrite);
1246  #endif
1247      // Lock on non-existent directory should fail
1248      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::ErrorWrite);
1249  
1250      fs::create_directories(dirname);
1251  
1252      // Probing lock on new directory should succeed
1253      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1254  
1255      // Persistent lock on new directory should succeed
1256      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
1257  
1258      // Another lock on the directory from the same thread should succeed
1259      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
1260  
1261      // Another lock on the directory from a different thread within the same process should succeed
1262      util::LockResult threadresult;
1263      std::thread thr([&] { threadresult = util::LockDirectory(dirname, lockname); });
1264      thr.join();
1265      BOOST_CHECK_EQUAL(threadresult, util::LockResult::Success);
1266  #ifndef WIN32
1267      // Try to acquire lock in child process while we're holding it, this should fail.
1268      BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1269      BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1270      BOOST_CHECK_EQUAL(ch, ResErrorLock);
1271  
1272      // Give up our lock
1273      ReleaseDirectoryLocks();
1274      // Probing lock from our side now should succeed, but not hold on to the lock.
1275      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1276  
1277      // Try to acquire the lock in the child process, this should be successful.
1278      BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1279      BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1280      BOOST_CHECK_EQUAL(ch, ResSuccess);
1281  
1282      // When we try to probe the lock now, it should fail.
1283      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::ErrorLock);
1284  
1285      // Unlock the lock in the child process
1286      BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
1287      BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1288      BOOST_CHECK_EQUAL(ch, ResUnlockSuccess);
1289  
1290      // When we try to probe the lock now, it should succeed.
1291      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1292  
1293      // Re-lock the lock in the child process, then wait for it to exit, check
1294      // successful return. After that, we check that exiting the process
1295      // has released the lock as we would expect by probing it.
1296      int processstatus;
1297      BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1298      // The following line invokes the ~CNetCleanup dtor without
1299      // a paired SetupNetworking call. This is acceptable as long as
1300      // ~CNetCleanup is a no-op for non-Windows platforms.
1301      BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
1302      BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
1303      BOOST_CHECK_EQUAL(processstatus, 0);
1304      BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1305  
1306      // Restore SIGCHLD
1307      signal(SIGCHLD, old_handler);
1308      BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
1309  #endif
1310      // Clean up
1311      ReleaseDirectoryLocks();
1312      fs::remove_all(dirname);
1313  }
1314  
1315  BOOST_AUTO_TEST_CASE(test_ToLower)
1316  {
1317      BOOST_CHECK_EQUAL(ToLower('@'), '@');
1318      BOOST_CHECK_EQUAL(ToLower('A'), 'a');
1319      BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
1320      BOOST_CHECK_EQUAL(ToLower('['), '[');
1321      BOOST_CHECK_EQUAL(ToLower(0), 0);
1322      BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
1323  
1324      BOOST_CHECK_EQUAL(ToLower(""), "");
1325      BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
1326      BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
1327  }
1328  
1329  BOOST_AUTO_TEST_CASE(test_ToUpper)
1330  {
1331      BOOST_CHECK_EQUAL(ToUpper('`'), '`');
1332      BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
1333      BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
1334      BOOST_CHECK_EQUAL(ToUpper('{'), '{');
1335      BOOST_CHECK_EQUAL(ToUpper(0), 0);
1336      BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
1337  
1338      BOOST_CHECK_EQUAL(ToUpper(""), "");
1339      BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
1340      BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
1341  }
1342  
1343  BOOST_AUTO_TEST_CASE(test_Capitalize)
1344  {
1345      BOOST_CHECK_EQUAL(Capitalize(""), "");
1346      BOOST_CHECK_EQUAL(Capitalize("limenka"), "Limenka");
1347      BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
1348  }
1349  
1350  static std::string SpanToStr(const Span<const char>& span)
1351  {
1352      return std::string(span.begin(), span.end());
1353  }
1354  
1355  BOOST_AUTO_TEST_CASE(test_script_parsing)
1356  {
1357      using namespace script;
1358      std::string input;
1359      Span<const char> sp;
1360      bool success;
1361  
1362      // Const(...): parse a constant, update span to skip it if successful
1363      input = "MilkToastHoney";
1364      sp = input;
1365      success = Const("", sp); // empty
1366      BOOST_CHECK(success);
1367      BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");
1368  
1369      success = Const("Milk", sp);
1370      BOOST_CHECK(success);
1371      BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");
1372  
1373      success = Const("Bread", sp);
1374      BOOST_CHECK(!success);
1375  
1376      success = Const("Toast", sp);
1377      BOOST_CHECK(success);
1378      BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");
1379  
1380      success = Const("Honeybadger", sp);
1381      BOOST_CHECK(!success);
1382  
1383      success = Const("Honey", sp);
1384      BOOST_CHECK(success);
1385      BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1386  
1387      // Func(...): parse a function call, update span to argument if successful
1388      input = "Foo(Bar(xy,z()))";
1389      sp = input;
1390  
1391      success = Func("FooBar", sp);
1392      BOOST_CHECK(!success);
1393  
1394      success = Func("Foo(", sp);
1395      BOOST_CHECK(!success);
1396  
1397      success = Func("Foo", sp);
1398      BOOST_CHECK(success);
1399      BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");
1400  
1401      success = Func("Bar", sp);
1402      BOOST_CHECK(success);
1403      BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()");
1404  
1405      success = Func("xy", sp);
1406      BOOST_CHECK(!success);
1407  
1408      // Expr(...): return expression that span begins with, update span to skip it
1409      Span<const char> result;
1410  
1411      input = "(n*(n-1))/2";
1412      sp = input;
1413      result = Expr(sp);
1414      BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2");
1415      BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1416  
1417      input = "foo,bar";
1418      sp = input;
1419      result = Expr(sp);
1420      BOOST_CHECK_EQUAL(SpanToStr(result), "foo");
1421      BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar");
1422  
1423      input = "(aaaaa,bbbbb()),c";
1424      sp = input;
1425      result = Expr(sp);
1426      BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())");
1427      BOOST_CHECK_EQUAL(SpanToStr(sp), ",c");
1428  
1429      input = "xyz)foo";
1430      sp = input;
1431      result = Expr(sp);
1432      BOOST_CHECK_EQUAL(SpanToStr(result), "xyz");
1433      BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo");
1434  
1435      input = "((a),(b),(c)),xxx";
1436      sp = input;
1437      result = Expr(sp);
1438      BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))");
1439      BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx");
1440  
1441      // Split(...): split a string on every instance of sep, return vector
1442      std::vector<Span<const char>> results;
1443  
1444      input = "xxx";
1445      results = Split(input, 'x');
1446      BOOST_CHECK_EQUAL(results.size(), 4U);
1447      BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1448      BOOST_CHECK_EQUAL(SpanToStr(results[1]), "");
1449      BOOST_CHECK_EQUAL(SpanToStr(results[2]), "");
1450      BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1451  
1452      input = "one#two#three";
1453      results = Split(input, '-');
1454      BOOST_CHECK_EQUAL(results.size(), 1U);
1455      BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three");
1456  
1457      input = "one#two#three";
1458      results = Split(input, '#');
1459      BOOST_CHECK_EQUAL(results.size(), 3U);
1460      BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one");
1461      BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two");
1462      BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three");
1463  
1464      input = "*foo*bar*";
1465      results = Split(input, '*');
1466      BOOST_CHECK_EQUAL(results.size(), 4U);
1467      BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1468      BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo");
1469      BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar");
1470      BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1471  }
1472  
1473  BOOST_AUTO_TEST_CASE(test_SplitString)
1474  {
1475      // Empty string.
1476      {
1477          std::vector<std::string> result = SplitString("", '-');
1478          BOOST_CHECK_EQUAL(result.size(), 1);
1479          BOOST_CHECK_EQUAL(result[0], "");
1480      }
1481  
1482      // Empty items.
1483      {
1484          std::vector<std::string> result = SplitString("-", '-');
1485          BOOST_CHECK_EQUAL(result.size(), 2);
1486          BOOST_CHECK_EQUAL(result[0], "");
1487          BOOST_CHECK_EQUAL(result[1], "");
1488      }
1489  
1490      // More empty items.
1491      {
1492          std::vector<std::string> result = SplitString("--", '-');
1493          BOOST_CHECK_EQUAL(result.size(), 3);
1494          BOOST_CHECK_EQUAL(result[0], "");
1495          BOOST_CHECK_EQUAL(result[1], "");
1496          BOOST_CHECK_EQUAL(result[2], "");
1497      }
1498  
1499      // Separator is not present.
1500      {
1501          std::vector<std::string> result = SplitString("abc", '-');
1502          BOOST_CHECK_EQUAL(result.size(), 1);
1503          BOOST_CHECK_EQUAL(result[0], "abc");
1504      }
1505  
1506      // Basic behavior.
1507      {
1508          std::vector<std::string> result = SplitString("a-b", '-');
1509          BOOST_CHECK_EQUAL(result.size(), 2);
1510          BOOST_CHECK_EQUAL(result[0], "a");
1511          BOOST_CHECK_EQUAL(result[1], "b");
1512      }
1513  
1514      // Case-sensitivity of the separator.
1515      {
1516          std::vector<std::string> result = SplitString("AAA", 'a');
1517          BOOST_CHECK_EQUAL(result.size(), 1);
1518          BOOST_CHECK_EQUAL(result[0], "AAA");
1519      }
1520  
1521      // multiple split characters
1522      {
1523          using V = std::vector<std::string>;
1524          BOOST_TEST(SplitString("a,b.c:d;e", ",;") == V({"a", "b.c:d", "e"}));
1525          BOOST_TEST(SplitString("a,b.c:d;e", ",;:.") == V({"a", "b", "c", "d", "e"}));
1526          BOOST_TEST(SplitString("a,b.c:d;e", "") == V({"a,b.c:d;e"}));
1527          BOOST_TEST(SplitString("aaa", "bcdefg") == V({"aaa"}));
1528          BOOST_TEST(SplitString("x\0a,b"s, "\0"s) == V({"x", "a,b"}));
1529          BOOST_TEST(SplitString("x\0a,b"s, '\0') == V({"x", "a,b"}));
1530          BOOST_TEST(SplitString("x\0a,b"s, "\0,"s) == V({"x", "a", "b"}));
1531          BOOST_TEST(SplitString("abcdefg", "bcd") == V({"a", "", "", "efg"}));
1532      }
1533  }
1534  
1535  BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
1536  {
1537      // ASCII and UTF-8 must pass through unaltered.
1538      BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
1539      // Newlines must pass through unaltered.
1540      BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
1541      // Other control characters are escaped in C syntax.
1542      BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
1543      // Embedded NULL characters are escaped too.
1544      const std::string NUL("O\x00O", 3);
1545      BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
1546  }
1547  
1548  namespace {
1549  
1550  struct Tracker
1551  {
1552      //! Points to the original object (possibly itself) we moved/copied from
1553      const Tracker* origin;
1554      //! How many copies where involved between the original object and this one (moves are not counted)
1555      int copies{0};
1556  
1557      Tracker() noexcept : origin(this) {}
1558      Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
1559      Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
1560      Tracker& operator=(const Tracker& t) noexcept
1561      {
1562          if (this != &t) {
1563              origin = t.origin;
1564              copies = t.copies + 1;
1565          }
1566          return *this;
1567      }
1568  };
1569  
1570  }
1571  
1572  BOOST_AUTO_TEST_CASE(test_tracked_vector)
1573  {
1574      Tracker t1;
1575      Tracker t2;
1576      Tracker t3;
1577  
1578      BOOST_CHECK(t1.origin == &t1);
1579      BOOST_CHECK(t2.origin == &t2);
1580      BOOST_CHECK(t3.origin == &t3);
1581  
1582      auto v1 = Vector(t1);
1583      BOOST_CHECK_EQUAL(v1.size(), 1U);
1584      BOOST_CHECK(v1[0].origin == &t1);
1585      BOOST_CHECK_EQUAL(v1[0].copies, 1);
1586  
1587      auto v2 = Vector(std::move(t2));
1588      BOOST_CHECK_EQUAL(v2.size(), 1U);
1589      BOOST_CHECK(v2[0].origin == &t2); // NOLINT(*-use-after-move)
1590      BOOST_CHECK_EQUAL(v2[0].copies, 0);
1591  
1592      auto v3 = Vector(t1, std::move(t2));
1593      BOOST_CHECK_EQUAL(v3.size(), 2U);
1594      BOOST_CHECK(v3[0].origin == &t1);
1595      BOOST_CHECK(v3[1].origin == &t2); // NOLINT(*-use-after-move)
1596      BOOST_CHECK_EQUAL(v3[0].copies, 1);
1597      BOOST_CHECK_EQUAL(v3[1].copies, 0);
1598  
1599      auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
1600      BOOST_CHECK_EQUAL(v4.size(), 3U);
1601      BOOST_CHECK(v4[0].origin == &t1);
1602      BOOST_CHECK(v4[1].origin == &t2);
1603      BOOST_CHECK(v4[2].origin == &t3); // NOLINT(*-use-after-move)
1604      BOOST_CHECK_EQUAL(v4[0].copies, 1);
1605      BOOST_CHECK_EQUAL(v4[1].copies, 1);
1606      BOOST_CHECK_EQUAL(v4[2].copies, 0);
1607  
1608      auto v5 = Cat(v1, v4);
1609      BOOST_CHECK_EQUAL(v5.size(), 4U);
1610      BOOST_CHECK(v5[0].origin == &t1);
1611      BOOST_CHECK(v5[1].origin == &t1);
1612      BOOST_CHECK(v5[2].origin == &t2);
1613      BOOST_CHECK(v5[3].origin == &t3);
1614      BOOST_CHECK_EQUAL(v5[0].copies, 2);
1615      BOOST_CHECK_EQUAL(v5[1].copies, 2);
1616      BOOST_CHECK_EQUAL(v5[2].copies, 2);
1617      BOOST_CHECK_EQUAL(v5[3].copies, 1);
1618  
1619      auto v6 = Cat(std::move(v1), v3);
1620      BOOST_CHECK_EQUAL(v6.size(), 3U);
1621      BOOST_CHECK(v6[0].origin == &t1);
1622      BOOST_CHECK(v6[1].origin == &t1);
1623      BOOST_CHECK(v6[2].origin == &t2);
1624      BOOST_CHECK_EQUAL(v6[0].copies, 1);
1625      BOOST_CHECK_EQUAL(v6[1].copies, 2);
1626      BOOST_CHECK_EQUAL(v6[2].copies, 1);
1627  
1628      auto v7 = Cat(v2, std::move(v4));
1629      BOOST_CHECK_EQUAL(v7.size(), 4U);
1630      BOOST_CHECK(v7[0].origin == &t2);
1631      BOOST_CHECK(v7[1].origin == &t1);
1632      BOOST_CHECK(v7[2].origin == &t2);
1633      BOOST_CHECK(v7[3].origin == &t3);
1634      BOOST_CHECK_EQUAL(v7[0].copies, 1);
1635      BOOST_CHECK_EQUAL(v7[1].copies, 1);
1636      BOOST_CHECK_EQUAL(v7[2].copies, 1);
1637      BOOST_CHECK_EQUAL(v7[3].copies, 0);
1638  
1639      auto v8 = Cat(std::move(v2), std::move(v3));
1640      BOOST_CHECK_EQUAL(v8.size(), 3U);
1641      BOOST_CHECK(v8[0].origin == &t2);
1642      BOOST_CHECK(v8[1].origin == &t1);
1643      BOOST_CHECK(v8[2].origin == &t2);
1644      BOOST_CHECK_EQUAL(v8[0].copies, 0);
1645      BOOST_CHECK_EQUAL(v8[1].copies, 1);
1646      BOOST_CHECK_EQUAL(v8[2].copies, 0);
1647  }
1648  
1649  BOOST_AUTO_TEST_CASE(message_sign)
1650  {
1651      const std::array<unsigned char, 32> privkey_bytes = {
1652          // just some random data
1653          // derived address from this private key: 15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs
1654          0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
1655          0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
1656          0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
1657          0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
1658      };
1659  
1660      const std::string message = "Trust no one";
1661  
1662      const std::string expected_signature =
1663          "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=";
1664  
1665      CKey privkey;
1666      std::string generated_signature;
1667  
1668      BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
1669          "Confirm the private key is invalid");
1670  
1671      BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
1672          "Sign with an invalid private key");
1673  
1674      privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
1675  
1676      BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
1677          "Confirm the private key is valid");
1678  
1679      BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
1680          "Sign with a valid private key");
1681  
1682      BOOST_CHECK_EQUAL(expected_signature, generated_signature);
1683  
1684      // BIP-322 tests
1685      // (no signing done here, as we need a wallet to do so)
1686  
1687      auto pubkey = privkey.GetPubKey();
1688      MessageVerificationResult mvr{MessageVerificationResult::OK};
1689  
1690      // LEGACY pubkey type
1691      auto dest_legacy = GetDestinationForKey(pubkey, OutputType::LEGACY);
1692      BOOST_CHECK_EQUAL("15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs", EncodeDestination(dest_legacy));
1693      auto txs_legacy = BIP322Txs::Create(dest_legacy, message, mvr);
1694      if (!txs_legacy || mvr != MessageVerificationResult::OK) {
1695          BOOST_FAIL("Failed to create BIP-322 txs for legacy address");
1696      }
1697  
1698      // P2SH_SEGWIT pubkey type
1699      auto dest_p2sh_segwit = GetDestinationForKey(pubkey, OutputType::P2SH_SEGWIT);
1700      BOOST_CHECK_EQUAL("35uijJkf4rcCnGzEZsn12YJenTHToDKpr2", EncodeDestination(dest_p2sh_segwit));
1701      auto txs_p2sh_segwit = BIP322Txs::Create(dest_p2sh_segwit, message, mvr);
1702      if (!txs_p2sh_segwit || mvr != MessageVerificationResult::OK) {
1703          BOOST_FAIL("Failed to create BIP-322 txs for p2sh-segwit address");
1704      }
1705  
1706      // BECH32
1707      auto dest_bech32 = GetDestinationForKey(pubkey, OutputType::BECH32);
1708      BOOST_CHECK_EQUAL("bc1q9cy7s7nmzah0m6mt2ftmu6x723esjxqkkl4wsw", EncodeDestination(dest_bech32));
1709      auto txs_bech32 = BIP322Txs::Create(dest_bech32, message, mvr);
1710      if (!txs_bech32 || mvr != MessageVerificationResult::OK) {
1711          BOOST_FAIL("Failed to create BIP-322 txs for bech32 address");
1712      }
1713  
1714      // TODO: BECH32M
1715  }
1716  
1717  BOOST_AUTO_TEST_CASE(message_verify)
1718  {
1719      BOOST_CHECK_EQUAL(
1720          MessageVerify(
1721              "invalid address",
1722              "AA==",
1723              "message too"),
1724          MessageVerificationResult::ERR_INVALID_ADDRESS);
1725  
1726      BOOST_CHECK_EQUAL(
1727          MessageVerify(
1728              "3B5fQsEXEaV8v6U3ejYc8XaKXAkyQj2MjV",
1729              "AA==",
1730              "message too"),
1731          MessageVerificationResult::ERR_INVALID /* ERR_ADDRESS_NO_KEY */);
1732  
1733      BOOST_CHECK_EQUAL(
1734          MessageVerify(
1735              "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
1736              "invalid signature, not in base64 encoding",
1737              "message should be irrelevant"),
1738          MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
1739  
1740      BOOST_CHECK_EQUAL(
1741          MessageVerify(
1742              "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
1743              "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1744              "message should be irrelevant"),
1745          MessageVerificationResult::ERR_INVALID /* ERR_PUBKEY_NOT_RECOVERED */);
1746  
1747      BOOST_CHECK_EQUAL(
1748          MessageVerify(
1749              "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
1750              "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
1751              "I never signed this"),
1752          MessageVerificationResult::ERR_NOT_SIGNED);
1753  
1754      BOOST_CHECK_EQUAL(
1755          MessageVerify(
1756              "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
1757              "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
1758              "Trust no one"),
1759          MessageVerificationResult::OK);
1760  
1761      BOOST_CHECK_EQUAL(
1762          MessageVerify(
1763              "11canuhp9X2NocwCq7xNrQYTmUgZAnLK3",
1764              "IIcaIENoYW5jZWxsb3Igb24gYnJpbmsgb2Ygc2Vjb25kIGJhaWxvdXQgZm9yIGJhbmtzIAaHRtbCeDZINyavx14=",
1765              "Trust me"),
1766          MessageVerificationResult::OK);
1767  
1768      // BIP-322 tests
1769  
1770      // privkey: L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k
1771  
1772      BOOST_CHECK_EQUAL(
1773          MessageVerify(
1774              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1775              "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1776              ""),
1777          MessageVerificationResult::OK);
1778  
1779      BOOST_CHECK_EQUAL(
1780          MessageVerify(
1781              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1782              "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1783              "Hello World"),
1784          MessageVerificationResult::OK);
1785  
1786      // BIP322 signature created using buidl-python library with same parameters as test on line 2596
1787      BOOST_CHECK_EQUAL(
1788          MessageVerify(
1789              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1790           "AkgwRQIhAOzyynlqt93lOKJr+wmmxIens//zPzl9tqIOua93wO6MAiBi5n5EyAcPScOjf1lAqIUIQtr3zKNeavYabHyR8eGhowEhAsfxIAMZZEKUPYWI4BruhAQjzFT8FSFSajuFwrDL1Yhy",
1791              "Hello World"),
1792          MessageVerificationResult::OK);
1793  
1794      // 2-of-3 p2sh multisig BIP322 signature (created with the buidl-python library)
1795      // Keys are defined as (HDRootWIF, bip322_path)
1796      // Key1 (L4DksdGZ4KQJfcLHD5Dv25fu8Rxyv7hHi2RjZR4TYzr8c6h9VNrp, m/45'/0/0/1)
1797      // Key2 (KzSRqnCVwjzY8id2X5oHEJWXkSHwKUYaAXusjwgkES8BuQPJnPNu, m/45'/0/0/3)
1798      // Key3 (L1zt9Rw7HrU7jaguMbVzhiX8ffuVkmMis5wLHddXYuHWYf8u8uRj, m/45'/0/0/6)
1799      // BIP322 includes signs from Key2 and Key3
1800      BOOST_CHECK_EQUAL(
1801          MessageVerify(
1802              "3LnYoUkFrhyYP3V7rq3mhpwALz1XbCY9Uq",
1803           "AAAAAAHNcfHaNfl8f/+ZC2gTr8aF+0KgppYjKM94egaNm/u1ZAAAAAD8AEcwRAIhAJ6hdj61vLDP+aFa30qUZQmrbBfE0kiOObYvt5nqPSxsAh9IrOKFwflfPRUcQ/5e0REkdFHVP2GGdUsMgDet+sNlAUcwRAIgH3eW/VyFDoXvCasd8qxgwj5NDVo0weXvM6qyGXLCR5YCIEwjbEV6fS6RWP6QsKOcMwvlGr1/SgdCC6pW4eH87/YgAUxpUiECKJfGy28imLcuAeNBLHCNv3NRP5jnJwFDNRXCYNY/vJ4hAv1RQtaZs7+vKqQeWl2rb/jd/gMxkEjUnjZdDGPDZkMLIQL65cH2X5O7LujjTLDL2l8Pxy0Y2UUR99u1qCfjdz7dklOuAAAAAAEAAAAAAAAAAAFqAAAAAA==",
1804              "This will be a p2sh 2-of-3 multisig BIP 322 signed message"),
1805          MessageVerificationResult::OK);
1806  
1807      // 3-of-3 p2wsh multisig BIP322 signature (created with the buidl-python library)
1808      // Keys are defined as (HDRootWIF, bip322_path)
1809      // Key1 (L4DksdGZ4KQJfcLHD5Dv25fu8Rxyv7hHi2RjZR4TYzr8c6h9VNrp, m/45'/0/0/6)
1810      // Key2 (KzSRqnCVwjzY8id2X5oHEJWXkSHwKUYaAXusjwgkES8BuQPJnPNu, m/45'/0/0/9)
1811      // Key3 (L1zt9Rw7HrU7jaguMbVzhiX8ffuVkmMis5wLHddXYuHWYf8u8uRj, m/45'/0/0/11)
1812      BOOST_CHECK_EQUAL(
1813          MessageVerify(
1814              "bc1qlqtuzpmazp2xmcutlwv0qvggdvem8vahkc333usey4gskug8nutsz53msw",    "BQBIMEUCIQDQoXvGKLH58exuujBOta+7+GN7vi0lKwiQxzBpuNuXuAIgIE0XYQlFDOfxbegGYYzlf+tqegleAKE6SXYIa1U+uCcBRzBEAiATegywVl6GWrG9jJuPpNwtgHKyVYCX2yfuSSDRFATAaQIgTLlU6reLQsSIrQSF21z3PtUO2yAUseUWGZqRUIE7VKoBSDBFAiEAgxtpidsU0Z4u/+5RB9cyeQtoCW5NcreLJmWXZ8kXCZMCIBR1sXoEinhZE4CF9P9STGIcMvCuZjY6F5F0XTVLj9SjAWlTIQP3dyWvTZjUENWJowMWBsQrrXCUs20Gu5YF79CG5Ga0XSEDwqI5GVBOuFkFzQOGH5eTExSAj2Z/LDV/hbcvAPQdlJMhA17FuuJd+4wGuj+ZbVxEsFapTKAOwyhfw9qpch52JKxbU64=",
1815              "This will be a p2wsh 3-of-3 multisig BIP 322 signed message"),
1816          MessageVerificationResult::OK);
1817  
1818      // Single key p2tr BIP322 signature (created with the buidl-python library)
1819      // PrivateKeyWIF L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k
1820      BOOST_CHECK_EQUAL(
1821          MessageVerify(
1822              "bc1ppv609nr0vr25u07u95waq5lucwfm6tde4nydujnu8npg4q75mr5sxq8lt3",
1823              "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==",
1824              "Hello World"),
1825          MessageVerificationResult::OK);
1826  
1827      // Same p2tr BIP322 signature as above (created with the buidl-python library)
1828      // Signature should not verify against the message
1829      BOOST_CHECK_EQUAL(
1830          MessageVerify(
1831              "bc1ppv609nr0vr25u07u95waq5lucwfm6tde4nydujnu8npg4q75mr5sxq8lt3",
1832              "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==",
1833              "Hello World - This should fail"),
1834          MessageVerificationResult::ERR_INVALID);
1835  
1836      // wrong address
1837  
1838      BOOST_CHECK_EQUAL(
1839          MessageVerify(
1840              "bc1qkecg9ly2xwxqgdy9egpuy87qc9x26smpts562s",
1841              "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1842              ""),
1843          MessageVerificationResult::ERR_INVALID);
1844  
1845      BOOST_CHECK_EQUAL(
1846          MessageVerify(
1847              "bc1qkecg9ly2xwxqgdy9egpuy87qc9x26smpts562s",
1848              "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1849              "Hello World"),
1850          MessageVerificationResult::ERR_INVALID);
1851  
1852      // wrong signature / message (signatures swapped)
1853  
1854      BOOST_CHECK_EQUAL(
1855          MessageVerify(
1856              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1857              "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1858              ""),
1859          MessageVerificationResult::ERR_INVALID);
1860  
1861      BOOST_CHECK_EQUAL(
1862          MessageVerify(
1863              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1864              "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1865              "Hello World"),
1866          MessageVerificationResult::ERR_INVALID);
1867  
1868      // invalid address
1869  
1870      BOOST_CHECK_EQUAL(
1871          MessageVerify(
1872              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx1l",
1873              "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1874              ""),
1875          MessageVerificationResult::ERR_INVALID_ADDRESS);
1876  
1877      // malformed signature
1878  
1879      BOOST_CHECK_EQUAL(
1880          MessageVerify(
1881              "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1882              "AkcwRAIgClVQ8S9yX1h8YThlGElD9lOrQbOwbFDjkYb0ebfiq+oCIDHgb/X9WNalNNtqTXb465ufbv9JuLxcJf8qi7DP6yOXASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI",
1883              ""),
1884          MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
1885  }
1886  
1887  BOOST_AUTO_TEST_CASE(message_hash)
1888  {
1889      const std::string unsigned_tx = "...";
1890      const std::string prefixed_message =
1891          std::string(1, (char)MESSAGE_MAGIC.length()) +
1892          MESSAGE_MAGIC +
1893          std::string(1, (char)unsigned_tx.length()) +
1894          unsigned_tx;
1895  
1896      const uint256 signature_hash = Hash(unsigned_tx);
1897      const uint256 message_hash1 = Hash(prefixed_message);
1898      const uint256 message_hash2 = MessageHash(unsigned_tx, MessageSignatureFormat::LEGACY);
1899  
1900      BOOST_CHECK_EQUAL(message_hash1, message_hash2);
1901      BOOST_CHECK_NE(message_hash1, signature_hash);
1902  
1903      // BIP-322 tests
1904  
1905      const uint256 signature_hash_0x = MessageHash("", MessageSignatureFormat::FULL);
1906      const uint256 signature_hash_Hello_World = MessageHash("Hello World", MessageSignatureFormat::FULL);
1907  
1908      std::vector<unsigned char> vec(signature_hash_0x.begin(), signature_hash_0x.end());
1909      BOOST_CHECK_EQUAL("c90c269c4f8fcbe6880f72a721ddfbf1914268a794cbb21cfafee13770ae19f1", HexStr(vec));
1910      vec = std::vector<unsigned char>(signature_hash_Hello_World.begin(), signature_hash_Hello_World.end());
1911      BOOST_CHECK_EQUAL("f0eb03b1a75ac6d9847f55c624a99169b5dccba2a31f5b23bea77ba270de0a7a", HexStr(vec));
1912  }
1913  
1914  BOOST_AUTO_TEST_CASE(remove_prefix)
1915  {
1916      BOOST_CHECK_EQUAL(RemovePrefix("./common/system.h", "./"), "common/system.h");
1917      BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), "");
1918      BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o");
1919      BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo");
1920      BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo");
1921      BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo");
1922      BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f");
1923      BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), "");
1924      BOOST_CHECK_EQUAL(RemovePrefix("", ""), "");
1925  }
1926  
1927  BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
1928  {
1929      auto noop = ByteUnit::NOOP;
1930  
1931      // no multiplier
1932      BOOST_CHECK_EQUAL(ParseByteUnits("1", noop).value(), 1);
1933      BOOST_CHECK_EQUAL(ParseByteUnits("0", noop).value(), 0);
1934  
1935      BOOST_CHECK_EQUAL(ParseByteUnits("1k", noop).value(), 1000ULL);
1936      BOOST_CHECK_EQUAL(ParseByteUnits("1K", noop).value(), 1ULL << 10);
1937  
1938      BOOST_CHECK_EQUAL(ParseByteUnits("2m", noop).value(), 2'000'000ULL);
1939      BOOST_CHECK_EQUAL(ParseByteUnits("2M", noop).value(), 2ULL << 20);
1940  
1941      BOOST_CHECK_EQUAL(ParseByteUnits("3g", noop).value(), 3'000'000'000ULL);
1942      BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3ULL << 30);
1943  
1944      BOOST_CHECK_EQUAL(ParseByteUnits("4t", noop).value(), 4'000'000'000'000ULL);
1945      BOOST_CHECK_EQUAL(ParseByteUnits("4T", noop).value(), 4ULL << 40);
1946  
1947      // check default multiplier
1948      BOOST_CHECK_EQUAL(ParseByteUnits("5", ByteUnit::K).value(), 5ULL << 10);
1949  
1950      // NaN
1951      BOOST_CHECK(!ParseByteUnits("", noop));
1952      BOOST_CHECK(!ParseByteUnits("foo", noop));
1953  
1954      // whitespace
1955      BOOST_CHECK(!ParseByteUnits("123m ", noop));
1956      BOOST_CHECK(!ParseByteUnits(" 123m", noop));
1957  
1958      // no +-
1959      BOOST_CHECK(!ParseByteUnits("-123m", noop));
1960      BOOST_CHECK(!ParseByteUnits("+123m", noop));
1961  
1962      // zero padding
1963      BOOST_CHECK_EQUAL(ParseByteUnits("020M", noop).value(), 20ULL << 20);
1964  
1965      // fractions not allowed
1966      BOOST_CHECK(!ParseByteUnits("0.5T", noop));
1967  
1968      // overflow
1969      BOOST_CHECK(!ParseByteUnits("18446744073709551615g", noop));
1970  
1971      // invalid unit
1972      BOOST_CHECK(!ParseByteUnits("1x", noop));
1973  }
1974  
1975  BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
1976  {
1977      fs::path tmpfolder = m_args.GetDataDirBase();
1978      fs::path tmpfile = tmpfolder / "read_binary.dat";
1979      std::string expected_text;
1980      for (int i = 0; i < 30; i++) {
1981          expected_text += "0123456789";
1982      }
1983      {
1984          std::ofstream file{tmpfile};
1985          file << expected_text;
1986      }
1987      {
1988          // read all contents in file
1989          auto [valid, text] = ReadBinaryFile(tmpfile);
1990          BOOST_CHECK(valid);
1991          BOOST_CHECK_EQUAL(text, expected_text);
1992      }
1993      {
1994          // read half contents in file
1995          auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
1996          BOOST_CHECK(valid);
1997          BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
1998      }
1999      {
2000          // read from non-existent file
2001          fs::path invalid_file = tmpfolder / "invalid_binary.dat";
2002          auto [valid, text] = ReadBinaryFile(invalid_file);
2003          BOOST_CHECK(!valid);
2004          BOOST_CHECK(text.empty());
2005      }
2006  }
2007  
2008  BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
2009  {
2010      fs::path tmpfolder = m_args.GetDataDirBase();
2011      fs::path tmpfile = tmpfolder / "write_binary.dat";
2012      std::string expected_text = "limenka";
2013      auto valid = WriteBinaryFile(tmpfile, expected_text);
2014      std::string actual_text;
2015      std::ifstream file{tmpfile};
2016      file >> actual_text;
2017      BOOST_CHECK(valid);
2018      BOOST_CHECK_EQUAL(actual_text, expected_text);
2019  }
2020  
2021  BOOST_AUTO_TEST_CASE(clearshrink_test)
2022  {
2023      {
2024          std::vector<uint8_t> v = {1, 2, 3};
2025          ClearShrink(v);
2026          BOOST_CHECK_EQUAL(v.size(), 0);
2027          BOOST_CHECK_EQUAL(v.capacity(), 0);
2028      }
2029  
2030      {
2031          std::vector<bool> v = {false, true, false, false, true, true};
2032          ClearShrink(v);
2033          BOOST_CHECK_EQUAL(v.size(), 0);
2034          BOOST_CHECK_EQUAL(v.capacity(), 0);
2035      }
2036  
2037      {
2038          std::deque<int> v = {1, 3, 3, 7};
2039          ClearShrink(v);
2040          BOOST_CHECK_EQUAL(v.size(), 0);
2041          // std::deque has no capacity() we can observe.
2042      }
2043  }
2044  
2045  template <typename T>
2046  void TestCheckedLeftShift()
2047  {
2048      constexpr auto MAX{std::numeric_limits<T>::max()};
2049  
2050      // Basic operations
2051      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(0, 1), 0);
2052      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(0, 127), 0);
2053      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(1, 1), 2);
2054      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(2, 2), 8);
2055      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(MAX >> 1, 1), MAX - 1);
2056  
2057      // Max left shift
2058      BOOST_CHECK_EQUAL(CheckedLeftShift<T>(1, std::numeric_limits<T>::digits - 1), MAX / 2 + 1);
2059  
2060      // Overflow cases
2061      BOOST_CHECK(!CheckedLeftShift<T>((MAX >> 1) + 1, 1));
2062      BOOST_CHECK(!CheckedLeftShift<T>(MAX, 1));
2063      BOOST_CHECK(!CheckedLeftShift<T>(1, std::numeric_limits<T>::digits));
2064      BOOST_CHECK(!CheckedLeftShift<T>(1, std::numeric_limits<T>::digits + 1));
2065  
2066      if constexpr (std::is_signed_v<T>) {
2067          constexpr auto MIN{std::numeric_limits<T>::min()};
2068          // Negative input
2069          BOOST_CHECK_EQUAL(CheckedLeftShift<T>(-1, 1), -2);
2070          BOOST_CHECK_EQUAL(CheckedLeftShift<T>((MIN >> 2), 1), MIN / 2);
2071          BOOST_CHECK_EQUAL(CheckedLeftShift<T>((MIN >> 1) + 1, 1), MIN + 2);
2072          BOOST_CHECK_EQUAL(CheckedLeftShift<T>(MIN >> 1, 1), MIN);
2073          // Overflow negative
2074          BOOST_CHECK(!CheckedLeftShift<T>((MIN >> 1) - 1, 1));
2075          BOOST_CHECK(!CheckedLeftShift<T>(MIN >> 1, 2));
2076          BOOST_CHECK(!CheckedLeftShift<T>(-1, 100));
2077      }
2078  }
2079  
2080  template <typename T>
2081  void TestSaturatingLeftShift()
2082  {
2083      constexpr auto MAX{std::numeric_limits<T>::max()};
2084  
2085      // Basic operations
2086      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(0, 1), 0);
2087      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(0, 127), 0);
2088      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, 1), 2);
2089      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(2, 2), 8);
2090      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MAX >> 1, 1), MAX - 1);
2091  
2092      // Max left shift
2093      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits - 1), MAX / 2 + 1);
2094  
2095      // Saturation cases
2096      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MAX >> 1) + 1, 1), MAX);
2097      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MAX, 1), MAX);
2098      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits), MAX);
2099      BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits + 1), MAX);
2100  
2101      if constexpr (std::is_signed_v<T>) {
2102          constexpr auto MIN{std::numeric_limits<T>::min()};
2103          // Negative input
2104          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(-1, 1), -2);
2105          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 2), 1), MIN / 2);
2106          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 1) + 1, 1), MIN + 2);
2107          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MIN >> 1, 1), MIN);
2108          // Saturation negative
2109          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 1) - 1, 1), MIN);
2110          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MIN >> 1, 2), MIN);
2111          BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(-1, 100), MIN);
2112      }
2113  }
2114  
2115  BOOST_AUTO_TEST_CASE(checked_left_shift_test)
2116  {
2117      TestCheckedLeftShift<uint8_t>();
2118      TestCheckedLeftShift<int8_t>();
2119      TestCheckedLeftShift<size_t>();
2120      TestCheckedLeftShift<uint64_t>();
2121      TestCheckedLeftShift<int64_t>();
2122  }
2123  
2124  BOOST_AUTO_TEST_CASE(saturating_left_shift_test)
2125  {
2126      TestSaturatingLeftShift<uint8_t>();
2127      TestSaturatingLeftShift<int8_t>();
2128      TestSaturatingLeftShift<size_t>();
2129      TestSaturatingLeftShift<uint64_t>();
2130      TestSaturatingLeftShift<int64_t>();
2131  }
2132  
2133  template <class Int, auto bytes>
2134  concept BraceInitializesTo = requires { Int{bytes}; };
2135  
2136  BOOST_AUTO_TEST_CASE(mib_string_literal_test)
2137  {
2138      // Basic equivalences and simple arithmetic operations
2139      BOOST_CHECK_EQUAL(0_MiB, 0);
2140      BOOST_CHECK_EQUAL(1_MiB, 1 << 20);
2141      BOOST_CHECK_EQUAL(1_MiB, 1024 * 1024);
2142      BOOST_CHECK_EQUAL(1_MiB, 0x100000U);
2143      BOOST_CHECK_EQUAL(1_MiB, 1048576U);
2144      BOOST_CHECK_EQUAL(2ULL * 1_MiB, 2ULL << 20);
2145      BOOST_CHECK_EQUAL((3_MiB + 123) / double(1_MiB), (3_MiB + 123) / 1024.0 / 1024.0);
2146  
2147      // Specific codebase values
2148      BOOST_CHECK_EQUAL(4_MiB, 1 << 22);
2149      BOOST_CHECK_EQUAL(8_MiB, 1 << 23);
2150      BOOST_CHECK_EQUAL(16_MiB, 0x1000000U);
2151      BOOST_CHECK_EQUAL(16_MiB, 1 << 24);
2152      BOOST_CHECK_EQUAL(32_MiB, 0x2000000U);
2153      BOOST_CHECK_EQUAL(32_MiB, 32U << 20);
2154      BOOST_CHECK_EQUAL(50_MiB / 1_MiB, 50U);
2155      BOOST_CHECK_EQUAL(50_MiB, 52428800U);
2156      BOOST_CHECK_EQUAL(128_MiB, 0x8000000U);
2157      BOOST_CHECK_EQUAL(550_MiB, 550ULL * 1024 * 1024);
2158  
2159      // 4095 MiB fits in uint32_t bytes. 4096 MiB requires the uint64_t return type.
2160      static_assert(BraceInitializesTo<uint32_t, 4095_MiB>);
2161      static_assert(!BraceInitializesTo<uint32_t, 4096_MiB>);
2162      static_assert(BraceInitializesTo<uint64_t, 4096_MiB>);
2163      BOOST_CHECK_EQUAL(4095_MiB, uint32_t{4095} << 20);
2164      BOOST_CHECK_EQUAL(4096_MiB, uint64_t{4096} << 20);
2165  }
2166  
2167  BOOST_AUTO_TEST_CASE(gib_string_literal_test)
2168  {
2169      // Basic equivalences and simple arithmetic operations
2170      BOOST_CHECK_EQUAL(0_GiB, 0);
2171      BOOST_CHECK_EQUAL(1_GiB, 1 << 30);
2172      BOOST_CHECK_EQUAL(1_GiB, 1024 * 1024 * 1024);
2173      BOOST_CHECK_EQUAL(1_GiB, 0x40000000U);
2174      BOOST_CHECK_EQUAL(1_GiB, 1073741824U);
2175      BOOST_CHECK_EQUAL(1_GiB, 1_MiB * 1024);
2176      BOOST_CHECK_EQUAL(1_GiB, 1024_MiB);
2177      BOOST_CHECK_EQUAL((1_GiB + 123) / double(1_GiB), (1_GiB + 123) / 1024.0 / 1024.0 / 1024.0);
2178      BOOST_CHECK_EQUAL(2ULL * 1_GiB, 2ULL << 30);
2179      BOOST_CHECK_EQUAL(4 * uint64_t{1_GiB}, uint64_t{4} << 30);
2180      BOOST_CHECK_EQUAL(2_GiB, 2048_MiB);
2181      BOOST_CHECK_EQUAL(3_GiB / 1_GiB, 3U);
2182      BOOST_CHECK_EQUAL(3_GiB, 3U << 30);
2183  
2184      // 3 GiB fits in uint32_t bytes. 4 GiB requires the uint64_t return type.
2185      static_assert(BraceInitializesTo<uint32_t, 3_GiB>);
2186      static_assert(!BraceInitializesTo<uint32_t, 4_GiB>);
2187      static_assert(BraceInitializesTo<uint64_t, 4_GiB>);
2188      BOOST_CHECK_EQUAL(3_GiB, uint32_t{3} << 30);
2189      BOOST_CHECK_EQUAL(4_GiB, uint64_t{4} << 30);
2190  
2191      // Specific codebase values
2192      BOOST_CHECK_EQUAL(4_GiB, 4096_MiB);
2193      BOOST_CHECK_EQUAL(8_GiB, 8192_MiB);
2194      BOOST_CHECK_EQUAL(16_GiB, 16384_MiB);
2195      BOOST_CHECK_EQUAL(32_GiB, 32768_MiB);
2196  }
2197  
2198  BOOST_AUTO_TEST_CASE(is_space_byte_range_test)
2199  {
2200      std::vector expected(256, false);
2201      for (auto c : std::string_view(" \f\n\r\t\v")) expected[c] = true;
2202  
2203      for (auto i{0U}; i < expected.size(); ++i) {
2204          auto c = static_cast<char>(i);
2205          BOOST_CHECK_MESSAGE(IsSpace(c) == expected[i], "IsSpace test failed for char value: " << i);
2206      }
2207  }
2208  
2209  static std::string CheckModifyRWConfigFile(std::map<std::string, std::string>& settings_to_change, const std::string& current_config_file)
2210  {
2211      std::istringstream stream_in(current_config_file);
2212      std::ostringstream stream_out;
2213      try {
2214          ModifyRWConfigStream(stream_in, stream_out, settings_to_change);
2215      } catch (...) {
2216          settings_to_change.clear();
2217          throw;
2218      }
2219      settings_to_change.clear();
2220      return stream_out.str();
2221  }
2222  
2223  BOOST_AUTO_TEST_CASE(test_ModifyRWConfigFile)
2224  {
2225      std::map<std::string, std::string> cs;
2226  
2227      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b"), "a=b");
2228  
2229      cs["a"] = "c";
2230      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b"), "a=c");
2231      BOOST_CHECK(cs.empty());
2232  
2233      // Multi-char name/value
2234      cs["ab"] = "cd";
2235      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "ab=bc"), "ab=cd");
2236  
2237      // Preserved final newline
2238      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n"), "a=b\n");
2239      cs["a"] = "c";
2240      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n"), "a=c\n");
2241  
2242      // Preserved final tab
2243      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t"), "a=b\t");
2244      cs["a"] = "c";
2245      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t"), "a=c\t");
2246  
2247      // Preserved final space
2248      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b "), "a=b ");
2249      cs["a"] = "c";
2250      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b "), "a=c ");
2251  
2252      // Preserved final crnl
2253      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\r\n"), "a=b\r\n");
2254      cs["a"] = "c";
2255      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\r\n"), "a=c\r\n");
2256  
2257      // Empty file
2258      cs["a"] = "c";
2259      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, ""), "a=c\n");
2260  
2261      // Ignore k=v in comment
2262      cs["a"] = "c";
2263      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "#a=b"), "#a=b\na=c\n");
2264  
2265      // Preserved comment
2266      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t# c"), "a=b\t# c");
2267  
2268      // Commented out commented value
2269      cs["a"] = "c";
2270      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t# c"), "a=c\n#a=b\t# c");
2271  
2272      // Preserved whitespace before name
2273      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, " \t \ta=b"), " \t \ta=b");
2274      cs["a"] = "c";
2275      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, " \t \ta=b"), " \t \ta=c");
2276  
2277      // Preserved whitespace after name
2278      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a \t \t=b"), "a \t \t=b");
2279      cs["a"] = "c";
2280      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a \t \t=b"), "a \t \t=c");
2281  
2282      // Preserved whitespace before value
2283      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a= \t \tb"), "a= \t \tb");
2284      cs["a"] = "c";
2285      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a= \t \tb"), "a= \t \tc");
2286  
2287      // Modifying value between others
2288      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=bc\nd=e");
2289      cs["ab"] = "x";
2290      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=x\nd=e");
2291  
2292      // Blank key/value
2293      cs["ab"] = "";
2294      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=\nd=e");
2295      cs[""] = "x";
2296      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=bc\nd=e\n=x\n");
2297  
2298      // Blank line in source
2299      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\nab=bc\n\nd=e"), "a=b\n\nab=bc\n\nd=e");
2300      cs["ab"] = "x";
2301      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\nab=bc\n\nd=e"), "a=b\n\nab=x\n\nd=e");
2302  
2303      // Duplicate keys in the source
2304      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nf=x\nab=zx\nd=e"), "a=b\nab=bc\nf=x\nab=zx\nd=e");
2305      cs["ab"] = "x";
2306      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nf=x\nab=zx\nd=e"), "a=b\nab=x\nf=x\nab=zx\nd=e");
2307  
2308      // Comment out entire file if invalid input line
2309      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e"), "[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e");
2310      cs["ab"] = "x";
2311      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e"), "ab=x\n[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e");
2312      cs["ab"] = "x";
2313      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e\n"), "ab=x\n[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e\n");
2314  
2315      // Whitespace inside values
2316      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=b\t \t c\nd=e"), "a=b\nab=b\t \t c\nd=e");
2317      cs["ab"] = "x \t \tx";
2318      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=b\t \t c\nd=e"), "a=b\nab=x \t \tx\nd=e");
2319  
2320      // Newline inside name/value
2321      cs["a"] = "x\nx";
2322      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2323      cs["a"] = "x\rx";
2324      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2325      cs["a\nb"] = "x";
2326      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2327      cs["a\rb"] = "x";
2328      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2329  
2330      // Whitespace leading/trailing name/value
2331      cs["a"] = " x";
2332      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2333      cs["a"] = "\tx";
2334      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2335      cs[" a"] = "x";
2336      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2337      cs["\ta"] = "x";
2338      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2339      cs["a"] = "x ";
2340      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2341      cs["a"] = "x\t";
2342      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2343      cs["a "] = "x";
2344      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2345      cs["a\t"] = "x";
2346      BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2347  
2348      // Ignore groups
2349      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nd=e"), "a=b\n[group]\nab=bc\nd=e");
2350      cs["ab"] = "x";
2351      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nd=e"), "a=b\nab=x\n[group]\nab=bc\nd=e");
2352      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\t [group] \t#c\nab=bc\nd=e"), "a=b\n\t [group] \t#c\nab=bc\nd=e");
2353      cs["ab"] = "x";
2354      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\t [group] \t#c\nab=bc\nd=e"), "a=b\nab=x\n\t [group] \t#c\nab=bc\nd=e");
2355  
2356      // Comment out entire file if invalid input line, even after a group
2357      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nGARBAGE\nd=e"), "[INVALID]\n# Error parsing line 4: GARBAGE\n#a=b\n#[group]\n#ab=bc\n#GARBAGE\n#d=e");
2358      cs["ab"] = "x";
2359      BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nGARBAGE\nd=e"), "ab=x\n[INVALID]\n# Error parsing line 4: GARBAGE\n#a=b\n#[group]\n#ab=bc\n#GARBAGE\n#d=e");
2360  }
2361  
2362  BOOST_AUTO_TEST_CASE(ceil_div_test)
2363  {
2364      // Return type is effectively the wider of the two types.
2365      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, uint32_t{1})), uint32_t>));
2366      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, uint64_t{1})), uint64_t>));
2367      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint64_t{0}, uint32_t{1})), uint64_t>));
2368      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, uint32_t{1})), size_t>));
2369      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, size_t{1})), size_t>));
2370      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, size_t{1})), size_t>));
2371      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, uint64_t{1})), uint64_t>));
2372      BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint64_t{0}, size_t{1})), uint64_t>));
2373  
2374      // Basic ceiling division: exact divisions and rounding up.
2375      BOOST_CHECK_EQUAL(CeilDiv(0ULL, 1ULL), 0ULL);
2376      BOOST_CHECK_EQUAL(CeilDiv(1ULL, 1ULL), 1ULL);
2377      BOOST_CHECK_EQUAL(CeilDiv(2ULL, 2ULL), 1ULL);
2378      BOOST_CHECK_EQUAL(CeilDiv(3ULL, 2ULL), 2ULL);
2379      BOOST_CHECK_EQUAL(CeilDiv(5ULL, 3ULL), 2ULL);
2380  
2381      // Works with size_t.
2382      BOOST_CHECK_EQUAL(CeilDiv(size_t{0}, size_t{1}), size_t{0});
2383      BOOST_CHECK_EQUAL(CeilDiv(size_t{3}, size_t{2}), size_t{2});
2384  
2385      // Works with uint32_t.
2386      BOOST_CHECK_EQUAL(CeilDiv(0U, 1U), 0U);
2387      BOOST_CHECK_EQUAL(CeilDiv(3U, 2U), 2U);
2388  
2389      // CeilDiv avoids overflow at max values.
2390      constexpr uint64_t max_u64{std::numeric_limits<uint64_t>::max()};
2391      BOOST_CHECK_EQUAL(CeilDiv(max_u64, 2ULL), (max_u64 / 2) + 1);
2392  
2393      // Mixed types: size_t dividend with uint32_t divisor.
2394      constexpr size_t max_u32_as_size{std::numeric_limits<uint32_t>::max()};
2395      BOOST_CHECK_EQUAL(CeilDiv(max_u32_as_size, uint32_t{2}), (max_u32_as_size / 2) + 1);
2396  }
2397  
2398  BOOST_AUTO_TEST_CASE(ceil_div_zero_divisor_test)
2399  {
2400      test_only_CheckFailuresAreExceptionsNotAborts check_failures;
2401      BOOST_CHECK_THROW((void)CeilDiv(1ULL, 0ULL), NonFatalCheckError);
2402      BOOST_CHECK_THROW((void)CeilDiv(size_t{1}, size_t{0}), NonFatalCheckError);
2403  }
2404  
2405  BOOST_AUTO_TEST_SUITE_END()
2406