Skip to content

Commit 25c56cd

Browse files
committed
Merge #12878: [refactor] Config handling refactoring in preparation for network-specific sections
77a733a [tests] Add additional unit tests for -nofoo edge cases (Anthony Towns) af173c2 [tests] Check GetChainName works with config entries (Anthony Towns) fa27f1c [tests] Add unit tests for ReadConfigStream (Anthony Towns) 087c5d2 ReadConfigStream: assume the stream is good (Anthony Towns) 6d5815a Separate out ReadConfigStream from ReadConfigFile (Anthony Towns) 834d303 [tests] Add unit tests for GetChainName (Anthony Towns) 11b6b5b Move ChainNameFromCommandLine into ArgsManager and rename to GetChainName (Anthony Towns) Pull request description: This does a bit of refactoring of the configuration handling code in order to add additional tests to make adding support for [test]/[regtest] sections in the config file in #11862 easier. Should not cause any behaviour changes. Tree-SHA512: 8d2ce1449fc180de03414e7e569d1a21ba1e9f6564e13d3faf3961f710adc725fa0d4ab49b89ebd2baa11ea36ac5018377f693a84037d386a8b8697c9d6db3e9
2 parents 7e23972 + 77a733a commit 25c56cd

File tree

10 files changed

+245
-46
lines changed

10 files changed

+245
-46
lines changed

