Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <common/args.h>6#include <sync.h>7#include <test/util/logging.h>8#include <test/util/setup_common.h>9#include <test/util/str.h>10#include <univalue.h>11#include <util/chaintype.h>12#include <util/fs.h>13#include <util/strencodings.h>15#include <array>16#include <optional>17#include <cstdint>18#include <cstring>19#include <vector>21#include <boost/test/unit_test.hpp>23using util::ToString;25BOOST_FIXTURE_TEST_SUITE(argsman_tests, BasicTestingSetup)27BOOST_AUTO_TEST_CASE(util_datadir)28{29// Use local args variable instead of m_args to avoid making assumptions about test setup30ArgsManager args;31args.ForceSetArg("-datadir", fs::PathToString(m_path_root));33const fs::path dd_norm = args.GetDataDirBase();35args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/");36args.ClearPathCache();37BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());39args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.");40args.ClearPathCache();41BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());43args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/./");44args.ClearPathCache();45BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());47args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.//");48args.ClearPathCache();49BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());50}52struct TestArgsManager : public ArgsManager53{54void ReadConfigString(const std::string& str_config)55{56BOOST_REQUIRE(ArgsManager::ReadConfigString(str_config));57}58void SetupArgs(const std::vector<std::pair<std::string, unsigned int>>& args)59{60for (const auto& arg : args) {61AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);62}63}65// make protected methods available for testing66using ArgsManager::ReadConfigStream;67};69//! Test GetSetting and GetArg type coercion, negation, and default value handling.70class CheckValueTest : public TestChain100Setup71{72public:73struct Expect {74common::SettingsValue setting;75bool default_string = false;76bool default_int = false;77bool default_bool = false;78const char* string_value = nullptr;79std::optional<int64_t> int_value;80std::optional<bool> bool_value;81std::optional<std::vector<std::string>> list_value;82const char* error = nullptr;84explicit Expect(common::SettingsValue s) : setting(std::move(s)) {}85Expect& DefaultString() { default_string = true; return *this; }86Expect& DefaultInt() { default_int = true; return *this; }87Expect& DefaultBool() { default_bool = true; return *this; }88Expect& String(const char* s) { string_value = s; return *this; }89Expect& Int(int64_t i) { int_value = i; return *this; }90Expect& Bool(bool b) { bool_value = b; return *this; }91Expect& List(std::vector<std::string> m) { list_value = std::move(m); return *this; }92Expect& Error(const char* e) { error = e; return *this; }93};95void CheckValue(unsigned int flags, const char* arg, const Expect& expect)96{97TestArgsManager test;98test.SetupArgs({{"-value", flags}});99const char* argv[] = {"ignored", arg};100std::string error;101bool success = test.ParseParameters(arg ? 2 : 1, argv, error);103BOOST_CHECK_EQUAL(test.GetSetting("-value").write(), expect.setting.write());104auto settings_list = test.GetSettingsList("-value");105if (expect.setting.isNull() || expect.setting.isFalse()) {106BOOST_CHECK_EQUAL(settings_list.size(), 0U);107} else {108BOOST_CHECK_EQUAL(settings_list.size(), 1U);109BOOST_CHECK_EQUAL(settings_list[0].write(), expect.setting.write());110}112if (expect.error) {113BOOST_CHECK(!success);114BOOST_CHECK_NE(error.find(expect.error), std::string::npos);115} else {116BOOST_CHECK(success);117BOOST_CHECK_EQUAL(error, "");118}120if (expect.default_string) {121BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), "zzzzz");122} else if (expect.string_value) {123BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), expect.string_value);124} else {125BOOST_CHECK(!success);126}128if (expect.default_int) {129BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), 99999);130} else if (expect.int_value) {131BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), *expect.int_value);132} else {133BOOST_CHECK(!success);134}136if (expect.default_bool) {137BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), false);138BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), true);139} else if (expect.bool_value) {140BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), *expect.bool_value);141BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), *expect.bool_value);142} else {143BOOST_CHECK(!success);144}146if (expect.list_value) {147auto l = test.GetArgs("-value");148BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(), expect.list_value->begin(), expect.list_value->end());149} else {150BOOST_CHECK(!success);151}152}153};155BOOST_FIXTURE_TEST_CASE(util_CheckValue, CheckValueTest)156{157using M = ArgsManager;159CheckValue(M::ALLOW_ANY, nullptr, Expect{{}}.DefaultString().DefaultInt().DefaultBool().List({}));160CheckValue(M::ALLOW_ANY, "-novalue", Expect{false}.String("0").Int(0).Bool(false).List({}));161CheckValue(M::ALLOW_ANY, "-novalue=", Expect{false}.String("0").Int(0).Bool(false).List({}));162CheckValue(M::ALLOW_ANY, "-novalue=0", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));163CheckValue(M::ALLOW_ANY, "-novalue=1", Expect{false}.String("0").Int(0).Bool(false).List({}));164CheckValue(M::ALLOW_ANY, "-novalue=2", Expect{false}.String("0").Int(0).Bool(false).List({}));165CheckValue(M::ALLOW_ANY, "-novalue=abc", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));166CheckValue(M::ALLOW_ANY, "-value", Expect{""}.String("").Int(0).Bool(true).List({""}));167CheckValue(M::ALLOW_ANY, "-value=", Expect{""}.String("").Int(0).Bool(true).List({""}));168CheckValue(M::ALLOW_ANY, "-value=0", Expect{"0"}.String("0").Int(0).Bool(false).List({"0"}));169CheckValue(M::ALLOW_ANY, "-value=1", Expect{"1"}.String("1").Int(1).Bool(true).List({"1"}));170CheckValue(M::ALLOW_ANY, "-value=2", Expect{"2"}.String("2").Int(2).Bool(true).List({"2"}));171CheckValue(M::ALLOW_ANY, "-value=abc", Expect{"abc"}.String("abc").Int(0).Bool(false).List({"abc"}));172}174struct NoIncludeConfTest {175std::string Parse(const char* arg)176{177TestArgsManager test;178test.SetupArgs({{"-includeconf", ArgsManager::ALLOW_ANY}});179std::array argv{"ignored", arg};180std::string error;181(void)test.ParseParameters(argv.size(), argv.data(), error);182return error;183}184};186BOOST_FIXTURE_TEST_CASE(util_NoIncludeConf, NoIncludeConfTest)187{188BOOST_CHECK_EQUAL(Parse("-noincludeconf"), "");189BOOST_CHECK_EQUAL(Parse("-includeconf"), "-includeconf cannot be used from commandline; -includeconf=\"\"");190BOOST_CHECK_EQUAL(Parse("-includeconf=file"), "-includeconf cannot be used from commandline; -includeconf=\"file\"");191}193BOOST_AUTO_TEST_CASE(util_ParseParameters)194{195TestArgsManager testArgs;196const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);197const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);198const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);199const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);201const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};203std::string error;204testArgs.SetupArgs({a, b, ccc, d});205BOOST_CHECK(testArgs.ParseParameters(0, argv_test, error));206testArgs.LockSettings([&](const common::Settings& s) {207BOOST_CHECK(s.command_line_options.empty());208BOOST_CHECK(s.ro_config.empty());209});211BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error));212testArgs.LockSettings([&](const common::Settings& s) {213BOOST_CHECK(s.command_line_options.empty());214BOOST_CHECK(s.ro_config.empty());215});217BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error));218// expectation: -ignored is ignored (program name argument),219// -a, -b and -ccc end up in map, -d ignored because it is after220// a non-option argument (non-GNU option parsing)221BOOST_CHECK(testArgs.IsArgSet("-a"));222BOOST_CHECK(testArgs.IsArgSet("-b"));223BOOST_CHECK(testArgs.IsArgSet("-ccc"));224BOOST_CHECK(!testArgs.IsArgSet("f"));225BOOST_CHECK(!testArgs.IsArgSet("-d"));226testArgs.LockSettings([&](const common::Settings& s) {227BOOST_CHECK(s.command_line_options.size() == 3);228BOOST_CHECK(s.ro_config.empty());229BOOST_CHECK(s.command_line_options.contains("a"));230BOOST_CHECK(s.command_line_options.contains("b"));231BOOST_CHECK(s.command_line_options.contains("ccc"));232BOOST_CHECK(!s.command_line_options.contains("f"));233BOOST_CHECK(!s.command_line_options.contains("d"));235BOOST_CHECK(s.command_line_options.at("a").size() == 1);236BOOST_CHECK(s.command_line_options.at("a").front().get_str() == "");237BOOST_CHECK(s.command_line_options.at("ccc").size() == 2);238BOOST_CHECK(s.command_line_options.at("ccc").front().get_str() == "argument");239BOOST_CHECK(s.command_line_options.at("ccc").back().get_str() == "multiple");240});241BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);242}244BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)245{246TestArgsManager test;247test.SetupArgs({{"-registered", ArgsManager::ALLOW_ANY}});249const char* argv[] = {"ignored", "-registered"};250std::string error;
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.