Branch data Line data Source code
1 : : // Copyright (c) 2011-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <common/args.h>
6 : : #include <sync.h>
7 : : #include <test/util/logging.h>
8 : : #include <test/util/setup_common.h>
9 : : #include <test/util/str.h>
10 : : #include <univalue.h>
11 : : #include <util/chaintype.h>
12 : : #include <util/fs.h>
13 : : #include <util/strencodings.h>
14 : :
15 : : #include <array>
16 : : #include <optional>
17 : : #include <cstdint>
18 : : #include <cstring>
19 : : #include <vector>
20 : :
21 : : #include <boost/test/unit_test.hpp>
22 : :
23 : : using util::ToString;
24 : :
25 : : BOOST_FIXTURE_TEST_SUITE(argsman_tests, BasicTestingSetup)
26 : :
27 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_datadir)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
28 : : {
29 : : // Use local args variable instead of m_args to avoid making assumptions about test setup
30 : 1 : ArgsManager args;
31 [ - + + - : 3 : args.ForceSetArg("-datadir", fs::PathToString(m_path_root));
+ - ]
32 : :
33 [ + - ]: 1 : const fs::path dd_norm = args.GetDataDirBase();
34 : :
35 [ - + + - : 4 : args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/");
+ - + - ]
36 [ + - ]: 1 : args.ClearPathCache();
37 [ + - + - : 1 : BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
+ - ]
38 : :
39 [ - + + - : 4 : args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.");
+ - + - ]
40 [ + - ]: 1 : args.ClearPathCache();
41 [ + - + - : 1 : BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
+ - ]
42 : :
43 [ - + + - : 4 : args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/./");
+ - + - ]
44 [ + - ]: 1 : args.ClearPathCache();
45 [ + - + - : 1 : BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
+ - ]
46 : :
47 [ - + + - : 4 : args.ForceSetArg("-datadir", fs::PathToString(dd_norm) + "/.//");
+ - + - ]
48 [ + - ]: 1 : args.ClearPathCache();
49 [ + - + - : 2 : BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase());
+ - ]
50 : 1 : }
51 : :
52 : 0 : struct TestArgsManager : public ArgsManager
53 : : {
54 : 14 : void ReadConfigString(const std::string& str_config)
55 : : {
56 [ + - + - ]: 28 : BOOST_REQUIRE(ArgsManager::ReadConfigString(str_config));
57 : 14 : }
58 : 54 : void SetupArgs(const std::vector<std::pair<std::string, unsigned int>>& args)
59 : : {
60 [ + + ]: 137 : for (const auto& arg : args) {
61 [ + - ]: 166 : AddArg(arg.first, "", arg.second, OptionsCategory::OPTIONS);
62 : : }
63 : 54 : }
64 : :
65 : : // make protected methods available for testing
66 : : using ArgsManager::ReadConfigStream;
67 : : };
68 : :
69 : : //! Test GetSetting and GetArg type coercion, negation, and default value handling.
70 : 2 : class CheckValueTest : public TestChain100Setup
71 : : {
72 : : public:
73 : 13 : struct Expect {
74 : : common::SettingsValue setting;
75 : : bool default_string = false;
76 : : bool default_int = false;
77 : : bool default_bool = false;
78 : : const char* string_value = nullptr;
79 : : std::optional<int64_t> int_value;
80 : : std::optional<bool> bool_value;
81 : : std::optional<std::vector<std::string>> list_value;
82 : : const char* error = nullptr;
83 : :
84 : 13 : explicit Expect(common::SettingsValue s) : setting(std::move(s)) {}
85 : 1 : Expect& DefaultString() { default_string = true; return *this; }
86 : 1 : Expect& DefaultInt() { default_int = true; return *this; }
87 : 1 : Expect& DefaultBool() { default_bool = true; return *this; }
88 : 12 : Expect& String(const char* s) { string_value = s; return *this; }
89 : 12 : Expect& Int(int64_t i) { int_value = i; return *this; }
90 [ + - + - : 8 : Expect& Bool(bool b) { bool_value = b; return *this; }
+ - + - +
- + - + -
+ - ]
91 : 12 : Expect& List(std::vector<std::string> m) { list_value = std::move(m); return *this; }
92 : : Expect& Error(const char* e) { error = e; return *this; }
93 : : };
94 : :
95 : 13 : void CheckValue(unsigned int flags, const char* arg, const Expect& expect)
96 : : {
97 : 13 : TestArgsManager test;
98 [ + - + + : 26 : test.SetupArgs({{"-value", flags}});
- - ]
99 : 13 : const char* argv[] = {"ignored", arg};
100 [ + + ]: 13 : std::string error;
101 [ + + + - ]: 14 : bool success = test.ParseParameters(arg ? 2 : 1, argv, error);
102 : :
103 [ + - + - : 13 : BOOST_CHECK_EQUAL(test.GetSetting("-value").write(), expect.setting.write());
+ - + - +
- + - ]
104 [ + - + - ]: 13 : auto settings_list = test.GetSettingsList("-value");
105 [ + + + + ]: 13 : if (expect.setting.isNull() || expect.setting.isFalse()) {
106 [ + - - + : 5 : BOOST_CHECK_EQUAL(settings_list.size(), 0U);
+ - ]
107 : : } else {
108 [ + - - + : 8 : BOOST_CHECK_EQUAL(settings_list.size(), 1U);
+ - ]
109 [ + - + - : 8 : BOOST_CHECK_EQUAL(settings_list[0].write(), expect.setting.write());
+ - + - ]
110 : : }
111 : :
112 [ - + ]: 13 : if (expect.error) {
113 [ # # # # : 0 : BOOST_CHECK(!success);
# # ]
114 [ # # # # ]: 0 : BOOST_CHECK_NE(error.find(expect.error), std::string::npos);
115 : : } else {
116 [ + - + - : 26 : BOOST_CHECK(success);
+ - ]
117 [ + - + - ]: 13 : BOOST_CHECK_EQUAL(error, "");
118 : : }
119 : :
120 [ + + ]: 13 : if (expect.default_string) {
121 [ + - + - : 1 : BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), "zzzzz");
+ - + - +
- ]
122 [ + - ]: 12 : } else if (expect.string_value) {
123 [ + - + - : 12 : BOOST_CHECK_EQUAL(test.GetArg("-value", "zzzzz"), expect.string_value);
+ - + - +
- ]
124 : : } else {
125 [ # # # # ]: 0 : BOOST_CHECK(!success);
126 : : }
127 : :
128 [ + + ]: 13 : if (expect.default_int) {
129 [ + - + - : 2 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), 99999);
+ - ]
130 [ + - ]: 12 : } else if (expect.int_value) {
131 [ + - + - : 24 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), *expect.int_value);
+ - ]
132 : : } else {
133 [ # # # # ]: 0 : BOOST_CHECK(!success);
134 : : }
135 : :
136 [ + + ]: 13 : if (expect.default_bool) {
137 [ + - + - : 1 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), false);
+ - + - ]
138 [ + - + - : 1 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), true);
+ - + - ]
139 [ + - ]: 12 : } else if (expect.bool_value) {
140 [ + - + - : 12 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), *expect.bool_value);
+ - + - ]
141 [ + - + - : 12 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), *expect.bool_value);
+ - + - ]
142 : : } else {
143 [ # # # # ]: 0 : BOOST_CHECK(!success);
144 : : }
145 : :
146 [ + - ]: 13 : if (expect.list_value) {
147 [ + - + - ]: 13 : auto l = test.GetArgs("-value");
148 [ + - + - : 26 : BOOST_CHECK_EQUAL_COLLECTIONS(l.begin(), l.end(), expect.list_value->begin(), expect.list_value->end());
+ - ]
149 : 13 : } else {
150 [ # # # # ]: 0 : BOOST_CHECK(!success);
151 : : }
152 [ + - + - ]: 26 : }
153 : : };
154 : :
155 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_CheckValue, CheckValueTest)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
156 : : {
157 : 1 : using M = ArgsManager;
158 : :
159 [ + - ]: 2 : CheckValue(M::ALLOW_ANY, nullptr, Expect{{}}.DefaultString().DefaultInt().DefaultBool().List({}));
160 [ + - ]: 2 : CheckValue(M::ALLOW_ANY, "-novalue", Expect{false}.String("0").Int(0).Bool(false).List({}));
161 [ + - ]: 2 : CheckValue(M::ALLOW_ANY, "-novalue=", Expect{false}.String("0").Int(0).Bool(false).List({}));
162 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-novalue=0", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));
163 [ + - ]: 2 : CheckValue(M::ALLOW_ANY, "-novalue=1", Expect{false}.String("0").Int(0).Bool(false).List({}));
164 [ + - ]: 2 : CheckValue(M::ALLOW_ANY, "-novalue=2", Expect{false}.String("0").Int(0).Bool(false).List({}));
165 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-novalue=abc", Expect{true}.String("1").Int(1).Bool(true).List({"1"}));
166 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value", Expect{""}.String("").Int(0).Bool(true).List({""}));
167 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value=", Expect{""}.String("").Int(0).Bool(true).List({""}));
168 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value=0", Expect{"0"}.String("0").Int(0).Bool(false).List({"0"}));
169 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value=1", Expect{"1"}.String("1").Int(1).Bool(true).List({"1"}));
170 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value=2", Expect{"2"}.String("2").Int(2).Bool(true).List({"2"}));
171 [ + - + - ]: 3 : CheckValue(M::ALLOW_ANY, "-value=abc", Expect{"abc"}.String("abc").Int(0).Bool(false).List({"abc"}));
172 : 1 : }
173 : :
174 : : struct NoIncludeConfTest {
175 : 3 : std::string Parse(const char* arg)
176 : : {
177 : 3 : TestArgsManager test;
178 [ + - + - : 9 : test.SetupArgs({{"-includeconf", ArgsManager::ALLOW_ANY}});
+ + - - ]
179 : 3 : std::array argv{"ignored", arg};
180 [ + - ]: 3 : std::string error;
181 [ + - ]: 3 : (void)test.ParseParameters(argv.size(), argv.data(), error);
182 : 3 : return error;
183 [ + - ]: 6 : }
184 : : };
185 : :
186 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_NoIncludeConf, NoIncludeConfTest)
+ - + - -
+ + - + -
+ - + - +
- - + + -
+ - + - +
- + - - +
+ - + - +
- + - + -
- + + - +
- + - + -
+ - - + +
- ]
187 : : {
188 [ + - ]: 1 : BOOST_CHECK_EQUAL(Parse("-noincludeconf"), "");
189 [ + - ]: 1 : BOOST_CHECK_EQUAL(Parse("-includeconf"), "-includeconf cannot be used from commandline; -includeconf=\"\"");
190 [ + - ]: 1 : BOOST_CHECK_EQUAL(Parse("-includeconf=file"), "-includeconf cannot be used from commandline; -includeconf=\"file\"");
191 : 1 : }
192 : :
193 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ParseParameters)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
194 : : {
195 : 1 : TestArgsManager testArgs;
196 : 1 : const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
197 : 1 : const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
198 : 1 : const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);
199 : 1 : const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
200 : :
201 : 1 : const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
202 : :
203 [ + - ]: 1 : std::string error;
204 [ + - + + : 5 : testArgs.SetupArgs({a, b, ccc, d});
- - ]
205 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(0, argv_test, error));
+ - + - ]
206 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
207 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.empty());
208 [ + - ]: 2 : BOOST_CHECK(s.ro_config.empty());
209 : 1 : });
210 : :
211 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error));
+ - + - ]
212 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
213 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.empty());
214 [ + - ]: 2 : BOOST_CHECK(s.ro_config.empty());
215 : 1 : });
216 : :
217 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error));
+ - + - ]
218 : : // expectation: -ignored is ignored (program name argument),
219 : : // -a, -b and -ccc end up in map, -d ignored because it is after
220 : : // a non-option argument (non-GNU option parsing)
221 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgSet("-a"));
+ - + - +
- ]
222 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgSet("-b"));
+ - + - +
- ]
223 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgSet("-ccc"));
+ - + - +
- ]
224 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgSet("f"));
+ - + - +
- ]
225 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgSet("-d"));
+ - + - +
- ]
226 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
227 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.size() == 3);
228 [ + - ]: 2 : BOOST_CHECK(s.ro_config.empty());
229 [ + - + - ]: 2 : BOOST_CHECK(s.command_line_options.contains("a"));
230 [ + - + - ]: 2 : BOOST_CHECK(s.command_line_options.contains("b"));
231 [ + - + - ]: 2 : BOOST_CHECK(s.command_line_options.contains("ccc"));
232 [ + - + - ]: 2 : BOOST_CHECK(!s.command_line_options.contains("f"));
233 [ + - + - ]: 2 : BOOST_CHECK(!s.command_line_options.contains("d"));
234 : :
235 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("a").size() == 1);
- + + - ]
236 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("a").front().get_str() == "");
+ - + - ]
237 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").size() == 2);
- + + - ]
238 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").front().get_str() == "argument");
+ - + - ]
239 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").back().get_str() == "multiple");
+ - + - ]
240 : 1 : });
241 [ + - + - : 3 : BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
+ - + - ]
242 [ + - + - : 2 : }
+ - + - +
- - - ]
243 : :
244 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
245 : : {
246 : 1 : TestArgsManager test;
247 [ + - + - : 3 : test.SetupArgs({{"-registered", ArgsManager::ALLOW_ANY}});
+ + - - ]
248 : :
249 : 1 : const char* argv[] = {"ignored", "-registered"};
250 [ + - ]: 1 : std::string error;
251 [ + - + - : 2 : BOOST_CHECK(test.ParseParameters(2, argv, error));
+ - + - ]
252 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "");
253 : :
254 : 1 : argv[1] = "-unregistered";
255 [ + - + - : 2 : BOOST_CHECK(!test.ParseParameters(2, argv, error));
+ - + - ]
256 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered");
257 : :
258 : : // Make sure registered parameters prefixed with a chain type trigger errors.
259 : : // (Previously, they were accepted and ignored.)
260 : 1 : argv[1] = "-test.registered";
261 [ + - + - : 2 : BOOST_CHECK(!test.ParseParameters(2, argv, error));
+ - + - ]
262 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "Invalid parameter -test.registered");
263 [ + - ]: 2 : }
264 : :
265 : 31 : static void TestParse(const std::string& str, bool expected_bool, int64_t expected_int)
266 : : {
267 : 31 : TestArgsManager test;
268 [ + - + - : 93 : test.SetupArgs({{"-value", ArgsManager::ALLOW_ANY}});
+ + - - ]
269 [ + - ]: 31 : std::string arg = "-value=" + str;
270 [ + - ]: 31 : const char* argv[] = {"ignored", arg.c_str()};
271 [ + - ]: 31 : std::string error;
272 [ + - + - : 62 : BOOST_CHECK(test.ParseParameters(2, argv, error));
+ - + - ]
273 [ + - + - : 31 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), expected_bool);
+ - + - ]
274 [ + - + - : 31 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), expected_bool);
+ - + - ]
275 [ + - + - : 62 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99998), expected_int);
+ - ]
276 [ + - + - : 62 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), expected_int);
+ - ]
277 [ + - ]: 62 : }
278 : :
279 : : // Test bool and int parsing.
280 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ArgParsing)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
281 : : {
282 : : // Some of these cases could be ambiguous or surprising to users, and might
283 : : // be worth triggering errors or warnings in the future. But for now basic
284 : : // test coverage is useful to avoid breaking backwards compatibility
285 : : // unintentionally.
286 [ + - ]: 1 : TestParse("", true, 0);
287 [ + - ]: 1 : TestParse(" ", false, 0);
288 [ + - ]: 1 : TestParse("0", false, 0);
289 [ + - ]: 1 : TestParse("0 ", false, 0);
290 [ + - ]: 1 : TestParse(" 0", false, 0);
291 [ + - ]: 1 : TestParse("+0", false, 0);
292 [ + - ]: 1 : TestParse("-0", false, 0);
293 [ + - ]: 1 : TestParse("5", true, 5);
294 [ + - ]: 1 : TestParse("5 ", true, 5);
295 [ + - ]: 1 : TestParse(" 5", true, 5);
296 [ + - ]: 1 : TestParse("+5", true, 5);
297 [ + - ]: 1 : TestParse("-5", true, -5);
298 [ + - ]: 1 : TestParse("0 5", false, 0);
299 [ + - ]: 1 : TestParse("5 0", true, 5);
300 [ + - ]: 1 : TestParse("050", true, 50);
301 [ + - ]: 1 : TestParse("0.", false, 0);
302 [ + - ]: 1 : TestParse("5.", true, 5);
303 [ + - ]: 1 : TestParse("0.0", false, 0);
304 [ + - ]: 1 : TestParse("0.5", false, 0);
305 [ + - ]: 1 : TestParse("5.0", true, 5);
306 [ + - ]: 1 : TestParse("5.5", true, 5);
307 [ + - ]: 1 : TestParse("x", false, 0);
308 [ + - ]: 1 : TestParse("x0", false, 0);
309 [ + - ]: 1 : TestParse("x5", false, 0);
310 [ + - ]: 1 : TestParse("0x", false, 0);
311 [ + - ]: 1 : TestParse("5x", true, 5);
312 [ + - ]: 1 : TestParse("0x5", false, 0);
313 [ + - ]: 1 : TestParse("false", false, 0);
314 [ + - ]: 1 : TestParse("true", false, 0);
315 [ + - ]: 1 : TestParse("yes", false, 0);
316 [ + - ]: 1 : TestParse("no", false, 0);
317 : 1 : }
318 : :
319 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetBoolArg)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
320 : : {
321 : 1 : TestArgsManager testArgs;
322 : 1 : const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
323 : 1 : const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
324 : 1 : const auto c = std::make_pair("-c", ArgsManager::ALLOW_ANY);
325 : 1 : const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
326 : 1 : const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
327 : 1 : const auto f = std::make_pair("-f", ArgsManager::ALLOW_ANY);
328 : :
329 : 1 : const char *argv_test[] = {
330 : : "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
331 [ + - ]: 1 : std::string error;
332 [ + - + + : 7 : testArgs.SetupArgs({a, b, c, d, e, f});
- - ]
333 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error));
+ - ]
334 : :
335 : : // Each letter should be set.
336 [ + + ]: 8 : for (const char opt : "abcdef")
337 [ + - + - : 14 : BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
+ - + + -
+ + - -
- ]
338 : :
339 : : // Nothing else should be in the map
340 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
341 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.size() == 6);
342 [ + - ]: 2 : BOOST_CHECK(s.ro_config.empty());
343 : 1 : });
344 : :
345 : : // The -no prefix should get stripped on the way in.
346 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgSet("-nob"));
+ - + - +
- ]
347 : :
348 : : // The -b option is flagged as negated, and nothing else is
349 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgNegated("-b"));
+ - + - +
- ]
350 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-a"));
+ - + - +
- ]
351 : :
352 : : // Check expected values.
353 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
+ - + - +
- ]
354 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
+ - + - +
- ]
355 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
+ - + - +
- ]
356 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
+ - + - +
- ]
357 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
+ - + - +
- ]
358 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
+ - + - ]
359 [ + - + - : 2 : }
+ - + - +
- + - + -
- - ]
360 : :
361 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
362 : : {
363 : : // Test some awful edge cases that hopefully no user will ever exercise.
364 : 1 : TestArgsManager testArgs;
365 : :
366 : : // Params test
367 : 1 : const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
368 : 1 : const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
369 : 1 : const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
370 [ + - + + : 3 : testArgs.SetupArgs({foo, bar});
- - ]
371 [ + - ]: 1 : std::string error;
372 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(4, argv_test, error));
+ - + - ]
373 : :
374 : : // This was passed twice, second one overrides the negative setting.
375 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
376 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
+ - + - +
- + - ]
377 : :
378 : : // A double negative is a positive, and not marked as negated.
379 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
380 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+ - + - +
- + - ]
381 : :
382 : : // Config test
383 : 1 : const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
384 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error));
+ - + - ]
385 [ + - + - ]: 1 : testArgs.ReadConfigString(conf_test);
386 : :
387 : : // This was passed twice, second one overrides the negative setting,
388 : : // and the value.
389 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
390 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
+ - + - +
- + - ]
391 : :
392 : : // A double negative is a positive, and does not count as negated.
393 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
394 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+ - + - +
- + - ]
395 : :
396 : : // Combined test
397 : 1 : const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
398 : 1 : const char *combo_test_conf = "foo=1\nnobar=1\n";
399 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(3, combo_test_args, error));
+ - + - ]
400 [ + - + - ]: 1 : testArgs.ReadConfigString(combo_test_conf);
401 : :
402 : : // Command line overrides, but doesn't erase old setting
403 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
404 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
+ - + - +
- + - ]
405 [ + - + - : 3 : BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
+ - + - +
- ]
406 : :
407 : : // Command line overrides, but doesn't erase old setting
408 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
409 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
+ - + - +
- + - ]
410 [ + - + - : 3 : BOOST_REQUIRE(testArgs.GetArgs("-bar").size() == 1);
+ - + - +
- ]
411 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArgs("-bar").front() == "");
+ - + - ]
412 [ + - + - : 2 : }
+ - - - ]
413 : :
414 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
415 : : {
416 : 1 : const char *str_config =
417 : : "a=\n"
418 : : "b=1\n"
419 : : "ccc=argument\n"
420 : : "ccc=multiple\n"
421 : : "d=e\n"
422 : : "nofff=1\n"
423 : : "noggg=0\n"
424 : : "h=1\n"
425 : : "noh=1\n"
426 : : "noi=1\n"
427 : : "i=1\n"
428 : : "sec1.ccc=extend1\n"
429 : : "\n"
430 : : "[sec1]\n"
431 : : "ccc=extend2\n"
432 : : "d=eee\n"
433 : : "h=1\n"
434 : : "[sec2]\n"
435 : : "ccc=extend3\n"
436 : : "iii=2\n";
437 : :
438 : 1 : TestArgsManager test_args;
439 : 1 : const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
440 : 1 : const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
441 : 1 : const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);
442 : 1 : const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
443 : 1 : const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
444 : 1 : const auto fff = std::make_pair("-fff", ArgsManager::ALLOW_ANY);
445 : 1 : const auto ggg = std::make_pair("-ggg", ArgsManager::ALLOW_ANY);
446 : 1 : const auto h = std::make_pair("-h", ArgsManager::ALLOW_ANY);
447 : 1 : const auto i = std::make_pair("-i", ArgsManager::ALLOW_ANY);
448 : 1 : const auto iii = std::make_pair("-iii", ArgsManager::ALLOW_ANY);
449 [ + - + + : 11 : test_args.SetupArgs({a, b, ccc, d, e, fff, ggg, h, i, iii});
- - ]
450 : :
451 [ + - + - ]: 1 : test_args.ReadConfigString(str_config);
452 : : // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
453 : : // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
454 : :
455 [ + - ]: 2 : test_args.LockSettings([&](const common::Settings& s) {
456 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.empty());
457 [ + - ]: 2 : BOOST_CHECK(s.ro_config.size() == 3);
458 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").size() == 8);
+ - ]
459 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").size() == 3);
+ - ]
460 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").size() == 2);
+ - ]
461 : :
462 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("a"));
+ - + - ]
463 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("b"));
+ - + - ]
464 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("ccc"));
+ - + - ]
465 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("d"));
+ - + - ]
466 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("fff"));
+ - + - ]
467 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("ggg"));
+ - + - ]
468 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("h"));
+ - + - ]
469 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("i"));
+ - + - ]
470 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").contains("ccc"));
+ - + - ]
471 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").contains("h"));
+ - + - ]
472 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").contains("ccc"));
+ - + - ]
473 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").contains("iii"));
+ - + - ]
474 : 1 : });
475 : :
476 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-a"));
+ - + - +
- ]
477 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-b"));
+ - + - +
- ]
478 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-ccc"));
+ - + - +
- ]
479 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-d"));
+ - + - +
- ]
480 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-fff"));
+ - + - +
- ]
481 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-ggg"));
+ - + - +
- ]
482 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-h"));
+ - + - +
- ]
483 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-i"));
+ - + - +
- ]
484 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgSet("-zzz"));
+ - + - +
- ]
485 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgSet("-iii"));
+ - + - +
- ]
486 : :
487 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
+ - + - +
- ]
488 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
+ - + - +
- ]
489 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ccc", "xxx"), "argument");
+ - + - +
- ]
490 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-d", "xxx"), "e");
+ - + - +
- ]
491 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
+ - + - +
- ]
492 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
+ - + - +
- ]
493 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-h", "xxx"), "0");
+ - + - +
- ]
494 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-i", "xxx"), "1");
+ - + - +
- ]
495 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
+ - + - +
- ]
496 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
+ - + - +
- ]
497 : :
498 [ + + ]: 3 : for (const bool def : {false, true}) {
499 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-a", def));
+ - + - +
- ]
500 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-b", def));
+ - + - +
- ]
501 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-ccc", def));
+ - + - +
- ]
502 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-d", def));
+ - + - +
- ]
503 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-fff", def));
+ - + - +
- ]
504 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-ggg", def));
+ - + - +
- ]
505 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-h", def));
+ - + - +
- ]
506 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-i", def));
+ - + - +
- ]
507 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-zzz", def) == def);
+ - + - +
- ]
508 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-iii", def) == def);
+ - + - ]
509 : : }
510 : :
511 [ + - + - : 3 : BOOST_REQUIRE(test_args.GetArgs("-a").size() == 1);
+ - + - +
- ]
512 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-a").front() == "");
+ - + - +
- ]
513 [ + - + - : 3 : BOOST_REQUIRE(test_args.GetArgs("-b").size() == 1);
+ - + - +
- ]
514 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-b").front() == "1");
+ - + - +
- ]
515 [ + - + - : 3 : BOOST_REQUIRE(test_args.GetArgs("-ccc").size() == 2);
+ - + - +
- ]
516 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-ccc").front() == "argument");
+ - + - +
- ]
517 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-ccc").back() == "multiple");
+ - + - +
- ]
518 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
+ - + - +
- ]
519 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
+ - + - +
- ]
520 [ + - + - : 3 : BOOST_REQUIRE(test_args.GetArgs("-ggg").size() == 1);
+ - + - +
- ]
521 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-ggg").front() == "1");
+ - + - +
- ]
522 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
+ - + - +
- ]
523 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
+ - + - +
- ]
524 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
+ - + - +
- ]
525 [ + - + - : 3 : BOOST_REQUIRE(test_args.GetArgs("-i").size() == 1);
+ - + - +
- ]
526 [ + - + - : 2 : BOOST_CHECK(test_args.GetArgs("-i").front() == "1");
+ - + - +
- ]
527 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
+ - + - +
- ]
528 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
+ - + - +
- ]
529 : :
530 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-a"));
+ - + - +
- ]
531 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-b"));
+ - + - +
- ]
532 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
+ - + - +
- ]
533 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-d"));
+ - + - +
- ]
534 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgNegated("-fff"));
+ - + - +
- ]
535 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
+ - + - +
- ]
536 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
+ - + - +
- ]
537 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
+ - + - +
- ]
538 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
+ - + - +
- ]
539 : :
540 : : // Test sections work
541 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec1");
542 : :
543 : : // same as original
544 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
+ - + - +
- ]
545 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
+ - + - +
- ]
546 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
+ - + - +
- ]
547 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
+ - + - +
- ]
548 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
+ - + - +
- ]
549 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
+ - + - +
- ]
550 : : // d is overridden
551 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ - + - +
- + - ]
552 : : // section-specific setting
553 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+ - + - +
- + - ]
554 : : // section takes priority for multiple values
555 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
+ - + - +
- + - ]
556 : : // check multiple values works
557 [ + - ]: 1 : const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
558 [ + - + - ]: 1 : const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
559 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
+ - + - ]
560 : :
561 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec2");
562 : :
563 : : // same as original
564 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");
+ - + - +
- + - ]
565 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-b", "xxx") == "1");
+ - + - +
- + - ]
566 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
+ - + - +
- + - ]
567 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-fff", "xxx") == "0");
+ - + - +
- + - ]
568 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ggg", "xxx") == "1");
+ - + - +
- + - ]
569 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-zzz", "xxx") == "xxx");
+ - + - +
- + - ]
570 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- + - ]
571 : : // section-specific setting
572 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
+ - + - +
- + - ]
573 : : // section takes priority for multiple values
574 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
+ - + - +
- + - ]
575 : : // check multiple values works
576 [ + - ]: 1 : const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
577 [ + - + - ]: 1 : const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
578 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
+ - + - ]
579 : :
580 : : // Test section only options
581 : :
582 : 1 : const auto ccc2 = std::make_pair("-ccc", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
583 : 1 : const auto d2 = std::make_pair("-d", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
584 : 1 : const auto h2 = std::make_pair("-h", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
585 [ + - ]: 1 : test_args.ClearArgs();
586 [ + - + + : 11 : test_args.SetupArgs({a, b, ccc2, d2, e, fff, ggg, h2, i, iii});
- - ]
587 [ + - + - ]: 1 : test_args.ReadConfigString(str_config);
588 : :
589 [ + - + - ]: 1 : test_args.SelectConfigNetwork(ChainTypeToString(ChainType::MAIN));
590 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
+ - + - +
- + - ]
591 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ - + - +
- ]
592 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- + - ]
593 : :
594 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec1");
595 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ - + - +
- + - ]
596 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
+ - + - +
- ]
597 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ - + - +
- ]
598 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+ - + - +
- + - ]
599 : :
600 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec2");
601 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
+ - + - +
- + - ]
602 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
+ - + - +
- ]
603 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
+ - + - +
- ]
604 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- ]
605 [ + - + - : 3 : }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- - - - ]
606 : :
607 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetArg)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
608 : : {
609 : 1 : TestArgsManager testArgs;
610 [ + - ]: 2 : testArgs.LockSettings([&](common::Settings& s) {
611 : 1 : s.command_line_options.clear();
612 [ + - + - : 3 : s.command_line_options["strtest1"] = {"string..."};
+ - + + -
- ]
613 : : // strtest2 undefined on purpose
614 [ + - + - : 3 : s.command_line_options["inttest1"] = {"12345"};
+ - + + -
- ]
615 [ + - + - : 3 : s.command_line_options["inttest2"] = {"81985529216486895"};
+ - + + -
- ]
616 : : // inttest3 undefined on purpose
617 [ + - + - : 3 : s.command_line_options["booltest1"] = {""};
+ - + + -
- ]
618 : : // booltest2 undefined on purpose
619 [ + - + - : 3 : s.command_line_options["booltest3"] = {"0"};
+ - + + -
- ]
620 [ + - + - : 3 : s.command_line_options["booltest4"] = {"1"};
+ - + + -
- ]
621 : :
622 : : // priorities
623 [ + - + - : 4 : s.command_line_options["pritest1"] = {"a", "b"};
+ - + + -
- ]
624 [ + - + - : 4 : s.ro_config[""]["pritest2"] = {"a", "b"};
+ - + - +
- + + -
- ]
625 [ + - + - : 3 : s.command_line_options["pritest3"] = {"a"};
+ - + + -
- ]
626 [ + - + - : 3 : s.ro_config[""]["pritest3"] = {"b"};
+ - + - +
- + + -
- ]
627 [ + - + - : 4 : s.command_line_options["pritest4"] = {"a","b"};
+ - + + -
- ]
628 [ + - + - : 4 : s.ro_config[""]["pritest4"] = {"c","d"};
+ - + - +
- + + -
- ]
629 [ + - + - : 13 : });
+ - + - +
- + - + -
+ - - - -
- - - -
- ]
630 : :
631 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
+ - + - +
- ]
632 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
+ - + - +
- ]
633 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest1", -1), 12345);
+ - ]
634 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest2", -1), 81985529216486895LL);
+ - ]
635 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest3", -1), -1);
+ - ]
636 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
+ - + - ]
637 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
+ - + - ]
638 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
+ - + - ]
639 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
+ - + - ]
640 : :
641 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
+ - + - +
- ]
642 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
+ - + - +
- ]
643 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
+ - + - +
- ]
644 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
+ - + - +
- ]
645 : 1 : }
646 : :
647 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_AddCommand)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
648 : : {
649 : 1 : enum TestFail { SUCCESS,
650 : : PARSE_FAIL,
651 : : PARSE_ERROR,
652 : : NO_COMMAND,
653 : : COMMAND_OPTS_BAD_DETAILS,
654 : : COMMAND_OPTS };
655 : :
656 : 17 : auto testfn = [&](const auto& argv) -> TestFail {
657 : 16 : TestArgsManager test_args;
658 [ + - + - : 32 : test_args.AddArg("-opt1=<file name>", "Opt 1", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::COMMAND_OPTIONS);
+ - ]
659 [ + - + - : 32 : test_args.AddArg("-opt2=<file name>", "Opt 2", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::COMMAND_OPTIONS);
+ - ]
660 [ + - + - : 32 : test_args.AddArg("-opt3=<file name>", "Opt 3", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
+ - ]
661 : :
662 [ + - + - : 32 : test_args.AddCommand("cmd1", "No specific options");
+ - ]
663 [ + - + - : 32 : test_args.AddCommand("cmd2", "Opt 1", {"-opt1"});
+ - + - ]
664 [ + - + - : 32 : test_args.AddCommand("cmd3", "Opt 1 or 2", {"-opt1", "-opt2"});
+ - + - +
- ]
665 : :
666 [ + - ]: 16 : std::string error;
667 [ + - + + ]: 16 : if (!test_args.ParseParameters(argv.size(), argv.data(), error)) return PARSE_FAIL;
668 [ + - ]: 14 : if (!error.empty()) return PARSE_ERROR;
669 [ + - ]: 14 : const auto command = test_args.GetCommand();
670 [ + + ]: 14 : if (!command) return NO_COMMAND;
671 [ + - ]: 13 : std::vector<std::string> details;
672 [ + - + + ]: 13 : if (!test_args.CheckCommandOptions(command->command, &details)) {
673 [ + - ]: 5 : if (details.empty()) return COMMAND_OPTS_BAD_DETAILS;
674 : 5 : return COMMAND_OPTS;
675 [ - + ]: 8 : } else if (!details.empty()) {
676 : 0 : return COMMAND_OPTS_BAD_DETAILS;
677 : : }
678 : : return SUCCESS;
679 : 43 : };
680 : :
681 [ + - ]: 1 : BOOST_CHECK_EQUAL(COMMAND_OPTS, testfn(std::array{"x", "-opt1=foo", "cmd1"}));
682 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "cmd1", "-opt1=foo"})); // things after the command are "args" and left unparsed, not options
683 : :
684 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt1=foo", "cmd2"}));
685 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt1=foo", "cmd3"}));
686 [ + - ]: 1 : BOOST_CHECK_EQUAL(COMMAND_OPTS, testfn(std::array{"x", "-opt2=foo", "cmd1"}));
687 [ + - ]: 1 : BOOST_CHECK_EQUAL(COMMAND_OPTS, testfn(std::array{"x", "-opt2=foo", "cmd2"}));
688 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt2=foo", "cmd3"}));
689 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt3=foo", "cmd1"}));
690 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt3=foo", "cmd2"}));
691 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt3=foo", "cmd3"}));
692 : :
693 [ + - ]: 1 : BOOST_CHECK_EQUAL(COMMAND_OPTS, testfn(std::array{"x", "-opt1=foo", "-opt3=bar", "-opt2=baz", "cmd1"}));
694 [ + - ]: 1 : BOOST_CHECK_EQUAL(COMMAND_OPTS, testfn(std::array{"x", "-opt1=foo", "-opt3=bar", "-opt2=baz", "cmd2"}));
695 [ + - ]: 1 : BOOST_CHECK_EQUAL(SUCCESS, testfn(std::array{"x", "-opt1=foo", "-opt3=bar", "-opt2=baz", "cmd3"}));
696 : :
697 [ + - ]: 1 : BOOST_CHECK_EQUAL(PARSE_FAIL, testfn(std::array{"x", "cmd4"}));
698 [ + - ]: 1 : BOOST_CHECK_EQUAL(NO_COMMAND, testfn(std::array{"x", "-opt3=foo"}));
699 [ + - ]: 1 : BOOST_CHECK_EQUAL(PARSE_FAIL, testfn(std::array{"x", "-opt4=foo"}));
700 : 1 : }
701 : :
702 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_AddCommand_clearargs_replaces_command_options)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
703 : : {
704 : 3 : const auto add_command{[&](TestArgsManager& test_args, const std::string& option) {
705 [ + - ]: 2 : test_args.AddArg(option, "option", ArgsManager::ALLOW_ANY, OptionsCategory::COMMAND_OPTIONS);
706 [ + - + - : 6 : test_args.AddCommand("cmd", "cmd", {option});
+ - + + -
- ]
707 [ - + + - ]: 6 : }};
708 : :
709 : 1 : TestArgsManager test_args;
710 [ + - + - ]: 1 : add_command(test_args, "-opt1");
711 [ + - ]: 1 : test_args.ClearArgs();
712 [ + - + - ]: 1 : add_command(test_args, "-opt2");
713 : :
714 [ + - ]: 1 : const auto help{test_args.GetHelpMessage()};
715 [ + - + - : 2 : BOOST_CHECK(help.find("-opt2") != std::string::npos);
+ - ]
716 : :
717 [ + - + - : 2 : test_args.ForceSetArg("-opt2", "1");
+ - ]
718 : 1 : std::vector<std::string> details;
719 [ + - + - : 2 : BOOST_CHECK(test_args.CheckCommandOptions("cmd", &details));
+ - + - +
- ]
720 [ + - + - ]: 2 : BOOST_CHECK(details.empty());
721 : 1 : }
722 : :
723 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetChainTypeString)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
724 : : {
725 : 1 : TestArgsManager test_args;
726 : 1 : const auto testnet = std::make_pair("-testnet", ArgsManager::ALLOW_ANY);
727 : 1 : const auto testnet4 = std::make_pair("-testnet4", ArgsManager::ALLOW_ANY);
728 : 1 : const auto regtest = std::make_pair("-regtest", ArgsManager::ALLOW_ANY);
729 [ + - + + : 4 : test_args.SetupArgs({testnet, testnet4, regtest});
- - ]
730 : :
731 : 1 : const char* argv_testnet4[] = {"cmd", "-testnet4"};
732 : 1 : const char* argv_regtest[] = {"cmd", "-regtest"};
733 : 1 : const char* argv_test_no_reg[] = {"cmd", "-testnet4", "-noregtest"};
734 : 1 : const char* argv_both[] = {"cmd", "-testnet4", "-regtest"};
735 : :
736 : : // regtest in test network section is ignored
737 : 1 : const char* testnetconf = "testnet4=1\nregtest=0\n[testnet4]\nregtest=1";
738 [ + - ]: 1 : std::string error;
739 : :
740 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
741 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
+ - ]
742 : :
743 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
744 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
+ - ]
745 : :
746 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
747 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
748 : :
749 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
750 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "regtest");
+ - ]
751 : :
752 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));
+ - + - ]
753 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
754 : :
755 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
756 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
757 : :
758 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
759 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
760 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
761 : :
762 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
763 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
764 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
765 : :
766 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
767 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
768 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
769 : :
770 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));
+ - + - ]
771 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
772 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
773 : :
774 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
775 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
776 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
777 : :
778 : : // check setting the network to testnet4 (and thus making
779 : : // [testnet4] regtest=1 potentially relevant) doesn't break things
780 [ + - + - ]: 1 : test_args.SelectConfigNetwork("testnet4");
781 : :
782 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
783 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
784 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
785 : :
786 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
787 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
788 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
789 : :
790 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
791 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
792 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
793 : :
794 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_test_no_reg, error));
+ - + - ]
795 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
796 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
797 : :
798 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
799 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
800 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
801 [ + - + - : 2 : }
+ - + - -
- ]
802 : :
803 : : // Test different ways settings can be merged, and verify results. This test can
804 : : // be used to confirm that updates to settings code don't change behavior
805 : : // unintentionally.
806 : : //
807 : : // The test covers:
808 : : //
809 : : // - Combining different setting actions. Possible actions are: configuring a
810 : : // setting, negating a setting (adding "-no" prefix), and configuring/negating
811 : : // settings in a network section (adding "main." or "test." prefixes).
812 : : //
813 : : // - Combining settings from command line arguments and a config file.
814 : : //
815 : : // - Combining SoftSet and ForceSet calls.
816 : : //
817 : : // - Testing "main" and "testnet4" network values to make sure settings from network
818 : : // sections are applied and to check for mainnet-specific behaviors like
819 : : // inheriting settings from the default section.
820 : : //
821 : : // - Testing network-specific settings like "-wallet", that may be ignored
822 : : // outside a network section, and non-network specific settings like "-server"
823 : : // that aren't sensitive to the network.
824 : : //
825 : 2 : struct ArgsMergeTestingSetup : public BasicTestingSetup {
826 : : //! Max number of actions to sequence together. Can decrease this when
827 : : //! debugging to make test results easier to understand.
828 : : static constexpr int MAX_ACTIONS = 3;
829 : :
830 : : enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE };
831 : : using ActionList = Action[MAX_ACTIONS];
832 : :
833 : : //! Enumerate all possible test configurations.
834 : : template <typename Fn>
835 : 1 : void ForEachMergeSetup(Fn&& fn)
836 : : {
837 : 1 : ActionList arg_actions = {};
838 : : // command_line_options do not have sections. Only iterate over SET and NEGATE
839 : 1 : ForEachNoDup(arg_actions, SET, NEGATE, [&] {
840 : 7 : ActionList conf_actions = {};
841 : 378 : ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
842 [ + + ]: 1113 : for (bool soft_set : {false, true}) {
843 [ + + ]: 2226 : for (bool force_set : {false, true}) {
844 [ + - + - : 14840 : for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
+ - + - +
+ + + - -
- - ]
845 [ + - + - : 59360 : for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
+ - + - +
+ + + - -
- - ]
846 [ + + ]: 71232 : for (bool net_specific : {false, true}) {
847 [ - + ]: 47488 : fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
848 : : }
849 : : }
850 : : }
851 : : }
852 : : }
853 : : });
854 : : });
855 : 1 : }
856 : :
857 : : //! Translate actions into a list of <key>=<value> setting strings.
858 : 94976 : std::vector<std::string> GetValues(const ActionList& actions,
859 : : const std::string& section,
860 : : const std::string& name,
861 : : const std::string& value_prefix)
862 : : {
863 : 94976 : std::vector<std::string> values;
864 : 94976 : int suffix = 0;
865 [ + + ]: 298240 : for (Action action : actions) {
866 [ + + ]: 252416 : if (action == NONE) break;
867 [ + + ]: 203264 : std::string prefix;
868 [ + + + - ]: 203264 : if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";
869 [ + + ]: 203264 : if (action == SET || action == SECTION_SET) {
870 [ + + ]: 304896 : for (int i = 0; i < 2; ++i) {
871 [ + - + - : 609792 : values.push_back(prefix + name + "=" + value_prefix + ToString(++suffix));
+ - + - ]
872 : : }
873 : : }
874 [ + + ]: 203264 : if (action == NEGATE || action == SECTION_NEGATE) {
875 [ + - + - : 203264 : values.push_back(prefix + "no" + name + "=1");
+ - ]
876 : : }
877 : 203264 : }
878 : 94976 : return values;
879 : 0 : }
880 : : };
881 : :
882 : : // Regression test covering different ways config settings can be merged. The
883 : : // test parses and merges settings, representing the results as strings that get
884 : : // compared against an expected hash. To debug, the result strings can be dumped
885 : : // to a file (see comments below).
886 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
887 : : {
888 : 1 : CHash256 out_sha;
889 : 1 : FILE* out_file = nullptr;
890 [ - + ]: 1 : if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) {
891 [ # # ]: 0 : out_file = fsbridge::fopen(out_path, "w");
892 [ # # # # ]: 0 : if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
893 : : }
894 : :
895 : 47489 : ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool soft_set, bool force_set,
896 : : const std::string& section, const std::string& network, bool net_specific) {
897 : 47488 : TestArgsManager parser;
898 : :
899 [ + - ]: 47488 : std::string desc = "net=";
900 [ - + ]: 47488 : desc += network;
901 [ + - ]: 47488 : parser.SelectConfigNetwork(network);
902 : :
903 [ + + + - : 71232 : const std::string& name = net_specific ? "wallet" : "server";
+ - ]
904 [ + - ]: 47488 : const std::string key = "-" + name;
905 : 47488 : unsigned int flags = ArgsManager::ALLOW_ANY;
906 [ + + ]: 47488 : if (net_specific) flags |= ArgsManager::NETWORK_ONLY;
907 [ + - ]: 47488 : parser.AddArg(key, name, flags, OptionsCategory::OPTIONS);
908 : :
909 [ + - + - ]: 47488 : auto args = GetValues(arg_actions, section, name, "a");
910 [ + - ]: 47488 : std::vector<const char*> argv = {"ignored"};
911 [ + + ]: 169600 : for (auto& arg : args) {
912 [ + - ]: 122112 : arg.insert(0, "-");
913 [ + - ]: 122112 : desc += " ";
914 [ - + ]: 122112 : desc += arg;
915 [ + - ]: 122112 : argv.push_back(arg.c_str());
916 : : }
917 [ + - ]: 47488 : std::string error;
918 [ + - - + : 94976 : BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ - + - +
- ]
919 [ + - + - ]: 47488 : BOOST_CHECK_EQUAL(error, "");
920 : :
921 [ + - ]: 47488 : std::string conf;
922 [ + - + - : 230272 : for (auto& conf_val : GetValues(conf_actions, section, name, "c")) {
+ + ]
923 [ + - ]: 182784 : desc += " ";
924 [ - + ]: 182784 : desc += conf_val;
925 [ - + ]: 182784 : conf += conf_val;
926 [ + - ]: 182784 : conf += "\n";
927 : 47488 : }
928 [ + - ]: 47488 : std::istringstream conf_stream(conf);
929 [ + - + - : 94976 : BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ - + - +
- ]
930 [ + - + - ]: 47488 : BOOST_CHECK_EQUAL(error, "");
931 : :
932 [ + + ]: 47488 : if (soft_set) {
933 [ + - ]: 23744 : desc += " soft";
934 [ + - + - ]: 23744 : parser.SoftSetArg(key, "soft1");
935 [ + - + - ]: 47488 : parser.SoftSetArg(key, "soft2");
936 : : }
937 : :
938 [ + + ]: 47488 : if (force_set) {
939 [ + - ]: 23744 : desc += " force";
940 [ + - + - ]: 23744 : parser.ForceSetArg(key, "force1");
941 [ + - + - ]: 47488 : parser.ForceSetArg(key, "force2");
942 : : }
943 : :
944 [ + - ]: 47488 : desc += " || ";
945 : :
946 [ + - + + ]: 47488 : if (!parser.IsArgSet(key)) {
947 [ + - ]: 392 : desc += "unset";
948 [ + - + - : 784 : BOOST_CHECK(!parser.IsArgNegated(key));
+ - + - ]
949 [ + - + - : 392 : BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default");
+ - + - ]
950 [ + - + - : 784 : BOOST_CHECK(parser.GetArgs(key).empty());
+ - ]
951 [ + - + + ]: 47096 : } else if (parser.IsArgNegated(key)) {
952 [ + - ]: 11696 : desc += "negated";
953 [ + - + - : 11696 : BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0");
+ - + - ]
954 [ + - + - : 23392 : BOOST_CHECK(parser.GetArgs(key).empty());
+ - ]
955 : : } else {
956 [ + - + - ]: 70800 : desc += parser.GetArg(key, "default");
957 [ + - ]: 35400 : desc += " |";
958 [ + - + + ]: 110468 : for (const auto& arg : parser.GetArgs(key)) {
959 [ + - ]: 75068 : desc += " ";
960 [ - + ]: 150136 : desc += arg;
961 : 35400 : }
962 : : }
963 : :
964 [ + - ]: 47488 : std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs();
965 [ + + ]: 47488 : if (!ignored.empty()) {
966 [ + - ]: 1752 : desc += " | ignored";
967 [ + + ]: 3504 : for (const auto& arg : ignored) {
968 [ + - ]: 1752 : desc += " ";
969 [ - + ]: 3504 : desc += arg;
970 : : }
971 : : }
972 : :
973 [ + - ]: 47488 : desc += "\n";
974 : :
975 [ + - ]: 47488 : out_sha.Write(MakeUCharSpan(desc));
976 [ - + ]: 47488 : if (out_file) {
977 [ # # # # : 0 : BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
# # # # #
# ]
978 : : }
979 : 47488 : });
980 : :
981 [ - + ]: 1 : if (out_file) {
982 [ # # # # ]: 0 : if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
983 : 0 : out_file = nullptr;
984 : : }
985 : :
986 : 1 : unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
987 : 1 : out_sha.Finalize(out_sha_bytes);
988 : 1 : std::string out_sha_hex = HexStr(out_sha_bytes);
989 : :
990 : : // If check below fails, should manually dump the results with:
991 : : //
992 : : // ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=argsman_tests/util_ArgsMerge
993 : : //
994 : : // And verify diff against previous results to make sure the changes are expected.
995 : : //
996 : : // Results file is formatted like:
997 : : //
998 : : // <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
999 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(out_sha_hex, "f1ee5ab094cc43d16a6086fa7f2c10389e0f99902616b31bbf29189972ad1473");
1000 : 1 : }
1001 : :
1002 : : // Similar test as above, but for ArgsManager::GetChainTypeString function.
1003 : 2 : struct ChainMergeTestingSetup : public BasicTestingSetup {
1004 : : static constexpr int MAX_ACTIONS = 2;
1005 : :
1006 : : enum Action { NONE, ENABLE_TEST, DISABLE_TEST, NEGATE_TEST, ENABLE_REG, DISABLE_REG, NEGATE_REG };
1007 : : using ActionList = Action[MAX_ACTIONS];
1008 : :
1009 : : //! Enumerate all possible test configurations.
1010 : : template <typename Fn>
1011 : 1 : void ForEachMergeSetup(Fn&& fn)
1012 : : {
1013 : 1 : ActionList arg_actions = {};
1014 : 1 : ForEachNoDup(arg_actions, ENABLE_TEST, NEGATE_REG, [&] {
1015 : 37 : ActionList conf_actions = {};
1016 : 1406 : ForEachNoDup(conf_actions, ENABLE_TEST, NEGATE_REG, [&] { fn(arg_actions, conf_actions); });
1017 : : });
1018 : 1 : }
1019 : : };
1020 : :
1021 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
1022 : : {
1023 : 1 : CHash256 out_sha;
1024 : 1 : FILE* out_file = nullptr;
1025 [ - + ]: 1 : if (const char* out_path = getenv("CHAIN_MERGE_TEST_OUT")) {
1026 [ # # ]: 0 : out_file = fsbridge::fopen(out_path, "w");
1027 [ # # # # ]: 0 : if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
1028 : : }
1029 : :
1030 : 1370 : ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions) {
1031 : 1369 : TestArgsManager parser;
1032 [ + - + - : 2738 : parser.AddArg("-regtest", "regtest", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ - ]
1033 [ + - + - : 2738 : parser.AddArg("-testnet4", "testnet4", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ - ]
1034 : :
1035 [ + + ]: 5402 : auto arg = [](Action action) { return action == ENABLE_TEST ? "-testnet4=1" :
1036 [ + + ]: 4588 : action == DISABLE_TEST ? "-testnet4=0" :
1037 [ + + ]: 3774 : action == NEGATE_TEST ? "-notestnet4=1" :
1038 [ + + ]: 2960 : action == ENABLE_REG ? "-regtest=1" :
1039 [ + + ]: 2146 : action == DISABLE_REG ? "-regtest=0" :
1040 [ + + ]: 1332 : action == NEGATE_REG ? "-noregtest=1" : nullptr; };
1041 : :
1042 [ + - ]: 1369 : std::string desc;
1043 [ + - ]: 1369 : std::vector<const char*> argv = {"ignored"};
1044 [ + + ]: 3811 : for (Action action : arg_actions) {
1045 : 2701 : const char* argstr = arg(action);
1046 [ + + ]: 2701 : if (!argstr) break;
1047 [ + - ]: 2442 : argv.push_back(argstr);
1048 [ + - ]: 2442 : desc += " ";
1049 [ + - ]: 2442 : desc += argv.back();
1050 : : }
1051 [ + - ]: 1369 : std::string error;
1052 [ + - - + : 2738 : BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ - + - +
- ]
1053 [ + - + - ]: 1369 : BOOST_CHECK_EQUAL(error, "");
1054 : :
1055 : 1369 : std::string conf;
1056 [ + + ]: 3811 : for (Action action : conf_actions) {
1057 : 2701 : const char* argstr = arg(action);
1058 [ + + ]: 2701 : if (!argstr) break;
1059 [ + - ]: 2442 : desc += " ";
1060 [ + - ]: 2442 : desc += argstr + 1;
1061 [ + - ]: 2442 : conf += argstr + 1;
1062 [ + - ]: 2442 : conf += "\n";
1063 : : }
1064 [ + - ]: 1369 : std::istringstream conf_stream(conf);
1065 [ + - + - : 2738 : BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ - + - +
- ]
1066 [ + - + - ]: 1369 : BOOST_CHECK_EQUAL(error, "");
1067 : :
1068 [ + - ]: 1369 : desc += " || ";
1069 : 1369 : try {
1070 [ + + ]: 2556 : desc += parser.GetChainTypeString();
1071 [ - + ]: 182 : } catch (const std::runtime_error& e) {
1072 [ + - ]: 182 : desc += "error: ";
1073 [ + - ]: 182 : desc += e.what();
1074 : 182 : }
1075 [ + - ]: 1369 : desc += "\n";
1076 : :
1077 [ + - ]: 1369 : out_sha.Write(MakeUCharSpan(desc));
1078 [ - + ]: 1369 : if (out_file) {
1079 [ # # # # : 0 : BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
# # # # #
# ]
1080 : : }
1081 : 1369 : });
1082 : :
1083 [ - + ]: 1 : if (out_file) {
1084 [ # # # # ]: 0 : if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
1085 : 0 : out_file = nullptr;
1086 : : }
1087 : :
1088 : 1 : unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
1089 : 1 : out_sha.Finalize(out_sha_bytes);
1090 : 1 : std::string out_sha_hex = HexStr(out_sha_bytes);
1091 : :
1092 : : // If check below fails, should manually dump the results with:
1093 : : //
1094 : : // CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=argsman_tests/util_ChainMerge
1095 : : //
1096 : : // And verify diff against previous results to make sure the changes are expected.
1097 : : //
1098 : : // Results file is formatted like:
1099 : : //
1100 : : // <input> || <output>
1101 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(out_sha_hex, "c0e33aab0c74e040ddcee9edad59e8148d8e1cacb3cccd9ea1a1f485cb6bad21");
1102 : 1 : }
1103 : :
1104 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
1105 : : {
1106 : : // Test writing setting.
1107 : 1 : TestArgsManager args1;
1108 [ - + + - : 3 : args1.ForceSetArg("-datadir", fs::PathToString(m_path_root));
+ - ]
1109 [ + - + - ]: 2 : args1.LockSettings([&](common::Settings& s) { s.rw_settings["name"] = "value"; });
1110 [ + - ]: 1 : args1.WriteSettingsFile();
1111 : :
1112 : : // Test reading setting.
1113 [ + - ]: 1 : TestArgsManager args2;
1114 [ - + + - : 3 : args2.ForceSetArg("-datadir", fs::PathToString(m_path_root));
+ - ]
1115 [ + - ]: 1 : args2.ReadSettingsFile();
1116 [ + - + - : 2 : args2.LockSettings([&](common::Settings& s) { BOOST_CHECK_EQUAL(s.rw_settings["name"].get_str(), "value"); });
+ - ]
1117 : :
1118 : : // Test error logging, and remove previously written setting.
1119 : 1 : {
1120 [ + - + - ]: 2 : ASSERT_DEBUG_LOG("Failed renaming settings file");
1121 [ + - + - ]: 3 : fs::remove(args1.GetDataDirBase() / "settings.json");
1122 [ + - + - ]: 3 : fs::create_directory(args1.GetDataDirBase() / "settings.json");
1123 [ + - ]: 1 : args2.WriteSettingsFile();
1124 [ + - + - ]: 3 : fs::remove(args1.GetDataDirBase() / "settings.json");
1125 : 1 : }
1126 : 1 : }
1127 : :
1128 : : BOOST_AUTO_TEST_SUITE_END()
|