mirror of https://github.com/bitcoin/bitcoin
Update ArgManager GetArg helper methods to work better with ALLOW flags
Update GetArg, GetArgs, GetBoolArg, and GetIntArg helper methods to work conveniently with ALLOW_BOOL, ALLOW_INT, and ALLOW_STRING flags. This commit does not change application behavior in any way because these flags are new and currently only used in unit tests. The GetArg methods are convenience wrappers around the GetSetting method. The GetSetting method returns the originally parsed settings values in their declared bool/int/string types, while the GetArg wrappers provide extra type-coercion and default-value fallback features as additional conveniences for callers. This commit makes two changes to GetArg, GetArgs, GetBoolArg, and GetIntArg helper methods when BOOL/INT/STRING flags are used: 1. GetArg methods will now raise errors if they are called with inconsistent flags. For example, GetArgs will raise a logic_error if it is called on a non-LIST setting, GetIntArg will raise a logic_error if it is called on a non-INT setting. 2. GetArg methods will now avoid various type coersion footguns when they are called on new BOOL/INT/STRING settings. Existing ALLOW_ANY settings are unaffected. For example, negated settings will return "" empty strings instead of "0" strings (in the past the "0" strings caused strangeness like "-nowallet" options creating wallet files named "0"). The new behaviors are fully specified and checked by the `CheckValueTest` unit test. The ergonomics of the GetArg helper methods are subjective and the behaviors they implement can be nitpicked and debated endlessly. But behavior of these helper methods does not dictate application behavior, and they be bypassed by calling GetSetting and GetSettingList methods instead. If it's necessary, behavior of these helper methods can also be changed again in the future. The changes have no effect on current application behavior because the new flags are only used in unit tests. The `setting_args` unit test and ALLOW_ANY checks in the `CheckValueTest` unit test are unchanged and confirm that `GetArg` methods behave exactly the same (returning the same values and throwing the same exceptions) for ALLOW_ANY flags before and after this change.
This commit is contained in:
parent
a256f42f79
commit
98d8b63562
|
@ -181,6 +181,41 @@ std::optional<common::SettingsValue> InterpretValue(const KeyInfo& key, const st
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
//! Return string if setting is a nonempty string (-setting=abc), "" if setting
|
||||
//! is false (-nosetting), otherwise return nullopt. For legacy untyped args,
|
||||
//! coerce bool and number settings to strings as well.
|
||||
static inline std::optional<std::string> ConvertToString(const common::SettingsValue& value, bool typed_arg)
|
||||
{
|
||||
if (value.isStr() && !value.get_str().empty()) return value.get_str();
|
||||
if (typed_arg && value.isFalse()) return "";
|
||||
if (!typed_arg && !value.isNull()) {
|
||||
if (value.isBool()) return value.get_bool() ? "1" : "0";
|
||||
if (value.isNum()) return value.getValStr();
|
||||
return value.get_str();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//! Return int64 if setting is a number or bool, otherwise return nullopt. For
|
||||
//! legacy untyped args, coerce string settings as well.
|
||||
static inline std::optional<int64_t> ConvertToInt(const common::SettingsValue& value, bool typed_arg)
|
||||
{
|
||||
if (value.isNum()) return value.getInt<int64_t>();
|
||||
if (value.isBool()) return value.get_bool();
|
||||
if (!typed_arg && !value.isNull()) return LocaleIndependentAtoi<int64_t>(value.get_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
//! Return bool if setting is a bool or number, otherwise return nullopt. For
|
||||
//! legacy untyped args, coerce strings settings as well.
|
||||
static inline std::optional<bool> ConvertToBool(const common::SettingsValue& value, bool typed_arg)
|
||||
{
|
||||
if (value.isBool()) return value.get_bool();
|
||||
if (typed_arg && value.isNum()) return value.getInt<int64_t>() != 0;
|
||||
if (!typed_arg && !value.isNull()) return InterpretBool(value.get_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
// Define default constructor and destructor that are not inline, so code instantiating this class doesn't need to
|
||||
// #include class definitions for all members.
|
||||
// For example, m_settings has an internal dependency on univalue.
|
||||
|
@ -322,6 +357,29 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that arg has the right flags for use in a given context. Raises
|
||||
* logic_error if this isn't the case, indicating the argument was registered
|
||||
* with bad AddArg flags.
|
||||
*
|
||||
* Returns true if the arg is registered and has type checking enabled. Returns
|
||||
* false if the arg was never registered or is untyped.
|
||||
*/
|
||||
bool ArgsManager::CheckArgFlags(const std::string& name,
|
||||
uint32_t require,
|
||||
uint32_t forbid,
|
||||
const char* context) const
|
||||
{
|
||||
std::optional<unsigned int> flags = GetArgFlags(name);
|
||||
if (!flags || !TypedArg(*flags)) return false;
|
||||
if ((*flags & require) != require || (*flags & forbid) != 0) {
|
||||
throw std::logic_error(
|
||||
strprintf("Bug: Can't call %s on arg %s registered with flags 0x%08x (requires 0x%x, disallows 0x%x)",
|
||||
context, name, *flags, require, forbid));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const
|
||||
{
|
||||
if (IsArgNegated(arg)) return fs::path{};
|
||||
|
@ -414,9 +472,10 @@ std::optional<const ArgsManager::Command> ArgsManager::GetCommand() const
|
|||
|
||||
std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const
|
||||
{
|
||||
bool typed_arg = CheckArgFlags(strArg, /*require=*/ ALLOW_STRING | ALLOW_LIST, /*forbid=*/ 0, __func__);
|
||||
std::vector<std::string> result;
|
||||
for (const common::SettingsValue& value : GetSettingsList(strArg)) {
|
||||
result.push_back(value.isFalse() ? "0" : value.isTrue() ? "1" : value.get_str());
|
||||
result.push_back(ConvertToString(value, typed_arg).value_or(""));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -514,22 +573,13 @@ std::string ArgsManager::GetArg(const std::string& strArg, const std::string& st
|
|||
|
||||
std::optional<std::string> ArgsManager::GetArg(const std::string& strArg) const
|
||||
{
|
||||
const common::SettingsValue value = GetSetting(strArg);
|
||||
return SettingToString(value);
|
||||
}
|
||||
|
||||
std::optional<std::string> SettingToString(const common::SettingsValue& value)
|
||||
{
|
||||
if (value.isNull()) return std::nullopt;
|
||||
if (value.isFalse()) return "0";
|
||||
if (value.isTrue()) return "1";
|
||||
if (value.isNum()) return value.getValStr();
|
||||
return value.get_str();
|
||||
bool typed_arg = CheckArgFlags(strArg, /*require=*/ ALLOW_STRING, /*forbid=*/ ALLOW_LIST, __func__);
|
||||
return ConvertToString(GetSetting(strArg), typed_arg);
|
||||
}
|
||||
|
||||
std::string SettingToString(const common::SettingsValue& value, const std::string& strDefault)
|
||||
{
|
||||
return SettingToString(value).value_or(strDefault);
|
||||
return ConvertToString(value, /*typed_arg=*/false).value_or(strDefault);
|
||||
}
|
||||
|
||||
int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const
|
||||
|
@ -539,22 +589,13 @@ int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) cons
|
|||
|
||||
std::optional<int64_t> ArgsManager::GetIntArg(const std::string& strArg) const
|
||||
{
|
||||
const common::SettingsValue value = GetSetting(strArg);
|
||||
return SettingToInt(value);
|
||||
}
|
||||
|
||||
std::optional<int64_t> SettingToInt(const common::SettingsValue& value)
|
||||
{
|
||||
if (value.isNull()) return std::nullopt;
|
||||
if (value.isFalse()) return 0;
|
||||
if (value.isTrue()) return 1;
|
||||
if (value.isNum()) return value.getInt<int64_t>();
|
||||
return LocaleIndependentAtoi<int64_t>(value.get_str());
|
||||
bool typed_arg = CheckArgFlags(strArg, /*require=*/ ALLOW_INT, /*forbid=*/ ALLOW_LIST, __func__);
|
||||
return ConvertToInt(GetSetting(strArg), typed_arg);
|
||||
}
|
||||
|
||||
int64_t SettingToInt(const common::SettingsValue& value, int64_t nDefault)
|
||||
{
|
||||
return SettingToInt(value).value_or(nDefault);
|
||||
return ConvertToInt(value, /*typed_arg=*/false).value_or(nDefault);
|
||||
}
|
||||
|
||||
bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
|
||||
|
@ -564,20 +605,13 @@ bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
|
|||
|
||||
std::optional<bool> ArgsManager::GetBoolArg(const std::string& strArg) const
|
||||
{
|
||||
const common::SettingsValue value = GetSetting(strArg);
|
||||
return SettingToBool(value);
|
||||
}
|
||||
|
||||
std::optional<bool> SettingToBool(const common::SettingsValue& value)
|
||||
{
|
||||
if (value.isNull()) return std::nullopt;
|
||||
if (value.isBool()) return value.get_bool();
|
||||
return InterpretBool(value.get_str());
|
||||
bool typed_arg = CheckArgFlags(strArg, /*require=*/ 0, /*forbid=*/ ALLOW_LIST, __func__);
|
||||
return ConvertToBool(GetSetting(strArg), typed_arg);
|
||||
}
|
||||
|
||||
bool SettingToBool(const common::SettingsValue& value, bool fDefault)
|
||||
{
|
||||
return SettingToBool(value).value_or(fDefault);
|
||||
return ConvertToBool(value, /*typed_arg=*/false).value_or(fDefault);
|
||||
}
|
||||
|
||||
bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
|
||||
|
@ -591,6 +625,7 @@ bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strVa
|
|||
bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
CheckArgFlags(strArg, /*require=*/ ALLOW_BOOL, /*forbid=*/ ALLOW_LIST, __func__);
|
||||
if (IsArgSet(strArg)) return false;
|
||||
m_settings.forced_settings[SettingName(strArg)] = fValue;
|
||||
return true;
|
||||
|
@ -599,6 +634,7 @@ bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue)
|
|||
void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strValue)
|
||||
{
|
||||
LOCK(cs_args);
|
||||
CheckArgFlags(strArg, /*require=*/ ALLOW_STRING, /*forbid=*/ 0, __func__);
|
||||
m_settings.forced_settings[SettingName(strArg)] = strValue;
|
||||
}
|
||||
|
||||
|
@ -810,7 +846,7 @@ std::variant<ChainType, std::string> ArgsManager::GetChainArg() const
|
|||
/* ignore_default_section_config= */ false,
|
||||
/*ignore_nonpersistent=*/false,
|
||||
/* get_chain_type= */ true);
|
||||
return value.isNull() ? false : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
|
||||
return ConvertToBool(value, /*typed_arg=*/false).value_or(false);
|
||||
};
|
||||
|
||||
const bool fRegTest = get_net("-regtest");
|
||||
|
|
|
@ -85,13 +85,8 @@ struct SectionInfo {
|
|||
};
|
||||
|
||||
std::string SettingToString(const common::SettingsValue&, const std::string&);
|
||||
std::optional<std::string> SettingToString(const common::SettingsValue&);
|
||||
|
||||
int64_t SettingToInt(const common::SettingsValue&, int64_t);
|
||||
std::optional<int64_t> SettingToInt(const common::SettingsValue&);
|
||||
|
||||
bool SettingToBool(const common::SettingsValue&, bool);
|
||||
std::optional<bool> SettingToBool(const common::SettingsValue&);
|
||||
|
||||
class ArgsManager
|
||||
{
|
||||
|
@ -142,6 +137,8 @@ protected:
|
|||
mutable fs::path m_cached_datadir_path GUARDED_BY(cs_args);
|
||||
mutable fs::path m_cached_network_datadir_path GUARDED_BY(cs_args);
|
||||
|
||||
bool CheckArgFlags(const std::string& name, uint32_t require, uint32_t forbid, const char* context) const;
|
||||
|
||||
[[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
|
||||
|
||||
/**
|
||||
|
|
|
@ -135,12 +135,16 @@ public:
|
|||
BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), "zzzzz");
|
||||
} else if (expect.string_value) {
|
||||
BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), expect.string_value);
|
||||
} else if (success) {
|
||||
BOOST_CHECK_THROW(test.GetArg("-value", "zzzzz"), std::logic_error);
|
||||
}
|
||||
|
||||
if (expect.default_int) {
|
||||
BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), 99999);
|
||||
} else if (expect.int_value) {
|
||||
BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), *expect.int_value);
|
||||
} else if (success) {
|
||||
BOOST_CHECK_THROW(test.GetIntArg("-value", 99999), std::logic_error);
|
||||
}
|
||||
|
||||
if (expect.default_bool) {
|
||||
|
@ -149,11 +153,16 @@ public:
|
|||
} else if (expect.bool_value) {
|
||||
BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), *expect.bool_value);
|
||||
BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), *expect.bool_value);
|
||||
} else if (success) {
|
||||
BOOST_CHECK_THROW(test.GetBoolArg("-value", false), std::logic_error);
|
||||
BOOST_CHECK_THROW(test.GetBoolArg("-value", true), std::logic_error);
|
||||
}
|
||||
|
||||
if (expect.list_value) {
|
||||
auto l = test.GetArgs("-value");
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(), expect.list_value->begin(), expect.list_value->end());
|
||||
} else if (success) {
|
||||
BOOST_CHECK_THROW(test.GetArgs("-value"), std::logic_error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -176,89 +185,89 @@ BOOST_FIXTURE_TEST_CASE(util_CheckValue, CheckValueTest)
|
|||
CheckValue(M::ALLOW_ANY, "-value=2", Expect{"2"}.String("2").Int(2).Bool(true).List({"2"}));
|
||||
CheckValue(M::ALLOW_ANY, "-value=abc", Expect{"abc"}.String("abc").Int(0).Bool(false).List({"abc"}));
|
||||
|
||||
CheckValue(M::ALLOW_BOOL, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_BOOL, nullptr, Expect{{}}.DefaultBool());
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue", Expect{false}.Bool(false));
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=1", Expect{false}.Bool(false));
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_BOOL, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_BOOL, "-value", Expect{true});
|
||||
CheckValue(M::ALLOW_BOOL, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_BOOL, "-value=0", Expect{false});
|
||||
CheckValue(M::ALLOW_BOOL, "-value=1", Expect{true});
|
||||
CheckValue(M::ALLOW_BOOL, "-value", Expect{true}.Bool(true));
|
||||
CheckValue(M::ALLOW_BOOL, "-value=", Expect{""}.DefaultBool());
|
||||
CheckValue(M::ALLOW_BOOL, "-value=0", Expect{false}.Bool(false));
|
||||
CheckValue(M::ALLOW_BOOL, "-value=1", Expect{true}.Bool(true));
|
||||
CheckValue(M::ALLOW_BOOL, "-value=2", Expect{{}}.Error("Can not set -value value to '2'. It must be set to 0 or 1."));
|
||||
CheckValue(M::ALLOW_BOOL, "-value=abc", Expect{{}}.Error("Can not set -value value to 'abc'. It must be set to 0 or 1."));
|
||||
|
||||
CheckValue(M::ALLOW_INT, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_INT, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_INT, nullptr, Expect{{}}.DefaultInt().DefaultBool());
|
||||
CheckValue(M::ALLOW_INT, "-novalue", Expect{false}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_INT, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_INT, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_INT, "-novalue=1", Expect{false}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_INT, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_INT, "-value", Expect{{}}.Error("Can not set -value with no value. Please specify value with -value=value. It must be set to an integer."));
|
||||
CheckValue(M::ALLOW_INT, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_INT, "-value=0", Expect{0});
|
||||
CheckValue(M::ALLOW_INT, "-value=1", Expect{1});
|
||||
CheckValue(M::ALLOW_INT, "-value=2", Expect{2});
|
||||
CheckValue(M::ALLOW_INT, "-value=", Expect{""}.DefaultInt().DefaultBool());
|
||||
CheckValue(M::ALLOW_INT, "-value=0", Expect{0}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT, "-value=1", Expect{1}.Int(1).Bool(true));
|
||||
CheckValue(M::ALLOW_INT, "-value=2", Expect{2}.Int(2).Bool(true));
|
||||
CheckValue(M::ALLOW_INT, "-value=abc", Expect{{}}.Error("Can not set -value value to 'abc'. It must be set to an integer."));
|
||||
|
||||
CheckValue(M::ALLOW_STRING, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_STRING, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING, nullptr, Expect{{}}.DefaultString().DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING, "-novalue", Expect{false}.String("").Bool(false));
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=1", Expect{false}.String("").Bool(false));
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_STRING, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_STRING, "-value", Expect{{}}.Error("Can not set -value with no value. Please specify value with -value=value. It must be set to a string."));
|
||||
CheckValue(M::ALLOW_STRING, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_STRING, "-value=0", Expect{"0"});
|
||||
CheckValue(M::ALLOW_STRING, "-value=1", Expect{"1"});
|
||||
CheckValue(M::ALLOW_STRING, "-value=2", Expect{"2"});
|
||||
CheckValue(M::ALLOW_STRING, "-value=abc", Expect{"abc"});
|
||||
CheckValue(M::ALLOW_STRING, "-value=", Expect{""}.DefaultString().DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING, "-value=0", Expect{"0"}.String("0").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING, "-value=1", Expect{"1"}.String("1").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING, "-value=2", Expect{"2"}.String("2").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING, "-value=abc", Expect{"abc"}.String("abc").DefaultBool());
|
||||
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, nullptr, Expect{{}}.DefaultInt().DefaultBool());
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue", Expect{false}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=1", Expect{false}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value", Expect{true});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=0", Expect{0});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=1", Expect{1});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=2", Expect{2});
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value", Expect{true}.Int(1).Bool(true));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=", Expect{""}.DefaultInt().DefaultBool());
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=0", Expect{0}.Int(0).Bool(false));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=1", Expect{1}.Int(1).Bool(true));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=2", Expect{2}.Int(2).Bool(true));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=abc", Expect{{}}.Error("Can not set -value value to 'abc'. It must be set to an integer."));
|
||||
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, nullptr, Expect{{}}.DefaultString().DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue", Expect{false}.String("").Bool(false));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=1", Expect{false}.String("").Bool(false));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value", Expect{true});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=0", Expect{"0"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=1", Expect{"1"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=2", Expect{"2"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=abc", Expect{"abc"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value", Expect{true}.DefaultString().Bool(true));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=", Expect{""}.DefaultString().DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=0", Expect{"0"}.String("0").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=1", Expect{"1"}.String("1").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=2", Expect{"2"}.String("2").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=abc", Expect{"abc"}.String("abc").DefaultBool());
|
||||
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, nullptr, Expect{{}});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, nullptr, Expect{{}}.List({}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue", Expect{false}.List({}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=", Expect{{}}.Error("Can not negate -value at the same time as setting value ''."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=0", Expect{{}}.Error("Can not negate -value at the same time as setting value '0'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=1", Expect{false});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=1", Expect{false}.List({}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=2", Expect{{}}.Error("Can not negate -value at the same time as setting value '2'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-novalue=abc", Expect{{}}.Error("Can not negate -value at the same time as setting value 'abc'."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value", Expect{{}}.Error("Can not set -value with no value. Please specify value with -value=value. It must be set to a string."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=", Expect{""});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=0", Expect{"0"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=1", Expect{"1"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=2", Expect{"2"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=abc", Expect{"abc"});
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=", Expect{""}.List({""}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=0", Expect{"0"}.List({"0"}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=1", Expect{"1"}.List({"1"}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=2", Expect{"2"}.List({"2"}));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_LIST, "-value=abc", Expect{"abc"}.List({"abc"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(util_CheckBoolStringsNotSpecial, CheckValueTest)
|
||||
|
@ -274,6 +283,18 @@ BOOST_FIXTURE_TEST_CASE(util_CheckBoolStringsNotSpecial, CheckValueTest)
|
|||
using M = ArgsManager;
|
||||
CheckValue(M::ALLOW_BOOL, "-value=true", Expect{{}}.Error("Can not set -value value to 'true'. It must be set to 0 or 1."));
|
||||
CheckValue(M::ALLOW_BOOL, "-value=false", Expect{{}}.Error("Can not set -value value to 'false'. It must be set to 0 or 1."));
|
||||
|
||||
// Similarly, check "true" and "false" are not treated specially when
|
||||
// ALLOW_BOOL is combined with ALLOW_INT and ALLOW_STRING. (The only
|
||||
// difference ALLOW_BOOL makes for int and string arguments is that it
|
||||
// enables "-foo" syntax with no equal sign assigning explicit int or string
|
||||
// values. This is useful for arguments like "-upgradewallet" or "-listen"
|
||||
// that primarily toggle features on and off, but also accept optional int
|
||||
// or string values to influence behavior.)
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=true", Expect{{}}.Error("Can not set -value value to 'true'. It must be set to an integer."));
|
||||
CheckValue(M::ALLOW_INT | M::ALLOW_BOOL, "-value=false", Expect{{}}.Error("Can not set -value value to 'false'. It must be set to an integer."));
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=true", Expect{"true"}.String("true").DefaultBool());
|
||||
CheckValue(M::ALLOW_STRING | M::ALLOW_BOOL, "-value=false", Expect{"false"}.String("false").DefaultBool());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_CheckSingleValue)
|
||||
|
|
|
@ -44,13 +44,21 @@ FUZZ_TARGET(system, .init = initialize_system)
|
|||
args_manager.SelectConfigNetwork(fuzzed_data_provider.ConsumeRandomLengthString(16));
|
||||
},
|
||||
[&] {
|
||||
args_manager.SoftSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
|
||||
// Avoid Can't call SoftSetArg on arg registered with flags 0x8d8d8d00 (requires 0x2, disallows 0x10)
|
||||
try {
|
||||
args_manager.SoftSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
args_manager.ForceSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
|
||||
},
|
||||
[&] {
|
||||
args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
|
||||
// Avoid Can't call SoftSetBoolArg on arg registered with flags 0x8d8d8d00 (requires 0x2, disallows 0x10)
|
||||
try {
|
||||
args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::HIDDEN});
|
||||
|
@ -107,11 +115,23 @@ FUZZ_TARGET(system, .init = initialize_system)
|
|||
const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
|
||||
const bool b = fuzzed_data_provider.ConsumeBool();
|
||||
|
||||
(void)args_manager.GetIntArg(s1, i64);
|
||||
(void)args_manager.GetArg(s1, s2);
|
||||
try {
|
||||
(void)args_manager.GetIntArg(s1, i64);
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
try {
|
||||
(void)args_manager.GetArg(s1, s2);
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
(void)args_manager.GetArgFlags(s1);
|
||||
(void)args_manager.GetArgs(s1);
|
||||
(void)args_manager.GetBoolArg(s1, b);
|
||||
try {
|
||||
(void)args_manager.GetArgs(s1);
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
try {
|
||||
(void)args_manager.GetBoolArg(s1, b);
|
||||
} catch (const std::logic_error&) {
|
||||
}
|
||||
try {
|
||||
(void)args_manager.GetChainTypeString();
|
||||
} catch (const std::runtime_error&) {
|
||||
|
|
Loading…
Reference in New Issue