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