diff options
author | Akio Nakamura <nakamura@dgtechnologies.co.jp> | 2018-11-12 11:06:36 +0900 |
---|---|---|
committer | Akio Nakamura <nakamura@dgtechnologies.co.jp> | 2018-11-20 18:28:16 +0900 |
commit | 3fb09b9889665a24b34f25e9d1385a05058a28b7 (patch) | |
tree | 22584858721f4dfbeb637fdc3238858a92d2f9db | |
parent | 1b99d153d0713ec62b3bde7adbe78c271b5a36ea (diff) |
Warn unrecognized sections in the config file
In the config file, sections are specified by square bracket pair "[]"$,
or included in the option name itself which separated by a period"(.)".
Typicaly, [testnet] is not a correct section name and specified options
in that section are ignored but user cannot recognize what is happen.
So, add some log/stderr-warning messages if unrecognized section names
are present in the config file after checking section only args.
-rw-r--r-- | src/init.cpp | 10 | ||||
-rw-r--r-- | src/util/system.cpp | 42 | ||||
-rw-r--r-- | src/util/system.h | 8 | ||||
-rwxr-xr-x | test/functional/feature_config_args.py | 5 |
4 files changed, 56 insertions, 9 deletions
diff --git a/src/init.cpp b/src/init.cpp index 3ab97be329..d6f04bea14 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -803,7 +803,15 @@ void InitParameterInteraction() // Warn if network-specific options (-addnode, -connect, etc) are // specified in default section of config file, but not overridden // on the command line or in this network's section of the config file. - gArgs.WarnForSectionOnlyArgs(); + std::string network = gArgs.GetChainName(); + for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) { + InitWarning(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network)); + } + + // Warn if unrecognized section name are present in the config file. + for (const auto& section : gArgs.GetUnrecognizedSections()) { + InitWarning(strprintf(_("Section [%s] is not recognized."), section)); + } } static std::string ResolveErrMsg(const char * const optname, const std::string& strBind) diff --git a/src/util/system.cpp b/src/util/system.cpp index cc87d255a9..8e201ec590 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -371,15 +371,17 @@ ArgsManager::ArgsManager() : // nothing to do } -void ArgsManager::WarnForSectionOnlyArgs() +const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const { + std::set<std::string> unsuitables; + LOCK(cs_args); // if there's no section selected, don't worry - if (m_network.empty()) return; + if (m_network.empty()) return std::set<std::string> {}; // if it's okay to use the default section for this network, don't worry - if (m_network == CBaseChainParams::MAIN) return; + if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {}; for (const auto& arg : m_network_only_args) { std::pair<bool, std::string> found_result; @@ -397,8 +399,28 @@ void ArgsManager::WarnForSectionOnlyArgs() if (!found_result.first) continue; // otherwise, issue a warning - LogPrintf("Warning: Config setting for %s only applied on %s network when in [%s] section.\n", arg, m_network, m_network); + unsuitables.insert(arg); } + return unsuitables; +} + + +const std::set<std::string> ArgsManager::GetUnrecognizedSections() const +{ + // Section names to be recognized in the config file. + static const std::set<std::string> available_sections{ + CBaseChainParams::REGTEST, + CBaseChainParams::TESTNET, + CBaseChainParams::MAIN + }; + std::set<std::string> diff; + + LOCK(cs_args); + std::set_difference( + m_config_sections.begin(), m_config_sections.end(), + available_sections.begin(), available_sections.end(), + std::inserter(diff, diff.end())); + return diff; } void ArgsManager::SelectConfigNetwork(const std::string& network) @@ -819,7 +841,7 @@ static std::string TrimString(const std::string& str, const std::string& pattern return str.substr(front, end - front + 1); } -static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>> &options) +static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::set<std::string>& sections) { std::string str, prefix; std::string::size_type pos; @@ -834,7 +856,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect str = TrimString(str, pattern); if (!str.empty()) { if (*str.begin() == '[' && *str.rbegin() == ']') { - prefix = str.substr(1, str.size() - 2) + '.'; + const std::string section = str.substr(1, str.size() - 2); + sections.insert(section); + prefix = section + '.'; } else if (*str.begin() == '-') { error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str); return false; @@ -846,6 +870,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect return false; } options.emplace_back(name, value); + if ((pos = name.rfind('.')) != std::string::npos) { + sections.insert(name.substr(0, pos)); + } } else { error = strprintf("parse error on line %i: %s", linenr, str); if (str.size() >= 2 && str.substr(0, 2) == "no") { @@ -863,7 +890,8 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, boo { LOCK(cs_args); std::vector<std::pair<std::string, std::string>> options; - if (!GetConfigOptions(stream, error, options)) { + m_config_sections.clear(); + if (!GetConfigOptions(stream, error, options, m_config_sections)) { return false; } for (const std::pair<std::string, std::string>& option : options) { diff --git a/src/util/system.h b/src/util/system.h index bebb089a2a..66049dfb3a 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -149,6 +149,7 @@ protected: std::string m_network GUARDED_BY(cs_args); std::set<std::string> m_network_only_args GUARDED_BY(cs_args); std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args); + std::set<std::string> m_config_sections GUARDED_BY(cs_args); bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false); @@ -169,7 +170,12 @@ public: * on the command line or in a network-specific section in the * config file. */ - void WarnForSectionOnlyArgs(); + const std::set<std::string> GetUnsuitableSectionOnlyArgs() const; + + /** + * Log warnings for unrecognized section names in the config file. + */ + const std::set<std::string> GetUnrecognizedSections() const; /** * Return a vector of strings of the given argument diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 88a9aadc7b..d87eabaa6d 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -34,6 +34,11 @@ class ConfArgsTest(BitcoinTestFramework): self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: + conf.write('testnot.datadir=1\n[testnet]\n') + self.restart_node(0) + self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.') + + with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('') # clear def run_test(self): |