src/bitcoin-cli.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static int AppInitRPC(int argc, char* argv[])
114114
}
115115
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
116116
try {
117-
SelectBaseParams(ChainNameFromCommandLine());
117+
SelectBaseParams(gArgs.GetChainName());
118118
} catch (const std::exception& e) {
119119
fprintf(stderr, "Error: %s\n", e.what());
120120
return EXIT_FAILURE;

src/bitcoin-tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static int AppInitRawTx(int argc, char* argv[])
4444

4545
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
4646
try {
47-
SelectParams(ChainNameFromCommandLine());
47+
SelectParams(gArgs.GetChainName());
4848
} catch (const std::exception& e) {
4949
fprintf(stderr, "Error: %s\n", e.what());
5050
return EXIT_FAILURE;

src/bitcoind.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ bool AppInit(int argc, char* argv[])
102102
}
103103
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
104104
try {
105-
SelectParams(ChainNameFromCommandLine());
105+
SelectParams(gArgs.GetChainName());
106106
} catch (const std::exception& e) {
107107
fprintf(stderr, "Error: %s\n", e.what());
108108
return false;

src/chainparamsbase.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,3 @@ void SelectBaseParams(const std::string& chain)
4949
{
5050
globalChainBaseParams = CreateBaseChainParams(chain);
5151
}
52-
53-
std::string ChainNameFromCommandLine()
54-
{
55-
bool fRegTest = gArgs.GetBoolArg("-regtest", false);
56-
bool fTestNet = gArgs.GetBoolArg("-testnet", false);
57-
58-
if (fTestNet && fRegTest)
59-
throw std::runtime_error("Invalid combination of -regtest and -testnet.");
60-
if (fRegTest)
61-
return CBaseChainParams::REGTEST;
62-
if (fTestNet)
63-
return CBaseChainParams::TESTNET;
64-
return CBaseChainParams::MAIN;
65-
}

src/chainparamsbase.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,4 @@ const CBaseChainParams& BaseParams();
5454
/** Sets the params returned by Params() to those for the given network. */
5555
void SelectBaseParams(const std::string& chain);
5656

57-
/**
58-
* Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
59-
* @return CBaseChainParams::MAX_NETWORK_TYPES if an invalid combination is given. CBaseChainParams::MAIN by default.
60-
*/
61-
std::string ChainNameFromCommandLine();
62-
6357
#endif // BITCOIN_CHAINPARAMSBASE_H

src/qt/bitcoin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ int main(int argc, char *argv[])
627627

628628
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
629629
try {
630-
node->selectParams(ChainNameFromCommandLine());
630+
node->selectParams(gArgs.GetChainName());
631631
} catch(std::exception &e) {
632632
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what()));
633633
return EXIT_FAILURE;

src/qt/guiutil.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t
599599
#ifdef WIN32
600600
fs::path static StartupShortcutPath()
601601
{
602-
std::string chain = ChainNameFromCommandLine();
602+
std::string chain = gArgs.GetChainName();
603603
if (chain == CBaseChainParams::MAIN)
604604
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
605605
if (chain == CBaseChainParams::TESTNET) // Remove this special case when CBaseChainParams::TESTNET = "testnet4"
@@ -697,7 +697,7 @@ fs::path static GetAutostartDir()
697697

698698
fs::path static GetAutostartFilePath()
699699
{
700-
std::string chain = ChainNameFromCommandLine();
700+
std::string chain = gArgs.GetChainName();
701701
if (chain == CBaseChainParams::MAIN)
702702
return GetAutostartDir() / "bitcoin.desktop";
703703
return GetAutostartDir() / strprintf("bitcoin-%s.lnk", chain);
@@ -739,7 +739,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
739739
fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
740740
if (!optionFile.good())
741741
return false;
742-
std::string chain = ChainNameFromCommandLine();
742+
std::string chain = gArgs.GetChainName();
743743
// Write a bitcoin.desktop file to the autostart directory:
744744
optionFile << "[Desktop Entry]\n";
745745
optionFile << "Type=Application\n";

src/test/util_tests.cpp

Lines changed: 193 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ struct TestArgsManager : public ArgsManager
190190
std::map<std::string, std::string>& GetMapArgs() { return mapArgs; }
191191
const std::map<std::string, std::vector<std::string> >& GetMapMultiArgs() { return mapMultiArgs; }
192192
const std::unordered_set<std::string>& GetNegatedArgs() { return m_negated_args; }
193+
void ReadConfigString(const std::string str_config)
194+
{
195+
std::istringstream stream(str_config);
196+
ReadConfigStream(stream);
197+
}
193198
};
194199

195200
BOOST_AUTO_TEST_CASE(util_ParseParameters)
@@ -253,16 +258,154 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
253258
{
254259
// Test some awful edge cases that hopefully no user will ever exercise.
255260
TestArgsManager testArgs;
261+
262+
// Params test
256263
const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
257264
testArgs.ParseParameters(4, (char**)argv_test);
258265

259266
// This was passed twice, second one overrides the negative setting.
260267
BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
261-
BOOST_CHECK(testArgs.GetBoolArg("-foo", false) == true);
268+
BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
269+
270+
// A double negative is a positive.
271+
BOOST_CHECK(testArgs.IsArgNegated("-bar"));
272+
BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
273+
274+
// Config test
275+
const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
276+
testArgs.ParseParameters(1, (char**)argv_test);
277+
testArgs.ReadConfigString(conf_test);
278+
279+
// This was passed twice, second one overrides the negative setting,
280+
// but not the value.
281+
BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
282+
BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
262283

263284
// A double negative is a positive.
264285
BOOST_CHECK(testArgs.IsArgNegated("-bar"));
265-
BOOST_CHECK(testArgs.GetBoolArg("-bar", false) == true);
286+
BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
287+
288+
// Combined test
289+
const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
290+
const char *combo_test_conf = "foo=1\nnobar=1\n";
291+
testArgs.ParseParameters(3, (char**)combo_test_args);
292+
testArgs.ReadConfigString(combo_test_conf);
293+
294+
// Command line overrides, but doesn't erase old setting
295+
BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
296+
BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
297+
BOOST_CHECK(testArgs.GetArgs("-foo").size() == 2
298+
&& testArgs.GetArgs("-foo").front() == "0"
299+
&& testArgs.GetArgs("-foo").back() == "1");
300+
301+
// Command line overrides, but doesn't erase old setting
302+
BOOST_CHECK(testArgs.IsArgNegated("-bar"));
303+
BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
304+
BOOST_CHECK(testArgs.GetArgs("-bar").size() == 2
305+
&& testArgs.GetArgs("-bar").front() == ""
306+
&& testArgs.GetArgs("-bar").back() == "0");
307+
}
308+
309+
BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
310+
{
311+
const char *str_config =
312+
"a=\n"
313+
"b=1\n"
314+
"ccc=argument\n"
315+
"ccc=multiple\n"
316+
"d=e\n"
317+
"nofff=1\n"
318+
"noggg=0\n"
319+
"h=1\n"
320+
"noh=1\n"
321+
"noi=1\n"
322+
"i=1\n";
323+
324+
TestArgsManager test_args;
325+
326+
test_args.ReadConfigString(str_config);
327+
// expectation: a, b, ccc, d, fff, ggg, h, i end up in map
328+
329+
BOOST_CHECK(test_args.GetMapArgs().size() == 8);
330+
BOOST_CHECK(test_args.GetMapMultiArgs().size() == 8);
331+
332+
BOOST_CHECK(test_args.GetMapArgs().count("-a")
333+
&& test_args.GetMapArgs().count("-b")
334+
&& test_args.GetMapArgs().count("-ccc")
335+
&& test_args.GetMapArgs().count("-d")
336+
&& test_args.GetMapArgs().count("-fff")
337+
&& test_args.GetMapArgs().count("-ggg")
338+
&& test_args.GetMapArgs().count("-h")
339+
&& test_args.GetMapArgs().count("-i")
340+
);
341+
342+
BOOST_CHECK(test_args.IsArgSet("-a")
343+
&& test_args.IsArgSet("-b")
344+
&& test_args.IsArgSet("-ccc")
345+
&& test_args.IsArgSet("-d")
346+
&& test_args.IsArgSet("-fff")
347+
&& test_args.IsArgSet("-ggg")
348+
&& test_args.IsArgSet("-h")
349+
&& test_args.IsArgSet("-i")
350+
&& !test_args.IsArgSet("-zzz")
351+
);
352+
353+
BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
354+
&& test_args.GetArg("-b", "xxx") == "1"
355+
&& test_args.GetArg("-ccc", "xxx") == "argument"
356+
&& test_args.GetArg("-d", "xxx") == "e"
357+
&& test_args.GetArg("-fff", "xxx") == "0"
358+
&& test_args.GetArg("-ggg", "xxx") == "1"
359+
&& test_args.GetArg("-h", "xxx") == "1" // 1st value takes precedence
360+
&& test_args.GetArg("-i", "xxx") == "0" // 1st value takes precedence
361+
&& test_args.GetArg("-zzz", "xxx") == "xxx"
362+
);
363+
364+
for (bool def : {false, true}) {
365+
BOOST_CHECK(test_args.GetBoolArg("-a", def)
366+
&& test_args.GetBoolArg("-b", def)
367+
&& !test_args.GetBoolArg("-ccc", def)
368+
&& !test_args.GetBoolArg("-d", def)
369+
&& !test_args.GetBoolArg("-fff", def)
370+
&& test_args.GetBoolArg("-ggg", def)
371+
&& test_args.GetBoolArg("-h", def)
372+
&& !test_args.GetBoolArg("-i", def)
373+
&& test_args.GetBoolArg("-zzz", def) == def
374+
);
375+
}
376+
377+
BOOST_CHECK(test_args.GetArgs("-a").size() == 1
378+
&& test_args.GetArgs("-a").front() == "");
379+
BOOST_CHECK(test_args.GetArgs("-b").size() == 1
380+
&& test_args.GetArgs("-b").front() == "1");
381+
BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
382+
&& test_args.GetArgs("-ccc").front() == "argument"
383+
&& test_args.GetArgs("-ccc").back() == "multiple");
384+
BOOST_CHECK(test_args.GetArgs("-fff").size() == 1
385+
&& test_args.GetArgs("-fff").front() == "0");
386+
BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
387+
BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
388+
&& test_args.GetArgs("-ggg").front() == "1");
389+
BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
390+
BOOST_CHECK(test_args.GetArgs("-h").size() == 2
391+
&& test_args.GetArgs("-h").front() == "1"
392+
&& test_args.GetArgs("-h").back() == "0");
393+
BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
394+
BOOST_CHECK(test_args.GetArgs("-i").size() == 2
395+
&& test_args.GetArgs("-i").front() == "0"
396+
&& test_args.GetArgs("-i").back() == "1");
397+
BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
398+
BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
399+
400+
BOOST_CHECK(!test_args.IsArgNegated("-a"));
401+
BOOST_CHECK(!test_args.IsArgNegated("-b"));
402+
BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
403+
BOOST_CHECK(!test_args.IsArgNegated("-d"));
404+
BOOST_CHECK(test_args.IsArgNegated("-fff"));
405+
BOOST_CHECK(test_args.IsArgNegated("-ggg")); // IsArgNegated==true when noggg=0
406+
BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
407+
BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
408+
BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
266409
}
267410

