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.
752BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));753BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");755BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));756BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);758BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));759test_args.ReadConfigString(testnetconf);760BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");762BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));763test_args.ReadConfigString(testnetconf);764BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");766BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));767test_args.ReadConfigString(testnetconf);768BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);770BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));771test_args.ReadConfigString(testnetconf);772BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");774BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));775test_args.ReadConfigString(testnetconf);776BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);778// check setting the network to testnet4 (and thus making779// [testnet4] regtest=1 potentially relevant) doesn't break things780test_args.SelectConfigNetwork("testnet4");782BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));783test_args.ReadConfigString(testnetconf);784BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");786BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));787test_args.ReadConfigString(testnetconf);788BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");790BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));791test_args.ReadConfigString(testnetconf);792BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);794BOOST_CHECK(test_args.ParseParameters(2, argv_test_no_reg, error));795test_args.ReadConfigString(testnetconf);796BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");798BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));799test_args.ReadConfigString(testnetconf);800BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);801}803// Test different ways settings can be merged, and verify results. This test can804// be used to confirm that updates to settings code don't change behavior805// unintentionally.806//807// The test covers:808//809// - Combining different setting actions. Possible actions are: configuring a810// setting, negating a setting (adding "-no" prefix), and configuring/negating811// settings in a network section (adding "main." or "test." prefixes).812//813// - Combining settings from command line arguments and a config file.814//815// - Combining SoftSet and ForceSet calls.816//817// - Testing "main" and "testnet4" network values to make sure settings from network818// sections are applied and to check for mainnet-specific behaviors like819// inheriting settings from the default section.820//821// - Testing network-specific settings like "-wallet", that may be ignored822// outside a network section, and non-network specific settings like "-server"823// that aren't sensitive to the network.824//825struct ArgsMergeTestingSetup : public BasicTestingSetup {826//! Max number of actions to sequence together. Can decrease this when827//! debugging to make test results easier to understand.828static constexpr int MAX_ACTIONS = 3;830enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE };831using ActionList = Action[MAX_ACTIONS];833//! Enumerate all possible test configurations.834template <typename Fn>835void ForEachMergeSetup(Fn&& fn)836{837ActionList arg_actions = {};838// command_line_options do not have sections. Only iterate over SET and NEGATE839ForEachNoDup(arg_actions, SET, NEGATE, [&] {840ActionList conf_actions = {};841ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {842for (bool soft_set : {false, true}) {843for (bool force_set : {false, true}) {844for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {845for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {846for (bool net_specific : {false, true}) {847fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);848}849}850}851}852}853});854});855}857//! Translate actions into a list of <key>=<value> setting strings.858std::vector<std::string> GetValues(const ActionList& actions,859const std::string& section,860const std::string& name,861const std::string& value_prefix)862{863std::vector<std::string> values;864int suffix = 0;865for (Action action : actions) {866if (action == NONE) break;867std::string prefix;868if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";869if (action == SET || action == SECTION_SET) {870for (int i = 0; i < 2; ++i) {871values.push_back(prefix + name + "=" + value_prefix + ToString(++suffix));872}873}874if (action == NEGATE || action == SECTION_NEGATE) {875values.push_back(prefix + "no" + name + "=1");876}877}878return values;879}880};882// Regression test covering different ways config settings can be merged. The883// test parses and merges settings, representing the results as strings that get884// compared against an expected hash. To debug, the result strings can be dumped885// to a file (see comments below).886BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)887{888CHash256 out_sha;889FILE* out_file = nullptr;890if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) {891out_file = fsbridge::fopen(out_path, "w");892if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");893}895ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool soft_set, bool force_set,896const std::string& section, const std::string& network, bool net_specific) {897TestArgsManager parser;899std::string desc = "net=";900desc += network;901parser.SelectConfigNetwork(network);903const std::string& name = net_specific ? "wallet" : "server";904const std::string key = "-" + name;905unsigned int flags = ArgsManager::ALLOW_ANY;906if (net_specific) flags |= ArgsManager::NETWORK_ONLY;907parser.AddArg(key, name, flags, OptionsCategory::OPTIONS);909auto args = GetValues(arg_actions, section, name, "a");910std::vector<const char*> argv = {"ignored"};911for (auto& arg : args) {912arg.insert(0, "-");913desc += " ";914desc += arg;915argv.push_back(arg.c_str());916}917std::string error;918BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));919BOOST_CHECK_EQUAL(error, "");921std::string conf;922for (auto& conf_val : GetValues(conf_actions, section, name, "c")) {923desc += " ";924desc += conf_val;925conf += conf_val;926conf += "\n";927}928std::istringstream conf_stream(conf);929BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));930BOOST_CHECK_EQUAL(error, "");932if (soft_set) {933desc += " soft";934parser.SoftSetArg(key, "soft1");935parser.SoftSetArg(key, "soft2");936}938if (force_set) {939desc += " force";940parser.ForceSetArg(key, "force1");941parser.ForceSetArg(key, "force2");942}944desc += " || ";946if (!parser.IsArgSet(key)) {947desc += "unset";948BOOST_CHECK(!parser.IsArgNegated(key));949BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default");950BOOST_CHECK(parser.GetArgs(key).empty());951} else if (parser.IsArgNegated(key)) {952desc += "negated";953BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0");954BOOST_CHECK(parser.GetArgs(key).empty());955} else {956desc += parser.GetArg(key, "default");957desc += " |";958for (const auto& arg : parser.GetArgs(key)) {959desc += " ";960desc += arg;961}962}964std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs();965if (!ignored.empty()) {966desc += " | ignored";967for (const auto& arg : ignored) {968desc += " ";969desc += arg;970}971}973desc += "\n";975out_sha.Write(MakeUCharSpan(desc));976if (out_file) {977BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());978}979});981if (out_file) {982if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");983out_file = nullptr;984}986unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];987out_sha.Finalize(out_sha_bytes);988std::string out_sha_hex = HexStr(out_sha_bytes);990// If check below fails, should manually dump the results with:991//992// ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=argsman_tests/util_ArgsMerge993//994// And verify diff against previous results to make sure the changes are expected.995//996// Results file is formatted like:997//998// <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>999BOOST_CHECK_EQUAL(out_sha_hex, "f1ee5ab094cc43d16a6086fa7f2c10389e0f99902616b31bbf29189972ad1473");1000}
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.