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() && s.ro_config.empty());
+ - ]
208 : 1 : });
209 : :
210 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error));
+ - + - ]
211 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
212 [ + - - + : 2 : BOOST_CHECK(s.command_line_options.empty() && s.ro_config.empty());
+ - ]
213 : 1 : });
214 : :
215 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error));
+ - + - ]
216 : : // expectation: -ignored is ignored (program name argument),
217 : : // -a, -b and -ccc end up in map, -d ignored because it is after
218 : : // a non-option argument (non-GNU option parsing)
219 [ + - + - : 7 : BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc")
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- - + + -
+ - + - +
- + - + -
- - - - -
- - - -
- ]
220 : : && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d"));
221 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
222 [ + - - + : 2 : BOOST_CHECK(s.command_line_options.size() == 3 && s.ro_config.empty());
+ - ]
223 [ + - + - : 7 : BOOST_CHECK(s.command_line_options.contains("a") && s.command_line_options.contains("b") && s.command_line_options.contains("ccc")
+ - + - +
- + - + -
+ - + - -
+ + - + -
+ - + - +
- - - - -
- - - - -
- ]
224 : : && !s.command_line_options.contains("f") && !s.command_line_options.contains("d"));
225 : :
226 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("a").size() == 1);
- + + - ]
227 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("a").front().get_str() == "");
+ - + - ]
228 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").size() == 2);
- + + - ]
229 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").front().get_str() == "argument");
+ - + - ]
230 [ + - + - : 2 : BOOST_CHECK(s.command_line_options.at("ccc").back().get_str() == "multiple");
+ - + - ]
231 : 1 : });
232 [ + - + - : 3 : BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
+ - + - ]
233 [ + - + - : 2 : }
+ - + - +
- - - ]
234 : :
235 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)
+ - + - -
+ - + + -
+ - + - +
- + - + -
- + - + +
- + - + -
+ - + - +
- - + - +
+ - + - +
- + - + -
+ - + - -
+ - + + -
+ - + - +
- + - + -
- + - + +
- ]
236 : : {
237 : 1 : TestArgsManager test;
238 [ + - + - : 3 : test.SetupArgs({{"-registered", ArgsManager::ALLOW_ANY}});
+ + - - ]
239 : :
240 : 1 : const char* argv[] = {"ignored", "-registered"};
241 [ + - ]: 1 : std::string error;
242 [ + - + - : 2 : BOOST_CHECK(test.ParseParameters(2, argv, error));
+ - + - ]
243 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "");
244 : :
245 : 1 : argv[1] = "-unregistered";
246 [ + - + - : 2 : BOOST_CHECK(!test.ParseParameters(2, argv, error));
+ - + - ]
247 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered");
248 : :
249 : : // Make sure registered parameters prefixed with a chain type trigger errors.
250 : : // (Previously, they were accepted and ignored.)
251 : 1 : argv[1] = "-test.registered";
252 [ + - + - : 2 : BOOST_CHECK(!test.ParseParameters(2, argv, error));
+ - + - ]
253 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(error, "Invalid parameter -test.registered");
254 [ + - ]: 2 : }
255 : :
256 : 31 : static void TestParse(const std::string& str, bool expected_bool, int64_t expected_int)
257 : : {
258 : 31 : TestArgsManager test;
259 [ + - + - : 93 : test.SetupArgs({{"-value", ArgsManager::ALLOW_ANY}});
+ + - - ]
260 [ + - ]: 31 : std::string arg = "-value=" + str;
261 [ + - ]: 31 : const char* argv[] = {"ignored", arg.c_str()};
262 [ + - ]: 31 : std::string error;
263 [ + - + - : 62 : BOOST_CHECK(test.ParseParameters(2, argv, error));
+ - + - ]
264 [ + - + - : 31 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), expected_bool);
+ - + - ]
265 [ + - + - : 31 : BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), expected_bool);
+ - + - ]
266 [ + - + - : 62 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99998), expected_int);
+ - ]
267 [ + - + - : 62 : BOOST_CHECK_EQUAL(test.GetIntArg("-value", 99999), expected_int);
+ - ]
268 [ + - ]: 62 : }
269 : :
270 : : // Test bool and int parsing.
271 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ArgParsing)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
272 : : {
273 : : // Some of these cases could be ambiguous or surprising to users, and might
274 : : // be worth triggering errors or warnings in the future. But for now basic
275 : : // test coverage is useful to avoid breaking backwards compatibility
276 : : // unintentionally.
277 [ + - ]: 1 : TestParse("", true, 0);
278 [ + - ]: 1 : TestParse(" ", false, 0);
279 [ + - ]: 1 : TestParse("0", false, 0);
280 [ + - ]: 1 : TestParse("0 ", false, 0);
281 [ + - ]: 1 : TestParse(" 0", false, 0);
282 [ + - ]: 1 : TestParse("+0", false, 0);
283 [ + - ]: 1 : TestParse("-0", false, 0);
284 [ + - ]: 1 : TestParse("5", true, 5);
285 [ + - ]: 1 : TestParse("5 ", true, 5);
286 [ + - ]: 1 : TestParse(" 5", true, 5);
287 [ + - ]: 1 : TestParse("+5", true, 5);
288 [ + - ]: 1 : TestParse("-5", true, -5);
289 [ + - ]: 1 : TestParse("0 5", false, 0);
290 [ + - ]: 1 : TestParse("5 0", true, 5);
291 [ + - ]: 1 : TestParse("050", true, 50);
292 [ + - ]: 1 : TestParse("0.", false, 0);
293 [ + - ]: 1 : TestParse("5.", true, 5);
294 [ + - ]: 1 : TestParse("0.0", false, 0);
295 [ + - ]: 1 : TestParse("0.5", false, 0);
296 [ + - ]: 1 : TestParse("5.0", true, 5);
297 [ + - ]: 1 : TestParse("5.5", true, 5);
298 [ + - ]: 1 : TestParse("x", false, 0);
299 [ + - ]: 1 : TestParse("x0", false, 0);
300 [ + - ]: 1 : TestParse("x5", false, 0);
301 [ + - ]: 1 : TestParse("0x", false, 0);
302 [ + - ]: 1 : TestParse("5x", true, 5);
303 [ + - ]: 1 : TestParse("0x5", false, 0);
304 [ + - ]: 1 : TestParse("false", false, 0);
305 [ + - ]: 1 : TestParse("true", false, 0);
306 [ + - ]: 1 : TestParse("yes", false, 0);
307 [ + - ]: 1 : TestParse("no", false, 0);
308 : 1 : }
309 : :
310 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetBoolArg)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
311 : : {
312 : 1 : TestArgsManager testArgs;
313 : 1 : const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
314 : 1 : const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
315 : 1 : const auto c = std::make_pair("-c", ArgsManager::ALLOW_ANY);
316 : 1 : const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
317 : 1 : const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
318 : 1 : const auto f = std::make_pair("-f", ArgsManager::ALLOW_ANY);
319 : :
320 : 1 : const char *argv_test[] = {
321 : : "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
322 [ + - ]: 1 : std::string error;
323 [ + - + + : 7 : testArgs.SetupArgs({a, b, c, d, e, f});
- - ]
324 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(7, argv_test, error));
+ - ]
325 : :
326 : : // Each letter should be set.
327 [ + + ]: 8 : for (const char opt : "abcdef")
328 [ + - + - : 14 : BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
+ - + + -
+ + - -
- ]
329 : :
330 : : // Nothing else should be in the map
331 [ + - ]: 2 : testArgs.LockSettings([&](const common::Settings& s) {
332 [ + - - + : 2 : BOOST_CHECK(s.command_line_options.size() == 6 && s.ro_config.empty());
+ - ]
333 : 1 : });
334 : :
335 : : // The -no prefix should get stripped on the way in.
336 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgSet("-nob"));
+ - + - +
- ]
337 : :
338 : : // The -b option is flagged as negated, and nothing else is
339 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgNegated("-b"));
+ - + - +
- ]
340 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-a"));
+ - + - +
- ]
341 : :
342 : : // Check expected values.
343 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
+ - + - +
- ]
344 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
+ - + - +
- ]
345 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
+ - + - +
- ]
346 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
+ - + - +
- ]
347 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
+ - + - +
- ]
348 [ + - + - : 2 : BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
+ - + - ]
349 [ + - + - : 2 : }
+ - + - +
- + - + -
- - ]
350 : :
351 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
352 : : {
353 : : // Test some awful edge cases that hopefully no user will ever exercise.
354 : 1 : TestArgsManager testArgs;
355 : :
356 : : // Params test
357 : 1 : const auto foo = std::make_pair("-foo", ArgsManager::ALLOW_ANY);
358 : 1 : const auto bar = std::make_pair("-bar", ArgsManager::ALLOW_ANY);
359 : 1 : const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
360 [ + - + + : 3 : testArgs.SetupArgs({foo, bar});
- - ]
361 [ + - ]: 1 : std::string error;
362 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(4, argv_test, error));
+ - + - ]
363 : :
364 : : // This was passed twice, second one overrides the negative setting.
365 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
366 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
+ - + - +
- + - ]
367 : :
368 : : // A double negative is a positive, and not marked as negated.
369 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
370 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+ - + - +
- + - ]
371 : :
372 : : // Config test
373 : 1 : const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
374 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(1, argv_test, error));
+ - + - ]
375 [ + - + - ]: 1 : testArgs.ReadConfigString(conf_test);
376 : :
377 : : // This was passed twice, second one overrides the negative setting,
378 : : // and the value.
379 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
380 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
+ - + - +
- + - ]
381 : :
382 : : // A double negative is a positive, and does not count as negated.
383 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
384 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+ - + - +
- + - ]
385 : :
386 : : // Combined test
387 : 1 : const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
388 : 1 : const char *combo_test_conf = "foo=1\nnobar=1\n";
389 [ + - + - : 2 : BOOST_CHECK(testArgs.ParseParameters(3, combo_test_args, error));
+ - + - ]
390 [ + - + - ]: 1 : testArgs.ReadConfigString(combo_test_conf);
391 : :
392 : : // Command line overrides, but doesn't erase old setting
393 [ + - + - : 2 : BOOST_CHECK(testArgs.IsArgNegated("-foo"));
+ - + - +
- ]
394 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
+ - + - +
- + - ]
395 [ + - + - : 3 : BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
+ - + - +
- ]
396 : :
397 : : // Command line overrides, but doesn't erase old setting
398 [ + - + - : 2 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ - + - +
- ]
399 [ + - + - : 2 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
+ - + - +
- + - ]
400 [ + - + - : 4 : BOOST_CHECK(testArgs.GetArgs("-bar").size() == 1
+ - - + +
- + - + -
- + + - +
- + - - -
- - - - -
- ]
401 : : && testArgs.GetArgs("-bar").front() == "");
402 [ + - + - : 2 : }
+ - - - ]
403 : :
404 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
405 : : {
406 : 1 : const char *str_config =
407 : : "a=\n"
408 : : "b=1\n"
409 : : "ccc=argument\n"
410 : : "ccc=multiple\n"
411 : : "d=e\n"
412 : : "nofff=1\n"
413 : : "noggg=0\n"
414 : : "h=1\n"
415 : : "noh=1\n"
416 : : "noi=1\n"
417 : : "i=1\n"
418 : : "sec1.ccc=extend1\n"
419 : : "\n"
420 : : "[sec1]\n"
421 : : "ccc=extend2\n"
422 : : "d=eee\n"
423 : : "h=1\n"
424 : : "[sec2]\n"
425 : : "ccc=extend3\n"
426 : : "iii=2\n";
427 : :
428 : 1 : TestArgsManager test_args;
429 : 1 : const auto a = std::make_pair("-a", ArgsManager::ALLOW_ANY);
430 : 1 : const auto b = std::make_pair("-b", ArgsManager::ALLOW_ANY);
431 : 1 : const auto ccc = std::make_pair("-ccc", ArgsManager::ALLOW_ANY);
432 : 1 : const auto d = std::make_pair("-d", ArgsManager::ALLOW_ANY);
433 : 1 : const auto e = std::make_pair("-e", ArgsManager::ALLOW_ANY);
434 : 1 : const auto fff = std::make_pair("-fff", ArgsManager::ALLOW_ANY);
435 : 1 : const auto ggg = std::make_pair("-ggg", ArgsManager::ALLOW_ANY);
436 : 1 : const auto h = std::make_pair("-h", ArgsManager::ALLOW_ANY);
437 : 1 : const auto i = std::make_pair("-i", ArgsManager::ALLOW_ANY);
438 : 1 : const auto iii = std::make_pair("-iii", ArgsManager::ALLOW_ANY);
439 [ + - + + : 11 : test_args.SetupArgs({a, b, ccc, d, e, fff, ggg, h, i, iii});
- - ]
440 : :
441 [ + - + - ]: 1 : test_args.ReadConfigString(str_config);
442 : : // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
443 : : // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
444 : :
445 [ + - ]: 2 : test_args.LockSettings([&](const common::Settings& s) {
446 [ + - ]: 2 : BOOST_CHECK(s.command_line_options.empty());
447 [ + - ]: 2 : BOOST_CHECK(s.ro_config.size() == 3);
448 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").size() == 8);
+ - ]
449 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").size() == 3);
+ - ]
450 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").size() == 2);
+ - ]
451 : :
452 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("a"));
+ - + - ]
453 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("b"));
+ - + - ]
454 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("ccc"));
+ - + - ]
455 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("d"));
+ - + - ]
456 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("fff"));
+ - + - ]
457 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("ggg"));
+ - + - ]
458 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("h"));
+ - + - ]
459 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("").contains("i"));
+ - + - ]
460 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").contains("ccc"));
+ - + - ]
461 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec1").contains("h"));
+ - + - ]
462 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").contains("ccc"));
+ - + - ]
463 [ + - + - : 2 : BOOST_CHECK(s.ro_config.at("sec2").contains("iii"));
+ - + - ]
464 : 1 : });
465 : :
466 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-a"));
+ - + - +
- ]
467 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-b"));
+ - + - +
- ]
468 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-ccc"));
+ - + - +
- ]
469 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-d"));
+ - + - +
- ]
470 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-fff"));
+ - + - +
- ]
471 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-ggg"));
+ - + - +
- ]
472 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-h"));
+ - + - +
- ]
473 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgSet("-i"));
+ - + - +
- ]
474 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgSet("-zzz"));
+ - + - +
- ]
475 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgSet("-iii"));
+ - + - +
- ]
476 : :
477 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
+ - + - +
- ]
478 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
+ - + - +
- ]
479 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ccc", "xxx"), "argument");
+ - + - +
- ]
480 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-d", "xxx"), "e");
+ - + - +
- ]
481 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
+ - + - +
- ]
482 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
+ - + - +
- ]
483 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-h", "xxx"), "0");
+ - + - +
- ]
484 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-i", "xxx"), "1");
+ - + - +
- ]
485 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
+ - + - +
- ]
486 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
+ - + - +
- ]
487 : :
488 [ + + ]: 3 : for (const bool def : {false, true}) {
489 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-a", def));
+ - + - +
- ]
490 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-b", def));
+ - + - +
- ]
491 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-ccc", def));
+ - + - +
- ]
492 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-d", def));
+ - + - +
- ]
493 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-fff", def));
+ - + - +
- ]
494 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-ggg", def));
+ - + - +
- ]
495 [ + - + - : 4 : BOOST_CHECK(!test_args.GetBoolArg("-h", def));
+ - + - +
- ]
496 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-i", def));
+ - + - +
- ]
497 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-zzz", def) == def);
+ - + - +
- ]
498 [ + - + - : 4 : BOOST_CHECK(test_args.GetBoolArg("-iii", def) == def);
+ - + - ]
499 : : }
500 : :
501 [ + - + - : 4 : BOOST_CHECK(test_args.GetArgs("-a").size() == 1
+ - - + +
- + - + -
- + + - +
- + - + -
- - - - -
- - - ]
502 : : && test_args.GetArgs("-a").front() == "");
503 [ + - + - : 4 : BOOST_CHECK(test_args.GetArgs("-b").size() == 1
+ - - + +
- + - + -
- + + - +
- + - + -
- - - - -
- - - ]
504 : : && test_args.GetArgs("-b").front() == "1");
505 [ + - + - : 5 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
+ - - + +
- + - + -
+ - + - +
- - + + -
+ - + - +
- + - + -
- - - - -
- - - - -
- - ]
506 : : && test_args.GetArgs("-ccc").front() == "argument"
507 : : && test_args.GetArgs("-ccc").back() == "multiple");
508 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
+ - + - +
- ]
509 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
+ - + - +
- ]
510 [ + - + - : 4 : BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
+ - - + +
- + - + -
- + + - +
- + - + -
- - - - -
- - - ]
511 : : && test_args.GetArgs("-ggg").front() == "1");
512 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
+ - + - +
- ]
513 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
+ - + - +
- ]
514 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
+ - + - +
- ]
515 [ + - + - : 4 : BOOST_CHECK(test_args.GetArgs("-i").size() == 1
+ - - + +
- + - + -
- + + - +
- + - + -
- - - - -
- - - ]
516 : : && test_args.GetArgs("-i").front() == "1");
517 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
+ - + - +
- ]
518 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
+ - + - +
- ]
519 : :
520 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-a"));
+ - + - +
- ]
521 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-b"));
+ - + - +
- ]
522 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
+ - + - +
- ]
523 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-d"));
+ - + - +
- ]
524 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgNegated("-fff"));
+ - + - +
- ]
525 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
+ - + - +
- ]
526 [ + - + - : 2 : BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
+ - + - +
- ]
527 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
+ - + - +
- ]
528 [ + - + - : 2 : BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
+ - + - +
- ]
529 : :
530 : : // Test sections work
531 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec1");
532 : :
533 : : // same as original
534 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");
+ - + - +
- ]
535 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-b", "xxx"), "1");
+ - + - +
- ]
536 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-fff", "xxx"), "0");
+ - + - +
- ]
537 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-ggg", "xxx"), "1");
+ - + - +
- ]
538 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-zzz", "xxx"), "xxx");
+ - + - +
- ]
539 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetArg("-iii", "xxx"), "xxx");
+ - + - +
- ]
540 : : // d is overridden
541 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ - + - +
- + - ]
542 : : // section-specific setting
543 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+ - + - +
- + - ]
544 : : // section takes priority for multiple values
545 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
+ - + - +
- + - ]
546 : : // check multiple values works
547 [ + - ]: 1 : const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
548 [ + - + - ]: 1 : const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
549 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
+ - + - ]
550 : :
551 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec2");
552 : :
553 : : // same as original
554 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");
+ - + - +
- + - ]
555 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-b", "xxx") == "1");
+ - + - +
- + - ]
556 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
+ - + - +
- + - ]
557 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-fff", "xxx") == "0");
+ - + - +
- + - ]
558 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ggg", "xxx") == "1");
+ - + - +
- + - ]
559 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-zzz", "xxx") == "xxx");
+ - + - +
- + - ]
560 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- + - ]
561 : : // section-specific setting
562 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
+ - + - +
- + - ]
563 : : // section takes priority for multiple values
564 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
+ - + - +
- + - ]
565 : : // check multiple values works
566 [ + - ]: 1 : const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
567 [ + - + - ]: 1 : const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
568 [ + - + - : 2 : BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
+ - + - ]
569 : :
570 : : // Test section only options
571 : :
572 : 1 : const auto ccc2 = std::make_pair("-ccc", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
573 : 1 : const auto d2 = std::make_pair("-d", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
574 : 1 : const auto h2 = std::make_pair("-h", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY);
575 [ + - ]: 1 : test_args.ClearArgs();
576 [ + - + + : 11 : test_args.SetupArgs({a, b, ccc2, d2, e, fff, ggg, h2, i, iii});
- - ]
577 [ + - + - ]: 1 : test_args.ReadConfigString(str_config);
578 : :
579 [ + - + - ]: 1 : test_args.SelectConfigNetwork(ChainTypeToString(ChainType::MAIN));
580 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
+ - + - +
- + - ]
581 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ - + - +
- ]
582 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- + - ]
583 : :
584 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec1");
585 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ - + - +
- + - ]
586 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
+ - + - +
- ]
587 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ - + - +
- ]
588 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+ - + - +
- + - ]
589 : :
590 [ + - + - ]: 1 : test_args.SelectConfigNetwork("sec2");
591 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
+ - + - +
- + - ]
592 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
+ - + - +
- ]
593 [ + - + - : 3 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
+ - + - +
- ]
594 [ + - + - : 2 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+ - + - +
- ]
595 [ + - + - : 3 : }
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
- - - - ]
596 : :
597 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetArg)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
598 : : {
599 : 1 : TestArgsManager testArgs;
600 [ + - ]: 2 : testArgs.LockSettings([&](common::Settings& s) {
601 : 1 : s.command_line_options.clear();
602 [ + - + - : 3 : s.command_line_options["strtest1"] = {"string..."};
+ - + + -
- ]
603 : : // strtest2 undefined on purpose
604 [ + - + - : 3 : s.command_line_options["inttest1"] = {"12345"};
+ - + + -
- ]
605 [ + - + - : 3 : s.command_line_options["inttest2"] = {"81985529216486895"};
+ - + + -
- ]
606 : : // inttest3 undefined on purpose
607 [ + - + - : 3 : s.command_line_options["booltest1"] = {""};
+ - + + -
- ]
608 : : // booltest2 undefined on purpose
609 [ + - + - : 3 : s.command_line_options["booltest3"] = {"0"};
+ - + + -
- ]
610 [ + - + - : 3 : s.command_line_options["booltest4"] = {"1"};
+ - + + -
- ]
611 : :
612 : : // priorities
613 [ + - + - : 4 : s.command_line_options["pritest1"] = {"a", "b"};
+ - + + -
- ]
614 [ + - + - : 4 : s.ro_config[""]["pritest2"] = {"a", "b"};
+ - + - +
- + + -
- ]
615 [ + - + - : 3 : s.command_line_options["pritest3"] = {"a"};
+ - + + -
- ]
616 [ + - + - : 3 : s.ro_config[""]["pritest3"] = {"b"};
+ - + - +
- + + -
- ]
617 [ + - + - : 4 : s.command_line_options["pritest4"] = {"a","b"};
+ - + + -
- ]
618 [ + - + - : 4 : s.ro_config[""]["pritest4"] = {"c","d"};
+ - + - +
- + + -
- ]
619 [ + - + - : 13 : });
+ - + - +
- + - + -
+ - - - -
- - - -
- ]
620 : :
621 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
+ - + - +
- ]
622 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
+ - + - +
- ]
623 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest1", -1), 12345);
+ - ]
624 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest2", -1), 81985529216486895LL);
+ - ]
625 [ + - + - : 2 : BOOST_CHECK_EQUAL(testArgs.GetIntArg("inttest3", -1), -1);
+ - ]
626 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
+ - + - ]
627 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
+ - + - ]
628 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
+ - + - ]
629 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
+ - + - ]
630 : :
631 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
+ - + - +
- ]
632 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
+ - + - +
- ]
633 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
+ - + - +
- ]
634 [ + - + - : 1 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
+ - + - +
- ]
635 : 1 : }
636 : :
637 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_GetChainTypeString)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
638 : : {
639 : 1 : TestArgsManager test_args;
640 : 1 : const auto testnet = std::make_pair("-testnet", ArgsManager::ALLOW_ANY);
641 : 1 : const auto testnet4 = std::make_pair("-testnet4", ArgsManager::ALLOW_ANY);
642 : 1 : const auto regtest = std::make_pair("-regtest", ArgsManager::ALLOW_ANY);
643 [ + - + + : 4 : test_args.SetupArgs({testnet, testnet4, regtest});
- - ]
644 : :
645 : 1 : const char* argv_testnet4[] = {"cmd", "-testnet4"};
646 : 1 : const char* argv_regtest[] = {"cmd", "-regtest"};
647 : 1 : const char* argv_test_no_reg[] = {"cmd", "-testnet4", "-noregtest"};
648 : 1 : const char* argv_both[] = {"cmd", "-testnet4", "-regtest"};
649 : :
650 : : // regtest in test network section is ignored
651 : 1 : const char* testnetconf = "testnet4=1\nregtest=0\n[testnet4]\nregtest=1";
652 [ + - ]: 1 : std::string error;
653 : :
654 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
655 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
+ - ]
656 : :
657 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
658 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
+ - ]
659 : :
660 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
661 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
662 : :
663 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
664 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "regtest");
+ - ]
665 : :
666 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));
+ - + - ]
667 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
668 : :
669 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
670 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
671 : :
672 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
673 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
674 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
675 : :
676 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
677 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
678 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
679 : :
680 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
681 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
682 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
683 : :
684 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_test_no_reg, error));
+ - + - ]
685 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
686 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
687 : :
688 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
689 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
690 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
691 : :
692 : : // check setting the network to testnet4 (and thus making
693 : : // [testnet4] regtest=1 potentially relevant) doesn't break things
694 [ + - + - ]: 1 : test_args.SelectConfigNetwork("testnet4");
695 : :
696 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(0, argv_testnet4, error));
+ - + - ]
697 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
698 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
699 : :
700 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_testnet4, error));
+ - + - ]
701 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
702 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
703 : :
704 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_regtest, error));
+ - + - ]
705 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
706 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
707 : :
708 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(2, argv_test_no_reg, error));
+ - + - ]
709 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
710 [ + - + - : 1 : BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "testnet4");
+ - ]
711 : :
712 [ + - + - : 2 : BOOST_CHECK(test_args.ParseParameters(3, argv_both, error));
+ - + - ]
713 [ + - + - ]: 1 : test_args.ReadConfigString(testnetconf);
714 [ + - - + : 2 : BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
- - - - -
+ + - +
- ]
715 [ + - + - : 2 : }
+ - + - -
- ]
716 : :
717 : : // Test different ways settings can be merged, and verify results. This test can
718 : : // be used to confirm that updates to settings code don't change behavior
719 : : // unintentionally.
720 : : //
721 : : // The test covers:
722 : : //
723 : : // - Combining different setting actions. Possible actions are: configuring a
724 : : // setting, negating a setting (adding "-no" prefix), and configuring/negating
725 : : // settings in a network section (adding "main." or "test." prefixes).
726 : : //
727 : : // - Combining settings from command line arguments and a config file.
728 : : //
729 : : // - Combining SoftSet and ForceSet calls.
730 : : //
731 : : // - Testing "main" and "testnet4" network values to make sure settings from network
732 : : // sections are applied and to check for mainnet-specific behaviors like
733 : : // inheriting settings from the default section.
734 : : //
735 : : // - Testing network-specific settings like "-wallet", that may be ignored
736 : : // outside a network section, and non-network specific settings like "-server"
737 : : // that aren't sensitive to the network.
738 : : //
739 : 2 : struct ArgsMergeTestingSetup : public BasicTestingSetup {
740 : : //! Max number of actions to sequence together. Can decrease this when
741 : : //! debugging to make test results easier to understand.
742 : : static constexpr int MAX_ACTIONS = 3;
743 : :
744 : : enum Action { NONE, SET, NEGATE, SECTION_SET, SECTION_NEGATE };
745 : : using ActionList = Action[MAX_ACTIONS];
746 : :
747 : : //! Enumerate all possible test configurations.
748 : : template <typename Fn>
749 : 1 : void ForEachMergeSetup(Fn&& fn)
750 : : {
751 : 1 : ActionList arg_actions = {};
752 : : // command_line_options do not have sections. Only iterate over SET and NEGATE
753 : 1 : ForEachNoDup(arg_actions, SET, NEGATE, [&] {
754 : 7 : ActionList conf_actions = {};
755 : 378 : ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
756 [ + + ]: 1113 : for (bool soft_set : {false, true}) {
757 [ + + ]: 2226 : for (bool force_set : {false, true}) {
758 [ + - + - : 14840 : for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
+ - + - +
+ + + - -
- - ]
759 [ + - + - : 59360 : for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::TESTNET4), ChainTypeToString(ChainType::SIGNET)}) {
+ - + - +
+ + + - -
- - ]
760 [ + + ]: 71232 : for (bool net_specific : {false, true}) {
761 [ - + ]: 47488 : fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
762 : : }
763 : : }
764 : : }
765 : : }
766 : : }
767 : : });
768 : : });
769 : 1 : }
770 : :
771 : : //! Translate actions into a list of <key>=<value> setting strings.
772 : 94976 : std::vector<std::string> GetValues(const ActionList& actions,
773 : : const std::string& section,
774 : : const std::string& name,
775 : : const std::string& value_prefix)
776 : : {
777 : 94976 : std::vector<std::string> values;
778 : 94976 : int suffix = 0;
779 [ + + ]: 298240 : for (Action action : actions) {
780 [ + + ]: 252416 : if (action == NONE) break;
781 [ + + ]: 203264 : std::string prefix;
782 [ + + + - ]: 203264 : if (action == SECTION_SET || action == SECTION_NEGATE) prefix = section + ".";
783 [ + + ]: 203264 : if (action == SET || action == SECTION_SET) {
784 [ + + ]: 304896 : for (int i = 0; i < 2; ++i) {
785 [ + - + - : 609792 : values.push_back(prefix + name + "=" + value_prefix + ToString(++suffix));
+ - + - ]
786 : : }
787 : : }
788 [ + + ]: 203264 : if (action == NEGATE || action == SECTION_NEGATE) {
789 [ + - + - : 203264 : values.push_back(prefix + "no" + name + "=1");
+ - ]
790 : : }
791 : 203264 : }
792 : 94976 : return values;
793 : 0 : }
794 : : };
795 : :
796 : : // Regression test covering different ways config settings can be merged. The
797 : : // test parses and merges settings, representing the results as strings that get
798 : : // compared against an expected hash. To debug, the result strings can be dumped
799 : : // to a file (see comments below).
800 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
801 : : {
802 : 1 : CHash256 out_sha;
803 : 1 : FILE* out_file = nullptr;
804 [ - + ]: 1 : if (const char* out_path = getenv("ARGS_MERGE_TEST_OUT")) {
805 [ # # ]: 0 : out_file = fsbridge::fopen(out_path, "w");
806 [ # # # # ]: 0 : if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
807 : : }
808 : :
809 : 47489 : 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) {
811 : 47488 : TestArgsManager parser;
812 : :
813 [ + - ]: 47488 : std::string desc = "net=";
814 [ - + ]: 47488 : desc += network;
815 [ + - ]: 47488 : parser.SelectConfigNetwork(network);
816 : :
817 [ + + + - : 71232 : const std::string& name = net_specific ? "wallet" : "server";
+ - ]
818 [ + - ]: 47488 : const std::string key = "-" + name;
819 : 47488 : unsigned int flags = ArgsManager::ALLOW_ANY;
820 [ + + ]: 47488 : if (net_specific) flags |= ArgsManager::NETWORK_ONLY;
821 [ + - ]: 47488 : parser.AddArg(key, name, flags, OptionsCategory::OPTIONS);
822 : :
823 [ + - + - ]: 47488 : auto args = GetValues(arg_actions, section, name, "a");
824 [ + - ]: 47488 : std::vector<const char*> argv = {"ignored"};
825 [ + + ]: 169600 : for (auto& arg : args) {
826 [ + - ]: 122112 : arg.insert(0, "-");
827 [ + - ]: 122112 : desc += " ";
828 [ - + ]: 122112 : desc += arg;
829 [ + - ]: 122112 : argv.push_back(arg.c_str());
830 : : }
831 [ + - ]: 47488 : std::string error;
832 [ + - - + : 94976 : BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ - + - +
- ]
833 [ + - + - ]: 47488 : BOOST_CHECK_EQUAL(error, "");
834 : :
835 [ + - ]: 47488 : std::string conf;
836 [ + - + - : 230272 : for (auto& conf_val : GetValues(conf_actions, section, name, "c")) {
+ + ]
837 [ + - ]: 182784 : desc += " ";
838 [ - + ]: 182784 : desc += conf_val;
839 [ - + ]: 182784 : conf += conf_val;
840 [ + - ]: 182784 : conf += "\n";
841 : 47488 : }
842 [ + - ]: 47488 : std::istringstream conf_stream(conf);
843 [ + - + - : 94976 : BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ - + - +
- ]
844 [ + - + - ]: 47488 : BOOST_CHECK_EQUAL(error, "");
845 : :
846 [ + + ]: 47488 : if (soft_set) {
847 [ + - ]: 23744 : desc += " soft";
848 [ + - + - ]: 23744 : parser.SoftSetArg(key, "soft1");
849 [ + - + - ]: 47488 : parser.SoftSetArg(key, "soft2");
850 : : }
851 : :
852 [ + + ]: 47488 : if (force_set) {
853 [ + - ]: 23744 : desc += " force";
854 [ + - + - ]: 23744 : parser.ForceSetArg(key, "force1");
855 [ + - + - ]: 47488 : parser.ForceSetArg(key, "force2");
856 : : }
857 : :
858 [ + - ]: 47488 : desc += " || ";
859 : :
860 [ + - + + ]: 47488 : if (!parser.IsArgSet(key)) {
861 [ + - ]: 392 : desc += "unset";
862 [ + - + - : 784 : BOOST_CHECK(!parser.IsArgNegated(key));
+ - + - ]
863 [ + - + - : 392 : BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "default");
+ - + - ]
864 [ + - + - : 784 : BOOST_CHECK(parser.GetArgs(key).empty());
+ - ]
865 [ + - + + ]: 47096 : } else if (parser.IsArgNegated(key)) {
866 [ + - ]: 11696 : desc += "negated";
867 [ + - + - : 11696 : BOOST_CHECK_EQUAL(parser.GetArg(key, "default"), "0");
+ - + - ]
868 [ + - + - : 23392 : BOOST_CHECK(parser.GetArgs(key).empty());
+ - ]
869 : : } else {
870 [ + - + - ]: 70800 : desc += parser.GetArg(key, "default");
871 [ + - ]: 35400 : desc += " |";
872 [ + - + + ]: 110468 : for (const auto& arg : parser.GetArgs(key)) {
873 [ + - ]: 75068 : desc += " ";
874 [ - + ]: 150136 : desc += arg;
875 : 35400 : }
876 : : }
877 : :
878 [ + - ]: 47488 : std::set<std::string> ignored = parser.GetUnsuitableSectionOnlyArgs();
879 [ + + ]: 47488 : if (!ignored.empty()) {
880 [ + - ]: 1752 : desc += " | ignored";
881 [ + + ]: 3504 : for (const auto& arg : ignored) {
882 [ + - ]: 1752 : desc += " ";
883 [ - + ]: 3504 : desc += arg;
884 : : }
885 : : }
886 : :
887 [ + - ]: 47488 : desc += "\n";
888 : :
889 [ + - ]: 47488 : out_sha.Write(MakeUCharSpan(desc));
890 [ - + ]: 47488 : if (out_file) {
891 [ # # # # : 0 : BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
# # # # #
# ]
892 : : }
893 : 47488 : });
894 : :
895 [ - + ]: 1 : if (out_file) {
896 [ # # # # ]: 0 : if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
897 : 0 : out_file = nullptr;
898 : : }
899 : :
900 : 1 : unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
901 : 1 : out_sha.Finalize(out_sha_bytes);
902 : 1 : std::string out_sha_hex = HexStr(out_sha_bytes);
903 : :
904 : : // If check below fails, should manually dump the results with:
905 : : //
906 : : // ARGS_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=argsman_tests/util_ArgsMerge
907 : : //
908 : : // And verify diff against previous results to make sure the changes are expected.
909 : : //
910 : : // Results file is formatted like:
911 : : //
912 : : // <input> || <IsArgSet/IsArgNegated/GetArg output> | <GetArgs output> | <GetUnsuitable output>
913 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(out_sha_hex, "f1ee5ab094cc43d16a6086fa7f2c10389e0f99902616b31bbf29189972ad1473");
914 : 1 : }
915 : :
916 : : // Similar test as above, but for ArgsManager::GetChainTypeString function.
917 : 2 : struct ChainMergeTestingSetup : public BasicTestingSetup {
918 : : static constexpr int MAX_ACTIONS = 2;
919 : :
920 : : enum Action { NONE, ENABLE_TEST, DISABLE_TEST, NEGATE_TEST, ENABLE_REG, DISABLE_REG, NEGATE_REG };
921 : : using ActionList = Action[MAX_ACTIONS];
922 : :
923 : : //! Enumerate all possible test configurations.
924 : : template <typename Fn>
925 : 1 : void ForEachMergeSetup(Fn&& fn)
926 : : {
927 : 1 : ActionList arg_actions = {};
928 : 1 : ForEachNoDup(arg_actions, ENABLE_TEST, NEGATE_REG, [&] {
929 : 37 : ActionList conf_actions = {};
930 : 1406 : ForEachNoDup(conf_actions, ENABLE_TEST, NEGATE_REG, [&] { fn(arg_actions, conf_actions); });
931 : : });
932 : 1 : }
933 : : };
934 : :
935 [ + - + - : 7 : BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
936 : : {
937 : 1 : CHash256 out_sha;
938 : 1 : FILE* out_file = nullptr;
939 [ - + ]: 1 : if (const char* out_path = getenv("CHAIN_MERGE_TEST_OUT")) {
940 [ # # ]: 0 : out_file = fsbridge::fopen(out_path, "w");
941 [ # # # # ]: 0 : if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
942 : : }
943 : :
944 : 1370 : ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions) {
945 : 1369 : TestArgsManager parser;
946 [ + - + - : 2738 : parser.AddArg("-regtest", "regtest", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ - ]
947 [ + - + - : 2738 : parser.AddArg("-testnet4", "testnet4", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ - ]
948 : :
949 [ + + ]: 5402 : auto arg = [](Action action) { return action == ENABLE_TEST ? "-testnet4=1" :
950 [ + + ]: 4588 : action == DISABLE_TEST ? "-testnet4=0" :
951 [ + + ]: 3774 : action == NEGATE_TEST ? "-notestnet4=1" :
952 [ + + ]: 2960 : action == ENABLE_REG ? "-regtest=1" :
953 [ + + ]: 2146 : action == DISABLE_REG ? "-regtest=0" :
954 [ + + ]: 1332 : action == NEGATE_REG ? "-noregtest=1" : nullptr; };
955 : :
956 [ + - ]: 1369 : std::string desc;
957 [ + - ]: 1369 : std::vector<const char*> argv = {"ignored"};
958 [ + + ]: 3811 : for (Action action : arg_actions) {
959 : 2701 : const char* argstr = arg(action);
960 [ + + ]: 2701 : if (!argstr) break;
961 [ + - ]: 2442 : argv.push_back(argstr);
962 [ + - ]: 2442 : desc += " ";
963 [ + - ]: 2442 : desc += argv.back();
964 : : }
965 [ + - ]: 1369 : std::string error;
966 [ + - - + : 2738 : BOOST_CHECK(parser.ParseParameters(argv.size(), argv.data(), error));
+ - + - +
- ]
967 [ + - + - ]: 1369 : BOOST_CHECK_EQUAL(error, "");
968 : :
969 : 1369 : std::string conf;
970 [ + + ]: 3811 : for (Action action : conf_actions) {
971 : 2701 : const char* argstr = arg(action);
972 [ + + ]: 2701 : if (!argstr) break;
973 [ + - ]: 2442 : desc += " ";
974 [ + - ]: 2442 : desc += argstr + 1;
975 [ + - ]: 2442 : conf += argstr + 1;
976 [ + - ]: 2442 : conf += "\n";
977 : : }
978 [ + - ]: 1369 : std::istringstream conf_stream(conf);
979 [ + - + - : 2738 : BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error));
+ - + - +
- ]
980 [ + - + - ]: 1369 : BOOST_CHECK_EQUAL(error, "");
981 : :
982 [ + - ]: 1369 : desc += " || ";
983 : 1369 : try {
984 [ + + ]: 2556 : desc += parser.GetChainTypeString();
985 [ - + ]: 182 : } catch (const std::runtime_error& e) {
986 [ + - ]: 182 : desc += "error: ";
987 [ + - ]: 182 : desc += e.what();
988 : 182 : }
989 [ + - ]: 1369 : desc += "\n";
990 : :
991 [ + - ]: 1369 : out_sha.Write(MakeUCharSpan(desc));
992 [ - + ]: 1369 : if (out_file) {
993 [ # # # # : 0 : BOOST_REQUIRE(fwrite(desc.data(), 1, desc.size(), out_file) == desc.size());
# # # # #
# ]
994 : : }
995 : 1369 : });
996 : :
997 [ - + ]: 1 : if (out_file) {
998 [ # # # # ]: 0 : if (fclose(out_file)) throw std::system_error(errno, std::generic_category(), "fclose failed");
999 : 0 : out_file = nullptr;
1000 : : }
1001 : :
1002 : 1 : unsigned char out_sha_bytes[CSHA256::OUTPUT_SIZE];
1003 : 1 : out_sha.Finalize(out_sha_bytes);
1004 : 1 : std::string out_sha_hex = HexStr(out_sha_bytes);
1005 : :
1006 : : // If check below fails, should manually dump the results with:
1007 : : //
1008 : : // CHAIN_MERGE_TEST_OUT=results.txt ./test_bitcoin --run_test=argsman_tests/util_ChainMerge
1009 : : //
1010 : : // And verify diff against previous results to make sure the changes are expected.
1011 : : //
1012 : : // Results file is formatted like:
1013 : : //
1014 : : // <input> || <output>
1015 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(out_sha_hex, "c0e33aab0c74e040ddcee9edad59e8148d8e1cacb3cccd9ea1a1f485cb6bad21");
1016 : 1 : }
1017 : :
1018 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(util_ReadWriteSettings)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
1019 : : {
1020 : : // Test writing setting.
1021 : 1 : TestArgsManager args1;
1022 [ - + + - : 3 : args1.ForceSetArg("-datadir", fs::PathToString(m_path_root));
+ - ]
1023 [ + - + - ]: 2 : args1.LockSettings([&](common::Settings& s) { s.rw_settings["name"] = "value"; });
1024 [ + - ]: 1 : args1.WriteSettingsFile();
1025 : :
1026 : : // Test reading setting.
1027 [ + - ]: 1 : TestArgsManager args2;
1028 [ - + + - : 3 : args2.ForceSetArg("-datadir", fs::PathToString(m_path_root));
+ - ]
1029 [ + - ]: 1 : args2.ReadSettingsFile();
1030 [ + - + - : 2 : args2.LockSettings([&](common::Settings& s) { BOOST_CHECK_EQUAL(s.rw_settings["name"].get_str(), "value"); });
+ - ]
1031 : :
1032 : : // Test error logging, and remove previously written setting.
1033 : 1 : {
1034 [ + - + - ]: 2 : ASSERT_DEBUG_LOG("Failed renaming settings file");
1035 [ + - + - ]: 3 : fs::remove(args1.GetDataDirBase() / "settings.json");
1036 [ + - + - ]: 3 : fs::create_directory(args1.GetDataDirBase() / "settings.json");
1037 [ + - ]: 1 : args2.WriteSettingsFile();
1038 [ + - + - ]: 3 : fs::remove(args1.GetDataDirBase() / "settings.json");
1039 : 1 : }
1040 : 1 : }
1041 : :
1042 : : BOOST_AUTO_TEST_SUITE_END()
|