21#include <boost/test/unit_test.hpp>
57 std::istringstream streamConfig(str_config);
60 m_settings.ro_config.clear();
61 m_config_sections.clear();
69 m_network_only_args.insert(arg);
71 void SetupArgs(
const std::vector<std::pair<std::string, unsigned int>>&
args)
73 for (
const auto& arg :
args) {
81 using ArgsManager::m_network;
82 using ArgsManager::m_settings;
115 const char* argv[] = {
"ignored", arg};
121 if (
expect.setting.isNull() ||
expect.setting.isFalse()) {
130 BOOST_CHECK_NE(error.find(
expect.error), std::string::npos);
136 if (
expect.default_string) {
138 }
else if (
expect.string_value) {
146 }
else if (
expect.int_value) {
152 if (
expect.default_bool) {
155 }
else if (
expect.bool_value) {
163 auto l = test.
GetArgs(
"-value");
164 BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(),
expect.list_value->begin(),
expect.list_value->end());
175 CheckValue(M::ALLOW_ANY,
nullptr, Expect{{}}.DefaultString().DefaultInt().DefaultBool().List({}));
176 CheckValue(M::ALLOW_ANY,
"-novalue", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
177 CheckValue(M::ALLOW_ANY,
"-novalue=", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
178 CheckValue(M::ALLOW_ANY,
"-novalue=0", Expect{
true}.String(
"1").Int(1).Bool(
true).List({
"1"}));
179 CheckValue(M::ALLOW_ANY,
"-novalue=1", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
180 CheckValue(M::ALLOW_ANY,
"-novalue=2", Expect{
false}.String(
"0").Int(0).Bool(
false).List({}));
181 CheckValue(M::ALLOW_ANY,
"-novalue=abc", Expect{
true}.String(
"1").Int(1).Bool(
true).List({
"1"}));
182 CheckValue(M::ALLOW_ANY,
"-value", Expect{
""}.String(
"").Int(0).Bool(
true).List({
""}));
183 CheckValue(M::ALLOW_ANY,
"-value=", Expect{
""}.String(
"").Int(0).Bool(
true).List({
""}));
184 CheckValue(M::ALLOW_ANY,
"-value=0", Expect{
"0"}.String(
"0").Int(0).Bool(
false).List({
"0"}));
185 CheckValue(M::ALLOW_ANY,
"-value=1", Expect{
"1"}.String(
"1").Int(1).Bool(
true).List({
"1"}));
186 CheckValue(M::ALLOW_ANY,
"-value=2", Expect{
"2"}.String(
"2").Int(2).Bool(
true).List({
"2"}));
187 CheckValue(M::ALLOW_ANY,
"-value=abc", Expect{
"abc"}.String(
"abc").Int(0).Bool(
false).List({
"abc"}));
195 std::array argv{
"ignored", arg};
205 BOOST_CHECK_EQUAL(
Parse(
"-includeconf"),
"-includeconf cannot be used from commandline; -includeconf=\"\"");
206 BOOST_CHECK_EQUAL(
Parse(
"-includeconf=file"),
"-includeconf cannot be used from commandline; -includeconf=\"file\"");
217 const char *argv_test[] = {
"-ignored",
"-a",
"-b",
"-ccc=argument",
"-ccc=multiple",
"f",
"-d=e"};
223 BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
226 BOOST_CHECK(testArgs.m_settings.command_line_options.empty() && testArgs.m_settings.ro_config.empty());
232 BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 3 && testArgs.m_settings.ro_config.empty());
235 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")
236 && !testArgs.m_settings.command_line_options.count(
"f") && !testArgs.m_settings.command_line_options.count(
"d"));
238 BOOST_CHECK(testArgs.m_settings.command_line_options[
"a"].size() == 1);
239 BOOST_CHECK(testArgs.m_settings.command_line_options[
"a"].front().get_str() ==
"");
240 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].size() == 2);
241 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].front().get_str() ==
"argument");
242 BOOST_CHECK(testArgs.m_settings.command_line_options[
"ccc"].back().get_str() ==
"multiple");
251 const char* argv[] = {
"ignored",
"-registered"};
256 argv[1] =
"-unregistered";
262 argv[1] =
"-test.registered";
267static void TestParse(
const std::string& str,
bool expected_bool, int64_t expected_int)
271 std::string arg =
"-value=" + str;
272 const char* argv[] = {
"ignored", arg.c_str()};
331 const char *argv_test[] = {
332 "ignored",
"-a",
"-nob",
"-c=0",
"-d=1",
"-e=false",
"-f=true"};
339 for (
const char opt :
"abcdef")
343 BOOST_CHECK(testArgs.m_settings.command_line_options.size() == 6 &&
344 testArgs.m_settings.ro_config.empty());
370 const char *argv_test[] = {
"ignored",
"-nofoo",
"-foo",
"-nobar=0"};
384 const char *conf_test =
"nofoo=1\nfoo=1\nnobar=0\n";
398 const char *combo_test_args[] = {
"ignored",
"-nofoo",
"-bar"};
399 const char *combo_test_conf =
"foo=1\nnobar=1\n";
412 && testArgs.
GetArgs(
"-bar").front() ==
"");
417 const char *str_config =
451 test_args.
SetupArgs({a, b, ccc, d, e, fff, ggg, h, i, iii});
457 BOOST_CHECK(test_args.m_settings.command_line_options.empty());
458 BOOST_CHECK(test_args.m_settings.ro_config.size() == 3);
459 BOOST_CHECK(test_args.m_settings.ro_config[
""].size() == 8);
460 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].size() == 3);
461 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].size() == 2);
463 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"a"));
464 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"b"));
465 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"ccc"));
466 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"d"));
467 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"fff"));
468 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"ggg"));
469 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"h"));
470 BOOST_CHECK(test_args.m_settings.ro_config[
""].count(
"i"));
471 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].count(
"ccc"));
472 BOOST_CHECK(test_args.m_settings.ro_config[
"sec1"].count(
"h"));
473 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].count(
"ccc"));
474 BOOST_CHECK(test_args.m_settings.ro_config[
"sec2"].count(
"iii"));
498 for (
const bool def : {
false,
true}) {
512 && test_args.
GetArgs(
"-a").front() ==
"");
514 && test_args.
GetArgs(
"-b").front() ==
"1");
516 && test_args.
GetArgs(
"-ccc").front() ==
"argument"
517 && test_args.
GetArgs(
"-ccc").back() ==
"multiple");
521 && test_args.
GetArgs(
"-ggg").front() ==
"1");
526 && test_args.
GetArgs(
"-i").front() ==
"1");
557 const std::vector<std::string> sec1_ccc_expected = {
"extend1",
"extend2",
"argument",
"multiple"};
558 const auto& sec1_ccc_res = test_args.
GetArgs(
"-ccc");
559 BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
576 const std::vector<std::string> sec2_ccc_expected = {
"extend3",
"argument",
"multiple"};
577 const auto& sec2_ccc_res = test_args.
GetArgs(
"-ccc");
578 BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
608 testArgs.m_settings.command_line_options.clear();
609 testArgs.m_settings.command_line_options[
"strtest1"] = {
"string..."};
611 testArgs.m_settings.command_line_options[
"inttest1"] = {
"12345"};
612 testArgs.m_settings.command_line_options[
"inttest2"] = {
"81985529216486895"};
614 testArgs.m_settings.command_line_options[
"booltest1"] = {
""};
616 testArgs.m_settings.command_line_options[
"booltest3"] = {
"0"};
617 testArgs.m_settings.command_line_options[
"booltest4"] = {
"1"};
620 testArgs.m_settings.command_line_options[
"pritest1"] = {
"a",
"b"};
621 testArgs.m_settings.ro_config[
""][
"pritest2"] = {
"a",
"b"};
622 testArgs.m_settings.command_line_options[
"pritest3"] = {
"a"};
623 testArgs.m_settings.ro_config[
""][
"pritest3"] = {
"b"};
624 testArgs.m_settings.command_line_options[
"pritest4"] = {
"a",
"b"};
625 testArgs.m_settings.ro_config[
""][
"pritest4"] = {
"c",
"d"};
649 test_args.
SetupArgs({testnet, testnet4, regtest});
651 const char* argv_testnet[] = {
"cmd",
"-testnet"};
652 const char* argv_testnet4[] = {
"cmd",
"-testnet4"};
653 const char* argv_regtest[] = {
"cmd",
"-regtest"};
654 const char* argv_test_no_reg[] = {
"cmd",
"-testnet",
"-noregtest"};
655 const char* argv_both[] = {
"cmd",
"-testnet",
"-regtest"};
659 const char* testnetconf =
"testnet=1\nregtest=0\n[test]\nregtest=1";
759 template <
typename Fn>
767 for (
bool soft_set : {
false,
true}) {
768 for (
bool force_set : {
false,
true}) {
771 for (
bool net_specific : {
false,
true}) {
772 fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
784 const std::string& section,
785 const std::string&
name,
786 const std::string& value_prefix)
788 std::vector<std::string>
values;
790 for (
Action action : actions) {
791 if (action ==
NONE)
break;
795 for (
int i = 0; i < 2; ++i) {
814 FILE* out_file =
nullptr;
815 if (
const char* out_path = getenv(
"ARGS_MERGE_TEST_OUT")) {
817 if (!out_file)
throw std::system_error(errno, std::generic_category(),
"fopen failed");
820 ForEachMergeSetup([&](
const ActionList& arg_actions,
const ActionList& conf_actions,
bool soft_set,
bool force_set,
821 const std::string& section,
const std::string& network,
bool net_specific) {
825 std::string desc =
"net=";
827 parser.m_network = network;
829 const std::string&
name = net_specific ?
"wallet" :
"server";
830 const std::string key =
"-" +
name;
834 auto args = GetValues(arg_actions, section,
name,
"a");
835 std::vector<const char*> argv = {
"ignored"};
836 for (
auto& arg :
args) {
840 argv.push_back(arg.c_str());
847 for (
auto& conf_val : GetValues(conf_actions, section,
name,
"c")) {
853 std::istringstream conf_stream(conf);
881 desc += parser.
GetArg(key,
"default");
883 for (
const auto& arg : parser.
GetArgs(key)) {
890 if (!ignored.empty()) {
891 desc +=
" | ignored";
892 for (
const auto& arg : ignored) {
902 BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
907 if (fclose(out_file))
throw std::system_error(errno, std::generic_category(),
"fclose failed");
913 std::string out_sha_hex =
HexStr(out_sha_bytes);
924 BOOST_CHECK_EQUAL(out_sha_hex,
"f1ee5ab094cc43d16a6086fa7f2c10389e0f99902616b31bbf29189972ad1473");
935 template <
typename Fn>
949 FILE* out_file =
nullptr;
950 if (
const char* out_path = getenv(
"CHAIN_MERGE_TEST_OUT")) {
952 if (!out_file)
throw std::system_error(errno, std::generic_category(),
"fopen failed");
955 ForEachMergeSetup([&](
const ActionList& arg_actions,
const ActionList& conf_actions) {
961 auto arg = [](Action action) {
return action == ENABLE_TEST ?
"-testnet=1" :
962 action == DISABLE_TEST ?
"-testnet=0" :
963 action == NEGATE_TEST ?
"-notestnet=1" :
964 action == ENABLE_REG ?
"-regtest=1" :
965 action == DISABLE_REG ?
"-regtest=0" :
966 action == NEGATE_REG ?
"-noregtest=1" :
nullptr; };
969 std::vector<const char*> argv = {
"ignored"};
970 for (Action action : arg_actions) {
971 const char* argstr = arg(action);
973 argv.push_back(argstr);
982 for (Action action : conf_actions) {
983 const char* argstr = arg(action);
990 std::istringstream conf_stream(conf);
997 }
catch (
const std::runtime_error& e) {
1005 BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
1010 if (fclose(out_file))
throw std::system_error(errno, std::generic_category(),
"fclose failed");
1016 std::string out_sha_hex =
HexStr(out_sha_bytes);
1027 BOOST_CHECK_EQUAL(out_sha_hex,
"9e60306e1363528bbc19a47f22bcede88e5d6815212f18ec8e6cdc4638dddab4");
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::string ChainTypeToString(ChainType chain)
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
common::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
std::string GetChainTypeString() const
Returns the appropriate chain type string from the program arguments.
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.
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.
fs::path GetDataDirBase() const
Get data directory path.
std::vector< common::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.
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.
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
void Finalize(Span< unsigned char > output)
CHash256 & Write(Span< const unsigned char > input)
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:...
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static std::string PathToString(const path &path)
Convert path object to a byte string.
FILE * fopen(const fs::path &p, const char *mode)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
#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.
void ForEachMergeSetup(Fn &&fn)
Enumerate all possible test configurations.
static constexpr int MAX_ACTIONS
Max number of actions to sequence together.
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.
Action[MAX_ACTIONS] ActionList
void ForEachMergeSetup(Fn &&fn)
Enumerate all possible test configurations.
Action[MAX_ACTIONS] ActionList
static constexpr int MAX_ACTIONS
Expect(common::SettingsValue s)
Expect & List(std::vector< std::string > m)
Expect & String(const char *s)
std::optional< int64_t > int_value
std::optional< std::vector< std::string > > list_value
Expect & Error(const char *e)
common::SettingsValue setting
std::optional< bool > bool_value
const char * string_value
std::string Parse(const char *arg)
common::SettingsValue GetSetting(const std::string &arg) const
Get setting value.
void SetupArgs(const std::vector< std::pair< std::string, unsigned int > > &args)
void SetNetworkOnlyArg(const std::string arg)
std::vector< common::SettingsValue > GetSettingsList(const std::string &arg) const
Get list of setting values.
void ReadConfigString(const std::string str_config)
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.
#define ASSERT_DEBUG_LOG(message)