268411
BOOST_AUTO_TEST_CASE(util_GetArg)
@@ -290,6 +433,54 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
290433
BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
291434
}
292435

436+
BOOST_AUTO_TEST_CASE(util_GetChainName)
437+
{
438+
TestArgsManager test_args;
439+
440+
const char* argv_testnet[] = {"cmd", "-testnet"};
441+
const char* argv_regtest[] = {"cmd", "-regtest"};
442+
const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
443+
const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
444+
445+
// equivalent to "-testnet"
446+
const char* testnetconf = "testnet=1\nregtest=0\n";
447+
448+
test_args.ParseParameters(0, (char**)argv_testnet);
449+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
450+
451+
test_args.ParseParameters(2, (char**)argv_testnet);
452+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
453+
454+
test_args.ParseParameters(2, (char**)argv_regtest);
455+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
456+
457+
test_args.ParseParameters(3, (char**)argv_test_no_reg);
458+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
459+
460+
test_args.ParseParameters(3, (char**)argv_both);
461+
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
462+
463+
test_args.ParseParameters(0, (char**)argv_testnet);
464+
test_args.ReadConfigString(testnetconf);
465+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
466+
467+
test_args.ParseParameters(2, (char**)argv_testnet);
468+
test_args.ReadConfigString(testnetconf);
469+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
470+
471+
test_args.ParseParameters(2, (char**)argv_regtest);
472+
test_args.ReadConfigString(testnetconf);
473+
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
474+
475+
test_args.ParseParameters(3, (char**)argv_test_no_reg);
476+
test_args.ReadConfigString(testnetconf);
477+
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
478+
479+
test_args.ParseParameters(3, (char**)argv_both);
480+
test_args.ReadConfigString(testnetconf);
481+
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
482+
}
483+
293484
BOOST_AUTO_TEST_CASE(util_FormatMoney)
294485
{
295486
BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");

src/util.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -736,35 +736,55 @@ fs::path GetConfigFile(const std::string& confPath)
736736
return AbsPathForConfigVal(fs::path(confPath), false);
737737
}
738738

