Line data Source code
1 : // Copyright (c) 2011-2021 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 <util/system.h>
6 :
7 : #include <clientversion.h>
8 : #include <fs.h>
9 : #include <hash.h> // For Hash()
10 : #include <key.h> // For CKey
11 : #include <sync.h>
12 : #include <test/util/random.h>
13 : #include <test/util/setup_common.h>
14 : #include <uint256.h>
15 : #include <util/getuniquepath.h>
16 : #include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
17 : #include <util/moneystr.h>
18 : #include <util/overflow.h>
19 : #include <util/ranges_set.h>
20 : #include <util/readwritefile.h>
21 : #include <util/spanparsing.h>
22 : #include <util/strencodings.h>
23 : #include <util/string.h>
24 : #include <util/time.h>
25 : #include <util/vector.h>
26 :
27 : #include <array>
28 : #include <cmath>
29 : #include <fstream>
30 : #include <deque>
31 : #include <optional>
32 : #include <limits>
33 : #include <map>
34 : #include <random>
35 : #include <stdint.h>
36 : #include <string.h>
37 : #include <thread>
38 : #include <univalue.h>
39 : #include <unordered_set>
40 : #include <utility>
41 : #include <vector>
42 :
43 : #include <sys/types.h>
44 :
45 : #ifndef WIN32
46 : #include <signal.h>
47 : #include <sys/wait.h>
48 : #endif
49 :
50 : #include <boost/test/unit_test.hpp>
51 :
52 : using namespace std::literals;
53 :
54 : static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s};
55 :
56 : /* defined in logging.cpp */
57 : namespace BCLog {
58 : std::string LogEscapeMessage(const std::string& str);
59 : }
60 :
61 146 : BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
62 :
63 : namespace {
64 : class NoCopyOrMove
65 : {
66 : public:
67 : int i;
68 4 : explicit NoCopyOrMove(int i) : i{i} { }
69 :
70 : NoCopyOrMove() = delete;
71 : NoCopyOrMove(const NoCopyOrMove&) = delete;
72 : NoCopyOrMove(NoCopyOrMove&&) = delete;
73 : NoCopyOrMove& operator=(const NoCopyOrMove&) = delete;
74 : NoCopyOrMove& operator=(NoCopyOrMove&&) = delete;
75 :
76 6 : operator bool() const { return i != 0; }
77 :
78 8 : int get_ip1() { return i + 1; }
79 4 : bool test()
80 : {
81 : // Check that Assume can be used within a lambda and still call methods
82 8 : [&]() { Assume(get_ip1()); }();
83 4 : return Assume(get_ip1() != 5);
84 : }
85 : };
86 : } // namespace
87 :
88 152 : BOOST_AUTO_TEST_CASE(util_check)
89 : {
90 : // Check that Assert can forward
91 2 : const std::unique_ptr<int> p_two = Assert(std::make_unique<int>(2));
92 : // Check that Assert works on lvalues and rvalues
93 2 : const int two = *Assert(p_two);
94 2 : Assert(two == 2);
95 2 : Assert(true);
96 : // Check that Assume can be used as unary expression
97 2 : const bool result{Assume(two == 2)};
98 2 : Assert(result);
99 :
100 : // Check that Assert doesn't require copy/move
101 2 : NoCopyOrMove x{9};
102 2 : Assert(x).i += 3;
103 2 : Assert(x).test();
104 :
105 : // Check nested Asserts
106 2 : BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3);
107 :
108 : // Check -Wdangling-gsl does not trigger when copying the int. (It would
109 : // trigger on "const int&")
110 2 : const int nine{*Assert(std::optional<int>{9})};
111 2 : BOOST_CHECK_EQUAL(9, nine);
112 2 : }
113 :
114 152 : BOOST_AUTO_TEST_CASE(util_criticalsection)
115 : {
116 2 : RecursiveMutex cs;
117 :
118 2 : do {
119 2 : LOCK(cs);
120 : break;
121 :
122 : BOOST_ERROR("break was swallowed!");
123 2 : } while(0);
124 :
125 2 : do {
126 2 : TRY_LOCK(cs, lockTest);
127 2 : if (lockTest) {
128 2 : BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
129 2 : break;
130 : }
131 :
132 0 : BOOST_ERROR("break was swallowed!");
133 2 : } while(0);
134 2 : }
135 :
136 : static const unsigned char ParseHex_expected[65] = {
137 : 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
138 : 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
139 : 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
140 : 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
141 : 0x5f
142 : };
143 152 : BOOST_AUTO_TEST_CASE(parse_hex)
144 : {
145 2 : std::vector<unsigned char> result;
146 2 : std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
147 : // Basic test vector
148 2 : result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
149 2 : BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
150 2 : result = TryParseHex<uint8_t>("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").value();
151 2 : BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
152 :
153 : // Spaces between bytes must be supported
154 2 : result = ParseHex("12 34 56 78");
155 2 : BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
156 2 : result = TryParseHex<uint8_t>("12 34 56 78").value();
157 2 : BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
158 :
159 : // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
160 2 : result = ParseHex(" 89 34 56 78");
161 2 : BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
162 2 : result = TryParseHex<uint8_t>(" 89 34 56 78").value();
163 2 : BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
164 :
165 : // Mixed case and spaces are supported
166 2 : result = ParseHex(" Ff aA ");
167 2 : BOOST_CHECK(result.size() == 2 && result[0] == 0xff && result[1] == 0xaa);
168 2 : result = TryParseHex<uint8_t>(" Ff aA ").value();
169 2 : BOOST_CHECK(result.size() == 2 && result[0] == 0xff && result[1] == 0xaa);
170 :
171 : // Empty string is supported
172 2 : result = ParseHex("");
173 2 : BOOST_CHECK(result.size() == 0);
174 2 : result = TryParseHex<uint8_t>("").value();
175 2 : BOOST_CHECK(result.size() == 0);
176 :
177 : // Spaces between nibbles is treated as invalid
178 2 : BOOST_CHECK_EQUAL(ParseHex("AAF F").size(), 0);
179 2 : BOOST_CHECK(!TryParseHex("AAF F").has_value());
180 :
181 : // Embedded null is treated as invalid
182 2 : const std::string with_embedded_null{" 11 "s
183 : " \0 "
184 : " 22 "s};
185 2 : BOOST_CHECK_EQUAL(with_embedded_null.size(), 11);
186 2 : BOOST_CHECK_EQUAL(ParseHex(with_embedded_null).size(), 0);
187 2 : BOOST_CHECK(!TryParseHex(with_embedded_null).has_value());
188 :
189 : // Non-hex is treated as invalid
190 2 : BOOST_CHECK_EQUAL(ParseHex("1234 invalid 1234").size(), 0);
191 2 : BOOST_CHECK(!TryParseHex("1234 invalid 1234").has_value());
192 :
193 : // Truncated input is treated as invalid
194 2 : BOOST_CHECK_EQUAL(ParseHex("12 3").size(), 0);
195 2 : BOOST_CHECK(!TryParseHex("12 3").has_value());
196 2 : }
197 :
198 152 : BOOST_AUTO_TEST_CASE(util_HexStr)
199 : {
200 2 : BOOST_CHECK_EQUAL(
201 : HexStr(ParseHex_expected),
202 : "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
203 :
204 2 : BOOST_CHECK_EQUAL(
205 : HexStr(Span{ParseHex_expected}.last(0)),
206 : "");
207 :
208 2 : BOOST_CHECK_EQUAL(
209 : HexStr(Span{ParseHex_expected}.first(0)),
210 : "");
211 :
212 : {
213 2 : const std::vector<char> in_s{ParseHex_expected, ParseHex_expected + 5};
214 2 : const Span<const uint8_t> in_u{MakeUCharSpan(in_s)};
215 2 : const Span<const std::byte> in_b{MakeByteSpan(in_s)};
216 2 : const std::string out_exp{"04678afdb0"};
217 :
218 2 : BOOST_CHECK_EQUAL(HexStr(in_u), out_exp);
219 2 : BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
220 2 : BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
221 2 : }
222 :
223 : {
224 2 : auto input = std::string();
225 514 : for (size_t i=0; i<256; ++i) {
226 512 : input.push_back(static_cast<char>(i));
227 512 : }
228 :
229 2 : auto hex = HexStr(input);
230 2 : BOOST_TEST_REQUIRE(hex.size() == 512);
231 : static constexpr auto hexmap = std::string_view("0123456789abcdef");
232 514 : for (size_t i = 0; i < 256; ++i) {
233 512 : auto upper = hexmap.find(hex[i * 2]);
234 512 : auto lower = hexmap.find(hex[i * 2 + 1]);
235 512 : BOOST_TEST_REQUIRE(upper != std::string_view::npos);
236 512 : BOOST_TEST_REQUIRE(lower != std::string_view::npos);
237 512 : BOOST_TEST_REQUIRE(i == upper*16 + lower);
238 512 : }
239 2 : }
240 2 : }
241 :
242 152 : BOOST_AUTO_TEST_CASE(span_write_bytes)
243 : {
244 2 : std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}};
245 2 : const auto mut_bytes{MakeWritableByteSpan(mut_arr)};
246 2 : mut_bytes[1] = std::byte{0x11};
247 2 : BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa);
248 2 : BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11);
249 2 : }
250 :
251 152 : BOOST_AUTO_TEST_CASE(util_Join)
252 : {
253 : // Normal version
254 2 : BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
255 2 : BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
256 2 : BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
257 :
258 : // Version with unary operator
259 8 : const auto op_upper = [](const std::string& s) { return ToUpper(s); };
260 2 : BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
261 2 : BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
262 2 : BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
263 2 : }
264 :
265 152 : BOOST_AUTO_TEST_CASE(util_ReplaceAll)
266 : {
267 2 : const std::string original("A test \"%s\" string '%s'.");
268 12 : auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) {
269 10 : auto test = original;
270 10 : ReplaceAll(test, search, substitute);
271 10 : BOOST_CHECK_EQUAL(test, expected);
272 10 : };
273 :
274 2 : test_replaceall("", "foo", original);
275 2 : test_replaceall(original, "foo", "foo");
276 2 : test_replaceall("%s", "foo", "A test \"foo\" string 'foo'.");
277 2 : test_replaceall("\"", "foo", "A test foo%sfoo string '%s'.");
278 2 : test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo.");
279 2 : }
280 :
281 152 : BOOST_AUTO_TEST_CASE(util_TrimString)
282 : {
283 2 : BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar");
284 2 : BOOST_CHECK_EQUAL(TrimStringView("\t \n \n \f\n\r\t\v\tfoo \n \f\n\r\t\v\tbar\t \n \f\n\r\t\v\t\n "), "foo \n \f\n\r\t\v\tbar");
285 2 : BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar");
286 2 : BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
287 2 : BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar");
288 2 : BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " ");
289 2 : BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7));
290 2 : BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3));
291 2 : BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2));
292 2 : BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
293 2 : BOOST_CHECK_EQUAL(TrimString(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01", 5)), std::string("\0", 1));
294 2 : BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
295 2 : }
296 :
297 152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
298 : {
299 2 : BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890963199), "32767-12-31T23:59:59Z");
300 2 : BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890876800), "32767-12-31T00:00:00Z");
301 2 : BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
302 2 : BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z");
303 2 : }
304 :
305 152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
306 : {
307 2 : BOOST_CHECK_EQUAL(FormatISO8601Date(971890963199), "32767-12-31");
308 2 : BOOST_CHECK_EQUAL(FormatISO8601Date(971890876800), "32767-12-31");
309 2 : BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
310 2 : BOOST_CHECK_EQUAL(FormatISO8601Date(0), "1970-01-01");
311 2 : }
312 :
313 152 : BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
314 : {
315 2 : BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
316 2 : }
317 :
318 152 : BOOST_AUTO_TEST_CASE(util_FormatMoney)
319 : {
320 2 : BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
321 2 : BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
322 2 : BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
323 :
324 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
325 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
326 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
327 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
328 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
329 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
330 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
331 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
332 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
333 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
334 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
335 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
336 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
337 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
338 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
339 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
340 2 : BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
341 :
342 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max()), "92233720368.54775807");
343 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 1), "92233720368.54775806");
344 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 2), "92233720368.54775805");
345 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 3), "92233720368.54775804");
346 : // ...
347 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 3), "-92233720368.54775805");
348 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 2), "-92233720368.54775806");
349 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 1), "-92233720368.54775807");
350 2 : BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min()), "-92233720368.54775808");
351 2 : }
352 :
353 152 : BOOST_AUTO_TEST_CASE(util_ParseMoney)
354 : {
355 2 : BOOST_CHECK_EQUAL(ParseMoney("0.0").value(), 0);
356 2 : BOOST_CHECK_EQUAL(ParseMoney(".").value(), 0);
357 2 : BOOST_CHECK_EQUAL(ParseMoney("0.").value(), 0);
358 2 : BOOST_CHECK_EQUAL(ParseMoney(".0").value(), 0);
359 2 : BOOST_CHECK_EQUAL(ParseMoney(".6789").value(), 6789'0000);
360 2 : BOOST_CHECK_EQUAL(ParseMoney("12345.").value(), COIN * 12345);
361 :
362 2 : BOOST_CHECK_EQUAL(ParseMoney("12345.6789").value(), (COIN/10000)*123456789);
363 :
364 2 : BOOST_CHECK_EQUAL(ParseMoney("10000000.00").value(), COIN*10000000);
365 2 : BOOST_CHECK_EQUAL(ParseMoney("1000000.00").value(), COIN*1000000);
366 2 : BOOST_CHECK_EQUAL(ParseMoney("100000.00").value(), COIN*100000);
367 2 : BOOST_CHECK_EQUAL(ParseMoney("10000.00").value(), COIN*10000);
368 2 : BOOST_CHECK_EQUAL(ParseMoney("1000.00").value(), COIN*1000);
369 2 : BOOST_CHECK_EQUAL(ParseMoney("100.00").value(), COIN*100);
370 2 : BOOST_CHECK_EQUAL(ParseMoney("10.00").value(), COIN*10);
371 2 : BOOST_CHECK_EQUAL(ParseMoney("1.00").value(), COIN);
372 2 : BOOST_CHECK_EQUAL(ParseMoney("1").value(), COIN);
373 2 : BOOST_CHECK_EQUAL(ParseMoney(" 1").value(), COIN);
374 2 : BOOST_CHECK_EQUAL(ParseMoney("1 ").value(), COIN);
375 2 : BOOST_CHECK_EQUAL(ParseMoney(" 1 ").value(), COIN);
376 2 : BOOST_CHECK_EQUAL(ParseMoney("0.1").value(), COIN/10);
377 2 : BOOST_CHECK_EQUAL(ParseMoney("0.01").value(), COIN/100);
378 2 : BOOST_CHECK_EQUAL(ParseMoney("0.001").value(), COIN/1000);
379 2 : BOOST_CHECK_EQUAL(ParseMoney("0.0001").value(), COIN/10000);
380 2 : BOOST_CHECK_EQUAL(ParseMoney("0.00001").value(), COIN/100000);
381 2 : BOOST_CHECK_EQUAL(ParseMoney("0.000001").value(), COIN/1000000);
382 2 : BOOST_CHECK_EQUAL(ParseMoney("0.0000001").value(), COIN/10000000);
383 2 : BOOST_CHECK_EQUAL(ParseMoney("0.00000001").value(), COIN/100000000);
384 2 : BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001 ").value(), COIN/100000000);
385 2 : BOOST_CHECK_EQUAL(ParseMoney("0.00000001 ").value(), COIN/100000000);
386 2 : BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001").value(), COIN/100000000);
387 :
388 : // Parsing amount that cannot be represented should fail
389 2 : BOOST_CHECK(!ParseMoney("100000000.00"));
390 2 : BOOST_CHECK(!ParseMoney("0.000000001"));
391 :
392 : // Parsing empty string should fail
393 2 : BOOST_CHECK(!ParseMoney(""));
394 2 : BOOST_CHECK(!ParseMoney(" "));
395 2 : BOOST_CHECK(!ParseMoney(" "));
396 :
397 : // Parsing two numbers should fail
398 2 : BOOST_CHECK(!ParseMoney(".."));
399 2 : BOOST_CHECK(!ParseMoney("0..0"));
400 2 : BOOST_CHECK(!ParseMoney("1 2"));
401 2 : BOOST_CHECK(!ParseMoney(" 1 2 "));
402 2 : BOOST_CHECK(!ParseMoney(" 1.2 3 "));
403 2 : BOOST_CHECK(!ParseMoney(" 1 2.3 "));
404 :
405 : // Embedded whitespace should fail
406 2 : BOOST_CHECK(!ParseMoney(" -1 .2 "));
407 2 : BOOST_CHECK(!ParseMoney(" 1 .2 "));
408 2 : BOOST_CHECK(!ParseMoney(" +1 .2 "));
409 :
410 : // Attempted 63 bit overflow should fail
411 2 : BOOST_CHECK(!ParseMoney("92233720368.54775808"));
412 :
413 : // Parsing negative amounts must fail
414 2 : BOOST_CHECK(!ParseMoney("-1"));
415 :
416 : // Parsing strings with embedded NUL characters should fail
417 2 : BOOST_CHECK(!ParseMoney("\0-1"s));
418 2 : BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR));
419 2 : BOOST_CHECK(!ParseMoney("1\0"s));
420 2 : }
421 :
422 152 : BOOST_AUTO_TEST_CASE(util_IsHex)
423 : {
424 2 : BOOST_CHECK(IsHex("00"));
425 2 : BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
426 2 : BOOST_CHECK(IsHex("ff"));
427 2 : BOOST_CHECK(IsHex("FF"));
428 :
429 2 : BOOST_CHECK(!IsHex(""));
430 2 : BOOST_CHECK(!IsHex("0"));
431 2 : BOOST_CHECK(!IsHex("a"));
432 2 : BOOST_CHECK(!IsHex("eleven"));
433 2 : BOOST_CHECK(!IsHex("00xx00"));
434 2 : BOOST_CHECK(!IsHex("0x0000"));
435 2 : }
436 :
437 152 : BOOST_AUTO_TEST_CASE(util_IsHexNumber)
438 : {
439 2 : BOOST_CHECK(IsHexNumber("0x0"));
440 2 : BOOST_CHECK(IsHexNumber("0"));
441 2 : BOOST_CHECK(IsHexNumber("0x10"));
442 2 : BOOST_CHECK(IsHexNumber("10"));
443 2 : BOOST_CHECK(IsHexNumber("0xff"));
444 2 : BOOST_CHECK(IsHexNumber("ff"));
445 2 : BOOST_CHECK(IsHexNumber("0xFfa"));
446 2 : BOOST_CHECK(IsHexNumber("Ffa"));
447 2 : BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
448 2 : BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
449 :
450 2 : BOOST_CHECK(!IsHexNumber("")); // empty string not allowed
451 2 : BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
452 2 : BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
453 2 : BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
454 2 : BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
455 2 : BOOST_CHECK(!IsHexNumber(" ")); // etc.
456 2 : BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
457 2 : BOOST_CHECK(!IsHexNumber("x0")); // broken prefix
458 2 : BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
459 :
460 2 : }
461 :
462 152 : BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
463 : {
464 2 : SeedInsecureRand(SeedRand::ZEROS);
465 20 : for (int mod=2;mod<11;mod++)
466 : {
467 18 : int mask = 1;
468 : // Really rough binomial confidence approximation.
469 18 : int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
470 : //mask is 2^ceil(log2(mod))-1
471 50 : while(mask<mod-1)mask=(mask<<1)+1;
472 :
473 18 : int count = 0;
474 : //How often does it get a zero from the uniform range [0,mod)?
475 180018 : for (int i = 0; i < 10000; i++) {
476 : uint32_t rval;
477 180000 : do{
478 235652 : rval=InsecureRand32()&mask;
479 235652 : }while(rval>=(uint32_t)mod);
480 180000 : count += rval==0;
481 180000 : }
482 18 : BOOST_CHECK(count<=10000/mod+err);
483 18 : BOOST_CHECK(count>=10000/mod-err);
484 18 : }
485 2 : }
486 :
487 152 : BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
488 : {
489 2 : BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
490 2 : BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
491 2 : BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
492 2 : BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
493 2 : BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
494 2 : BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
495 2 : BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
496 2 : }
497 :
498 : /* Test strprintf formatting directives.
499 : * Put a string before and after to ensure sanity of element sizes on stack. */
500 : #define B "check_prefix"
501 : #define E "check_postfix"
502 152 : BOOST_AUTO_TEST_CASE(strprintf_numbers)
503 : {
504 2 : int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
505 2 : uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
506 2 : BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
507 2 : BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
508 2 : BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
509 :
510 2 : size_t st = 12345678; /* unsigned size_t test value */
511 2 : ssize_t sst = -12345678; /* signed size_t test value */
512 2 : BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
513 2 : BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
514 2 : BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
515 :
516 2 : ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
517 2 : ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
518 2 : BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
519 2 : BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
520 2 : BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
521 2 : }
522 : #undef B
523 : #undef E
524 :
525 : /* Check for mingw/wine issue #3494
526 : * Remove this test before time.ctime(0xffffffff) == 'Sun Feb 7 07:28:15 2106'
527 : */
528 152 : BOOST_AUTO_TEST_CASE(gettime)
529 : {
530 2 : BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
531 2 : }
532 :
533 152 : BOOST_AUTO_TEST_CASE(util_time_GetTime)
534 : {
535 2 : SetMockTime(111);
536 : // Check that mock time does not change after a sleep
537 6 : for (const auto& num_sleep : {0ms, 1ms}) {
538 4 : UninterruptibleSleep(num_sleep);
539 4 : BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
540 4 : BOOST_CHECK_EQUAL(111, Now<NodeSeconds>().time_since_epoch().count());
541 4 : BOOST_CHECK_EQUAL(111, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()));
542 4 : BOOST_CHECK_EQUAL(111, TicksSinceEpoch<SecondsDouble>(Now<NodeSeconds>()));
543 4 : BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
544 4 : BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
545 4 : BOOST_CHECK_EQUAL(111000, TicksSinceEpoch<std::chrono::milliseconds>(NodeClock::now()));
546 4 : BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
547 : }
548 :
549 2 : SetMockTime(0);
550 : // Check that steady time and system time changes after a sleep
551 2 : const auto steady_ms_0 = Now<SteadyMilliseconds>();
552 2 : const auto steady_0 = std::chrono::steady_clock::now();
553 2 : const auto ms_0 = GetTime<std::chrono::milliseconds>();
554 2 : const auto us_0 = GetTime<std::chrono::microseconds>();
555 2 : UninterruptibleSleep(1ms);
556 2 : BOOST_CHECK(steady_ms_0 < Now<SteadyMilliseconds>());
557 2 : BOOST_CHECK(steady_0 + 1ms <= std::chrono::steady_clock::now());
558 2 : BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
559 2 : BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
560 2 : }
561 :
562 152 : BOOST_AUTO_TEST_CASE(test_IsDigit)
563 : {
564 2 : BOOST_CHECK_EQUAL(IsDigit('0'), true);
565 2 : BOOST_CHECK_EQUAL(IsDigit('1'), true);
566 2 : BOOST_CHECK_EQUAL(IsDigit('8'), true);
567 2 : BOOST_CHECK_EQUAL(IsDigit('9'), true);
568 :
569 2 : BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
570 2 : BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
571 2 : BOOST_CHECK_EQUAL(IsDigit(0), false);
572 2 : BOOST_CHECK_EQUAL(IsDigit(1), false);
573 2 : BOOST_CHECK_EQUAL(IsDigit(8), false);
574 2 : BOOST_CHECK_EQUAL(IsDigit(9), false);
575 2 : }
576 :
577 : /* Check for overflow */
578 : template <typename T>
579 4 : static void TestAddMatrixOverflow()
580 : {
581 4 : constexpr T MAXI{std::numeric_limits<T>::max()};
582 4 : BOOST_CHECK(!CheckedAdd(T{1}, MAXI));
583 4 : BOOST_CHECK(!CheckedAdd(MAXI, MAXI));
584 4 : BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI));
585 4 : BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(MAXI, MAXI));
586 :
587 4 : BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value());
588 4 : BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value());
589 4 : BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value());
590 4 : BOOST_CHECK_EQUAL(MAXI - 1, CheckedAdd(T{1}, MAXI - 2).value());
591 4 : BOOST_CHECK_EQUAL(0, SaturatingAdd(T{0}, T{0}));
592 4 : BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{0}, MAXI));
593 4 : BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI - 1));
594 4 : BOOST_CHECK_EQUAL(MAXI - 1, SaturatingAdd(T{1}, MAXI - 2));
595 4 : }
596 :
597 : /* Check for overflow or underflow */
598 : template <typename T>
599 2 : static void TestAddMatrix()
600 : {
601 2 : TestAddMatrixOverflow<T>();
602 2 : constexpr T MINI{std::numeric_limits<T>::min()};
603 2 : constexpr T MAXI{std::numeric_limits<T>::max()};
604 2 : BOOST_CHECK(!CheckedAdd(T{-1}, MINI));
605 2 : BOOST_CHECK(!CheckedAdd(MINI, MINI));
606 2 : BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI));
607 2 : BOOST_CHECK_EQUAL(MINI, SaturatingAdd(MINI, MINI));
608 :
609 2 : BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value());
610 2 : BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value());
611 2 : BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value());
612 2 : BOOST_CHECK_EQUAL(MINI + 1, CheckedAdd(T{-1}, MINI + 2).value());
613 2 : BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{0}, MINI));
614 2 : BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI + 1));
615 2 : BOOST_CHECK_EQUAL(MINI + 1, SaturatingAdd(T{-1}, MINI + 2));
616 2 : BOOST_CHECK_EQUAL(-1, SaturatingAdd(MINI, MAXI));
617 2 : }
618 :
619 152 : BOOST_AUTO_TEST_CASE(util_overflow)
620 : {
621 2 : TestAddMatrixOverflow<unsigned>();
622 2 : TestAddMatrix<signed>();
623 2 : }
624 :
625 152 : BOOST_AUTO_TEST_CASE(test_ParseInt32)
626 : {
627 : int32_t n;
628 : // Valid values
629 2 : BOOST_CHECK(ParseInt32("1234", nullptr));
630 2 : BOOST_CHECK(ParseInt32("0", &n) && n == 0);
631 2 : BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
632 2 : BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
633 2 : BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
634 2 : BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
635 2 : BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
636 2 : BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
637 2 : BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
638 2 : BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
639 2 : BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
640 : // Invalid values
641 2 : BOOST_CHECK(!ParseInt32("", &n));
642 2 : BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
643 2 : BOOST_CHECK(!ParseInt32("1 ", &n));
644 2 : BOOST_CHECK(!ParseInt32("++1", &n));
645 2 : BOOST_CHECK(!ParseInt32("+-1", &n));
646 2 : BOOST_CHECK(!ParseInt32("-+1", &n));
647 2 : BOOST_CHECK(!ParseInt32("--1", &n));
648 2 : BOOST_CHECK(!ParseInt32("1a", &n));
649 2 : BOOST_CHECK(!ParseInt32("aap", &n));
650 2 : BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
651 2 : BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
652 : // Overflow and underflow
653 2 : BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
654 2 : BOOST_CHECK(!ParseInt32("2147483648", nullptr));
655 2 : BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
656 2 : BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
657 2 : }
658 :
659 : template <typename T>
660 16 : static void RunToIntegralTests()
661 : {
662 16 : BOOST_CHECK(!ToIntegral<T>(STRING_WITH_EMBEDDED_NULL_CHAR));
663 16 : BOOST_CHECK(!ToIntegral<T>(" 1"));
664 16 : BOOST_CHECK(!ToIntegral<T>("1 "));
665 16 : BOOST_CHECK(!ToIntegral<T>("1a"));
666 16 : BOOST_CHECK(!ToIntegral<T>("1.1"));
667 16 : BOOST_CHECK(!ToIntegral<T>("1.9"));
668 16 : BOOST_CHECK(!ToIntegral<T>("+01.9"));
669 16 : BOOST_CHECK(!ToIntegral<T>("-"));
670 16 : BOOST_CHECK(!ToIntegral<T>("+"));
671 16 : BOOST_CHECK(!ToIntegral<T>(" -1"));
672 16 : BOOST_CHECK(!ToIntegral<T>("-1 "));
673 16 : BOOST_CHECK(!ToIntegral<T>(" -1 "));
674 16 : BOOST_CHECK(!ToIntegral<T>("+1"));
675 16 : BOOST_CHECK(!ToIntegral<T>(" +1"));
676 16 : BOOST_CHECK(!ToIntegral<T>(" +1 "));
677 16 : BOOST_CHECK(!ToIntegral<T>("+-1"));
678 16 : BOOST_CHECK(!ToIntegral<T>("-+1"));
679 16 : BOOST_CHECK(!ToIntegral<T>("++1"));
680 16 : BOOST_CHECK(!ToIntegral<T>("--1"));
681 16 : BOOST_CHECK(!ToIntegral<T>(""));
682 16 : BOOST_CHECK(!ToIntegral<T>("aap"));
683 16 : BOOST_CHECK(!ToIntegral<T>("0x1"));
684 16 : BOOST_CHECK(!ToIntegral<T>("-32482348723847471234"));
685 16 : BOOST_CHECK(!ToIntegral<T>("32482348723847471234"));
686 16 : }
687 :
688 152 : BOOST_AUTO_TEST_CASE(test_ToIntegral)
689 : {
690 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("1234").value(), 1'234);
691 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("0").value(), 0);
692 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("01234").value(), 1'234);
693 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000001234").value(), 1'234);
694 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000001234").value(), -1'234);
695 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000000000").value(), 0);
696 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000000000").value(), 0);
697 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1234").value(), -1'234);
698 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1").value(), -1);
699 :
700 2 : RunToIntegralTests<uint64_t>();
701 2 : RunToIntegralTests<int64_t>();
702 2 : RunToIntegralTests<uint32_t>();
703 2 : RunToIntegralTests<int32_t>();
704 2 : RunToIntegralTests<uint16_t>();
705 2 : RunToIntegralTests<int16_t>();
706 2 : RunToIntegralTests<uint8_t>();
707 2 : RunToIntegralTests<int8_t>();
708 :
709 2 : BOOST_CHECK(!ToIntegral<int64_t>("-9223372036854775809"));
710 2 : BOOST_CHECK_EQUAL(ToIntegral<int64_t>("-9223372036854775808").value(), -9'223'372'036'854'775'807LL - 1LL);
711 2 : BOOST_CHECK_EQUAL(ToIntegral<int64_t>("9223372036854775807").value(), 9'223'372'036'854'775'807);
712 2 : BOOST_CHECK(!ToIntegral<int64_t>("9223372036854775808"));
713 :
714 2 : BOOST_CHECK(!ToIntegral<uint64_t>("-1"));
715 2 : BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("0").value(), 0U);
716 2 : BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("18446744073709551615").value(), 18'446'744'073'709'551'615ULL);
717 2 : BOOST_CHECK(!ToIntegral<uint64_t>("18446744073709551616"));
718 :
719 2 : BOOST_CHECK(!ToIntegral<int32_t>("-2147483649"));
720 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-2147483648").value(), -2'147'483'648LL);
721 2 : BOOST_CHECK_EQUAL(ToIntegral<int32_t>("2147483647").value(), 2'147'483'647);
722 2 : BOOST_CHECK(!ToIntegral<int32_t>("2147483648"));
723 :
724 2 : BOOST_CHECK(!ToIntegral<uint32_t>("-1"));
725 2 : BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("0").value(), 0U);
726 2 : BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("4294967295").value(), 4'294'967'295U);
727 2 : BOOST_CHECK(!ToIntegral<uint32_t>("4294967296"));
728 :
729 2 : BOOST_CHECK(!ToIntegral<int16_t>("-32769"));
730 2 : BOOST_CHECK_EQUAL(ToIntegral<int16_t>("-32768").value(), -32'768);
731 2 : BOOST_CHECK_EQUAL(ToIntegral<int16_t>("32767").value(), 32'767);
732 2 : BOOST_CHECK(!ToIntegral<int16_t>("32768"));
733 :
734 2 : BOOST_CHECK(!ToIntegral<uint16_t>("-1"));
735 2 : BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("0").value(), 0U);
736 2 : BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("65535").value(), 65'535U);
737 2 : BOOST_CHECK(!ToIntegral<uint16_t>("65536"));
738 :
739 2 : BOOST_CHECK(!ToIntegral<int8_t>("-129"));
740 2 : BOOST_CHECK_EQUAL(ToIntegral<int8_t>("-128").value(), -128);
741 2 : BOOST_CHECK_EQUAL(ToIntegral<int8_t>("127").value(), 127);
742 2 : BOOST_CHECK(!ToIntegral<int8_t>("128"));
743 :
744 2 : BOOST_CHECK(!ToIntegral<uint8_t>("-1"));
745 2 : BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("0").value(), 0U);
746 2 : BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("255").value(), 255U);
747 2 : BOOST_CHECK(!ToIntegral<uint8_t>("256"));
748 2 : }
749 :
750 16 : int64_t atoi64_legacy(const std::string& str)
751 : {
752 16 : return strtoll(str.c_str(), nullptr, 10);
753 : }
754 :
755 152 : BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
756 : {
757 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1234"), 1'234);
758 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0"), 0);
759 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("01234"), 1'234);
760 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1234"), -1'234);
761 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" 1"), 1);
762 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1 "), 1);
763 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1a"), 1);
764 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.1"), 1);
765 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.9"), 1);
766 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+01.9"), 1);
767 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1"), -1);
768 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1"), -1);
769 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1 "), -1);
770 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1 "), -1);
771 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+1"), 1);
772 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1"), 1);
773 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1 "), 1);
774 :
775 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+-1"), 0);
776 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-+1"), 0);
777 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("++1"), 0);
778 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("--1"), 0);
779 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(""), 0);
780 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("aap"), 0);
781 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0x1"), 0);
782 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-32482348723847471234"), -2'147'483'647 - 1);
783 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("32482348723847471234"), 2'147'483'647);
784 :
785 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775809"), -9'223'372'036'854'775'807LL - 1LL);
786 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775808"), -9'223'372'036'854'775'807LL - 1LL);
787 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775807"), 9'223'372'036'854'775'807);
788 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775808"), 9'223'372'036'854'775'807);
789 :
790 2 : std::map<std::string, int64_t> atoi64_test_pairs = {
791 2 : {"-9223372036854775809", std::numeric_limits<int64_t>::min()},
792 2 : {"-9223372036854775808", -9'223'372'036'854'775'807LL - 1LL},
793 2 : {"9223372036854775807", 9'223'372'036'854'775'807},
794 2 : {"9223372036854775808", std::numeric_limits<int64_t>::max()},
795 2 : {"+-", 0},
796 2 : {"0x1", 0},
797 2 : {"ox1", 0},
798 2 : {"", 0},
799 : };
800 :
801 18 : for (const auto& pair : atoi64_test_pairs) {
802 16 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), pair.second);
803 : }
804 :
805 : // Ensure legacy compatibility with previous versions of Bitcoin Core's atoi64
806 18 : for (const auto& pair : atoi64_test_pairs) {
807 16 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), atoi64_legacy(pair.first));
808 : }
809 :
810 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("-1"), 0U);
811 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("0"), 0U);
812 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551615"), 18'446'744'073'709'551'615ULL);
813 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551616"), 18'446'744'073'709'551'615ULL);
814 :
815 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483649"), -2'147'483'648LL);
816 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483648"), -2'147'483'648LL);
817 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483647"), 2'147'483'647);
818 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483648"), 2'147'483'647);
819 :
820 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("-1"), 0U);
821 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("0"), 0U);
822 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967295"), 4'294'967'295U);
823 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967296"), 4'294'967'295U);
824 :
825 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32769"), -32'768);
826 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32768"), -32'768);
827 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32767"), 32'767);
828 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32768"), 32'767);
829 :
830 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("-1"), 0U);
831 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("0"), 0U);
832 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65535"), 65'535U);
833 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65536"), 65'535U);
834 :
835 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-129"), -128);
836 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-128"), -128);
837 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("127"), 127);
838 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("128"), 127);
839 :
840 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("-1"), 0U);
841 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("0"), 0U);
842 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("255"), 255U);
843 2 : BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
844 2 : }
845 :
846 152 : BOOST_AUTO_TEST_CASE(test_ParseInt64)
847 : {
848 : int64_t n;
849 : // Valid values
850 2 : BOOST_CHECK(ParseInt64("1234", nullptr));
851 2 : BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
852 2 : BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
853 2 : BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
854 2 : BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
855 2 : BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
856 2 : BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
857 2 : BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
858 2 : BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
859 : // Invalid values
860 2 : BOOST_CHECK(!ParseInt64("", &n));
861 2 : BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
862 2 : BOOST_CHECK(!ParseInt64("1 ", &n));
863 2 : BOOST_CHECK(!ParseInt64("1a", &n));
864 2 : BOOST_CHECK(!ParseInt64("aap", &n));
865 2 : BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
866 2 : BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
867 : // Overflow and underflow
868 2 : BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
869 2 : BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
870 2 : BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
871 2 : BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
872 2 : }
873 :
874 152 : BOOST_AUTO_TEST_CASE(test_ParseUInt8)
875 : {
876 : uint8_t n;
877 : // Valid values
878 2 : BOOST_CHECK(ParseUInt8("255", nullptr));
879 2 : BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
880 2 : BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
881 2 : BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
882 2 : BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
883 2 : BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
884 2 : BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
885 2 : BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
886 : // Invalid values
887 2 : BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
888 2 : BOOST_CHECK(!ParseUInt8("", &n));
889 2 : BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
890 2 : BOOST_CHECK(!ParseUInt8(" -1", &n));
891 2 : BOOST_CHECK(!ParseUInt8("++1", &n));
892 2 : BOOST_CHECK(!ParseUInt8("+-1", &n));
893 2 : BOOST_CHECK(!ParseUInt8("-+1", &n));
894 2 : BOOST_CHECK(!ParseUInt8("--1", &n));
895 2 : BOOST_CHECK(!ParseUInt8("-1", &n));
896 2 : BOOST_CHECK(!ParseUInt8("1 ", &n));
897 2 : BOOST_CHECK(!ParseUInt8("1a", &n));
898 2 : BOOST_CHECK(!ParseUInt8("aap", &n));
899 2 : BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
900 2 : BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
901 : // Overflow and underflow
902 2 : BOOST_CHECK(!ParseUInt8("-255", &n));
903 2 : BOOST_CHECK(!ParseUInt8("256", &n));
904 2 : BOOST_CHECK(!ParseUInt8("-123", &n));
905 2 : BOOST_CHECK(!ParseUInt8("-123", nullptr));
906 2 : BOOST_CHECK(!ParseUInt8("256", nullptr));
907 2 : }
908 :
909 152 : BOOST_AUTO_TEST_CASE(test_ParseUInt16)
910 : {
911 : uint16_t n;
912 : // Valid values
913 2 : BOOST_CHECK(ParseUInt16("1234", nullptr));
914 2 : BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
915 2 : BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
916 2 : BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
917 2 : BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
918 2 : BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
919 2 : BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
920 2 : BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
921 : // Invalid values
922 2 : BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
923 2 : BOOST_CHECK(!ParseUInt16("", &n));
924 2 : BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
925 2 : BOOST_CHECK(!ParseUInt16(" -1", &n));
926 2 : BOOST_CHECK(!ParseUInt16("++1", &n));
927 2 : BOOST_CHECK(!ParseUInt16("+-1", &n));
928 2 : BOOST_CHECK(!ParseUInt16("-+1", &n));
929 2 : BOOST_CHECK(!ParseUInt16("--1", &n));
930 2 : BOOST_CHECK(!ParseUInt16("-1", &n));
931 2 : BOOST_CHECK(!ParseUInt16("1 ", &n));
932 2 : BOOST_CHECK(!ParseUInt16("1a", &n));
933 2 : BOOST_CHECK(!ParseUInt16("aap", &n));
934 2 : BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
935 2 : BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
936 : // Overflow and underflow
937 2 : BOOST_CHECK(!ParseUInt16("-65535", &n));
938 2 : BOOST_CHECK(!ParseUInt16("65536", &n));
939 2 : BOOST_CHECK(!ParseUInt16("-123", &n));
940 2 : BOOST_CHECK(!ParseUInt16("-123", nullptr));
941 2 : BOOST_CHECK(!ParseUInt16("65536", nullptr));
942 2 : }
943 :
944 152 : BOOST_AUTO_TEST_CASE(test_ParseUInt32)
945 : {
946 : uint32_t n;
947 : // Valid values
948 2 : BOOST_CHECK(ParseUInt32("1234", nullptr));
949 2 : BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
950 2 : BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
951 2 : BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
952 2 : BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
953 2 : BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
954 2 : BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
955 2 : BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
956 2 : BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
957 2 : BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
958 : // Invalid values
959 2 : BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
960 2 : BOOST_CHECK(!ParseUInt32("", &n));
961 2 : BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
962 2 : BOOST_CHECK(!ParseUInt32(" -1", &n));
963 2 : BOOST_CHECK(!ParseUInt32("++1", &n));
964 2 : BOOST_CHECK(!ParseUInt32("+-1", &n));
965 2 : BOOST_CHECK(!ParseUInt32("-+1", &n));
966 2 : BOOST_CHECK(!ParseUInt32("--1", &n));
967 2 : BOOST_CHECK(!ParseUInt32("-1", &n));
968 2 : BOOST_CHECK(!ParseUInt32("1 ", &n));
969 2 : BOOST_CHECK(!ParseUInt32("1a", &n));
970 2 : BOOST_CHECK(!ParseUInt32("aap", &n));
971 2 : BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
972 2 : BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
973 : // Overflow and underflow
974 2 : BOOST_CHECK(!ParseUInt32("-2147483648", &n));
975 2 : BOOST_CHECK(!ParseUInt32("4294967296", &n));
976 2 : BOOST_CHECK(!ParseUInt32("-1234", &n));
977 2 : BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
978 2 : BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
979 2 : }
980 :
981 152 : BOOST_AUTO_TEST_CASE(test_ParseUInt64)
982 : {
983 : uint64_t n;
984 : // Valid values
985 2 : BOOST_CHECK(ParseUInt64("1234", nullptr));
986 2 : BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
987 2 : BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
988 2 : BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
989 2 : BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
990 2 : BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
991 2 : BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
992 2 : BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
993 : // Invalid values
994 2 : BOOST_CHECK(!ParseUInt64("", &n));
995 2 : BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
996 2 : BOOST_CHECK(!ParseUInt64(" -1", &n));
997 2 : BOOST_CHECK(!ParseUInt64("1 ", &n));
998 2 : BOOST_CHECK(!ParseUInt64("1a", &n));
999 2 : BOOST_CHECK(!ParseUInt64("aap", &n));
1000 2 : BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
1001 2 : BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
1002 : // Overflow and underflow
1003 2 : BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
1004 2 : BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
1005 2 : BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
1006 2 : BOOST_CHECK(!ParseUInt64("-2147483648", &n));
1007 2 : BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
1008 2 : BOOST_CHECK(!ParseUInt64("-1234", &n));
1009 2 : }
1010 :
1011 152 : BOOST_AUTO_TEST_CASE(test_FormatParagraph)
1012 : {
1013 2 : BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
1014 2 : BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
1015 2 : BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
1016 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
1017 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
1018 2 : BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
1019 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test");
1020 :
1021 : // Make sure we don't indent a fully-new line following a too-long line ending
1022 2 : BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n test\nabc");
1023 :
1024 2 : BOOST_CHECK_EQUAL(FormatParagraph("This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length until it gets here", 79), "This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length\nuntil it gets here");
1025 :
1026 : // Test wrap length is exact
1027 2 : BOOST_CHECK_EQUAL(FormatParagraph("a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
1028 2 : BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
1029 : // Indent should be included in length of lines
1030 2 : BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg h i j k", 79, 4), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\n f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg\n h i j k");
1031 :
1032 2 : BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string.", 79), "This is a very long test string. This is a second sentence in the very long\ntest string.");
1033 2 : BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
1034 2 : BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
1035 2 : BOOST_CHECK_EQUAL(FormatParagraph("Testing that normal newlines do not get indented.\nLike here.", 79), "Testing that normal newlines do not get indented.\nLike here.");
1036 2 : }
1037 :
1038 152 : BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
1039 : {
1040 2 : std::vector<std::string> comments;
1041 2 : comments.emplace_back("comment1");
1042 2 : std::vector<std::string> comments2;
1043 2 : comments2.emplace_back("comment1");
1044 2 : comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
1045 2 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/"));
1046 2 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
1047 2 : BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
1048 2 : }
1049 :
1050 152 : BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
1051 : {
1052 2 : int64_t amount = 0;
1053 2 : BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
1054 2 : BOOST_CHECK_EQUAL(amount, 0LL);
1055 2 : BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
1056 2 : BOOST_CHECK_EQUAL(amount, 100000000LL);
1057 2 : BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
1058 2 : BOOST_CHECK_EQUAL(amount, 0LL);
1059 2 : BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
1060 2 : BOOST_CHECK_EQUAL(amount, -10000000LL);
1061 2 : BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
1062 2 : BOOST_CHECK_EQUAL(amount, 110000000LL);
1063 2 : BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
1064 2 : BOOST_CHECK_EQUAL(amount, 110000000LL);
1065 2 : BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
1066 2 : BOOST_CHECK_EQUAL(amount, 1100000000LL);
1067 2 : BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
1068 2 : BOOST_CHECK_EQUAL(amount, 11000000LL);
1069 2 : BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
1070 2 : BOOST_CHECK_EQUAL(amount, 100000000000LL);
1071 2 : BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
1072 2 : BOOST_CHECK_EQUAL(amount, -100000000000LL);
1073 2 : BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
1074 2 : BOOST_CHECK_EQUAL(amount, 1LL);
1075 2 : BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
1076 2 : BOOST_CHECK_EQUAL(amount, 1LL);
1077 2 : BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
1078 2 : BOOST_CHECK_EQUAL(amount, -1LL);
1079 2 : BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
1080 2 : BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
1081 2 : BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
1082 2 : BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
1083 2 : BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
1084 2 : BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
1085 :
1086 2 : BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
1087 2 : BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
1088 2 : BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
1089 2 : BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
1090 2 : BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
1091 2 : BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
1092 2 : BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
1093 2 : BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
1094 2 : BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
1095 2 : BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
1096 2 : BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
1097 2 : BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
1098 2 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
1099 2 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
1100 2 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
1101 2 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
1102 2 : BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
1103 2 : BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
1104 2 : BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
1105 2 : BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
1106 2 : BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
1107 2 : BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
1108 2 : BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
1109 2 : BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
1110 2 : BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
1111 2 : BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
1112 2 : BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
1113 :
1114 : // Test with 3 decimal places for fee rates in sat/vB.
1115 2 : BOOST_CHECK(ParseFixedPoint("0.001", 3, &amount));
1116 2 : BOOST_CHECK_EQUAL(amount, CAmount{1});
1117 2 : BOOST_CHECK(!ParseFixedPoint("0.0009", 3, &amount));
1118 2 : BOOST_CHECK(!ParseFixedPoint("31.00100001", 3, &amount));
1119 2 : BOOST_CHECK(!ParseFixedPoint("31.0011", 3, &amount));
1120 2 : BOOST_CHECK(!ParseFixedPoint("31.99999999", 3, &amount));
1121 2 : BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));
1122 2 : }
1123 :
1124 1 : static void TestOtherThread(fs::path dirname, fs::path lockname, bool *result)
1125 : {
1126 1 : *result = LockDirectory(dirname, lockname);
1127 1 : }
1128 :
1129 : #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
1130 : static constexpr char LockCommand = 'L';
1131 : static constexpr char UnlockCommand = 'U';
1132 : static constexpr char ExitCommand = 'X';
1133 :
1134 1 : [[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)
1135 : {
1136 : char ch;
1137 5 : while (true) {
1138 5 : int rv = read(fd, &ch, 1); // Wait for command
1139 5 : assert(rv == 1);
1140 5 : switch(ch) {
1141 : case LockCommand:
1142 3 : ch = LockDirectory(dirname, lockname);
1143 3 : rv = write(fd, &ch, 1);
1144 3 : assert(rv == 1);
1145 3 : break;
1146 : case UnlockCommand:
1147 1 : ReleaseDirectoryLocks();
1148 1 : ch = true; // Always succeeds
1149 1 : rv = write(fd, &ch, 1);
1150 1 : assert(rv == 1);
1151 1 : break;
1152 : case ExitCommand:
1153 1 : close(fd);
1154 1 : exit(0);
1155 : default:
1156 0 : assert(0);
1157 : }
1158 : }
1159 : }
1160 : #endif
1161 :
1162 152 : BOOST_AUTO_TEST_CASE(test_LockDirectory)
1163 : {
1164 2 : fs::path dirname = m_args.GetDataDirBase() / "lock_dir";
1165 2 : const fs::path lockname = ".lock";
1166 : #ifndef WIN32
1167 : // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
1168 : // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
1169 : // at build-time of the boost library
1170 2 : void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
1171 :
1172 : // Fork another process for testing before creating the lock, so that we
1173 : // won't fork while holding the lock (which might be undefined, and is not
1174 : // relevant as test case as that is avoided with -daemonize).
1175 : int fd[2];
1176 2 : BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
1177 2 : pid_t pid = fork();
1178 2 : if (!pid) {
1179 1 : BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
1180 1 : TestOtherProcess(dirname, lockname, fd[0]);
1181 : }
1182 1 : BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
1183 : #endif
1184 : // Lock on non-existent directory should fail
1185 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
1186 :
1187 1 : fs::create_directories(dirname);
1188 :
1189 : // Probing lock on new directory should succeed
1190 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1191 :
1192 : // Persistent lock on new directory should succeed
1193 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1194 :
1195 : // Another lock on the directory from the same thread should succeed
1196 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1197 :
1198 : // Another lock on the directory from a different thread within the same process should succeed
1199 : bool threadresult;
1200 1 : std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
1201 0 : thr.join();
1202 1 : BOOST_CHECK_EQUAL(threadresult, true);
1203 : #ifndef WIN32
1204 : // Try to acquire lock in child process while we're holding it, this should fail.
1205 : char ch;
1206 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1207 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1208 1 : BOOST_CHECK_EQUAL((bool)ch, false);
1209 :
1210 : // Give up our lock
1211 1 : ReleaseDirectoryLocks();
1212 : // Probing lock from our side now should succeed, but not hold on to the lock.
1213 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1214 :
1215 : // Try to acquire the lock in the child process, this should be successful.
1216 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1217 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1218 1 : BOOST_CHECK_EQUAL((bool)ch, true);
1219 :
1220 : // When we try to probe the lock now, it should fail.
1221 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
1222 :
1223 : // Unlock the lock in the child process
1224 1 : BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
1225 1 : BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1226 1 : BOOST_CHECK_EQUAL((bool)ch, true);
1227 :
1228 : // When we try to probe the lock now, it should succeed.
1229 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1230 :
1231 : // Re-lock the lock in the child process, then wait for it to exit, check
1232 : // successful return. After that, we check that exiting the process
1233 : // has released the lock as we would expect by probing it.
1234 : int processstatus;
1235 1 : BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1236 1 : BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
1237 1 : BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
1238 1 : BOOST_CHECK_EQUAL(processstatus, 0);
1239 1 : BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1240 :
1241 : // Restore SIGCHLD
1242 1 : signal(SIGCHLD, old_handler);
1243 1 : BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
1244 : #endif
1245 : // Clean up
1246 1 : ReleaseDirectoryLocks();
1247 1 : fs::remove_all(dirname);
1248 4 : }
1249 :
1250 149 : BOOST_AUTO_TEST_CASE(test_DirIsWritable)
1251 : {
1252 : // Should be able to write to the data dir.
1253 1 : fs::path tmpdirname = m_args.GetDataDirBase();
1254 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1255 :
1256 : // Should not be able to write to a non-existent dir.
1257 1 : tmpdirname = GetUniquePath(tmpdirname);
1258 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
1259 :
1260 1 : fs::create_directory(tmpdirname);
1261 : // Should be able to write to it now.
1262 1 : BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1263 1 : fs::remove(tmpdirname);
1264 1 : }
1265 :
1266 : namespace {
1267 :
1268 : struct Tracker
1269 : {
1270 : //! Points to the original object (possibly itself) we moved/copied from
1271 : const Tracker* origin;
1272 : //! How many copies where involved between the original object and this one (moves are not counted)
1273 3 : int copies{0};
1274 :
1275 9 : Tracker() noexcept : origin(this) {}
1276 20 : Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
1277 26 : Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
1278 : Tracker& operator=(const Tracker& t) noexcept
1279 : {
1280 : origin = t.origin;
1281 : copies = t.copies + 1;
1282 : return *this;
1283 : }
1284 : };
1285 :
1286 : }
1287 :
1288 149 : BOOST_AUTO_TEST_CASE(test_tracked_vector)
1289 : {
1290 1 : Tracker t1;
1291 1 : Tracker t2;
1292 1 : Tracker t3;
1293 :
1294 1 : BOOST_CHECK(t1.origin == &t1);
1295 1 : BOOST_CHECK(t2.origin == &t2);
1296 1 : BOOST_CHECK(t3.origin == &t3);
1297 :
1298 1 : auto v1 = Vector(t1);
1299 1 : BOOST_CHECK_EQUAL(v1.size(), 1U);
1300 1 : BOOST_CHECK(v1[0].origin == &t1);
1301 1 : BOOST_CHECK_EQUAL(v1[0].copies, 1);
1302 :
1303 1 : auto v2 = Vector(std::move(t2));
1304 1 : BOOST_CHECK_EQUAL(v2.size(), 1U);
1305 1 : BOOST_CHECK(v2[0].origin == &t2); // NOLINT(*-use-after-move)
1306 1 : BOOST_CHECK_EQUAL(v2[0].copies, 0);
1307 :
1308 1 : auto v3 = Vector(t1, std::move(t2));
1309 1 : BOOST_CHECK_EQUAL(v3.size(), 2U);
1310 1 : BOOST_CHECK(v3[0].origin == &t1);
1311 1 : BOOST_CHECK(v3[1].origin == &t2); // NOLINT(*-use-after-move)
1312 1 : BOOST_CHECK_EQUAL(v3[0].copies, 1);
1313 1 : BOOST_CHECK_EQUAL(v3[1].copies, 0);
1314 :
1315 1 : auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
1316 1 : BOOST_CHECK_EQUAL(v4.size(), 3U);
1317 1 : BOOST_CHECK(v4[0].origin == &t1);
1318 1 : BOOST_CHECK(v4[1].origin == &t2);
1319 1 : BOOST_CHECK(v4[2].origin == &t3); // NOLINT(*-use-after-move)
1320 1 : BOOST_CHECK_EQUAL(v4[0].copies, 1);
1321 1 : BOOST_CHECK_EQUAL(v4[1].copies, 1);
1322 1 : BOOST_CHECK_EQUAL(v4[2].copies, 0);
1323 :
1324 1 : auto v5 = Cat(v1, v4);
1325 1 : BOOST_CHECK_EQUAL(v5.size(), 4U);
1326 1 : BOOST_CHECK(v5[0].origin == &t1);
1327 1 : BOOST_CHECK(v5[1].origin == &t1);
1328 1 : BOOST_CHECK(v5[2].origin == &t2);
1329 1 : BOOST_CHECK(v5[3].origin == &t3);
1330 1 : BOOST_CHECK_EQUAL(v5[0].copies, 2);
1331 1 : BOOST_CHECK_EQUAL(v5[1].copies, 2);
1332 1 : BOOST_CHECK_EQUAL(v5[2].copies, 2);
1333 1 : BOOST_CHECK_EQUAL(v5[3].copies, 1);
1334 :
1335 1 : auto v6 = Cat(std::move(v1), v3);
1336 1 : BOOST_CHECK_EQUAL(v6.size(), 3U);
1337 1 : BOOST_CHECK(v6[0].origin == &t1);
1338 1 : BOOST_CHECK(v6[1].origin == &t1);
1339 1 : BOOST_CHECK(v6[2].origin == &t2);
1340 1 : BOOST_CHECK_EQUAL(v6[0].copies, 1);
1341 1 : BOOST_CHECK_EQUAL(v6[1].copies, 2);
1342 1 : BOOST_CHECK_EQUAL(v6[2].copies, 1);
1343 :
1344 1 : auto v7 = Cat(v2, std::move(v4));
1345 1 : BOOST_CHECK_EQUAL(v7.size(), 4U);
1346 1 : BOOST_CHECK(v7[0].origin == &t2);
1347 1 : BOOST_CHECK(v7[1].origin == &t1);
1348 1 : BOOST_CHECK(v7[2].origin == &t2);
1349 1 : BOOST_CHECK(v7[3].origin == &t3);
1350 1 : BOOST_CHECK_EQUAL(v7[0].copies, 1);
1351 1 : BOOST_CHECK_EQUAL(v7[1].copies, 1);
1352 1 : BOOST_CHECK_EQUAL(v7[2].copies, 1);
1353 1 : BOOST_CHECK_EQUAL(v7[3].copies, 0);
1354 :
1355 1 : auto v8 = Cat(std::move(v2), std::move(v3));
1356 1 : BOOST_CHECK_EQUAL(v8.size(), 3U);
1357 1 : BOOST_CHECK(v8[0].origin == &t2);
1358 1 : BOOST_CHECK(v8[1].origin == &t1);
1359 1 : BOOST_CHECK(v8[2].origin == &t2);
1360 1 : BOOST_CHECK_EQUAL(v8[0].copies, 0);
1361 1 : BOOST_CHECK_EQUAL(v8[1].copies, 1);
1362 1 : BOOST_CHECK_EQUAL(v8[2].copies, 0);
1363 1 : }
1364 :
1365 149 : BOOST_AUTO_TEST_CASE(test_ToLower)
1366 : {
1367 1 : BOOST_CHECK_EQUAL(ToLower('@'), '@');
1368 1 : BOOST_CHECK_EQUAL(ToLower('A'), 'a');
1369 1 : BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
1370 1 : BOOST_CHECK_EQUAL(ToLower('['), '[');
1371 1 : BOOST_CHECK_EQUAL(ToLower(0), 0);
1372 1 : BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
1373 :
1374 1 : BOOST_CHECK_EQUAL(ToLower(""), "");
1375 1 : BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
1376 1 : BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
1377 1 : }
1378 :
1379 149 : BOOST_AUTO_TEST_CASE(test_ToUpper)
1380 : {
1381 1 : BOOST_CHECK_EQUAL(ToUpper('`'), '`');
1382 1 : BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
1383 1 : BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
1384 1 : BOOST_CHECK_EQUAL(ToUpper('{'), '{');
1385 1 : BOOST_CHECK_EQUAL(ToUpper(0), 0);
1386 1 : BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
1387 :
1388 1 : BOOST_CHECK_EQUAL(ToUpper(""), "");
1389 1 : BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
1390 1 : BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
1391 1 : }
1392 :
1393 149 : BOOST_AUTO_TEST_CASE(test_Capitalize)
1394 : {
1395 1 : BOOST_CHECK_EQUAL(Capitalize(""), "");
1396 1 : BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin");
1397 1 : BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
1398 1 : }
1399 :
1400 149 : BOOST_AUTO_TEST_CASE(test_CRanges)
1401 : {
1402 1 : std::mt19937 gen;
1403 18 : for (int test = 0; test < 17; ++test) {
1404 17 : std::uniform_int_distribution<uint64_t> dist_value(0, (1 << test));
1405 17 : CRangesSet ranges;
1406 17 : std::unordered_set<uint64_t> set_2;
1407 262159 : for (int iter = 0; iter < (1 << test) * 2; ++iter) {
1408 262142 : uint64_t value = dist_value(gen);
1409 262142 : BOOST_CHECK_EQUAL(ranges.Contains(value), !!set_2.count(value));
1410 262142 : if (!ranges.Contains(value)) {
1411 163304 : BOOST_CHECK(ranges.Add(value));
1412 163304 : set_2.insert(value);
1413 163304 : } else {
1414 98838 : BOOST_CHECK(ranges.Remove(value));
1415 98838 : set_2.erase(set_2.find(value));
1416 : }
1417 262142 : BOOST_CHECK_EQUAL(ranges.Contains(value), !!set_2.count(value));
1418 262142 : BOOST_CHECK_EQUAL(ranges.Size(), set_2.size());
1419 262142 : }
1420 17 : if (test > 4) {
1421 12 : BOOST_CHECK(ranges.Size() > ((1u << test) / 4));
1422 12 : }
1423 17 : }
1424 1 : }
1425 :
1426 28 : static std::string SpanToStr(const Span<const char>& span)
1427 : {
1428 28 : return std::string(span.begin(), span.end());
1429 : }
1430 :
1431 149 : BOOST_AUTO_TEST_CASE(test_spanparsing)
1432 : {
1433 : using namespace spanparsing;
1434 1 : std::string input;
1435 1 : Span<const char> sp;
1436 : bool success;
1437 :
1438 : // Const(...): parse a constant, update span to skip it if successful
1439 1 : input = "MilkToastHoney";
1440 1 : sp = input;
1441 1 : success = Const("", sp); // empty
1442 1 : BOOST_CHECK(success);
1443 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");
1444 :
1445 1 : success = Const("Milk", sp);
1446 1 : BOOST_CHECK(success);
1447 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");
1448 :
1449 1 : success = Const("Bread", sp);
1450 1 : BOOST_CHECK(!success);
1451 :
1452 1 : success = Const("Toast", sp);
1453 1 : BOOST_CHECK(success);
1454 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");
1455 :
1456 1 : success = Const("Honeybadger", sp);
1457 1 : BOOST_CHECK(!success);
1458 :
1459 1 : success = Const("Honey", sp);
1460 1 : BOOST_CHECK(success);
1461 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1462 :
1463 : // Func(...): parse a function call, update span to argument if successful
1464 1 : input = "Foo(Bar(xy,z()))";
1465 1 : sp = input;
1466 :
1467 1 : success = Func("FooBar", sp);
1468 1 : BOOST_CHECK(!success);
1469 :
1470 1 : success = Func("Foo(", sp);
1471 1 : BOOST_CHECK(!success);
1472 :
1473 1 : success = Func("Foo", sp);
1474 1 : BOOST_CHECK(success);
1475 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");
1476 :
1477 1 : success = Func("Bar", sp);
1478 1 : BOOST_CHECK(success);
1479 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()");
1480 :
1481 1 : success = Func("xy", sp);
1482 1 : BOOST_CHECK(!success);
1483 :
1484 : // Expr(...): return expression that span begins with, update span to skip it
1485 1 : Span<const char> result;
1486 :
1487 1 : input = "(n*(n-1))/2";
1488 1 : sp = input;
1489 1 : result = Expr(sp);
1490 1 : BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2");
1491 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1492 :
1493 1 : input = "foo,bar";
1494 1 : sp = input;
1495 1 : result = Expr(sp);
1496 1 : BOOST_CHECK_EQUAL(SpanToStr(result), "foo");
1497 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar");
1498 :
1499 1 : input = "(aaaaa,bbbbb()),c";
1500 1 : sp = input;
1501 1 : result = Expr(sp);
1502 1 : BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())");
1503 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), ",c");
1504 :
1505 1 : input = "xyz)foo";
1506 1 : sp = input;
1507 1 : result = Expr(sp);
1508 1 : BOOST_CHECK_EQUAL(SpanToStr(result), "xyz");
1509 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo");
1510 :
1511 1 : input = "((a),(b),(c)),xxx";
1512 1 : sp = input;
1513 1 : result = Expr(sp);
1514 1 : BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))");
1515 1 : BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx");
1516 :
1517 : // Split(...): split a string on every instance of sep, return vector
1518 1 : std::vector<Span<const char>> results;
1519 :
1520 1 : input = "xxx";
1521 1 : results = Split(input, 'x');
1522 1 : BOOST_CHECK_EQUAL(results.size(), 4);
1523 1 : BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1524 1 : BOOST_CHECK_EQUAL(SpanToStr(results[1]), "");
1525 1 : BOOST_CHECK_EQUAL(SpanToStr(results[2]), "");
1526 1 : BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1527 :
1528 1 : input = "one#two#three";
1529 1 : results = Split(input, '-');
1530 1 : BOOST_CHECK_EQUAL(results.size(), 1);
1531 1 : BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three");
1532 :
1533 1 : input = "one#two#three";
1534 1 : results = Split(input, '#');
1535 1 : BOOST_CHECK_EQUAL(results.size(), 3);
1536 1 : BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one");
1537 1 : BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two");
1538 1 : BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three");
1539 :
1540 1 : input = "*foo*bar*";
1541 1 : results = Split(input, '*');
1542 1 : BOOST_CHECK_EQUAL(results.size(), 4);
1543 1 : BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1544 1 : BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo");
1545 1 : BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar");
1546 1 : BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1547 1 : }
1548 :
1549 149 : BOOST_AUTO_TEST_CASE(test_SplitString)
1550 : {
1551 : // Empty string.
1552 : {
1553 1 : std::vector<std::string> result = SplitString("", '-');
1554 1 : BOOST_CHECK_EQUAL(result.size(), 1);
1555 1 : BOOST_CHECK_EQUAL(result[0], "");
1556 1 : }
1557 :
1558 : // Empty items.
1559 : {
1560 1 : std::vector<std::string> result = SplitString("-", '-');
1561 1 : BOOST_CHECK_EQUAL(result.size(), 2);
1562 1 : BOOST_CHECK_EQUAL(result[0], "");
1563 1 : BOOST_CHECK_EQUAL(result[1], "");
1564 1 : }
1565 :
1566 : // More empty items.
1567 : {
1568 1 : std::vector<std::string> result = SplitString("--", '-');
1569 1 : BOOST_CHECK_EQUAL(result.size(), 3);
1570 1 : BOOST_CHECK_EQUAL(result[0], "");
1571 1 : BOOST_CHECK_EQUAL(result[1], "");
1572 1 : BOOST_CHECK_EQUAL(result[2], "");
1573 1 : }
1574 :
1575 : // Separator is not present.
1576 : {
1577 1 : std::vector<std::string> result = SplitString("abc", '-');
1578 1 : BOOST_CHECK_EQUAL(result.size(), 1);
1579 1 : BOOST_CHECK_EQUAL(result[0], "abc");
1580 1 : }
1581 :
1582 : // Basic behavior.
1583 : {
1584 1 : std::vector<std::string> result = SplitString("a-b", '-');
1585 1 : BOOST_CHECK_EQUAL(result.size(), 2);
1586 1 : BOOST_CHECK_EQUAL(result[0], "a");
1587 1 : BOOST_CHECK_EQUAL(result[1], "b");
1588 1 : }
1589 :
1590 : // Case-sensitivity of the separator.
1591 : {
1592 1 : std::vector<std::string> result = SplitString("AAA", 'a');
1593 1 : BOOST_CHECK_EQUAL(result.size(), 1);
1594 1 : BOOST_CHECK_EQUAL(result[0], "AAA");
1595 1 : }
1596 :
1597 : // multiple split characters
1598 : {
1599 : using V = std::vector<std::string>;
1600 1 : BOOST_TEST(SplitString("a,b.c:d;e", ",;") == V({"a", "b.c:d", "e"}));
1601 1 : BOOST_TEST(SplitString("a,b.c:d;e", ",;:.") == V({"a", "b", "c", "d", "e"}));
1602 1 : BOOST_TEST(SplitString("a,b.c:d;e", "") == V({"a,b.c:d;e"}));
1603 1 : BOOST_TEST(SplitString("aaa", "bcdefg") == V({"aaa"}));
1604 1 : BOOST_TEST(SplitString("x\0a,b"s, "\0"s) == V({"x", "a,b"}));
1605 1 : BOOST_TEST(SplitString("x\0a,b"s, '\0') == V({"x", "a,b"}));
1606 1 : BOOST_TEST(SplitString("x\0a,b"s, "\0,"s) == V({"x", "a", "b"}));
1607 1 : BOOST_TEST(SplitString("abcdefg", "bcd") == V({"a", "", "", "efg"}));
1608 : }
1609 1 : }
1610 :
1611 149 : BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
1612 : {
1613 : // ASCII and UTF-8 must pass through unaltered.
1614 1 : BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
1615 : // Newlines must pass through unaltered.
1616 1 : BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
1617 : // Other control characters are escaped in C syntax.
1618 1 : BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
1619 : // Embedded NULL characters are escaped too.
1620 1 : const std::string NUL("O\x00O", 3);
1621 1 : BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
1622 1 : }
1623 :
1624 149 : BOOST_AUTO_TEST_CASE(message_sign)
1625 : {
1626 1 : const std::array<unsigned char, 32> privkey_bytes = {
1627 : // just some random data
1628 : // derived address from this private key: XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j
1629 : 0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
1630 : 0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
1631 : 0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
1632 : 0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
1633 : };
1634 :
1635 1 : const std::string message = "Trust no one";
1636 :
1637 : const std::string expected_signature =
1638 1 : "IIOzMDkvw3GtLWXkeEYRRRH53MOLHM44sJ428Nu4NNacTPJTGcKesMJ+3s3OadYK34tpSQIhu922EviNNWTsiQg=";
1639 :
1640 1 : CKey privkey;
1641 1 : std::string generated_signature;
1642 :
1643 1 : BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
1644 : "Confirm the private key is invalid");
1645 :
1646 1 : BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
1647 : "Sign with an invalid private key");
1648 :
1649 1 : privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
1650 :
1651 1 : BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
1652 : "Confirm the private key is valid");
1653 :
1654 1 : BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
1655 : "Sign with a valid private key");
1656 :
1657 1 : BOOST_CHECK_EQUAL(expected_signature, generated_signature);
1658 1 : }
1659 :
1660 149 : BOOST_AUTO_TEST_CASE(message_verify)
1661 : {
1662 1 : BOOST_CHECK_EQUAL(
1663 : MessageVerify(
1664 : "invalid address",
1665 : "signature should be irrelevant",
1666 : "message too"),
1667 : MessageVerificationResult::ERR_INVALID_ADDRESS);
1668 :
1669 1 : BOOST_CHECK_EQUAL(
1670 : MessageVerify(
1671 : "7iRPy8FEHBzbChrktsG85YbDZ3SuiCxsNq",
1672 : "signature should be irrelevant",
1673 : "message too"),
1674 : MessageVerificationResult::ERR_ADDRESS_NO_KEY);
1675 :
1676 1 : BOOST_CHECK_EQUAL(
1677 : MessageVerify(
1678 : "XuXS24zs2xP1vPynvNt14kWLa64csH8Mur",
1679 : "invalid signature, not in base64 encoding",
1680 : "message should be irrelevant"),
1681 : MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
1682 :
1683 1 : BOOST_CHECK_EQUAL(
1684 : MessageVerify(
1685 : "XuXS24zs2xP1vPynvNt14kWLa64csH8Mur",
1686 : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1687 : "message should be irrelevant"),
1688 : MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED);
1689 :
1690 1 : BOOST_CHECK_EQUAL(
1691 : MessageVerify(
1692 : "XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j",
1693 : "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
1694 : "I never signed this"),
1695 : MessageVerificationResult::ERR_NOT_SIGNED);
1696 :
1697 1 : BOOST_CHECK_EQUAL(
1698 : MessageVerify(
1699 : "XetGnWHsPXV9VSkWzB6Wn2KhZLD24gqa5j",
1700 : "IIOzMDkvw3GtLWXkeEYRRRH53MOLHM44sJ428Nu4NNacTPJTGcKesMJ+3s3OadYK34tpSQIhu922EviNNWTsiQg=",
1701 : "Trust no one"),
1702 : MessageVerificationResult::OK);
1703 :
1704 1 : BOOST_CHECK_EQUAL(
1705 : MessageVerify(
1706 : "XenV77v8QQ3rwjyCb3j2fCwfvgbkC4Vwaj",
1707 : "IOACalWiJTLJ2U7wTKICx5mQ2tOAJ3to8dko8FMb2XSYbmvL+yMWedyfSfaK6V8jwoociyYx628nkXXnrOhPFIY=",
1708 : "Trust me"),
1709 : MessageVerificationResult::OK);
1710 1 : }
1711 :
1712 149 : BOOST_AUTO_TEST_CASE(message_hash)
1713 : {
1714 1 : const std::string unsigned_tx = "...";
1715 : const std::string prefixed_message =
1716 2 : std::string(1, (char)MESSAGE_MAGIC.length()) +
1717 1 : MESSAGE_MAGIC +
1718 2 : std::string(1, (char)unsigned_tx.length()) +
1719 : unsigned_tx;
1720 :
1721 1 : const uint256 signature_hash = Hash(unsigned_tx);
1722 1 : const uint256 message_hash1 = Hash(prefixed_message);
1723 1 : const uint256 message_hash2 = MessageHash(unsigned_tx);
1724 :
1725 1 : BOOST_CHECK_EQUAL(message_hash1, message_hash2);
1726 1 : BOOST_CHECK_NE(message_hash1, signature_hash);
1727 1 : }
1728 :
1729 149 : BOOST_AUTO_TEST_CASE(remove_prefix)
1730 : {
1731 1 : BOOST_CHECK_EQUAL(RemovePrefix("./util/system.h", "./"), "util/system.h");
1732 1 : BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), "");
1733 1 : BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o");
1734 1 : BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo");
1735 1 : BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo");
1736 1 : BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo");
1737 1 : BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f");
1738 1 : BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), "");
1739 1 : BOOST_CHECK_EQUAL(RemovePrefix("", ""), "");
1740 1 : }
1741 :
1742 149 : BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
1743 : {
1744 1 : auto noop = ByteUnit::NOOP;
1745 :
1746 : // no multiplier
1747 1 : BOOST_CHECK_EQUAL(ParseByteUnits("1", noop).value(), 1);
1748 1 : BOOST_CHECK_EQUAL(ParseByteUnits("0", noop).value(), 0);
1749 :
1750 1 : BOOST_CHECK_EQUAL(ParseByteUnits("1k", noop).value(), 1000ULL);
1751 1 : BOOST_CHECK_EQUAL(ParseByteUnits("1K", noop).value(), 1ULL << 10);
1752 :
1753 1 : BOOST_CHECK_EQUAL(ParseByteUnits("2m", noop).value(), 2'000'000ULL);
1754 1 : BOOST_CHECK_EQUAL(ParseByteUnits("2M", noop).value(), 2ULL << 20);
1755 :
1756 1 : BOOST_CHECK_EQUAL(ParseByteUnits("3g", noop).value(), 3'000'000'000ULL);
1757 1 : BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3ULL << 30);
1758 :
1759 1 : BOOST_CHECK_EQUAL(ParseByteUnits("4t", noop).value(), 4'000'000'000'000ULL);
1760 1 : BOOST_CHECK_EQUAL(ParseByteUnits("4T", noop).value(), 4ULL << 40);
1761 :
1762 : // check default multiplier
1763 1 : BOOST_CHECK_EQUAL(ParseByteUnits("5", ByteUnit::K).value(), 5ULL << 10);
1764 :
1765 : // NaN
1766 1 : BOOST_CHECK(!ParseByteUnits("", noop));
1767 1 : BOOST_CHECK(!ParseByteUnits("foo", noop));
1768 :
1769 : // whitespace
1770 1 : BOOST_CHECK(!ParseByteUnits("123m ", noop));
1771 1 : BOOST_CHECK(!ParseByteUnits(" 123m", noop));
1772 :
1773 : // no +-
1774 1 : BOOST_CHECK(!ParseByteUnits("-123m", noop));
1775 1 : BOOST_CHECK(!ParseByteUnits("+123m", noop));
1776 :
1777 : // zero padding
1778 1 : BOOST_CHECK_EQUAL(ParseByteUnits("020M", noop).value(), 20ULL << 20);
1779 :
1780 : // fractions not allowed
1781 1 : BOOST_CHECK(!ParseByteUnits("0.5T", noop));
1782 :
1783 : // overflow
1784 1 : BOOST_CHECK(!ParseByteUnits("18446744073709551615g", noop));
1785 :
1786 : // invalid unit
1787 1 : BOOST_CHECK(!ParseByteUnits("1x", noop));
1788 1 : }
1789 :
1790 149 : BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
1791 : {
1792 1 : fs::path tmpfolder = m_args.GetDataDirBase();
1793 1 : fs::path tmpfile = tmpfolder / "read_binary.dat";
1794 1 : std::string expected_text;
1795 31 : for (int i = 0; i < 30; i++) {
1796 30 : expected_text += "0123456789";
1797 30 : }
1798 : {
1799 1 : std::ofstream file{tmpfile};
1800 1 : file << expected_text;
1801 1 : }
1802 : {
1803 : // read all contents in file
1804 3 : auto [valid, text] = ReadBinaryFile(tmpfile);
1805 1 : BOOST_CHECK(valid);
1806 1 : BOOST_CHECK_EQUAL(text, expected_text);
1807 1 : }
1808 : {
1809 : // read half contents in file
1810 3 : auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
1811 1 : BOOST_CHECK(valid);
1812 1 : BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
1813 1 : }
1814 : {
1815 : // read from non-existent file
1816 1 : fs::path invalid_file = tmpfolder / "invalid_binary.dat";
1817 3 : auto [valid, text] = ReadBinaryFile(invalid_file);
1818 1 : BOOST_CHECK(!valid);
1819 1 : BOOST_CHECK(text.empty());
1820 1 : }
1821 1 : }
1822 :
1823 149 : BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
1824 : {
1825 1 : fs::path tmpfolder = m_args.GetDataDirBase();
1826 1 : fs::path tmpfile = tmpfolder / "write_binary.dat";
1827 1 : std::string expected_text = "bitcoin";
1828 1 : auto valid = WriteBinaryFile(tmpfile, expected_text);
1829 1 : std::string actual_text;
1830 1 : std::ifstream file{tmpfile};
1831 1 : file >> actual_text;
1832 1 : BOOST_CHECK(valid);
1833 1 : BOOST_CHECK_EQUAL(actual_text, expected_text);
1834 1 : }
1835 :
1836 149 : BOOST_AUTO_TEST_CASE(clearshrink_test)
1837 : {
1838 : {
1839 1 : std::vector<uint8_t> v = {1, 2, 3};
1840 1 : ClearShrink(v);
1841 1 : BOOST_CHECK_EQUAL(v.size(), 0);
1842 1 : BOOST_CHECK_EQUAL(v.capacity(), 0);
1843 1 : }
1844 :
1845 : {
1846 1 : std::vector<bool> v = {false, true, false, false, true, true};
1847 1 : ClearShrink(v);
1848 1 : BOOST_CHECK_EQUAL(v.size(), 0);
1849 1 : BOOST_CHECK_EQUAL(v.capacity(), 0);
1850 1 : }
1851 :
1852 : {
1853 1 : std::deque<int> v = {1, 3, 3, 7};
1854 1 : ClearShrink(v);
1855 1 : BOOST_CHECK_EQUAL(v.size(), 0);
1856 : // std::deque has no capacity() we can observe.
1857 1 : }
1858 1 : }
1859 :
1860 149 : BOOST_AUTO_TEST_CASE(padding_test)
1861 : {
1862 : /* By default strings will be padded to the left */
1863 1 : BOOST_CHECK_EQUAL(PadString("example", 8), " example");
1864 :
1865 : /* Check padding works on the correct side */
1866 1 : BOOST_CHECK_EQUAL(PadString("example", 8, /*left=*/true), " example");
1867 1 : BOOST_CHECK_EQUAL(PadString("example", 8, /*left=*/false), "example ");
1868 :
1869 : /* Padding lesser than the string size should return the string */
1870 1 : BOOST_CHECK_EQUAL(PadString("example", 6), "example");
1871 :
1872 : /* Padding equal to the string size should return the string */
1873 1 : BOOST_CHECK_EQUAL(PadString("example", 7), "example");
1874 :
1875 : /* Padding an empty string with zero length should return an empty string */
1876 1 : BOOST_CHECK(PadString("", 0).empty());
1877 :
1878 : /* An empty string should be padded if non-zero length specified */
1879 1 : BOOST_CHECK_EQUAL(PadString("", 1), " ");
1880 1 : }
1881 :
1882 146 : BOOST_AUTO_TEST_SUITE_END()
|