Line data Source code
1 : // Copyright (c) 2011-2014 The Bitcoin Core developers
2 : // Copyright (c) 2017-2022 The PIVX Core developers
3 : // Distributed under the MIT/X11 software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "util/system.h"
7 :
8 : #include "clientversion.h"
9 : #include "sync.h"
10 : #include "utilstrencodings.h"
11 : #include "util/string.h"
12 : #include "utilmoneystr.h"
13 : #include "test/test_pivx.h"
14 : #include "util/vector.h"
15 :
16 : #include <stdint.h>
17 : #include <vector>
18 : #ifndef WIN32
19 : #include <sys/types.h>
20 : #include <sys/wait.h>
21 : #endif
22 :
23 : #include <boost/test/unit_test.hpp>
24 :
25 : BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
26 :
27 4 : BOOST_AUTO_TEST_CASE(util_criticalsection)
28 : {
29 4 : RecursiveMutex cs;
30 :
31 2 : do {
32 2 : LOCK(cs);
33 2 : break;
34 :
35 : BOOST_ERROR("break was swallowed!");
36 : } while(0);
37 :
38 2 : do {
39 2 : TRY_LOCK(cs, lockTest);
40 2 : if (lockTest)
41 : break;
42 :
43 0 : BOOST_ERROR("break was swallowed!");
44 : } while(0);
45 2 : }
46 :
47 : static const unsigned char ParseHex_expected[65] = {
48 : 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
49 : 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
50 : 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
51 : 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
52 : 0x5f
53 : };
54 4 : BOOST_AUTO_TEST_CASE(util_ParseHex)
55 : {
56 2 : std::vector<unsigned char> result;
57 4 : std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
58 : // Basic test vector
59 2 : result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
60 4 : BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
61 :
62 : // Spaces between bytes must be supported
63 4 : result = ParseHex("12 34 56 78");
64 4 : BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
65 :
66 : // Stop parsing at invalid value
67 4 : result = ParseHex("1234 invalid 1234");
68 4 : BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34);
69 2 : }
70 :
71 4 : BOOST_AUTO_TEST_CASE(util_HexStr)
72 : {
73 4 : BOOST_CHECK_EQUAL(
74 : HexStr(ParseHex_expected),
75 : "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
76 :
77 2 : BOOST_CHECK_EQUAL(
78 : HexStr(Span<const unsigned char>(
79 : ParseHex_expected + sizeof(ParseHex_expected),
80 : ParseHex_expected + sizeof(ParseHex_expected))),
81 : "");
82 :
83 4 : BOOST_CHECK_EQUAL(
84 : HexStr(Span<const unsigned char>(ParseHex_expected, ParseHex_expected)),
85 : "");
86 :
87 2 : std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
88 :
89 2 : BOOST_CHECK_EQUAL(
90 : HexStr(ParseHex_vec),
91 : "04678afdb0"
92 : );
93 2 : }
94 :
95 4 : BOOST_AUTO_TEST_CASE(util_Join)
96 : {
97 : // Normal version
98 2 : BOOST_CHECK_EQUAL(Join({}, ", "), "");
99 6 : BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
100 8 : BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
101 :
102 : // Version with unary operator
103 8 : const auto op_upper = [](const std::string& s) { return ToUpper(s); };
104 2 : BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), "");
105 4 : BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO");
106 6 : BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR");
107 2 : }
108 :
109 4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
110 : {
111 4 : BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
112 2 : }
113 :
114 4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTimeForBackup)
115 : {
116 2 : BOOST_CHECK_EQUAL(FormatISO8601DateTimeForBackup(1586310600), ".20200408T0150Z");
117 2 : }
118 :
119 4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
120 : {
121 2 : BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
122 2 : }
123 :
124 4 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
125 : {
126 2 : BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
127 2 : }
128 :
129 10 : struct TestArgsManager : public ArgsManager
130 : {
131 12 : TestArgsManager() { m_network_only_args.clear(); }
132 12 : std::map<std::string, std::vector<std::string> >& GetOverrideArgs() { return m_override_args; }
133 6 : std::map<std::string, std::vector<std::string> >& GetConfigArgs() { return m_config_args; }
134 26 : void ReadConfigString(const std::string str_config)
135 : {
136 52 : std::istringstream streamConfig(str_config);
137 26 : {
138 26 : LOCK(cs_args);
139 26 : m_config_args.clear();
140 : }
141 26 : ReadConfigStream(streamConfig);
142 26 : }
143 6 : void SetNetworkOnlyArg(const std::string arg)
144 : {
145 6 : LOCK(cs_args);
146 6 : m_network_only_args.insert(arg);
147 6 : }
148 : };
149 :
150 4 : BOOST_AUTO_TEST_CASE(util_ParseParameters)
151 : {
152 2 : TestArgsManager testArgs;
153 2 : const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
154 :
155 2 : testArgs.ParseParameters(0, (char**)argv_test);
156 4 : BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
157 :
158 2 : testArgs.ParseParameters(1, (char**)argv_test);
159 4 : BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
160 :
161 2 : testArgs.ParseParameters(5, (char**)argv_test);
162 : // expectation: -ignored is ignored (program name argument),
163 : // -a, -b and -ccc end up in map, -d ignored because it is after
164 : // a non-option argument (non-GNU option parsing)
165 4 : BOOST_CHECK(testArgs.GetOverrideArgs().size() == 3 && testArgs.GetConfigArgs().empty());
166 12 : BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc")
167 : && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d"));
168 22 : BOOST_CHECK(testArgs.GetOverrideArgs().count("-a") && testArgs.GetOverrideArgs().count("-b") && testArgs.GetOverrideArgs().count("-ccc")
169 : && !testArgs.GetOverrideArgs().count("f") && !testArgs.GetOverrideArgs().count("-d"));
170 :
171 4 : BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].size() == 1);
172 4 : BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].front() == "");
173 4 : BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].size() == 2);
174 4 : BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].front() == "argument");
175 4 : BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].back() == "multiple");
176 2 : }
177 :
178 4 : BOOST_AUTO_TEST_CASE(util_GetBoolArg)
179 : {
180 2 : TestArgsManager testArgs;
181 2 : const char *argv_test[] = {
182 : "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
183 2 : testArgs.ParseParameters(7, (char**)argv_test);
184 :
185 : // Each letter should be set.
186 16 : for (char opt : "abcdef")
187 42 : BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
188 :
189 : // Nothing else should be in the map
190 4 : BOOST_CHECK(testArgs.GetOverrideArgs().size() == 6 &&
191 : testArgs.GetConfigArgs().empty());
192 :
193 : // The -no prefix should get stripped on the way in.
194 4 : BOOST_CHECK(!testArgs.IsArgSet("-nob"));
195 :
196 : // The -b option is flagged as negated, and nothing else is
197 4 : BOOST_CHECK(testArgs.IsArgNegated("-b"));
198 4 : BOOST_CHECK(!testArgs.IsArgNegated("-a"));
199 :
200 : // Check expected values.
201 4 : BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
202 4 : BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
203 4 : BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
204 4 : BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
205 4 : BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
206 4 : BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
207 2 : }
208 :
209 4 : BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
210 : {
211 : // Test some awful edge cases that hopefully no user will ever exercise.
212 2 : TestArgsManager testArgs;
213 :
214 : // Params test
215 2 : const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
216 2 : testArgs.ParseParameters(4, (char**)argv_test);
217 :
218 : // This was passed twice, second one overrides the negative setting.
219 4 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
220 6 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
221 :
222 : // A double negative is a positive, and not marked as negated.
223 4 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
224 6 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
225 :
226 : // Config test
227 2 : const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
228 2 : testArgs.ParseParameters(1, (char**)argv_test);
229 2 : testArgs.ReadConfigString(conf_test);
230 :
231 : // This was passed twice, second one overrides the negative setting,
232 : // and the value.
233 4 : BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
234 6 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
235 :
236 : // A double negative is a positive, and does not count as negated.
237 4 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
238 6 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
239 :
240 : // Combined test
241 2 : const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
242 2 : const char *combo_test_conf = "foo=1\nnobar=1\n";
243 2 : testArgs.ParseParameters(3, (char**)combo_test_args);
244 2 : testArgs.ReadConfigString(combo_test_conf);
245 :
246 : // Command line overrides, but doesn't erase old setting
247 4 : BOOST_CHECK(testArgs.IsArgNegated("-foo"));
248 6 : BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
249 4 : BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
250 :
251 : // Command line overrides, but doesn't erase old setting
252 4 : BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
253 6 : BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
254 6 : BOOST_CHECK(testArgs.GetArgs("-bar").size() == 1
255 : && testArgs.GetArgs("-bar").front() == "");
256 2 : }
257 :
258 4 : BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
259 : {
260 2 : const char *str_config =
261 : "a=\n"
262 : "b=1\n"
263 : "ccc=argument\n"
264 : "ccc=multiple\n"
265 : "d=e\n"
266 : "nofff=1\n"
267 : "noggg=0\n"
268 : "h=1\n"
269 : "noh=1\n"
270 : "noi=1\n"
271 : "i=1\n"
272 : "sec1.ccc=extend1\n"
273 : "\n"
274 : "[sec1]\n"
275 : "ccc=extend2\n"
276 : "d=eee\n"
277 : "h=1\n"
278 : "[sec2]\n"
279 : "ccc=extend3\n"
280 : "iii=2\n";
281 :
282 2 : TestArgsManager test_args;
283 :
284 2 : test_args.ReadConfigString(str_config);
285 : // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
286 : // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
287 :
288 4 : BOOST_CHECK(test_args.GetOverrideArgs().empty());
289 4 : BOOST_CHECK(test_args.GetConfigArgs().size() == 13);
290 :
291 34 : BOOST_CHECK(test_args.GetConfigArgs().count("-a")
292 : && test_args.GetConfigArgs().count("-b")
293 : && test_args.GetConfigArgs().count("-ccc")
294 : && test_args.GetConfigArgs().count("-d")
295 : && test_args.GetConfigArgs().count("-fff")
296 : && test_args.GetConfigArgs().count("-ggg")
297 : && test_args.GetConfigArgs().count("-h")
298 : && test_args.GetConfigArgs().count("-i")
299 : );
300 18 : BOOST_CHECK(test_args.GetConfigArgs().count("-sec1.ccc")
301 : && test_args.GetConfigArgs().count("-sec1.h")
302 : && test_args.GetConfigArgs().count("-sec2.ccc")
303 : && test_args.GetConfigArgs().count("-sec2.iii")
304 : );
305 :
306 22 : BOOST_CHECK(test_args.IsArgSet("-a")
307 : && test_args.IsArgSet("-b")
308 : && test_args.IsArgSet("-ccc")
309 : && test_args.IsArgSet("-d")
310 : && test_args.IsArgSet("-fff")
311 : && test_args.IsArgSet("-ggg")
312 : && test_args.IsArgSet("-h")
313 : && test_args.IsArgSet("-i")
314 : && !test_args.IsArgSet("-zzz")
315 : && !test_args.IsArgSet("-iii")
316 : );
317 :
318 58 : BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
319 : && test_args.GetArg("-b", "xxx") == "1"
320 : && test_args.GetArg("-ccc", "xxx") == "argument"
321 : && test_args.GetArg("-d", "xxx") == "e"
322 : && test_args.GetArg("-fff", "xxx") == "0"
323 : && test_args.GetArg("-ggg", "xxx") == "1"
324 : && test_args.GetArg("-h", "xxx") == "0"
325 : && test_args.GetArg("-i", "xxx") == "1"
326 : && test_args.GetArg("-zzz", "xxx") == "xxx"
327 : && test_args.GetArg("-iii", "xxx") == "xxx"
328 : );
329 :
330 6 : for (bool def : {false, true}) {
331 44 : BOOST_CHECK(test_args.GetBoolArg("-a", def)
332 : && test_args.GetBoolArg("-b", def)
333 : && !test_args.GetBoolArg("-ccc", def)
334 : && !test_args.GetBoolArg("-d", def)
335 : && !test_args.GetBoolArg("-fff", def)
336 : && test_args.GetBoolArg("-ggg", def)
337 : && !test_args.GetBoolArg("-h", def)
338 : && test_args.GetBoolArg("-i", def)
339 : && test_args.GetBoolArg("-zzz", def) == def
340 : && test_args.GetBoolArg("-iii", def) == def
341 : );
342 : }
343 :
344 6 : BOOST_CHECK(test_args.GetArgs("-a").size() == 1
345 : && test_args.GetArgs("-a").front() == "");
346 6 : BOOST_CHECK(test_args.GetArgs("-b").size() == 1
347 : && test_args.GetArgs("-b").front() == "1");
348 8 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
349 : && test_args.GetArgs("-ccc").front() == "argument"
350 : && test_args.GetArgs("-ccc").back() == "multiple");
351 4 : BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
352 4 : BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
353 6 : BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
354 : && test_args.GetArgs("-ggg").front() == "1");
355 4 : BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
356 4 : BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
357 4 : BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
358 6 : BOOST_CHECK(test_args.GetArgs("-i").size() == 1
359 : && test_args.GetArgs("-i").front() == "1");
360 4 : BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
361 4 : BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
362 :
363 4 : BOOST_CHECK(!test_args.IsArgNegated("-a"));
364 4 : BOOST_CHECK(!test_args.IsArgNegated("-b"));
365 4 : BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
366 4 : BOOST_CHECK(!test_args.IsArgNegated("-d"));
367 4 : BOOST_CHECK(test_args.IsArgNegated("-fff"));
368 4 : BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
369 4 : BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
370 4 : BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
371 4 : BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
372 :
373 : // Test sections work
374 2 : test_args.SelectConfigNetwork("sec1");
375 :
376 : // same as original
377 34 : BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
378 : && test_args.GetArg("-b", "xxx") == "1"
379 : && test_args.GetArg("-fff", "xxx") == "0"
380 : && test_args.GetArg("-ggg", "xxx") == "1"
381 : && test_args.GetArg("-zzz", "xxx") == "xxx"
382 : && test_args.GetArg("-iii", "xxx") == "xxx"
383 : );
384 : // d is overridden
385 6 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
386 : // section-specific setting
387 6 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
388 : // section takes priority for multiple values
389 6 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
390 : // check multiple values works
391 12 : const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
392 4 : const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
393 4 : BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
394 :
395 2 : test_args.SelectConfigNetwork("sec2");
396 :
397 : // same as original
398 40 : BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
399 : && test_args.GetArg("-b", "xxx") == "1"
400 : && test_args.GetArg("-d", "xxx") == "e"
401 : && test_args.GetArg("-fff", "xxx") == "0"
402 : && test_args.GetArg("-ggg", "xxx") == "1"
403 : && test_args.GetArg("-zzz", "xxx") == "xxx"
404 : && test_args.GetArg("-h", "xxx") == "0"
405 : );
406 : // section-specific setting
407 6 : BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
408 : // section takes priority for multiple values
409 6 : BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
410 : // check multiple values works
411 10 : const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
412 4 : const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
413 4 : BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
414 :
415 : // Test section only options
416 :
417 2 : test_args.SetNetworkOnlyArg("-d");
418 2 : test_args.SetNetworkOnlyArg("-ccc");
419 2 : test_args.SetNetworkOnlyArg("-h");
420 :
421 2 : test_args.SelectConfigNetwork(CBaseChainParams::MAIN);
422 6 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
423 4 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
424 6 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
425 :
426 2 : test_args.SelectConfigNetwork("sec1");
427 6 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
428 4 : BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
429 4 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
430 6 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
431 :
432 2 : test_args.SelectConfigNetwork("sec2");
433 6 : BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
434 4 : BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
435 4 : BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
436 6 : BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
437 2 : }
438 :
439 4 : BOOST_AUTO_TEST_CASE(util_GetArg)
440 : {
441 2 : TestArgsManager testArgs;
442 2 : testArgs.GetOverrideArgs().clear();
443 4 : testArgs.GetOverrideArgs()["strtest1"] = {"string..."};
444 : // strtest2 undefined on purpose
445 4 : testArgs.GetOverrideArgs()["inttest1"] = {"12345"};
446 4 : testArgs.GetOverrideArgs()["inttest2"] = {"81985529216486895"};
447 : // inttest3 undefined on purpose
448 4 : testArgs.GetOverrideArgs()["booltest1"] = {""};
449 : // booltest2 undefined on purpose
450 4 : testArgs.GetOverrideArgs()["booltest3"] = {"0"};
451 4 : testArgs.GetOverrideArgs()["booltest4"] = {"1"};
452 :
453 : // priorities
454 6 : testArgs.GetOverrideArgs()["pritest1"] = {"a", "b"};
455 6 : testArgs.GetConfigArgs()["pritest2"] = {"a", "b"};
456 4 : testArgs.GetOverrideArgs()["pritest3"] = {"a"};
457 4 : testArgs.GetConfigArgs()["pritest3"] = {"b"};
458 6 : testArgs.GetOverrideArgs()["pritest4"] = {"a","b"};
459 6 : testArgs.GetConfigArgs()["pritest4"] = {"c","d"};
460 :
461 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
462 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
463 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("inttest1", -1), 12345);
464 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("inttest2", -1), 81985529216486895LL);
465 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("inttest3", -1), -1);
466 2 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
467 2 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
468 2 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
469 2 : BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
470 :
471 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
472 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
473 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
474 2 : BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
475 2 : }
476 :
477 4 : BOOST_AUTO_TEST_CASE(util_GetChainName)
478 : {
479 2 : TestArgsManager test_args;
480 :
481 2 : const char* argv_testnet[] = {"cmd", "-testnet"};
482 2 : const char* argv_regtest[] = {"cmd", "-regtest"};
483 2 : const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
484 2 : const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
485 :
486 : // equivalent to "-testnet"
487 : // regtest in testnet section is ignored
488 2 : const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
489 :
490 2 : test_args.ParseParameters(0, (char**)argv_testnet);
491 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
492 :
493 2 : test_args.ParseParameters(2, (char**)argv_testnet);
494 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
495 :
496 2 : test_args.ParseParameters(2, (char**)argv_regtest);
497 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
498 :
499 2 : test_args.ParseParameters(3, (char**)argv_test_no_reg);
500 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
501 :
502 2 : test_args.ParseParameters(3, (char**)argv_both);
503 4 : BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
504 :
505 2 : test_args.ParseParameters(0, (char**)argv_testnet);
506 2 : test_args.ReadConfigString(testnetconf);
507 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
508 :
509 2 : test_args.ParseParameters(2, (char**)argv_testnet);
510 2 : test_args.ReadConfigString(testnetconf);
511 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
512 :
513 2 : test_args.ParseParameters(2, (char**)argv_regtest);
514 2 : test_args.ReadConfigString(testnetconf);
515 4 : BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
516 :
517 2 : test_args.ParseParameters(3, (char**)argv_test_no_reg);
518 2 : test_args.ReadConfigString(testnetconf);
519 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
520 :
521 2 : test_args.ParseParameters(3, (char**)argv_both);
522 2 : test_args.ReadConfigString(testnetconf);
523 4 : BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
524 :
525 : // check setting the network to test (and thus making
526 : // [test] regtest=1 potentially relevant) doesn't break things
527 2 : test_args.SelectConfigNetwork("test");
528 :
529 2 : test_args.ParseParameters(0, (char**)argv_testnet);
530 2 : test_args.ReadConfigString(testnetconf);
531 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
532 :
533 2 : test_args.ParseParameters(2, (char**)argv_testnet);
534 2 : test_args.ReadConfigString(testnetconf);
535 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
536 :
537 2 : test_args.ParseParameters(2, (char**)argv_regtest);
538 2 : test_args.ReadConfigString(testnetconf);
539 4 : BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
540 :
541 2 : test_args.ParseParameters(2, (char**)argv_test_no_reg);
542 2 : test_args.ReadConfigString(testnetconf);
543 2 : BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
544 :
545 2 : test_args.ParseParameters(3, (char**)argv_both);
546 2 : test_args.ReadConfigString(testnetconf);
547 4 : BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
548 2 : }
549 :
550 4 : BOOST_AUTO_TEST_CASE(util_FormatMoney)
551 : {
552 2 : BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00");
553 2 : BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789");
554 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00");
555 2 : BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00");
556 2 : BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00");
557 :
558 4 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00");
559 4 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00");
560 4 : BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00");
561 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00");
562 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00");
563 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00");
564 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00");
565 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00");
566 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00");
567 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10");
568 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01");
569 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001");
570 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
571 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
572 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
573 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
574 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
575 2 : }
576 :
577 4 : BOOST_AUTO_TEST_CASE(util_ParseMoney)
578 : {
579 2 : CAmount ret = 0;
580 4 : BOOST_CHECK(ParseMoney("0.0", ret));
581 2 : BOOST_CHECK_EQUAL(ret, 0);
582 :
583 4 : BOOST_CHECK(ParseMoney("12345.6789", ret));
584 2 : BOOST_CHECK_EQUAL(ret, (COIN/10000)*123456789);
585 :
586 4 : BOOST_CHECK(ParseMoney("100000000.00", ret));
587 2 : BOOST_CHECK_EQUAL(ret, COIN*100000000);
588 4 : BOOST_CHECK(ParseMoney("10000000.00", ret));
589 2 : BOOST_CHECK_EQUAL(ret, COIN*10000000);
590 4 : BOOST_CHECK(ParseMoney("1000000.00", ret));
591 2 : BOOST_CHECK_EQUAL(ret, COIN*1000000);
592 4 : BOOST_CHECK(ParseMoney("100000.00", ret));
593 2 : BOOST_CHECK_EQUAL(ret, COIN*100000);
594 4 : BOOST_CHECK(ParseMoney("10000.00", ret));
595 2 : BOOST_CHECK_EQUAL(ret, COIN*10000);
596 4 : BOOST_CHECK(ParseMoney("1000.00", ret));
597 2 : BOOST_CHECK_EQUAL(ret, COIN*1000);
598 4 : BOOST_CHECK(ParseMoney("100.00", ret));
599 2 : BOOST_CHECK_EQUAL(ret, COIN*100);
600 4 : BOOST_CHECK(ParseMoney("10.00", ret));
601 2 : BOOST_CHECK_EQUAL(ret, COIN*10);
602 4 : BOOST_CHECK(ParseMoney("1.00", ret));
603 2 : BOOST_CHECK_EQUAL(ret, COIN);
604 4 : BOOST_CHECK(ParseMoney("1", ret));
605 2 : BOOST_CHECK_EQUAL(ret, COIN);
606 4 : BOOST_CHECK(ParseMoney("0.1", ret));
607 2 : BOOST_CHECK_EQUAL(ret, COIN/10);
608 4 : BOOST_CHECK(ParseMoney("0.01", ret));
609 2 : BOOST_CHECK_EQUAL(ret, COIN/100);
610 4 : BOOST_CHECK(ParseMoney("0.001", ret));
611 2 : BOOST_CHECK_EQUAL(ret, COIN/1000);
612 4 : BOOST_CHECK(ParseMoney("0.0001", ret));
613 2 : BOOST_CHECK_EQUAL(ret, COIN/10000);
614 4 : BOOST_CHECK(ParseMoney("0.00001", ret));
615 2 : BOOST_CHECK_EQUAL(ret, COIN/100000);
616 4 : BOOST_CHECK(ParseMoney("0.000001", ret));
617 2 : BOOST_CHECK_EQUAL(ret, COIN/1000000);
618 4 : BOOST_CHECK(ParseMoney("0.0000001", ret));
619 2 : BOOST_CHECK_EQUAL(ret, COIN/10000000);
620 4 : BOOST_CHECK(ParseMoney("0.00000001", ret));
621 2 : BOOST_CHECK_EQUAL(ret, COIN/100000000);
622 :
623 : // Attempted 63 bit overflow should fail
624 4 : BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
625 :
626 : // Parsing negative amounts must fail
627 4 : BOOST_CHECK(!ParseMoney("-1", ret));
628 2 : }
629 :
630 4 : BOOST_AUTO_TEST_CASE(util_IsHex)
631 : {
632 4 : BOOST_CHECK(IsHex("00"));
633 6 : BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
634 4 : BOOST_CHECK(IsHex("ff"));
635 4 : BOOST_CHECK(IsHex("FF"));
636 :
637 4 : BOOST_CHECK(!IsHex(""));
638 4 : BOOST_CHECK(!IsHex("0"));
639 4 : BOOST_CHECK(!IsHex("a"));
640 4 : BOOST_CHECK(!IsHex("eleven"));
641 4 : BOOST_CHECK(!IsHex("00xx00"));
642 4 : BOOST_CHECK(!IsHex("0x0000"));
643 2 : }
644 :
645 4 : BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
646 : {
647 2 : int i;
648 2 : int count=0;
649 :
650 2 : SeedInsecureRand(SeedRand::ZEROS);
651 :
652 20 : for (int mod=2;mod<11;mod++)
653 : {
654 18 : int mask = 1;
655 : // Really rough binomal confidence approximation.
656 18 : int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
657 : //mask is 2^ceil(log2(mod))-1
658 50 : while(mask<mod-1)mask=(mask<<1)+1;
659 :
660 : count = 0;
661 : //How often does it get a zero from the uniform range [0,mod)?
662 180018 : for (i=0;i<10000;i++)
663 : {
664 235652 : uint32_t rval;
665 235652 : do{
666 235652 : rval=InsecureRand32()&mask;
667 235652 : }while(rval>=(uint32_t)mod);
668 180000 : count += rval==0;
669 : }
670 36 : BOOST_CHECK(count<=10000/mod+err);
671 36 : BOOST_CHECK(count>=10000/mod-err);
672 : }
673 2 : }
674 :
675 4 : BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
676 : {
677 4 : BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
678 4 : BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
679 4 : BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
680 4 : BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
681 4 : BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
682 4 : BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
683 4 : BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
684 2 : }
685 :
686 : /* Test strprintf formatting directives.
687 : * Put a string before and after to ensure sanity of element sizes on stack. */
688 : #define B "check_prefix"
689 : #define E "check_postfix"
690 4 : BOOST_AUTO_TEST_CASE(strprintf_numbers)
691 : {
692 2 : int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
693 2 : uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
694 8 : BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
695 8 : BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
696 8 : BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
697 :
698 2 : size_t st = 12345678; /* unsigned size_t test value */
699 2 : ssize_t sst = -12345678; /* signed size_t test value */
700 8 : BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
701 8 : BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
702 8 : BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
703 :
704 2 : ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
705 2 : ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
706 8 : BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
707 8 : BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
708 8 : BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
709 2 : }
710 : #undef B
711 : #undef E
712 :
713 : /* Check for mingw/wine issue #3494
714 : * Remove this test before time.ctime(0xffffffff) == 'Sun Feb 7 07:28:15 2106'
715 : */
716 4 : BOOST_AUTO_TEST_CASE(gettime)
717 : {
718 4 : BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
719 2 : }
720 :
721 4 : BOOST_AUTO_TEST_CASE(util_time_GetTime)
722 : {
723 2 : SetMockTime(111);
724 : // Check that mock time does not change after a sleep
725 6 : for (const auto& num_sleep : {0, 1}) {
726 4 : MilliSleep(num_sleep);
727 4 : BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
728 4 : BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
729 4 : BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
730 4 : BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
731 : }
732 :
733 2 : SetMockTime(0);
734 : // Check that system time changes after a sleep
735 2 : const auto ms_0 = GetTime<std::chrono::milliseconds>();
736 2 : const auto us_0 = GetTime<std::chrono::microseconds>();
737 2 : MilliSleep(1);
738 4 : BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
739 4 : BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
740 2 : }
741 :
742 4 : BOOST_AUTO_TEST_CASE(test_IsDigit)
743 : {
744 2 : BOOST_CHECK_EQUAL(IsDigit('0'), true);
745 2 : BOOST_CHECK_EQUAL(IsDigit('1'), true);
746 2 : BOOST_CHECK_EQUAL(IsDigit('8'), true);
747 2 : BOOST_CHECK_EQUAL(IsDigit('9'), true);
748 :
749 2 : BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
750 2 : BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
751 2 : BOOST_CHECK_EQUAL(IsDigit(0), false);
752 2 : BOOST_CHECK_EQUAL(IsDigit(1), false);
753 2 : BOOST_CHECK_EQUAL(IsDigit(8), false);
754 2 : BOOST_CHECK_EQUAL(IsDigit(9), false);
755 2 : }
756 :
757 4 : BOOST_AUTO_TEST_CASE(test_ParseInt32)
758 : {
759 2 : int32_t n;
760 : // Valid values
761 4 : BOOST_CHECK(ParseInt32("1234", nullptr));
762 4 : BOOST_CHECK(ParseInt32("0", &n) && n == 0);
763 4 : BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
764 4 : BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
765 4 : BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
766 4 : BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648);
767 4 : BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
768 : // Invalid values
769 4 : BOOST_CHECK(!ParseInt32("", &n));
770 4 : BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
771 4 : BOOST_CHECK(!ParseInt32("1 ", &n));
772 4 : BOOST_CHECK(!ParseInt32("1a", &n));
773 4 : BOOST_CHECK(!ParseInt32("aap", &n));
774 4 : BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
775 4 : BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
776 2 : const char test_bytes[] = {'1', 0, '1'};
777 2 : std::string teststr(test_bytes, sizeof(test_bytes));
778 4 : BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
779 : // Overflow and underflow
780 4 : BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
781 4 : BOOST_CHECK(!ParseInt32("2147483648", nullptr));
782 6 : BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
783 6 : BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
784 2 : }
785 :
786 4 : BOOST_AUTO_TEST_CASE(test_ParseInt64)
787 : {
788 2 : int64_t n;
789 : // Valid values
790 4 : BOOST_CHECK(ParseInt64("1234", nullptr));
791 4 : BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
792 4 : BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
793 4 : BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
794 4 : BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
795 4 : BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
796 6 : BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
797 6 : BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
798 4 : BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
799 : // Invalid values
800 4 : BOOST_CHECK(!ParseInt64("", &n));
801 4 : BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
802 4 : BOOST_CHECK(!ParseInt64("1 ", &n));
803 4 : BOOST_CHECK(!ParseInt64("1a", &n));
804 4 : BOOST_CHECK(!ParseInt64("aap", &n));
805 4 : BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
806 2 : const char test_bytes[] = {'1', 0, '1'};
807 2 : std::string teststr(test_bytes, sizeof(test_bytes));
808 4 : BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
809 : // Overflow and underflow
810 6 : BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
811 6 : BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
812 6 : BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
813 6 : BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
814 2 : }
815 :
816 4 : BOOST_AUTO_TEST_CASE(test_ParseDouble)
817 : {
818 2 : double n;
819 : // Valid values
820 4 : BOOST_CHECK(ParseDouble("1234", nullptr));
821 4 : BOOST_CHECK(ParseDouble("0", &n) && n == 0.0);
822 4 : BOOST_CHECK(ParseDouble("1234", &n) && n == 1234.0);
823 4 : BOOST_CHECK(ParseDouble("01234", &n) && n == 1234.0); // no octal
824 4 : BOOST_CHECK(ParseDouble("2147483647", &n) && n == 2147483647.0);
825 4 : BOOST_CHECK(ParseDouble("-2147483648", &n) && n == -2147483648.0);
826 4 : BOOST_CHECK(ParseDouble("-1234", &n) && n == -1234.0);
827 4 : BOOST_CHECK(ParseDouble("1e6", &n) && n == 1e6);
828 4 : BOOST_CHECK(ParseDouble("-1e6", &n) && n == -1e6);
829 : // Invalid values
830 4 : BOOST_CHECK(!ParseDouble("", &n));
831 4 : BOOST_CHECK(!ParseDouble(" 1", &n)); // no padding inside
832 4 : BOOST_CHECK(!ParseDouble("1 ", &n));
833 4 : BOOST_CHECK(!ParseDouble("1a", &n));
834 4 : BOOST_CHECK(!ParseDouble("aap", &n));
835 4 : BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
836 2 : const char test_bytes[] = {'1', 0, '1'};
837 2 : std::string teststr(test_bytes, sizeof(test_bytes));
838 4 : BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
839 : // Overflow and underflow
840 4 : BOOST_CHECK(!ParseDouble("-1e10000", nullptr));
841 4 : BOOST_CHECK(!ParseDouble("1e10000", nullptr));
842 2 : }
843 :
844 4 : BOOST_AUTO_TEST_CASE(test_FormatParagraph)
845 : {
846 2 : BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
847 2 : BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
848 2 : BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), "test");
849 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
850 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
851 2 : BOOST_CHECK_EQUAL(FormatParagraph("testerde test ", 4, 0), "testerde\ntest");
852 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test");
853 6 : BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string."), "This is a very long test string. This is a second sentence in the very long\ntest string.");
854 2 : }
855 :
856 4 : BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
857 : {
858 4 : std::vector<std::string> comments;
859 4 : comments.push_back(std::string("comment1"));
860 4 : std::vector<std::string> comments2;
861 4 : comments2.push_back(std::string("comment1"));
862 4 : comments2.push_back(std::string("comment2"));
863 2 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
864 6 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
865 6 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; comment2)/"));
866 2 : }
867 :
868 4 : BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
869 : {
870 2 : int64_t amount = 0;
871 4 : BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
872 2 : BOOST_CHECK_EQUAL(amount, 0LL);
873 4 : BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
874 2 : BOOST_CHECK_EQUAL(amount, 100000000LL);
875 4 : BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
876 2 : BOOST_CHECK_EQUAL(amount, 0LL);
877 4 : BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
878 2 : BOOST_CHECK_EQUAL(amount, -10000000LL);
879 4 : BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
880 2 : BOOST_CHECK_EQUAL(amount, 110000000LL);
881 6 : BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
882 2 : BOOST_CHECK_EQUAL(amount, 110000000LL);
883 4 : BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
884 2 : BOOST_CHECK_EQUAL(amount, 1100000000LL);
885 4 : BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
886 2 : BOOST_CHECK_EQUAL(amount, 11000000LL);
887 4 : BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
888 2 : BOOST_CHECK_EQUAL(amount, 100000000000LL);
889 4 : BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
890 2 : BOOST_CHECK_EQUAL(amount, -100000000000LL);
891 4 : BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
892 2 : BOOST_CHECK_EQUAL(amount, 1LL);
893 6 : BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
894 2 : BOOST_CHECK_EQUAL(amount, 1LL);
895 4 : BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
896 2 : BOOST_CHECK_EQUAL(amount, -1LL);
897 6 : BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
898 2 : BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
899 6 : BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
900 2 : BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
901 6 : BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
902 2 : BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
903 :
904 4 : BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
905 4 : BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
906 4 : BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
907 4 : BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
908 4 : BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
909 4 : BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
910 4 : BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
911 4 : BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
912 4 : BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
913 4 : BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
914 4 : BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
915 6 : BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
916 6 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
917 6 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
918 6 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
919 6 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
920 6 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
921 6 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
922 6 : BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
923 6 : BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
924 6 : BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
925 6 : BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
926 6 : BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
927 6 : BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
928 4 : BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
929 4 : BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
930 4 : BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
931 2 : }
932 :
933 4 : BOOST_AUTO_TEST_CASE(test_ToLower)
934 : {
935 2 : BOOST_CHECK_EQUAL(ToLower('@'), '@');
936 2 : BOOST_CHECK_EQUAL(ToLower('A'), 'a');
937 2 : BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
938 2 : BOOST_CHECK_EQUAL(ToLower('['), '[');
939 2 : BOOST_CHECK_EQUAL(ToLower(0), 0);
940 2 : BOOST_CHECK_EQUAL(ToLower(255), 255);
941 :
942 2 : std::string testVector;
943 2 : Downcase(testVector);
944 2 : BOOST_CHECK_EQUAL(testVector, "");
945 :
946 2 : testVector = "#HODL";
947 2 : Downcase(testVector);
948 2 : BOOST_CHECK_EQUAL(testVector, "#hodl");
949 :
950 2 : testVector = "\x00\xfe\xff";
951 2 : Downcase(testVector);
952 2 : BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff");
953 2 : }
954 :
955 4 : BOOST_AUTO_TEST_CASE(test_ToUpper)
956 : {
957 2 : BOOST_CHECK_EQUAL(ToUpper('`'), '`');
958 2 : BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
959 2 : BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
960 2 : BOOST_CHECK_EQUAL(ToUpper('{'), '{');
961 2 : BOOST_CHECK_EQUAL(ToUpper(0), 0);
962 2 : BOOST_CHECK_EQUAL(ToUpper(255), 255);
963 2 : }
964 :
965 4 : BOOST_AUTO_TEST_CASE(test_Capitalize)
966 : {
967 2 : BOOST_CHECK_EQUAL(Capitalize(""), "");
968 2 : BOOST_CHECK_EQUAL(Capitalize("pivx"), "Pivx");
969 2 : BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
970 2 : }
971 :
972 4 : BOOST_AUTO_TEST_CASE(test_validateURL)
973 : {
974 : // Must pass
975 4 : BOOST_CHECK(validateURL("http://foo.bar"));
976 4 : BOOST_CHECK(validateURL("https://foo.bar"));
977 6 : BOOST_CHECK(validateURL("https://foo.bar/"));
978 6 : BOOST_CHECK(validateURL("http://pivx.foo.bar"));
979 6 : BOOST_CHECK(validateURL("https://foo.bar/pivx"));
980 6 : BOOST_CHECK(validateURL("https://foo.bar/pivx/more/"));
981 6 : BOOST_CHECK(validateURL("https://142.2.3.1"));
982 6 : BOOST_CHECK(validateURL("https://foo_bar.pivx.com"));
983 6 : BOOST_CHECK(validateURL("http://foo.bar/?baz=some"));
984 6 : BOOST_CHECK(validateURL("http://foo.bar/?baz=some&p=364"));
985 :
986 : // Must fail
987 4 : BOOST_CHECK(!validateURL("BlahBlah"));
988 4 : BOOST_CHECK(!validateURL("foo.bar"));
989 4 : BOOST_CHECK(!validateURL("://foo.bar"));
990 4 : BOOST_CHECK(!validateURL("www.foo.bar"));
991 4 : BOOST_CHECK(!validateURL("http://foo..bar"));
992 4 : BOOST_CHECK(!validateURL("http:///foo.bar"));
993 4 : BOOST_CHECK(!validateURL("http:// foo.bar"));
994 4 : BOOST_CHECK(!validateURL("http://foo .bar"));
995 4 : BOOST_CHECK(!validateURL("http://foo"));
996 4 : BOOST_CHECK(!validateURL("http://foo.bar."));
997 6 : BOOST_CHECK(!validateURL("http://foo.bar.."));
998 4 : BOOST_CHECK(!validateURL("http://"));
999 6 : BOOST_CHECK(!validateURL("http://.something.com"));
1000 6 : BOOST_CHECK(!validateURL("http://?something.com"));
1001 6 : BOOST_CHECK(!validateURL("https://foo.bar/?q=Spaces are not encoded"));
1002 2 : }
1003 :
1004 1 : static void TestOtherThread(fs::path dirname, std::string lockname, bool *result)
1005 : {
1006 1 : *result = LockDirectory(dirname, lockname);
1007 1 : }
1008 :
1009 : #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
1010 : static constexpr char LockCommand = 'L';
1011 : static constexpr char UnlockCommand = 'U';
1012 : static constexpr char ExitCommand = 'X';
1013 :
1014 1 : static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
1015 : {
1016 5 : char ch;
1017 5 : int rv;
1018 5 : while (true) {
1019 10 : rv = read(fd, &ch, 1); // Wait for command
1020 5 : assert(rv == 1);
1021 5 : switch(ch) {
1022 3 : case LockCommand:
1023 3 : ch = LockDirectory(dirname, lockname);
1024 3 : rv = write(fd, &ch, 1);
1025 3 : assert(rv == 1);
1026 : break;
1027 1 : case UnlockCommand:
1028 1 : ReleaseDirectoryLocks();
1029 1 : ch = true; // Always succeeds
1030 6 : rv = write(fd, &ch, 1);
1031 : break;
1032 1 : case ExitCommand:
1033 1 : close(fd);
1034 1 : exit(0);
1035 0 : default:
1036 0 : assert(0);
1037 : }
1038 : }
1039 : }
1040 : #endif
1041 :
1042 4 : BOOST_AUTO_TEST_CASE(test_LockDirectory)
1043 : {
1044 6 : fs::path dirname = fs::temp_directory_path() / fs::unique_path();
1045 3 : const std::string lockname = ".lock";
1046 : #ifndef WIN32
1047 : // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
1048 : // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
1049 : // at build-time of the boost library
1050 2 : void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
1051 :
1052 : // Fork another process for testing before creating the lock, so that we
1053 : // won't fork while holding the lock (which might be undefined, and is not
1054 : // relevant as test case as that is avoided with -daemonize).
1055 2 : int fd[2];
1056 2 : BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
1057 2 : pid_t pid = fork();
1058 2 : if (!pid) {
1059 1 : BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
1060 3 : TestOtherProcess(dirname, lockname, fd[0]);
1061 : }
1062 1 : BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
1063 : #endif
1064 : // Lock on non-existent directory should fail
1065 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
1066 :
1067 1 : fs::create_directories(dirname);
1068 :
1069 : // Probing lock on new directory should succeed
1070 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1071 :
1072 : // Persistent lock on new directory should succeed
1073 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1074 :
1075 : // Another lock on the directory from the same thread should succeed
1076 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1077 :
1078 : // Another lock on the directory from a different thread within the same process should succeed
1079 1 : bool threadresult;
1080 2 : std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
1081 1 : thr.join();
1082 1 : BOOST_CHECK_EQUAL(threadresult, true);
1083 : #ifndef WIN32
1084 : // Try to acquire lock in child process while we're holding it, this should fail.
1085 1 : char ch;
1086 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1087 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1088 1 : BOOST_CHECK_EQUAL((bool)ch, false);
1089 :
1090 : // Give up our lock
1091 1 : ReleaseDirectoryLocks();
1092 : // Probing lock from our side now should succeed, but not hold on to the lock.
1093 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1094 :
1095 : // Try to acquire the lock in the child process, this should be successful.
1096 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1097 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1098 1 : BOOST_CHECK_EQUAL((bool)ch, true);
1099 :
1100 : // When we try to probe the lock now, it should fail.
1101 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
1102 :
1103 : // Unlock the lock in the child process
1104 1 : BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
1105 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1106 1 : BOOST_CHECK_EQUAL((bool)ch, true);
1107 :
1108 : // When we try to probe the lock now, it should succeed.
1109 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1110 :
1111 : // Re-lock the lock in the child process, then wait for it to exit, check
1112 : // successful return. After that, we check that exiting the process
1113 : // has released the lock as we would expect by probing it.
1114 1 : int processstatus;
1115 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1116 1 : BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
1117 1 : BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
1118 1 : BOOST_CHECK_EQUAL(processstatus, 0);
1119 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1120 :
1121 : // Restore SIGCHLD
1122 1 : signal(SIGCHLD, old_handler);
1123 1 : BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
1124 : #endif
1125 : // Clean up
1126 1 : ReleaseDirectoryLocks();
1127 1 : fs::remove_all(dirname);
1128 1 : }
1129 :
1130 2 : BOOST_AUTO_TEST_CASE(test_DirIsWritable)
1131 : {
1132 : // Should be able to write to the system tmp dir.
1133 1 : fs::path tmpdirname = fs::temp_directory_path();
1134 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1135 :
1136 : // Should not be able to write to a non-existent dir.
1137 3 : tmpdirname = fs::temp_directory_path() / fs::unique_path();
1138 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
1139 :
1140 1 : fs::create_directory(tmpdirname);
1141 : // Should be able to write to it now.
1142 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1143 1 : fs::remove(tmpdirname);
1144 1 : }
1145 :
1146 : namespace {
1147 :
1148 : struct Tracker
1149 : {
1150 : //! Points to the original object (possibly itself) we moved/copied from
1151 : const Tracker* origin;
1152 : //! How many copies where involved between the original object and this one (moves are not counted)
1153 : int copies;
1154 :
1155 1 : Tracker() noexcept : origin(this), copies(0) {}
1156 10 : Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
1157 13 : Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
1158 : Tracker& operator=(const Tracker& t) noexcept
1159 : {
1160 : origin = t.origin;
1161 : copies = t.copies + 1;
1162 : return *this;
1163 : }
1164 : Tracker& operator=(Tracker&& t) noexcept
1165 : {
1166 : origin = t.origin;
1167 : copies = t.copies;
1168 : return *this;
1169 : }
1170 : };
1171 :
1172 : }
1173 :
1174 2 : BOOST_AUTO_TEST_CASE(test_tracked_vector)
1175 : {
1176 1 : Tracker t1;
1177 1 : Tracker t2;
1178 1 : Tracker t3;
1179 :
1180 2 : BOOST_CHECK(t1.origin == &t1);
1181 2 : BOOST_CHECK(t2.origin == &t2);
1182 2 : BOOST_CHECK(t3.origin == &t3);
1183 :
1184 1 : auto v1 = Vector(t1);
1185 1 : BOOST_CHECK_EQUAL(v1.size(), 1);
1186 2 : BOOST_CHECK(v1[0].origin == &t1);
1187 1 : BOOST_CHECK_EQUAL(v1[0].copies, 1);
1188 :
1189 2 : auto v2 = Vector(std::move(t2));
1190 1 : BOOST_CHECK_EQUAL(v2.size(), 1);
1191 2 : BOOST_CHECK(v2[0].origin == &t2);
1192 1 : BOOST_CHECK_EQUAL(v2[0].copies, 0);
1193 :
1194 2 : auto v3 = Vector(t1, std::move(t2));
1195 1 : BOOST_CHECK_EQUAL(v3.size(), 2);
1196 2 : BOOST_CHECK(v3[0].origin == &t1);
1197 2 : BOOST_CHECK(v3[1].origin == &t2);
1198 1 : BOOST_CHECK_EQUAL(v3[0].copies, 1);
1199 1 : BOOST_CHECK_EQUAL(v3[1].copies, 0);
1200 :
1201 2 : auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
1202 1 : BOOST_CHECK_EQUAL(v4.size(), 3);
1203 2 : BOOST_CHECK(v4[0].origin == &t1);
1204 2 : BOOST_CHECK(v4[1].origin == &t2);
1205 2 : BOOST_CHECK(v4[2].origin == &t3);
1206 1 : BOOST_CHECK_EQUAL(v4[0].copies, 1);
1207 1 : BOOST_CHECK_EQUAL(v4[1].copies, 1);
1208 1 : BOOST_CHECK_EQUAL(v4[2].copies, 0);
1209 :
1210 2 : auto v5 = Cat(v1, v4);
1211 1 : BOOST_CHECK_EQUAL(v5.size(), 4);
1212 2 : BOOST_CHECK(v5[0].origin == &t1);
1213 2 : BOOST_CHECK(v5[1].origin == &t1);
1214 2 : BOOST_CHECK(v5[2].origin == &t2);
1215 2 : BOOST_CHECK(v5[3].origin == &t3);
1216 1 : BOOST_CHECK_EQUAL(v5[0].copies, 2);
1217 1 : BOOST_CHECK_EQUAL(v5[1].copies, 2);
1218 1 : BOOST_CHECK_EQUAL(v5[2].copies, 2);
1219 1 : BOOST_CHECK_EQUAL(v5[3].copies, 1);
1220 :
1221 2 : auto v6 = Cat(std::move(v1), v3);
1222 1 : BOOST_CHECK_EQUAL(v6.size(), 3);
1223 2 : BOOST_CHECK(v6[0].origin == &t1);
1224 2 : BOOST_CHECK(v6[1].origin == &t1);
1225 2 : BOOST_CHECK(v6[2].origin == &t2);
1226 1 : BOOST_CHECK_EQUAL(v6[0].copies, 1);
1227 1 : BOOST_CHECK_EQUAL(v6[1].copies, 2);
1228 1 : BOOST_CHECK_EQUAL(v6[2].copies, 1);
1229 :
1230 2 : auto v7 = Cat(v2, std::move(v4));
1231 1 : BOOST_CHECK_EQUAL(v7.size(), 4);
1232 2 : BOOST_CHECK(v7[0].origin == &t2);
1233 2 : BOOST_CHECK(v7[1].origin == &t1);
1234 2 : BOOST_CHECK(v7[2].origin == &t2);
1235 2 : BOOST_CHECK(v7[3].origin == &t3);
1236 1 : BOOST_CHECK_EQUAL(v7[0].copies, 1);
1237 1 : BOOST_CHECK_EQUAL(v7[1].copies, 1);
1238 1 : BOOST_CHECK_EQUAL(v7[2].copies, 1);
1239 1 : BOOST_CHECK_EQUAL(v7[3].copies, 0);
1240 :
1241 2 : auto v8 = Cat(std::move(v2), std::move(v3));
1242 1 : BOOST_CHECK_EQUAL(v8.size(), 3);
1243 2 : BOOST_CHECK(v8[0].origin == &t2);
1244 2 : BOOST_CHECK(v8[1].origin == &t1);
1245 2 : BOOST_CHECK(v8[2].origin == &t2);
1246 1 : BOOST_CHECK_EQUAL(v8[0].copies, 0);
1247 1 : BOOST_CHECK_EQUAL(v8[1].copies, 1);
1248 1 : BOOST_CHECK_EQUAL(v8[2].copies, 0);
1249 1 : }
1250 :
1251 : BOOST_AUTO_TEST_SUITE_END()
|