739-
void ArgsManager::ReadConfigFile(const std::string& confPath)
739+
void ArgsManager::ReadConfigStream(std::istream& stream)
740740
{
741-
fs::ifstream streamConfig(GetConfigFile(confPath));
742-
if (!streamConfig.good())
743-
return; // No bitcoin.conf file is OK
741+
LOCK(cs_args);
744742

743+
std::set<std::string> setOptions;
744+
setOptions.insert("*");
745+
746+
for (boost::program_options::detail::config_file_iterator it(stream, setOptions), end; it != end; ++it)
745747
{
746-
LOCK(cs_args);
747-
std::set<std::string> setOptions;
748-
setOptions.insert("*");
748+
// Don't overwrite existing settings so command line settings override bitcoin.conf
749+
std::string strKey = std::string("-") + it->string_key;
750+
std::string strValue = it->value[0];
751+
InterpretNegatedOption(strKey, strValue);
752+
if (mapArgs.count(strKey) == 0)
753+
mapArgs[strKey] = strValue;
754+
mapMultiArgs[strKey].push_back(strValue);
755+
}
756+
}
749757

750-
for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
751-
{
752-
// Don't overwrite existing settings so command line settings override bitcoin.conf
753-
std::string strKey = std::string("-") + it->string_key;
754-
std::string strValue = it->value[0];
755-
InterpretNegatedOption(strKey, strValue);
756-
if (mapArgs.count(strKey) == 0)
757-
mapArgs[strKey] = strValue;
758-
mapMultiArgs[strKey].push_back(strValue);
759-
}
758+
void ArgsManager::ReadConfigFile(const std::string& confPath)
759+
{
760+
fs::ifstream stream(GetConfigFile(confPath));
761+
762+
// ok to not have a config file
763+
if (stream.good()) {
764+
ReadConfigStream(stream);
760765
}
766+
761767
// If datadir is changed in .conf file:
762768
ClearDatadirCache();
763769
if (!fs::is_directory(GetDataDir(false))) {
764770
throw std::runtime_error(strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str()));
765771
}
766772
}
767773

774+
std::string ArgsManager::GetChainName() const
775+
{
776+
bool fRegTest = GetBoolArg("-regtest", false);
777+
bool fTestNet = GetBoolArg("-testnet", false);
778+
779+
if (fTestNet && fRegTest)
780+
throw std::runtime_error("Invalid combination of -regtest and -testnet.");
781+
if (fRegTest)
782+
return CBaseChainParams::REGTEST;
783+
if (fTestNet)
784+
return CBaseChainParams::TESTNET;
785+
return CBaseChainParams::MAIN;
786+
}
787+
768788
#ifndef WIN32
769789
fs::path GetPidFile()
770790
{

0 commit comments

Comments
 (0)