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