20 #include <boost/test/unit_test.hpp>
54 std::istringstream streamConfig(str_config);
57 m_settings.ro_config.clear();
58 m_config_sections.clear();
66 m_network_only_args.insert(arg);
68 void SetupArgs(
const std::vector<std::pair<std::string, unsigned int>>&
args)
70 for (
const auto& arg :
args) {
78 using ArgsManager::m_network;
79 using ArgsManager::m_settings;
112 const char* argv[] = {
"ignored", arg};
118 if (
expect.setting.isNull() ||
expect.setting.isFalse()) {
127 BOOST_CHECK_NE(
error.find(
expect.error), std::string::npos);
133 if (
expect.default_string) {
135 }
else if (
expect.string_value) {
143 }
else if (
expect.int_value) {
149 if (
expect.default_bool) {
152 }
else if (
expect.bool_value) {
160 auto l = test.
GetArgs(
"-value");
161 BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(),
expect.list_value->begin(),
expect.list_value->end());
172 CheckValue(M::ALLOW_ANY,
nullptr, Expect{{}}.DefaultString().DefaultInt().DefaultBool().List({}));
173 CheckValue(M::ALLOW_ANY,
"-novalue", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
174 CheckValue(M::ALLOW_ANY,
"-novalue=", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
175 CheckValue(M::ALLOW_ANY,
"-novalue=0", Expect{
true}.String(
"1").Int(1).Bool(
true).List({
"1"}));
176 CheckValue(M::ALLOW_ANY,
"-novalue=1", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
177 CheckValue(M::ALLOW_ANY,
"-novalue=2", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
178 CheckValue(M::ALLOW_ANY,
"-novalue=abc", Expect{
true}.String(
"1").Int(1).Bool(
true).List({
"1"}));
179 CheckValue(M::ALLOW_ANY,
"-value", Expect{
""}.String(
"").Int(0).Bool(
true).List({
""}));
180 CheckValue(M::ALLOW_ANY,
"-value=", Expect{
""}.String(
"").Int(0).Bool(
true).List({
""}));
181 CheckValue(M::ALLOW_ANY,
"-value=0", Expect{
"0"}.String(
"0").Int(0).Bool(
false).List({
"0"}));
182 CheckValue(M::ALLOW_ANY,
"-value=1", Expect{
"1"}.String(
"1").Int(1).Bool(
true).List({
"1"}));
183 CheckValue(M::ALLOW_ANY,
"-value=2", Expect{
"2"}.String(
"2").Int(2).Bool(
true).List({
"2"}));
184 CheckValue(M::ALLOW_ANY,
"-value=abc", Expect{
"abc"}.String(
"abc").Int(0).Bool(
false).List({
"abc"}));
192 std::array argv{
"ignored", arg};
202 BOOST_CHECK_EQUAL(
Parse(
"-includeconf"),
"-includeconf cannot be used from commandline; -includeconf=\"\"");
203 BOOST_CHECK_EQUAL(
Parse(
"-includeconf=file"),
"-includeconf cannot be used from commandline; -includeconf=\"file\"");
214 const char *argv_test[] = {
"-ignored",
"-a",
"-b",
"-ccc=argument",
"-ccc=multiple",
"f",
"-d=e"};
220 BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
223 BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
229 BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 3 && testArgs.m_settings.ro_config.empty());
232 BOOST_CHECK(testArgs.m_settings.command_line_options.count(
"a") && testArgs.m_settings.command_line_options.count(
"b") && testArgs.m_settings.command_line_options.count(
"ccc")
233 && !testArgs.m_settings.command_line_options.count(
"f") && !testArgs.m_settings.command_line_options.count(
"d"));
235 BOOST_CHECK(testArgs.m_settings.command_line_options[
"a"].size() == 1);
236 BOOST_CHECK(testArgs.m_settings.command_line_options[
"a"].front().get_str() ==
"");
237 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].size() == 2);
238 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].front().get_str() ==
"argument");
239 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].back().get_str() ==
"multiple");
248 const char* argv[] = {
"ignored",
"-registered"};
253 argv[1] =
"-unregistered";
259 argv[1] =
"-test.registered";
264 static void TestParse(
const std::string& str,
bool expected_bool, int64_t expected_int)
268 std::string arg =
"-value=" + str;
269 const char* argv[] = {
"ignored", arg.c_str()};
328 const char *argv_test[] = {
329 "ignored",
"-a",
"-nob",
"-c=0",
"-d=1",
"-e=false",
"-f=true"};
336 for (
const char opt :
"abcdef")
340 BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 6 &&
341 testArgs.m_settings.ro_config.empty());
367 const char *argv_test[] = {
"ignored",
"-nofoo",
"-foo",
"-nobar=0"};
381 const char *conf_test =
"nofoo=1\nfoo=1\nnobar=0\n";
395 const char *combo_test_args[] = {
"ignored",
"-nofoo",
"-bar"};
396 const char *combo_test_conf =
"foo=1\nnobar=1\n";
409 && testArgs.
GetArgs(
"-bar").front() ==
"");
414 const char *str_config =
448 test_args.
SetupArgs({a, b, ccc, d, e, fff, ggg, h, i, iii});
454 BOOST_CHECK(test_args.m_settings.command_line_options.empty());
455 BOOST_CHECK(test_args.m_settings.ro_config.size() == 3);
456 BOOST_CHECK(test_args.m_settings.ro_config[
""].size() == 8);
457 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].size() == 3);
458 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].size() == 2);
460 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"a"));
461 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"b"));
462 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"ccc"));
463 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"d"));
464 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"fff"));
465 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"ggg"));
466 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"h"));
467 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"i"));
468 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].count(
"ccc"));
469 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].count(
"h"));
470 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].count(
"ccc"));
471 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].count(
"iii"));
495 for (
const bool def : {
false,
true}) {
509 && test_args.
GetArgs(
"-a").front() ==
"");
511 && test_args.
GetArgs(
"-b").front() ==
"1");
513 && test_args.
GetArgs(
"-ccc").front() ==
"argument"
514 && test_args.
GetArgs(
"-ccc").back() ==
"multiple");
518 && test_args.
GetArgs(
"-ggg").front() ==
"1");
523 && test_args.
GetArgs(
"-i").front() ==
"1");
554 const std::vector<std::string> sec1_ccc_expected = {
"extend1",
"extend2",
"argument",
"multiple"};
555 const auto& sec1_ccc_res = test_args.
GetArgs(
"-ccc");
556 BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
573 const std::vector<std::string> sec2_ccc_expected = {
"extend3",
"argument",
"multiple"};
574 const auto& sec2_ccc_res = test_args.
GetArgs(
"-ccc");
575 BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
605 testArgs.m_settings.command_line_options.clear();
606 testArgs.m_settings.command_line_options[
"strtest1"] = {
"string..."};
608 testArgs.m_settings.command_line_options[
"inttest1"] = {
"12345"};
609 testArgs.m_settings.command_line_options[
"inttest2"] = {
"81985529216486895"};
611 testArgs.m_settings.command_line_options[
"booltest1"] = {
""};
613 testArgs.m_settings.command_line_options[
"booltest3"] = {
"0"};
614 testArgs.m_settings.command_line_options[
"booltest4"] = {
"1"};
617 testArgs.m_settings.command_line_options[
"pritest1"] = {
"a",
"b"};
618 testArgs.m_settings.ro_config[
""][
"pritest2"] = {
"a",
"b"};
619 testArgs.m_settings.command_line_options[
"pritest3"] = {
"a"};
620 testArgs.m_settings.ro_config[
""][
"pritest3"] = {
"b"};
621 testArgs.m_settings.command_line_options[
"pritest4"] = {
"a",
"b"};
622 testArgs.m_settings.ro_config[
""][
"pritest4"] = {
"c",
"d"};
647 const char* argv_testnet[] = {
"cmd",
"-testnet"};
648 const char* argv_regtest[] = {
"cmd",
"-regtest"};
649 const char* argv_test_no_reg[] = {
"cmd",
"-testnet",
"-noregtest"};
650 const char* argv_both[] = {
"cmd",
"-testnet",
"-regtest"};
654 const char* testnetconf =
"testnet=1\nregtest=0\n[test]\nregtest=1";
748 template <
typename Fn>
756 for (
bool soft_set : {
false,
true}) {
757 for (
bool force_set : {
false,
true}) {
760 for (
bool net_specific : {
false,
true}) {
761 fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
773 const std::string& section,
774 const std::string&
name,
775 const std::string& value_prefix)
777 std::vector<std::string>
values;
779 for (
Action action : actions) {
780 if (action ==
NONE)
break;
784 for (
int i = 0; i < 2; ++i) {
803 FILE* out_file =
nullptr;
804 if (
const char* out_path = getenv(
"ARGS_MERGE_TEST_OUT")) {
806 if (!out_file)
throw std::system_error(errno, std::generic_category(),
"fopen failed");
809 ForEachMergeSetup([&](
const ActionList& arg_actions,
const ActionList& conf_actions,
bool soft_set,
bool force_set,
810 const std::string& section,
const std::string& network,
bool net_specific) {
814 std::string desc =
"net=";
816 parser.m_network = network;
818 const std::string&
name = net_specific ?
"wallet" :
"server";
819 const std::string key =
"-" +
name;
823 auto args = GetValues(arg_actions, section,
name,
"a");
824 std::vector<const char*> argv = {
"ignored"};
825 for (
auto& arg :
args) {
829 argv.push_back(arg.c_str());
836 for (
auto& conf_val : GetValues(conf_actions, section,
name,
"c")) {
842 std::istringstream conf_stream(conf);
870 desc += parser.
GetArg(key,
"default");
872 for (
const auto& arg : parser.
GetArgs(key)) {
879 if (!ignored.empty()) {
880 desc +=
" | ignored";
881 for (
const auto& arg : ignored) {
891 BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
896 if (fclose(out_file))
throw std::system_error(errno, std::generic_category(),
"fclose failed");
902 std::string out_sha_hex =
HexStr(out_sha_bytes);
913 BOOST_CHECK_EQUAL(out_sha_hex,
"d1e436c1cd510d0ec44d5205d4b4e3bee6387d316e0075c58206cb16603f3d82");
924 template <
typename Fn>
938 FILE* out_file =
nullptr;
939 if (
const char* out_path = getenv(
"CHAIN_MERGE_TEST_OUT")) {
941 if (!out_file)
throw std::system_error(errno, std::generic_category(),
"fopen failed");
944 ForEachMergeSetup([&](
const ActionList& arg_actions,
const ActionList& conf_actions) {
950 auto arg = [](Action action) {
return action == ENABLE_TEST ?
"-testnet=1" :
951 action == DISABLE_TEST ?
"-testnet=0" :
952 action == NEGATE_TEST ?
"-notestnet=1" :
953 action == ENABLE_REG ?
"-regtest=1" :
954 action == DISABLE_REG ?
"-regtest=0" :
955 action == NEGATE_REG ?
"-noregtest=1" :
nullptr; };
958 std::vector<const char*> argv = {
"ignored"};
959 for (Action action : arg_actions) {
960 const char* argstr = arg(action);
962 argv.push_back(argstr);
971 for (Action action : conf_actions) {
972 const char* argstr = arg(action);
979 std::istringstream conf_stream(conf);
986 }
catch (
const std::runtime_error& e) {
994 BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
999 if (fclose(out_file))
throw std::system_error(errno, std::generic_category(),
"fclose failed");
1005 std::string out_sha_hex =
HexStr(out_sha_bytes);
1016 BOOST_CHECK_EQUAL(out_sha_hex,
"f263493e300023b6509963887444c41386f44b63bc30047eb8402e8c1144854c");
BOOST_FIXTURE_TEST_CASE(util_CheckValue, CheckValueTest)
static void TestParse(const std::string &str, bool expected_bool, int64_t expected_int)
BOOST_AUTO_TEST_CASE(util_datadir)
std::set< std::string > GetUnsuitableSectionOnlyArgs() const
Log warnings for options in m_section_only_args when they are specified in the default section but no...
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
@ ALLOW_ANY
disable validation
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
bool ParseParameters(int argc, const char *const argv[], std::string &error)
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
const fs::path & GetDataDirBase() const
Get data directory path.
void LockSettings(Fn &&fn)
Access settings with lock held.
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
void SelectConfigNetwork(const std::string &network)
Select the network in use.
void ClearPathCache()
Clear cached directory paths.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool WriteSettingsFile(std::vector< std::string > *errors=nullptr, bool backup=false) const
Write settings file or backup settings file.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
std::vector< util::SettingsValue > GetSettingsList(const std::string &arg) const
Get list of setting values.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
util::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
bool ReadConfigStream(std::istream &stream, const std::string &filepath, std::string &error, bool ignore_invalid_keys=false)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
std::string GetChainName() const
Returns the appropriate chain name from the program arguments.
static const std::string TESTNET
static const std::string SIGNET
static const std::string MAIN
Chain name strings.
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
CHash256 & Write(Span< const unsigned char > input)
void Finalize(Span< unsigned char > output)
static const size_t OUTPUT_SIZE
Test GetSetting and GetArg type coercion, negation, and default value handling.
void CheckValue(unsigned int flags, const char *arg, const Expect &expect)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
BOOST_AUTO_TEST_SUITE_END()
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
static std::string PathToString(const path &path)
Convert path object to a byte string.
FILE * fopen(const fs::path &p, const char *mode)
#define BOOST_CHECK_THROW(stmt, excMatch)
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) unsigned char member types only.
void ForEachNoDup(CharType(&string)[StringLength], CharType min_char, CharType max_char, Fn &&fn)
Iterate over string values and call function for each string without successive duplicate characters.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::vector< std::string > GetValues(const ActionList &actions, const std::string §ion, const std::string &name, const std::string &value_prefix)
Translate actions into a list of <key>=setting strings.
void ForEachMergeSetup(Fn &&fn)
Enumerate all possible test configurations.
static constexpr int MAX_ACTIONS
Max number of actions to sequence together.
Action[MAX_ACTIONS] ActionList
void ForEachMergeSetup(Fn &&fn)
Enumerate all possible test configurations.
Action[MAX_ACTIONS] ActionList
static constexpr int MAX_ACTIONS
Expect(util::SettingsValue s)
Expect & Error(const char *e)
std::optional< int64_t > int_value
Expect & List(std::vector< std::string > m)
std::optional< std::vector< std::string > > list_value
std::optional< bool > bool_value
util::SettingsValue setting
const char * string_value
Expect & String(const char *s)
std::string Parse(const char *arg)
void SetupArgs(const std::vector< std::pair< std::string, unsigned int >> &args)
void SetNetworkOnlyArg(const std::string arg)
void ReadConfigString(const std::string str_config)
std::vector< util::SettingsValue > GetSettingsList(const std::string &arg) const
Get list of setting values.
util::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
bool ReadConfigStream(std::istream &stream, const std::string &filepath, std::string &error, bool ignore_invalid_keys=false)
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
std::map< std::string, SettingsValue > rw_settings
Map of setting name to read-write file setting value.
bool error(const char *fmt, const Args &... args)
#define ASSERT_DEBUG_LOG(message)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.