util_tests.cpp raw
1 // Copyright (c) 2011-present The Limenka 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 <clientversion.h>
6 #include <common/signmessage.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
7 #include <hash.h> // For Hash()
8 #include <key.h> // For CKey
9 #include <key_io.h> // EncodeDestination
10 #include <outputtype.h> // For BIP-322 tests
11 #include <script/parsing.h>
12 #include <span.h>
13 #include <sync.h>
14 #include <test/util/random.h>
15 #include <test/util/setup_common.h>
16 #include <uint256.h>
17 #include <util/bitdeque.h>
18 #include <util/byte_units.h>
19 #include <util/fs.h>
20 #include <util/fs_helpers.h>
21 #include <util/moneystr.h>
22 #include <util/overflow.h>
23 #include <util/readwritefile.h>
24 #include <util/strencodings.h>
25 #include <util/string.h>
26 #include <util/time.h>
27 #include <util/vector.h>
28
29 #include <array>
30 #include <cmath>
31 #include <fstream>
32 #include <limits>
33 #include <map>
34 #include <optional>
35 #include <stdint.h>
36 #include <string.h>
37 #include <thread>
38 #include <univalue.h>
39 #include <type_traits>
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 using namespace util::hex_literals;
54 using util::ConstevalHexDigit;
55 using util::Join;
56 using util::RemovePrefix;
57 using util::RemovePrefixView;
58 using util::ReplaceAll;
59 using util::Split;
60 using util::SplitString;
61 using util::TrimString;
62 using util::TrimStringView;
63
64 static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s};
65
66 /* defined in logging.cpp */
67 namespace BCLog {
68 std::string LogEscapeMessage(std::string_view str);
69 }
70
71 BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
72
73 namespace {
74 class NoCopyOrMove
75 {
76 public:
77 int i;
78 explicit NoCopyOrMove(int i) : i{i} { }
79
80 NoCopyOrMove() = delete;
81 NoCopyOrMove(const NoCopyOrMove&) = delete;
82 NoCopyOrMove(NoCopyOrMove&&) = delete;
83 NoCopyOrMove& operator=(const NoCopyOrMove&) = delete;
84 NoCopyOrMove& operator=(NoCopyOrMove&&) = delete;
85
86 operator bool() const { return i != 0; }
87
88 int get_ip1() { return i + 1; }
89 bool test()
90 {
91 // Check that Assume can be used within a lambda and still call methods
92 [&]() { Assume(get_ip1()); }();
93 return Assume(get_ip1() != 5);
94 }
95 };
96 } // namespace
97
98 BOOST_AUTO_TEST_CASE(util_check)
99 {
100 // Check that Assert can forward
101 const std::unique_ptr<int> p_two = Assert(std::make_unique<int>(2));
102 // Check that Assert works on lvalues and rvalues
103 const int two = *Assert(p_two);
104 Assert(two == 2);
105 Assert(true);
106 // Check that Assume can be used as unary expression
107 const bool result{Assume(two == 2)};
108 Assert(result);
109
110 // Check that Assert doesn't require copy/move
111 NoCopyOrMove x{9};
112 Assert(x).i += 3;
113 Assert(x).test();
114
115 // Check nested Asserts
116 BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3);
117
118 // Check -Wdangling-gsl does not trigger when copying the int. (It would
119 // trigger on "const int&")
120 const int nine{*Assert(std::optional<int>{9})};
121 BOOST_CHECK_EQUAL(9, nine);
122 }
123
124 BOOST_AUTO_TEST_CASE(util_criticalsection)
125 {
126 RecursiveMutex cs;
127
128 do {
129 LOCK(cs);
130 break;
131
132 BOOST_ERROR("break was swallowed!");
133 } while(0);
134
135 do {
136 TRY_LOCK(cs, lockTest);
137 if (lockTest) {
138 BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
139 break;
140 }
141
142 BOOST_ERROR("break was swallowed!");
143 } while(0);
144 }
145
146 constexpr char HEX_PARSE_INPUT[] = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
147 constexpr uint8_t HEX_PARSE_OUTPUT[] = {
148 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
149 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
150 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
151 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
152 0x5f
153 };
154 static_assert((sizeof(HEX_PARSE_INPUT) - 1) == 2 * sizeof(HEX_PARSE_OUTPUT));
155 BOOST_AUTO_TEST_CASE(parse_hex)
156 {
157 std::vector<unsigned char> result;
158
159 // Basic test vector
160 std::vector<unsigned char> expected(std::begin(HEX_PARSE_OUTPUT), std::end(HEX_PARSE_OUTPUT));
161 constexpr std::array<std::byte, 65> hex_literal_array{operator""_hex<util::detail::Hex(HEX_PARSE_INPUT)>()};
162 auto hex_literal_span{MakeUCharSpan(hex_literal_array)};
163 BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
164
165 const std::vector<std::byte> hex_literal_vector{operator""_hex_v<util::detail::Hex(HEX_PARSE_INPUT)>()};
166 hex_literal_span = MakeUCharSpan(hex_literal_vector);
167 BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
168
169 constexpr std::array<uint8_t, 65> hex_literal_array_uint8{operator""_hex_u8<util::detail::Hex(HEX_PARSE_INPUT)>()};
170 BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_array_uint8.begin(), hex_literal_array_uint8.end(), expected.begin(), expected.end());
171
172 result = operator""_hex_v_u8<util::detail::Hex(HEX_PARSE_INPUT)>();
173 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
174
175 result = ParseHex(HEX_PARSE_INPUT);
176 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
177
178 result = TryParseHex<uint8_t>(HEX_PARSE_INPUT).value();
179 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
180
181 // Spaces between bytes must be supported
182 expected = {0x12, 0x34, 0x56, 0x78};
183 result = ParseHex("12 34 56 78");
184 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
185 result = TryParseHex<uint8_t>("12 34 56 78").value();
186 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
187
188 // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
189 expected = {0x89, 0x34, 0x56, 0x78};
190 result = ParseHex(" 89 34 56 78");
191 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
192 result = TryParseHex<uint8_t>(" 89 34 56 78").value();
193 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
194
195 // Mixed case and spaces are supported
196 expected = {0xff, 0xaa};
197 result = ParseHex(" Ff aA ");
198 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
199 result = TryParseHex<uint8_t>(" Ff aA ").value();
200 BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
201
202 // Empty string is supported
203 static_assert(""_hex.empty());
204 static_assert(""_hex_u8.empty());
205 BOOST_CHECK_EQUAL(""_hex_v.size(), 0);
206 BOOST_CHECK_EQUAL(""_hex_v_u8.size(), 0);
207 BOOST_CHECK_EQUAL(ParseHex("").size(), 0);
208 BOOST_CHECK_EQUAL(TryParseHex<uint8_t>("").value().size(), 0);
209
210 // Spaces between nibbles is treated as invalid
211 BOOST_CHECK_EQUAL(ParseHex("AAF F").size(), 0);
212 BOOST_CHECK(!TryParseHex("AAF F").has_value());
213
214 // Embedded null is treated as invalid
215 const std::string with_embedded_null{" 11 "s
216 " \0 "
217 " 22 "s};
218 BOOST_CHECK_EQUAL(with_embedded_null.size(), 11);
219 BOOST_CHECK_EQUAL(ParseHex(with_embedded_null).size(), 0);
220 BOOST_CHECK(!TryParseHex(with_embedded_null).has_value());
221
222 // Non-hex is treated as invalid
223 BOOST_CHECK_EQUAL(ParseHex("1234 invalid 1234").size(), 0);
224 BOOST_CHECK(!TryParseHex("1234 invalid 1234").has_value());
225
226 // Truncated input is treated as invalid
227 BOOST_CHECK_EQUAL(ParseHex("12 3").size(), 0);
228 BOOST_CHECK(!TryParseHex("12 3").has_value());
229 }
230
231 BOOST_AUTO_TEST_CASE(consteval_hex_digit)
232 {
233 BOOST_CHECK_EQUAL(ConstevalHexDigit('0'), 0);
234 BOOST_CHECK_EQUAL(ConstevalHexDigit('9'), 9);
235 BOOST_CHECK_EQUAL(ConstevalHexDigit('a'), 0xa);
236 BOOST_CHECK_EQUAL(ConstevalHexDigit('f'), 0xf);
237 }
238
239 BOOST_AUTO_TEST_CASE(util_HexStr)
240 {
241 BOOST_CHECK_EQUAL(HexStr(HEX_PARSE_OUTPUT), HEX_PARSE_INPUT);
242 BOOST_CHECK_EQUAL(HexStr(Span{HEX_PARSE_OUTPUT}.last(0)), "");
243 BOOST_CHECK_EQUAL(HexStr(Span{HEX_PARSE_OUTPUT}.first(0)), "");
244
245 {
246 constexpr std::string_view out_exp{"04678afdb0"};
247 constexpr std::span in_s{HEX_PARSE_OUTPUT, out_exp.size() / 2};
248 const Span<const uint8_t> in_u{MakeUCharSpan(in_s)};
249 const Span<const std::byte> in_b{MakeByteSpan(in_s)};
250
251 BOOST_CHECK_EQUAL(HexStr(in_u), out_exp);
252 BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
253 BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
254 }
255
256 {
257 auto input = std::string();
258 for (size_t i=0; i<256; ++i) {
259 input.push_back(static_cast<char>(i));
260 }
261
262 auto hex = HexStr(input);
263 BOOST_TEST_REQUIRE(hex.size() == 512);
264 static constexpr auto hexmap = std::string_view("0123456789abcdef");
265 for (size_t i = 0; i < 256; ++i) {
266 auto upper = hexmap.find(hex[i * 2]);
267 auto lower = hexmap.find(hex[i * 2 + 1]);
268 BOOST_TEST_REQUIRE(upper != std::string_view::npos);
269 BOOST_TEST_REQUIRE(lower != std::string_view::npos);
270 BOOST_TEST_REQUIRE(i == upper*16 + lower);
271 }
272 }
273 }
274
275 BOOST_AUTO_TEST_CASE(span_write_bytes)
276 {
277 std::array mut_arr{uint8_t{0xaa}, uint8_t{0xbb}};
278 const auto mut_bytes{MakeWritableByteSpan(mut_arr)};
279 mut_bytes[1] = std::byte{0x11};
280 BOOST_CHECK_EQUAL(mut_arr.at(0), 0xaa);
281 BOOST_CHECK_EQUAL(mut_arr.at(1), 0x11);
282 }
283
284 BOOST_AUTO_TEST_CASE(util_Join)
285 {
286 // Normal version
287 BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
288 BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
289 BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
290
291 // Version with unary operator
292 const auto op_upper = [](const std::string& s) { return ToUpper(s); };
293 BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
294 BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
295 BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
296 }
297
298 BOOST_AUTO_TEST_CASE(util_ReplaceAll)
299 {
300 const std::string original("A test \"%s\" string '%s'.");
301 auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) {
302 auto test = original;
303 ReplaceAll(test, search, substitute);
304 BOOST_CHECK_EQUAL(test, expected);
305 };
306
307 test_replaceall("", "foo", original);
308 test_replaceall(original, "foo", "foo");
309 test_replaceall("%s", "foo", "A test \"foo\" string 'foo'.");
310 test_replaceall("\"", "foo", "A test foo%sfoo string '%s'.");
311 test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo.");
312 }
313
314 BOOST_AUTO_TEST_CASE(util_TrimString)
315 {
316 BOOST_CHECK_EQUAL(TrimString(" foo bar "), "foo bar");
317 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");
318 BOOST_CHECK_EQUAL(TrimString("\t \n foo \n\tbar\t \n "), "foo \n\tbar");
319 BOOST_CHECK_EQUAL(TrimStringView("\t \n foo \n\tbar\t \n ", "fobar"), "\t \n foo \n\tbar\t \n ");
320 BOOST_CHECK_EQUAL(TrimString("foo bar"), "foo bar");
321 BOOST_CHECK_EQUAL(TrimStringView("foo bar", "fobar"), " ");
322 BOOST_CHECK_EQUAL(TrimString(std::string("\0 foo \0 ", 8)), std::string("\0 foo \0", 7));
323 BOOST_CHECK_EQUAL(TrimStringView(std::string(" foo ", 5)), std::string("foo", 3));
324 BOOST_CHECK_EQUAL(TrimString(std::string("\t\t\0\0\n\n", 6)), std::string("\0\0", 2));
325 BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6)), std::string("\x05\x04\x03\x02\x01\x00", 6));
326 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));
327 BOOST_CHECK_EQUAL(TrimStringView(std::string("\x05\x04\x03\x02\x01\x00", 6), std::string("\x05\x04\x03\x02\x01\x00", 6)), "");
328 }
329
330 BOOST_AUTO_TEST_CASE(util_ParseISO8601DateTime)
331 {
332 BOOST_CHECK_EQUAL(ParseISO8601DateTime("1969-12-31T23:59:59Z").value(), -1);
333 BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:00Z").value(), 0);
334 BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:01Z").value(), 1);
335 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:00:01Z").value(), 946684801);
336 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2011-09-30T23:36:17Z").value(), 1317425777);
337 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2100-12-31T23:59:59Z").value(), 4133980799);
338 BOOST_CHECK_EQUAL(ParseISO8601DateTime("9999-12-31T23:59:59Z").value(), 253402300799);
339
340 // Accept edge-cases, where the time overflows. They are not produced by
341 // FormatISO8601DateTime, so this can be changed in the future, if needed.
342 // For now, keep compatibility with the previous implementation.
343 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T99:00:00Z").value(), 947041200);
344 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:99:00Z").value(), 946690740);
345 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:00:99Z").value(), 946684899);
346 BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T99:99:99Z").value(), 947047239);
347
348 // Reject date overflows.
349 BOOST_CHECK(!ParseISO8601DateTime("2000-99-01T00:00:00Z"));
350 BOOST_CHECK(!ParseISO8601DateTime("2000-01-99T00:00:00Z"));
351
352 // Reject out-of-range years
353 BOOST_CHECK(!ParseISO8601DateTime("32768-12-31T23:59:59Z"));
354 BOOST_CHECK(!ParseISO8601DateTime("32767-12-31T23:59:59Z"));
355 BOOST_CHECK(!ParseISO8601DateTime("32767-12-31T00:00:00Z"));
356 BOOST_CHECK(!ParseISO8601DateTime("999-12-31T00:00:00Z"));
357
358 // Reject invalid format
359 const std::string valid{"2000-01-01T00:00:01Z"};
360 BOOST_CHECK(ParseISO8601DateTime(valid).has_value());
361 for (auto mut{0U}; mut < valid.size(); ++mut) {
362 std::string invalid{valid};
363 invalid[mut] = 'a';
364 BOOST_CHECK(!ParseISO8601DateTime(invalid));
365 }
366 }
367
368 BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
369 {
370 BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890963199), "32767-12-31T23:59:59Z");
371 BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890876800), "32767-12-31T00:00:00Z");
372
373 BOOST_CHECK_EQUAL(FormatISO8601DateTime(-1), "1969-12-31T23:59:59Z");
374 BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z");
375 BOOST_CHECK_EQUAL(FormatISO8601DateTime(1), "1970-01-01T00:00:01Z");
376 BOOST_CHECK_EQUAL(FormatISO8601DateTime(946684801), "2000-01-01T00:00:01Z");
377 BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
378 BOOST_CHECK_EQUAL(FormatISO8601DateTime(4133980799), "2100-12-31T23:59:59Z");
379 BOOST_CHECK_EQUAL(FormatISO8601DateTime(253402300799), "9999-12-31T23:59:59Z");
380 }
381
382 BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
383 {
384 BOOST_CHECK_EQUAL(FormatISO8601Date(971890963199), "32767-12-31");
385 BOOST_CHECK_EQUAL(FormatISO8601Date(971890876800), "32767-12-31");
386
387 BOOST_CHECK_EQUAL(FormatISO8601Date(0), "1970-01-01");
388 BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
389 }
390
391 BOOST_AUTO_TEST_CASE(util_FormatMoney)
392 {
393 BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
394 BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
395 BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
396
397 BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
398 BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
399 BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
400 BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
401 BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
402 BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
403 BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
404 BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
405 BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
406 BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
407 BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
408 BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
409 BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
410 BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
411 BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
412 BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
413 BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
414
415 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max()), "92233720368.54775807");
416 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 1), "92233720368.54775806");
417 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 2), "92233720368.54775805");
418 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::max() - 3), "92233720368.54775804");
419 // ...
420 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 3), "-92233720368.54775805");
421 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 2), "-92233720368.54775806");
422 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min() + 1), "-92233720368.54775807");
423 BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<int64_t>::min()), "-92233720368.54775808");
424 }
425
426 BOOST_AUTO_TEST_CASE(util_ParseMoney)
427 {
428 BOOST_CHECK_EQUAL(ParseMoney("0.0").value(), 0);
429 BOOST_CHECK_EQUAL(ParseMoney(".").value(), 0);
430 BOOST_CHECK_EQUAL(ParseMoney("0.").value(), 0);
431 BOOST_CHECK_EQUAL(ParseMoney(".0").value(), 0);
432 BOOST_CHECK_EQUAL(ParseMoney(".6789").value(), 6789'0000);
433 BOOST_CHECK_EQUAL(ParseMoney("12345.").value(), COIN * 12345);
434
435 BOOST_CHECK_EQUAL(ParseMoney("12345.6789").value(), (COIN/10000)*123456789);
436
437 BOOST_CHECK_EQUAL(ParseMoney("10000000.00").value(), COIN*10000000);
438 BOOST_CHECK_EQUAL(ParseMoney("1000000.00").value(), COIN*1000000);
439 BOOST_CHECK_EQUAL(ParseMoney("100000.00").value(), COIN*100000);
440 BOOST_CHECK_EQUAL(ParseMoney("10000.00").value(), COIN*10000);
441 BOOST_CHECK_EQUAL(ParseMoney("1000.00").value(), COIN*1000);
442 BOOST_CHECK_EQUAL(ParseMoney("100.00").value(), COIN*100);
443 BOOST_CHECK_EQUAL(ParseMoney("10.00").value(), COIN*10);
444 BOOST_CHECK_EQUAL(ParseMoney("1.00").value(), COIN);
445 BOOST_CHECK_EQUAL(ParseMoney("1").value(), COIN);
446 BOOST_CHECK_EQUAL(ParseMoney(" 1").value(), COIN);
447 BOOST_CHECK_EQUAL(ParseMoney("1 ").value(), COIN);
448 BOOST_CHECK_EQUAL(ParseMoney(" 1 ").value(), COIN);
449 BOOST_CHECK_EQUAL(ParseMoney("0.1").value(), COIN/10);
450 BOOST_CHECK_EQUAL(ParseMoney("0.01").value(), COIN/100);
451 BOOST_CHECK_EQUAL(ParseMoney("0.001").value(), COIN/1000);
452 BOOST_CHECK_EQUAL(ParseMoney("0.0001").value(), COIN/10000);
453 BOOST_CHECK_EQUAL(ParseMoney("0.00001").value(), COIN/100000);
454 BOOST_CHECK_EQUAL(ParseMoney("0.000001").value(), COIN/1000000);
455 BOOST_CHECK_EQUAL(ParseMoney("0.0000001").value(), COIN/10000000);
456 BOOST_CHECK_EQUAL(ParseMoney("0.00000001").value(), COIN/100000000);
457 BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001 ").value(), COIN/100000000);
458 BOOST_CHECK_EQUAL(ParseMoney("0.00000001 ").value(), COIN/100000000);
459 BOOST_CHECK_EQUAL(ParseMoney(" 0.00000001").value(), COIN/100000000);
460
461 // Parsing amount that cannot be represented should fail
462 BOOST_CHECK(!ParseMoney("100000000.00"));
463 BOOST_CHECK(!ParseMoney("0.000000001"));
464
465 // Parsing empty string should fail
466 BOOST_CHECK(!ParseMoney(""));
467 BOOST_CHECK(!ParseMoney(" "));
468 BOOST_CHECK(!ParseMoney(" "));
469
470 // Parsing two numbers should fail
471 BOOST_CHECK(!ParseMoney(".."));
472 BOOST_CHECK(!ParseMoney("0..0"));
473 BOOST_CHECK(!ParseMoney("1 2"));
474 BOOST_CHECK(!ParseMoney(" 1 2 "));
475 BOOST_CHECK(!ParseMoney(" 1.2 3 "));
476 BOOST_CHECK(!ParseMoney(" 1 2.3 "));
477
478 // Embedded whitespace should fail
479 BOOST_CHECK(!ParseMoney(" -1 .2 "));
480 BOOST_CHECK(!ParseMoney(" 1 .2 "));
481 BOOST_CHECK(!ParseMoney(" +1 .2 "));
482
483 // Attempted 63 bit overflow should fail
484 BOOST_CHECK(!ParseMoney("92233720368.54775808"));
485
486 // Parsing negative amounts must fail
487 BOOST_CHECK(!ParseMoney("-1"));
488
489 // Parsing strings with embedded NUL characters should fail
490 BOOST_CHECK(!ParseMoney("\0-1"s));
491 BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR));
492 BOOST_CHECK(!ParseMoney("1\0"s));
493 }
494
495 BOOST_AUTO_TEST_CASE(util_IsHex)
496 {
497 BOOST_CHECK(IsHex("00"));
498 BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
499 BOOST_CHECK(IsHex("ff"));
500 BOOST_CHECK(IsHex("FF"));
501
502 BOOST_CHECK(!IsHex(""));
503 BOOST_CHECK(!IsHex("0"));
504 BOOST_CHECK(!IsHex("a"));
505 BOOST_CHECK(!IsHex("eleven"));
506 BOOST_CHECK(!IsHex("00xx00"));
507 BOOST_CHECK(!IsHex("0x0000"));
508 }
509
510 BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
511 {
512 SeedRandomForTest(SeedRand::ZEROS);
513 for (int mod=2;mod<11;mod++)
514 {
515 int mask = 1;
516 // Really rough binomial confidence approximation.
517 int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
518 //mask is 2^ceil(log2(mod))-1
519 while(mask<mod-1)mask=(mask<<1)+1;
520
521 int count = 0;
522 //How often does it get a zero from the uniform range [0,mod)?
523 for (int i = 0; i < 10000; i++) {
524 uint32_t rval;
525 do{
526 rval=m_rng.rand32()&mask;
527 }while(rval>=(uint32_t)mod);
528 count += rval==0;
529 }
530 BOOST_CHECK(count<=10000/mod+err);
531 BOOST_CHECK(count>=10000/mod-err);
532 }
533 }
534
535 BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
536 {
537 BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
538 BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
539 BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
540 BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
541 BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
542 BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
543 BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
544 }
545
546 /* Test strprintf formatting directives.
547 * Put a string before and after to ensure sanity of element sizes on stack. */
548 #define B "check_prefix"
549 #define E "check_postfix"
550 BOOST_AUTO_TEST_CASE(strprintf_numbers)
551 {
552 int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
553 uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
554 BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
555 BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
556 BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
557
558 size_t st = 12345678; /* unsigned size_t test value */
559 ssize_t sst = -12345678; /* signed size_t test value */
560 BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
561 BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
562 BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
563
564 ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
565 ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
566 BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
567 BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
568 BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
569 }
570 #undef B
571 #undef E
572
573 BOOST_AUTO_TEST_CASE(util_time_GetTime)
574 {
575 SetMockTime(111);
576 // Check that mock time does not change after a sleep
577 for (const auto& num_sleep : {0ms, 1ms}) {
578 UninterruptibleSleep(num_sleep);
579 BOOST_CHECK_EQUAL(111, GetTime()); // Deprecated time getter
580 BOOST_CHECK_EQUAL(111, Now<NodeSeconds>().time_since_epoch().count());
581 BOOST_CHECK_EQUAL(111, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()));
582 BOOST_CHECK_EQUAL(111, TicksSinceEpoch<SecondsDouble>(Now<NodeSeconds>()));
583 BOOST_CHECK_EQUAL(111, GetTime<std::chrono::seconds>().count());
584 BOOST_CHECK_EQUAL(111000, GetTime<std::chrono::milliseconds>().count());
585 BOOST_CHECK_EQUAL(111000, TicksSinceEpoch<std::chrono::milliseconds>(NodeClock::now()));
586 BOOST_CHECK_EQUAL(111000000, GetTime<std::chrono::microseconds>().count());
587 }
588
589 SetMockTime(0);
590 // Check that steady time and system time changes after a sleep
591 const auto steady_ms_0 = Now<SteadyMilliseconds>();
592 const auto steady_0 = std::chrono::steady_clock::now();
593 const auto ms_0 = GetTime<std::chrono::milliseconds>();
594 const auto us_0 = GetTime<std::chrono::microseconds>();
595 UninterruptibleSleep(1ms);
596 BOOST_CHECK(steady_ms_0 < Now<SteadyMilliseconds>());
597 BOOST_CHECK(steady_0 + 1ms <= std::chrono::steady_clock::now());
598 BOOST_CHECK(ms_0 < GetTime<std::chrono::milliseconds>());
599 BOOST_CHECK(us_0 < GetTime<std::chrono::microseconds>());
600 }
601
602 BOOST_AUTO_TEST_CASE(util_ticksseconds)
603 {
604 BOOST_CHECK_EQUAL(TicksSeconds(0s), 0);
605 BOOST_CHECK_EQUAL(TicksSeconds(1s), 1);
606 BOOST_CHECK_EQUAL(TicksSeconds(999ms), 0);
607 BOOST_CHECK_EQUAL(TicksSeconds(1000ms), 1);
608 BOOST_CHECK_EQUAL(TicksSeconds(1500ms), 1);
609 }
610
611 BOOST_AUTO_TEST_CASE(test_IsDigit)
612 {
613 BOOST_CHECK_EQUAL(IsDigit('0'), true);
614 BOOST_CHECK_EQUAL(IsDigit('1'), true);
615 BOOST_CHECK_EQUAL(IsDigit('8'), true);
616 BOOST_CHECK_EQUAL(IsDigit('9'), true);
617
618 BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
619 BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
620 BOOST_CHECK_EQUAL(IsDigit(0), false);
621 BOOST_CHECK_EQUAL(IsDigit(1), false);
622 BOOST_CHECK_EQUAL(IsDigit(8), false);
623 BOOST_CHECK_EQUAL(IsDigit(9), false);
624 }
625
626 /* Check for overflow */
627 template <typename T>
628 static void TestAddMatrixOverflow()
629 {
630 constexpr T MAXI{std::numeric_limits<T>::max()};
631 BOOST_CHECK(!CheckedAdd(T{1}, MAXI));
632 BOOST_CHECK(!CheckedAdd(MAXI, MAXI));
633 BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI));
634 BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(MAXI, MAXI));
635
636 BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value());
637 BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value());
638 BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value());
639 BOOST_CHECK_EQUAL(MAXI - 1, CheckedAdd(T{1}, MAXI - 2).value());
640 BOOST_CHECK_EQUAL(0, SaturatingAdd(T{0}, T{0}));
641 BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{0}, MAXI));
642 BOOST_CHECK_EQUAL(MAXI, SaturatingAdd(T{1}, MAXI - 1));
643 BOOST_CHECK_EQUAL(MAXI - 1, SaturatingAdd(T{1}, MAXI - 2));
644 }
645
646 /* Check for overflow or underflow */
647 template <typename T>
648 static void TestAddMatrix()
649 {
650 TestAddMatrixOverflow<T>();
651 constexpr T MINI{std::numeric_limits<T>::min()};
652 constexpr T MAXI{std::numeric_limits<T>::max()};
653 BOOST_CHECK(!CheckedAdd(T{-1}, MINI));
654 BOOST_CHECK(!CheckedAdd(MINI, MINI));
655 BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI));
656 BOOST_CHECK_EQUAL(MINI, SaturatingAdd(MINI, MINI));
657
658 BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value());
659 BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value());
660 BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value());
661 BOOST_CHECK_EQUAL(MINI + 1, CheckedAdd(T{-1}, MINI + 2).value());
662 BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{0}, MINI));
663 BOOST_CHECK_EQUAL(MINI, SaturatingAdd(T{-1}, MINI + 1));
664 BOOST_CHECK_EQUAL(MINI + 1, SaturatingAdd(T{-1}, MINI + 2));
665 BOOST_CHECK_EQUAL(-1, SaturatingAdd(MINI, MAXI));
666 }
667
668 BOOST_AUTO_TEST_CASE(util_overflow)
669 {
670 TestAddMatrixOverflow<unsigned>();
671 TestAddMatrix<signed>();
672 }
673
674 BOOST_AUTO_TEST_CASE(test_ParseInt32)
675 {
676 int32_t n;
677 // Valid values
678 BOOST_CHECK(ParseInt32("1234", nullptr));
679 BOOST_CHECK(ParseInt32("0", &n) && n == 0);
680 BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
681 BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
682 BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
683 BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
684 BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
685 BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
686 BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
687 BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
688 BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
689 // Invalid values
690 BOOST_CHECK(!ParseInt32("", &n));
691 BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
692 BOOST_CHECK(!ParseInt32("1 ", &n));
693 BOOST_CHECK(!ParseInt32("++1", &n));
694 BOOST_CHECK(!ParseInt32("+-1", &n));
695 BOOST_CHECK(!ParseInt32("-+1", &n));
696 BOOST_CHECK(!ParseInt32("--1", &n));
697 BOOST_CHECK(!ParseInt32("1a", &n));
698 BOOST_CHECK(!ParseInt32("aap", &n));
699 BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
700 BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
701 // Overflow and underflow
702 BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
703 BOOST_CHECK(!ParseInt32("2147483648", nullptr));
704 BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
705 BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
706 }
707
708 template <typename T>
709 static void RunToIntegralTests()
710 {
711 BOOST_CHECK(!ToIntegral<T>(STRING_WITH_EMBEDDED_NULL_CHAR));
712 BOOST_CHECK(!ToIntegral<T>(" 1"));
713 BOOST_CHECK(!ToIntegral<T>("1 "));
714 BOOST_CHECK(!ToIntegral<T>("1a"));
715 BOOST_CHECK(!ToIntegral<T>("1.1"));
716 BOOST_CHECK(!ToIntegral<T>("1.9"));
717 BOOST_CHECK(!ToIntegral<T>("+01.9"));
718 BOOST_CHECK(!ToIntegral<T>("-"));
719 BOOST_CHECK(!ToIntegral<T>("+"));
720 BOOST_CHECK(!ToIntegral<T>(" -1"));
721 BOOST_CHECK(!ToIntegral<T>("-1 "));
722 BOOST_CHECK(!ToIntegral<T>(" -1 "));
723 BOOST_CHECK(!ToIntegral<T>("+1"));
724 BOOST_CHECK(!ToIntegral<T>(" +1"));
725 BOOST_CHECK(!ToIntegral<T>(" +1 "));
726 BOOST_CHECK(!ToIntegral<T>("+-1"));
727 BOOST_CHECK(!ToIntegral<T>("-+1"));
728 BOOST_CHECK(!ToIntegral<T>("++1"));
729 BOOST_CHECK(!ToIntegral<T>("--1"));
730 BOOST_CHECK(!ToIntegral<T>(""));
731 BOOST_CHECK(!ToIntegral<T>("aap"));
732 BOOST_CHECK(!ToIntegral<T>("0x1"));
733 BOOST_CHECK(!ToIntegral<T>("-32482348723847471234"));
734 BOOST_CHECK(!ToIntegral<T>("32482348723847471234"));
735 }
736
737 BOOST_AUTO_TEST_CASE(test_ToIntegral)
738 {
739 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("1234").value(), 1'234);
740 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("0").value(), 0);
741 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("01234").value(), 1'234);
742 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000001234").value(), 1'234);
743 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000001234").value(), -1'234);
744 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("00000000000000000000").value(), 0);
745 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-00000000000000000000").value(), 0);
746 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1234").value(), -1'234);
747 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-1").value(), -1);
748
749 RunToIntegralTests<uint64_t>();
750 RunToIntegralTests<int64_t>();
751 RunToIntegralTests<uint32_t>();
752 RunToIntegralTests<int32_t>();
753 RunToIntegralTests<uint16_t>();
754 RunToIntegralTests<int16_t>();
755 RunToIntegralTests<uint8_t>();
756 RunToIntegralTests<int8_t>();
757
758 BOOST_CHECK(!ToIntegral<int64_t>("-9223372036854775809"));
759 BOOST_CHECK_EQUAL(ToIntegral<int64_t>("-9223372036854775808").value(), -9'223'372'036'854'775'807LL - 1LL);
760 BOOST_CHECK_EQUAL(ToIntegral<int64_t>("9223372036854775807").value(), 9'223'372'036'854'775'807);
761 BOOST_CHECK(!ToIntegral<int64_t>("9223372036854775808"));
762
763 BOOST_CHECK(!ToIntegral<uint64_t>("-1"));
764 BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("0").value(), 0U);
765 BOOST_CHECK_EQUAL(ToIntegral<uint64_t>("18446744073709551615").value(), 18'446'744'073'709'551'615ULL);
766 BOOST_CHECK(!ToIntegral<uint64_t>("18446744073709551616"));
767
768 BOOST_CHECK(!ToIntegral<int32_t>("-2147483649"));
769 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("-2147483648").value(), -2'147'483'648LL);
770 BOOST_CHECK_EQUAL(ToIntegral<int32_t>("2147483647").value(), 2'147'483'647);
771 BOOST_CHECK(!ToIntegral<int32_t>("2147483648"));
772
773 BOOST_CHECK(!ToIntegral<uint32_t>("-1"));
774 BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("0").value(), 0U);
775 BOOST_CHECK_EQUAL(ToIntegral<uint32_t>("4294967295").value(), 4'294'967'295U);
776 BOOST_CHECK(!ToIntegral<uint32_t>("4294967296"));
777
778 BOOST_CHECK(!ToIntegral<int16_t>("-32769"));
779 BOOST_CHECK_EQUAL(ToIntegral<int16_t>("-32768").value(), -32'768);
780 BOOST_CHECK_EQUAL(ToIntegral<int16_t>("32767").value(), 32'767);
781 BOOST_CHECK(!ToIntegral<int16_t>("32768"));
782
783 BOOST_CHECK(!ToIntegral<uint16_t>("-1"));
784 BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("0").value(), 0U);
785 BOOST_CHECK_EQUAL(ToIntegral<uint16_t>("65535").value(), 65'535U);
786 BOOST_CHECK(!ToIntegral<uint16_t>("65536"));
787
788 BOOST_CHECK(!ToIntegral<int8_t>("-129"));
789 BOOST_CHECK_EQUAL(ToIntegral<int8_t>("-128").value(), -128);
790 BOOST_CHECK_EQUAL(ToIntegral<int8_t>("127").value(), 127);
791 BOOST_CHECK(!ToIntegral<int8_t>("128"));
792
793 BOOST_CHECK(!ToIntegral<uint8_t>("-1"));
794 BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("0").value(), 0U);
795 BOOST_CHECK_EQUAL(ToIntegral<uint8_t>("255").value(), 255U);
796 BOOST_CHECK(!ToIntegral<uint8_t>("256"));
797 }
798
799 int64_t atoi64_legacy(const std::string& str)
800 {
801 return strtoll(str.c_str(), nullptr, 10);
802 }
803
804 BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
805 {
806 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1234"), 1'234);
807 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0"), 0);
808 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("01234"), 1'234);
809 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1234"), -1'234);
810 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" 1"), 1);
811 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1 "), 1);
812 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1a"), 1);
813 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.1"), 1);
814 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("1.9"), 1);
815 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+01.9"), 1);
816 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1"), -1);
817 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1"), -1);
818 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-1 "), -1);
819 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" -1 "), -1);
820 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+1"), 1);
821 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1"), 1);
822 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(" +1 "), 1);
823
824 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("+-1"), 0);
825 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-+1"), 0);
826 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("++1"), 0);
827 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("--1"), 0);
828 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>(""), 0);
829 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("aap"), 0);
830 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("0x1"), 0);
831 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-32482348723847471234"), -2'147'483'647 - 1);
832 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("32482348723847471234"), 2'147'483'647);
833
834 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775809"), -9'223'372'036'854'775'807LL - 1LL);
835 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("-9223372036854775808"), -9'223'372'036'854'775'807LL - 1LL);
836 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775807"), 9'223'372'036'854'775'807);
837 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>("9223372036854775808"), 9'223'372'036'854'775'807);
838
839 std::map<std::string, int64_t> atoi64_test_pairs = {
840 {"-9223372036854775809", std::numeric_limits<int64_t>::min()},
841 {"-9223372036854775808", -9'223'372'036'854'775'807LL - 1LL},
842 {"9223372036854775807", 9'223'372'036'854'775'807},
843 {"9223372036854775808", std::numeric_limits<int64_t>::max()},
844 {"+-", 0},
845 {"0x1", 0},
846 {"ox1", 0},
847 {"", 0},
848 };
849
850 for (const auto& pair : atoi64_test_pairs) {
851 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), pair.second);
852 }
853
854 // Ensure legacy compatibility with previous versions of Limenka's atoi64
855 for (const auto& pair : atoi64_test_pairs) {
856 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int64_t>(pair.first), atoi64_legacy(pair.first));
857 }
858
859 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("-1"), 0U);
860 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("0"), 0U);
861 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551615"), 18'446'744'073'709'551'615ULL);
862 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint64_t>("18446744073709551616"), 18'446'744'073'709'551'615ULL);
863
864 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483649"), -2'147'483'648LL);
865 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("-2147483648"), -2'147'483'648LL);
866 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483647"), 2'147'483'647);
867 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int32_t>("2147483648"), 2'147'483'647);
868
869 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("-1"), 0U);
870 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("0"), 0U);
871 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967295"), 4'294'967'295U);
872 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint32_t>("4294967296"), 4'294'967'295U);
873
874 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32769"), -32'768);
875 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("-32768"), -32'768);
876 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32767"), 32'767);
877 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int16_t>("32768"), 32'767);
878
879 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("-1"), 0U);
880 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("0"), 0U);
881 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65535"), 65'535U);
882 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint16_t>("65536"), 65'535U);
883
884 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-129"), -128);
885 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("-128"), -128);
886 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("127"), 127);
887 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<int8_t>("128"), 127);
888
889 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("-1"), 0U);
890 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("0"), 0U);
891 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("255"), 255U);
892 BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
893 }
894
895 BOOST_AUTO_TEST_CASE(test_ParseInt64)
896 {
897 int64_t n;
898 // Valid values
899 BOOST_CHECK(ParseInt64("1234", nullptr));
900 BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
901 BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
902 BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
903 BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
904 BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
905 BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
906 BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
907 BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
908 // Invalid values
909 BOOST_CHECK(!ParseInt64("", &n));
910 BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
911 BOOST_CHECK(!ParseInt64("1 ", &n));
912 BOOST_CHECK(!ParseInt64("1a", &n));
913 BOOST_CHECK(!ParseInt64("aap", &n));
914 BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
915 BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
916 // Overflow and underflow
917 BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
918 BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
919 BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
920 BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
921 }
922
923 BOOST_AUTO_TEST_CASE(test_ParseUInt8)
924 {
925 uint8_t n;
926 // Valid values
927 BOOST_CHECK(ParseUInt8("255", nullptr));
928 BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
929 BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
930 BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
931 BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
932 BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
933 BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
934 BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
935 // Invalid values
936 BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
937 BOOST_CHECK(!ParseUInt8("", &n));
938 BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
939 BOOST_CHECK(!ParseUInt8(" -1", &n));
940 BOOST_CHECK(!ParseUInt8("++1", &n));
941 BOOST_CHECK(!ParseUInt8("+-1", &n));
942 BOOST_CHECK(!ParseUInt8("-+1", &n));
943 BOOST_CHECK(!ParseUInt8("--1", &n));
944 BOOST_CHECK(!ParseUInt8("-1", &n));
945 BOOST_CHECK(!ParseUInt8("1 ", &n));
946 BOOST_CHECK(!ParseUInt8("1a", &n));
947 BOOST_CHECK(!ParseUInt8("aap", &n));
948 BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
949 BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
950 // Overflow and underflow
951 BOOST_CHECK(!ParseUInt8("-255", &n));
952 BOOST_CHECK(!ParseUInt8("256", &n));
953 BOOST_CHECK(!ParseUInt8("-123", &n));
954 BOOST_CHECK(!ParseUInt8("-123", nullptr));
955 BOOST_CHECK(!ParseUInt8("256", nullptr));
956 }
957
958 BOOST_AUTO_TEST_CASE(test_ParseUInt16)
959 {
960 uint16_t n;
961 // Valid values
962 BOOST_CHECK(ParseUInt16("1234", nullptr));
963 BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
964 BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
965 BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
966 BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
967 BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
968 BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
969 BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
970 // Invalid values
971 BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
972 BOOST_CHECK(!ParseUInt16("", &n));
973 BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
974 BOOST_CHECK(!ParseUInt16(" -1", &n));
975 BOOST_CHECK(!ParseUInt16("++1", &n));
976 BOOST_CHECK(!ParseUInt16("+-1", &n));
977 BOOST_CHECK(!ParseUInt16("-+1", &n));
978 BOOST_CHECK(!ParseUInt16("--1", &n));
979 BOOST_CHECK(!ParseUInt16("-1", &n));
980 BOOST_CHECK(!ParseUInt16("1 ", &n));
981 BOOST_CHECK(!ParseUInt16("1a", &n));
982 BOOST_CHECK(!ParseUInt16("aap", &n));
983 BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
984 BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
985 // Overflow and underflow
986 BOOST_CHECK(!ParseUInt16("-65535", &n));
987 BOOST_CHECK(!ParseUInt16("65536", &n));
988 BOOST_CHECK(!ParseUInt16("-123", &n));
989 BOOST_CHECK(!ParseUInt16("-123", nullptr));
990 BOOST_CHECK(!ParseUInt16("65536", nullptr));
991 }
992
993 BOOST_AUTO_TEST_CASE(test_ParseUInt32)
994 {
995 uint32_t n;
996 // Valid values
997 BOOST_CHECK(ParseUInt32("1234", nullptr));
998 BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
999 BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
1000 BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
1001 BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
1002 BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
1003 BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
1004 BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
1005 BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
1006 BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
1007 // Invalid values
1008 BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
1009 BOOST_CHECK(!ParseUInt32("", &n));
1010 BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
1011 BOOST_CHECK(!ParseUInt32(" -1", &n));
1012 BOOST_CHECK(!ParseUInt32("++1", &n));
1013 BOOST_CHECK(!ParseUInt32("+-1", &n));
1014 BOOST_CHECK(!ParseUInt32("-+1", &n));
1015 BOOST_CHECK(!ParseUInt32("--1", &n));
1016 BOOST_CHECK(!ParseUInt32("-1", &n));
1017 BOOST_CHECK(!ParseUInt32("1 ", &n));
1018 BOOST_CHECK(!ParseUInt32("1a", &n));
1019 BOOST_CHECK(!ParseUInt32("aap", &n));
1020 BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
1021 BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
1022 // Overflow and underflow
1023 BOOST_CHECK(!ParseUInt32("-2147483648", &n));
1024 BOOST_CHECK(!ParseUInt32("4294967296", &n));
1025 BOOST_CHECK(!ParseUInt32("-1234", &n));
1026 BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
1027 BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
1028 }
1029
1030 BOOST_AUTO_TEST_CASE(test_ParseUInt64)
1031 {
1032 uint64_t n;
1033 // Valid values
1034 BOOST_CHECK(ParseUInt64("1234", nullptr));
1035 BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
1036 BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
1037 BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
1038 BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
1039 BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
1040 BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
1041 BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
1042 // Invalid values
1043 BOOST_CHECK(!ParseUInt64("", &n));
1044 BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
1045 BOOST_CHECK(!ParseUInt64(" -1", &n));
1046 BOOST_CHECK(!ParseUInt64("1 ", &n));
1047 BOOST_CHECK(!ParseUInt64("1a", &n));
1048 BOOST_CHECK(!ParseUInt64("aap", &n));
1049 BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
1050 BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
1051 // Overflow and underflow
1052 BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
1053 BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
1054 BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
1055 BOOST_CHECK(!ParseUInt64("-2147483648", &n));
1056 BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
1057 BOOST_CHECK(!ParseUInt64("-1234", &n));
1058 }
1059
1060 BOOST_AUTO_TEST_CASE(test_FormatParagraph)
1061 {
1062 BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
1063 BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
1064 BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
1065 BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
1066 BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
1067 BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
1068 BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test");
1069
1070 // Make sure we don't indent a fully-new line following a too-long line ending
1071 BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n test\nabc");
1072
1073 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");
1074
1075 // Test wrap length is exact
1076 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");
1077 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");
1078 // Indent should be included in length of lines
1079 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");
1080
1081 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.");
1082 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.");
1083 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.");
1084 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.");
1085 }
1086
1087 BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
1088 {
1089 std::vector<std::string> comments;
1090 comments.emplace_back("comment1");
1091 std::vector<std::string> comments2;
1092 comments2.emplace_back("comment1");
1093 comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
1094 BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>(), true),std::string("/Test:9.99.0/"));
1095 BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments, true),std::string("/Test:9.99.0(comment1)/"));
1096 BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2, true),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
1097 }
1098
1099 BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
1100 {
1101 int64_t amount = 0;
1102 BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
1103 BOOST_CHECK_EQUAL(amount, 0LL);
1104 BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
1105 BOOST_CHECK_EQUAL(amount, 100000000LL);
1106 BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
1107 BOOST_CHECK_EQUAL(amount, 0LL);
1108 BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
1109 BOOST_CHECK_EQUAL(amount, -10000000LL);
1110 BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
1111 BOOST_CHECK_EQUAL(amount, 110000000LL);
1112 BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
1113 BOOST_CHECK_EQUAL(amount, 110000000LL);
1114 BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
1115 BOOST_CHECK_EQUAL(amount, 1100000000LL);
1116 BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
1117 BOOST_CHECK_EQUAL(amount, 11000000LL);
1118 BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
1119 BOOST_CHECK_EQUAL(amount, 100000000000LL);
1120 BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
1121 BOOST_CHECK_EQUAL(amount, -100000000000LL);
1122 BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
1123 BOOST_CHECK_EQUAL(amount, 1LL);
1124 BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
1125 BOOST_CHECK_EQUAL(amount, 1LL);
1126 BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
1127 BOOST_CHECK_EQUAL(amount, -1LL);
1128 BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
1129 BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
1130 BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
1131 BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
1132 BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
1133 BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
1134
1135 BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
1136 BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
1137 BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
1138 BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
1139 BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
1140 BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
1141 BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
1142 BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
1143 BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
1144 BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
1145 BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
1146 BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
1147 BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
1148 BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
1149 BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
1150 BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
1151 BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
1152 BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
1153 BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
1154 BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
1155 BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
1156 BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
1157 BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
1158 BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
1159 BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
1160 BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
1161 BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
1162
1163 // Test with 3 decimal places for fee rates in sat/vB.
1164 BOOST_CHECK(ParseFixedPoint("0.001", 3, &amount));
1165 BOOST_CHECK_EQUAL(amount, CAmount{1});
1166 BOOST_CHECK(!ParseFixedPoint("0.0009", 3, &amount));
1167 BOOST_CHECK(!ParseFixedPoint("31.00100001", 3, &amount));
1168 BOOST_CHECK(!ParseFixedPoint("31.0011", 3, &amount));
1169 BOOST_CHECK(!ParseFixedPoint("31.99999999", 3, &amount));
1170 BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));
1171 }
1172
1173 #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
1174 static constexpr char LockCommand = 'L';
1175 static constexpr char UnlockCommand = 'U';
1176 static constexpr char ExitCommand = 'X';
1177 enum : char {
1178 ResSuccess = 2, // Start with 2 to avoid accidental collision with common values 0 and 1
1179 ResErrorWrite,
1180 ResErrorLock,
1181 ResUnlockSuccess,
1182 };
1183
1184 [[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)
1185 {
1186 char ch;
1187 while (true) {
1188 int rv = read(fd, &ch, 1); // Wait for command
1189 assert(rv == 1);
1190 switch (ch) {
1191 case LockCommand:
1192 ch = [&] {
1193 switch (util::LockDirectory(dirname, lockname)) {
1194 case util::LockResult::Success: return ResSuccess;
1195 case util::LockResult::ErrorWrite: return ResErrorWrite;
1196 case util::LockResult::ErrorLock: return ResErrorLock;
1197 } // no default case, so the compiler can warn about missing cases
1198 assert(false);
1199 }();
1200 rv = write(fd, &ch, 1);
1201 assert(rv == 1);
1202 break;
1203 case UnlockCommand:
1204 ReleaseDirectoryLocks();
1205 ch = ResUnlockSuccess; // Always succeeds
1206 rv = write(fd, &ch, 1);
1207 assert(rv == 1);
1208 break;
1209 case ExitCommand:
1210 close(fd);
1211 exit(0);
1212 default:
1213 assert(0);
1214 }
1215 }
1216 }
1217 #endif
1218
1219 BOOST_AUTO_TEST_CASE(test_LockDirectory)
1220 {
1221 fs::path dirname = m_args.GetDataDirBase() / "lock_dir";
1222 const fs::path lockname = ".lock";
1223 #ifndef WIN32
1224 // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
1225 // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
1226 // at build-time of the boost library
1227 void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
1228
1229 // Fork another process for testing before creating the lock, so that we
1230 // won't fork while holding the lock (which might be undefined, and is not
1231 // relevant as test case as that is avoided with -daemonize).
1232 int fd[2];
1233 BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
1234 pid_t pid = fork();
1235 if (!pid) {
1236 BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
1237 TestOtherProcess(dirname, lockname, fd[0]);
1238 }
1239 BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
1240
1241 char ch;
1242 // Lock on non-existent directory should fail
1243 BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1244 BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1245 BOOST_CHECK_EQUAL(ch, ResErrorWrite);
1246 #endif
1247 // Lock on non-existent directory should fail
1248 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::ErrorWrite);
1249
1250 fs::create_directories(dirname);
1251
1252 // Probing lock on new directory should succeed
1253 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1254
1255 // Persistent lock on new directory should succeed
1256 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
1257
1258 // Another lock on the directory from the same thread should succeed
1259 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
1260
1261 // Another lock on the directory from a different thread within the same process should succeed
1262 util::LockResult threadresult;
1263 std::thread thr([&] { threadresult = util::LockDirectory(dirname, lockname); });
1264 thr.join();
1265 BOOST_CHECK_EQUAL(threadresult, util::LockResult::Success);
1266 #ifndef WIN32
1267 // Try to acquire lock in child process while we're holding it, this should fail.
1268 BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1269 BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1270 BOOST_CHECK_EQUAL(ch, ResErrorLock);
1271
1272 // Give up our lock
1273 ReleaseDirectoryLocks();
1274 // Probing lock from our side now should succeed, but not hold on to the lock.
1275 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1276
1277 // Try to acquire the lock in the child process, this should be successful.
1278 BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1279 BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1280 BOOST_CHECK_EQUAL(ch, ResSuccess);
1281
1282 // When we try to probe the lock now, it should fail.
1283 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::ErrorLock);
1284
1285 // Unlock the lock in the child process
1286 BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
1287 BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1288 BOOST_CHECK_EQUAL(ch, ResUnlockSuccess);
1289
1290 // When we try to probe the lock now, it should succeed.
1291 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1292
1293 // Re-lock the lock in the child process, then wait for it to exit, check
1294 // successful return. After that, we check that exiting the process
1295 // has released the lock as we would expect by probing it.
1296 int processstatus;
1297 BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1298 // The following line invokes the ~CNetCleanup dtor without
1299 // a paired SetupNetworking call. This is acceptable as long as
1300 // ~CNetCleanup is a no-op for non-Windows platforms.
1301 BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
1302 BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
1303 BOOST_CHECK_EQUAL(processstatus, 0);
1304 BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
1305
1306 // Restore SIGCHLD
1307 signal(SIGCHLD, old_handler);
1308 BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
1309 #endif
1310 // Clean up
1311 ReleaseDirectoryLocks();
1312 fs::remove_all(dirname);
1313 }
1314
1315 BOOST_AUTO_TEST_CASE(test_ToLower)
1316 {
1317 BOOST_CHECK_EQUAL(ToLower('@'), '@');
1318 BOOST_CHECK_EQUAL(ToLower('A'), 'a');
1319 BOOST_CHECK_EQUAL(ToLower('Z'), 'z');
1320 BOOST_CHECK_EQUAL(ToLower('['), '[');
1321 BOOST_CHECK_EQUAL(ToLower(0), 0);
1322 BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
1323
1324 BOOST_CHECK_EQUAL(ToLower(""), "");
1325 BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
1326 BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
1327 }
1328
1329 BOOST_AUTO_TEST_CASE(test_ToUpper)
1330 {
1331 BOOST_CHECK_EQUAL(ToUpper('`'), '`');
1332 BOOST_CHECK_EQUAL(ToUpper('a'), 'A');
1333 BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');
1334 BOOST_CHECK_EQUAL(ToUpper('{'), '{');
1335 BOOST_CHECK_EQUAL(ToUpper(0), 0);
1336 BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
1337
1338 BOOST_CHECK_EQUAL(ToUpper(""), "");
1339 BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
1340 BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
1341 }
1342
1343 BOOST_AUTO_TEST_CASE(test_Capitalize)
1344 {
1345 BOOST_CHECK_EQUAL(Capitalize(""), "");
1346 BOOST_CHECK_EQUAL(Capitalize("limenka"), "Limenka");
1347 BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
1348 }
1349
1350 static std::string SpanToStr(const Span<const char>& span)
1351 {
1352 return std::string(span.begin(), span.end());
1353 }
1354
1355 BOOST_AUTO_TEST_CASE(test_script_parsing)
1356 {
1357 using namespace script;
1358 std::string input;
1359 Span<const char> sp;
1360 bool success;
1361
1362 // Const(...): parse a constant, update span to skip it if successful
1363 input = "MilkToastHoney";
1364 sp = input;
1365 success = Const("", sp); // empty
1366 BOOST_CHECK(success);
1367 BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");
1368
1369 success = Const("Milk", sp);
1370 BOOST_CHECK(success);
1371 BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");
1372
1373 success = Const("Bread", sp);
1374 BOOST_CHECK(!success);
1375
1376 success = Const("Toast", sp);
1377 BOOST_CHECK(success);
1378 BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");
1379
1380 success = Const("Honeybadger", sp);
1381 BOOST_CHECK(!success);
1382
1383 success = Const("Honey", sp);
1384 BOOST_CHECK(success);
1385 BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1386
1387 // Func(...): parse a function call, update span to argument if successful
1388 input = "Foo(Bar(xy,z()))";
1389 sp = input;
1390
1391 success = Func("FooBar", sp);
1392 BOOST_CHECK(!success);
1393
1394 success = Func("Foo(", sp);
1395 BOOST_CHECK(!success);
1396
1397 success = Func("Foo", sp);
1398 BOOST_CHECK(success);
1399 BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");
1400
1401 success = Func("Bar", sp);
1402 BOOST_CHECK(success);
1403 BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()");
1404
1405 success = Func("xy", sp);
1406 BOOST_CHECK(!success);
1407
1408 // Expr(...): return expression that span begins with, update span to skip it
1409 Span<const char> result;
1410
1411 input = "(n*(n-1))/2";
1412 sp = input;
1413 result = Expr(sp);
1414 BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2");
1415 BOOST_CHECK_EQUAL(SpanToStr(sp), "");
1416
1417 input = "foo,bar";
1418 sp = input;
1419 result = Expr(sp);
1420 BOOST_CHECK_EQUAL(SpanToStr(result), "foo");
1421 BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar");
1422
1423 input = "(aaaaa,bbbbb()),c";
1424 sp = input;
1425 result = Expr(sp);
1426 BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())");
1427 BOOST_CHECK_EQUAL(SpanToStr(sp), ",c");
1428
1429 input = "xyz)foo";
1430 sp = input;
1431 result = Expr(sp);
1432 BOOST_CHECK_EQUAL(SpanToStr(result), "xyz");
1433 BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo");
1434
1435 input = "((a),(b),(c)),xxx";
1436 sp = input;
1437 result = Expr(sp);
1438 BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))");
1439 BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx");
1440
1441 // Split(...): split a string on every instance of sep, return vector
1442 std::vector<Span<const char>> results;
1443
1444 input = "xxx";
1445 results = Split(input, 'x');
1446 BOOST_CHECK_EQUAL(results.size(), 4U);
1447 BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1448 BOOST_CHECK_EQUAL(SpanToStr(results[1]), "");
1449 BOOST_CHECK_EQUAL(SpanToStr(results[2]), "");
1450 BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1451
1452 input = "one#two#three";
1453 results = Split(input, '-');
1454 BOOST_CHECK_EQUAL(results.size(), 1U);
1455 BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three");
1456
1457 input = "one#two#three";
1458 results = Split(input, '#');
1459 BOOST_CHECK_EQUAL(results.size(), 3U);
1460 BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one");
1461 BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two");
1462 BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three");
1463
1464 input = "*foo*bar*";
1465 results = Split(input, '*');
1466 BOOST_CHECK_EQUAL(results.size(), 4U);
1467 BOOST_CHECK_EQUAL(SpanToStr(results[0]), "");
1468 BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo");
1469 BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar");
1470 BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
1471 }
1472
1473 BOOST_AUTO_TEST_CASE(test_SplitString)
1474 {
1475 // Empty string.
1476 {
1477 std::vector<std::string> result = SplitString("", '-');
1478 BOOST_CHECK_EQUAL(result.size(), 1);
1479 BOOST_CHECK_EQUAL(result[0], "");
1480 }
1481
1482 // Empty items.
1483 {
1484 std::vector<std::string> result = SplitString("-", '-');
1485 BOOST_CHECK_EQUAL(result.size(), 2);
1486 BOOST_CHECK_EQUAL(result[0], "");
1487 BOOST_CHECK_EQUAL(result[1], "");
1488 }
1489
1490 // More empty items.
1491 {
1492 std::vector<std::string> result = SplitString("--", '-');
1493 BOOST_CHECK_EQUAL(result.size(), 3);
1494 BOOST_CHECK_EQUAL(result[0], "");
1495 BOOST_CHECK_EQUAL(result[1], "");
1496 BOOST_CHECK_EQUAL(result[2], "");
1497 }
1498
1499 // Separator is not present.
1500 {
1501 std::vector<std::string> result = SplitString("abc", '-');
1502 BOOST_CHECK_EQUAL(result.size(), 1);
1503 BOOST_CHECK_EQUAL(result[0], "abc");
1504 }
1505
1506 // Basic behavior.
1507 {
1508 std::vector<std::string> result = SplitString("a-b", '-');
1509 BOOST_CHECK_EQUAL(result.size(), 2);
1510 BOOST_CHECK_EQUAL(result[0], "a");
1511 BOOST_CHECK_EQUAL(result[1], "b");
1512 }
1513
1514 // Case-sensitivity of the separator.
1515 {
1516 std::vector<std::string> result = SplitString("AAA", 'a');
1517 BOOST_CHECK_EQUAL(result.size(), 1);
1518 BOOST_CHECK_EQUAL(result[0], "AAA");
1519 }
1520
1521 // multiple split characters
1522 {
1523 using V = std::vector<std::string>;
1524 BOOST_TEST(SplitString("a,b.c:d;e", ",;") == V({"a", "b.c:d", "e"}));
1525 BOOST_TEST(SplitString("a,b.c:d;e", ",;:.") == V({"a", "b", "c", "d", "e"}));
1526 BOOST_TEST(SplitString("a,b.c:d;e", "") == V({"a,b.c:d;e"}));
1527 BOOST_TEST(SplitString("aaa", "bcdefg") == V({"aaa"}));
1528 BOOST_TEST(SplitString("x\0a,b"s, "\0"s) == V({"x", "a,b"}));
1529 BOOST_TEST(SplitString("x\0a,b"s, '\0') == V({"x", "a,b"}));
1530 BOOST_TEST(SplitString("x\0a,b"s, "\0,"s) == V({"x", "a", "b"}));
1531 BOOST_TEST(SplitString("abcdefg", "bcd") == V({"a", "", "", "efg"}));
1532 }
1533 }
1534
1535 BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
1536 {
1537 // ASCII and UTF-8 must pass through unaltered.
1538 BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
1539 // Newlines must pass through unaltered.
1540 BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
1541 // Other control characters are escaped in C syntax.
1542 BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
1543 // Embedded NULL characters are escaped too.
1544 const std::string NUL("O\x00O", 3);
1545 BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
1546 }
1547
1548 namespace {
1549
1550 struct Tracker
1551 {
1552 //! Points to the original object (possibly itself) we moved/copied from
1553 const Tracker* origin;
1554 //! How many copies where involved between the original object and this one (moves are not counted)
1555 int copies{0};
1556
1557 Tracker() noexcept : origin(this) {}
1558 Tracker(const Tracker& t) noexcept : origin(t.origin), copies(t.copies + 1) {}
1559 Tracker(Tracker&& t) noexcept : origin(t.origin), copies(t.copies) {}
1560 Tracker& operator=(const Tracker& t) noexcept
1561 {
1562 if (this != &t) {
1563 origin = t.origin;
1564 copies = t.copies + 1;
1565 }
1566 return *this;
1567 }
1568 };
1569
1570 }
1571
1572 BOOST_AUTO_TEST_CASE(test_tracked_vector)
1573 {
1574 Tracker t1;
1575 Tracker t2;
1576 Tracker t3;
1577
1578 BOOST_CHECK(t1.origin == &t1);
1579 BOOST_CHECK(t2.origin == &t2);
1580 BOOST_CHECK(t3.origin == &t3);
1581
1582 auto v1 = Vector(t1);
1583 BOOST_CHECK_EQUAL(v1.size(), 1U);
1584 BOOST_CHECK(v1[0].origin == &t1);
1585 BOOST_CHECK_EQUAL(v1[0].copies, 1);
1586
1587 auto v2 = Vector(std::move(t2));
1588 BOOST_CHECK_EQUAL(v2.size(), 1U);
1589 BOOST_CHECK(v2[0].origin == &t2); // NOLINT(*-use-after-move)
1590 BOOST_CHECK_EQUAL(v2[0].copies, 0);
1591
1592 auto v3 = Vector(t1, std::move(t2));
1593 BOOST_CHECK_EQUAL(v3.size(), 2U);
1594 BOOST_CHECK(v3[0].origin == &t1);
1595 BOOST_CHECK(v3[1].origin == &t2); // NOLINT(*-use-after-move)
1596 BOOST_CHECK_EQUAL(v3[0].copies, 1);
1597 BOOST_CHECK_EQUAL(v3[1].copies, 0);
1598
1599 auto v4 = Vector(std::move(v3[0]), v3[1], std::move(t3));
1600 BOOST_CHECK_EQUAL(v4.size(), 3U);
1601 BOOST_CHECK(v4[0].origin == &t1);
1602 BOOST_CHECK(v4[1].origin == &t2);
1603 BOOST_CHECK(v4[2].origin == &t3); // NOLINT(*-use-after-move)
1604 BOOST_CHECK_EQUAL(v4[0].copies, 1);
1605 BOOST_CHECK_EQUAL(v4[1].copies, 1);
1606 BOOST_CHECK_EQUAL(v4[2].copies, 0);
1607
1608 auto v5 = Cat(v1, v4);
1609 BOOST_CHECK_EQUAL(v5.size(), 4U);
1610 BOOST_CHECK(v5[0].origin == &t1);
1611 BOOST_CHECK(v5[1].origin == &t1);
1612 BOOST_CHECK(v5[2].origin == &t2);
1613 BOOST_CHECK(v5[3].origin == &t3);
1614 BOOST_CHECK_EQUAL(v5[0].copies, 2);
1615 BOOST_CHECK_EQUAL(v5[1].copies, 2);
1616 BOOST_CHECK_EQUAL(v5[2].copies, 2);
1617 BOOST_CHECK_EQUAL(v5[3].copies, 1);
1618
1619 auto v6 = Cat(std::move(v1), v3);
1620 BOOST_CHECK_EQUAL(v6.size(), 3U);
1621 BOOST_CHECK(v6[0].origin == &t1);
1622 BOOST_CHECK(v6[1].origin == &t1);
1623 BOOST_CHECK(v6[2].origin == &t2);
1624 BOOST_CHECK_EQUAL(v6[0].copies, 1);
1625 BOOST_CHECK_EQUAL(v6[1].copies, 2);
1626 BOOST_CHECK_EQUAL(v6[2].copies, 1);
1627
1628 auto v7 = Cat(v2, std::move(v4));
1629 BOOST_CHECK_EQUAL(v7.size(), 4U);
1630 BOOST_CHECK(v7[0].origin == &t2);
1631 BOOST_CHECK(v7[1].origin == &t1);
1632 BOOST_CHECK(v7[2].origin == &t2);
1633 BOOST_CHECK(v7[3].origin == &t3);
1634 BOOST_CHECK_EQUAL(v7[0].copies, 1);
1635 BOOST_CHECK_EQUAL(v7[1].copies, 1);
1636 BOOST_CHECK_EQUAL(v7[2].copies, 1);
1637 BOOST_CHECK_EQUAL(v7[3].copies, 0);
1638
1639 auto v8 = Cat(std::move(v2), std::move(v3));
1640 BOOST_CHECK_EQUAL(v8.size(), 3U);
1641 BOOST_CHECK(v8[0].origin == &t2);
1642 BOOST_CHECK(v8[1].origin == &t1);
1643 BOOST_CHECK(v8[2].origin == &t2);
1644 BOOST_CHECK_EQUAL(v8[0].copies, 0);
1645 BOOST_CHECK_EQUAL(v8[1].copies, 1);
1646 BOOST_CHECK_EQUAL(v8[2].copies, 0);
1647 }
1648
1649 BOOST_AUTO_TEST_CASE(message_sign)
1650 {
1651 const std::array<unsigned char, 32> privkey_bytes = {
1652 // just some random data
1653 // derived address from this private key: 15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs
1654 0xD9, 0x7F, 0x51, 0x08, 0xF1, 0x1C, 0xDA, 0x6E,
1655 0xEE, 0xBA, 0xAA, 0x42, 0x0F, 0xEF, 0x07, 0x26,
1656 0xB1, 0xF8, 0x98, 0x06, 0x0B, 0x98, 0x48, 0x9F,
1657 0xA3, 0x09, 0x84, 0x63, 0xC0, 0x03, 0x28, 0x66
1658 };
1659
1660 const std::string message = "Trust no one";
1661
1662 const std::string expected_signature =
1663 "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=";
1664
1665 CKey privkey;
1666 std::string generated_signature;
1667
1668 BOOST_REQUIRE_MESSAGE(!privkey.IsValid(),
1669 "Confirm the private key is invalid");
1670
1671 BOOST_CHECK_MESSAGE(!MessageSign(privkey, message, generated_signature),
1672 "Sign with an invalid private key");
1673
1674 privkey.Set(privkey_bytes.begin(), privkey_bytes.end(), true);
1675
1676 BOOST_REQUIRE_MESSAGE(privkey.IsValid(),
1677 "Confirm the private key is valid");
1678
1679 BOOST_CHECK_MESSAGE(MessageSign(privkey, message, generated_signature),
1680 "Sign with a valid private key");
1681
1682 BOOST_CHECK_EQUAL(expected_signature, generated_signature);
1683
1684 // BIP-322 tests
1685 // (no signing done here, as we need a wallet to do so)
1686
1687 auto pubkey = privkey.GetPubKey();
1688 MessageVerificationResult mvr{MessageVerificationResult::OK};
1689
1690 // LEGACY pubkey type
1691 auto dest_legacy = GetDestinationForKey(pubkey, OutputType::LEGACY);
1692 BOOST_CHECK_EQUAL("15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs", EncodeDestination(dest_legacy));
1693 auto txs_legacy = BIP322Txs::Create(dest_legacy, message, mvr);
1694 if (!txs_legacy || mvr != MessageVerificationResult::OK) {
1695 BOOST_FAIL("Failed to create BIP-322 txs for legacy address");
1696 }
1697
1698 // P2SH_SEGWIT pubkey type
1699 auto dest_p2sh_segwit = GetDestinationForKey(pubkey, OutputType::P2SH_SEGWIT);
1700 BOOST_CHECK_EQUAL("35uijJkf4rcCnGzEZsn12YJenTHToDKpr2", EncodeDestination(dest_p2sh_segwit));
1701 auto txs_p2sh_segwit = BIP322Txs::Create(dest_p2sh_segwit, message, mvr);
1702 if (!txs_p2sh_segwit || mvr != MessageVerificationResult::OK) {
1703 BOOST_FAIL("Failed to create BIP-322 txs for p2sh-segwit address");
1704 }
1705
1706 // BECH32
1707 auto dest_bech32 = GetDestinationForKey(pubkey, OutputType::BECH32);
1708 BOOST_CHECK_EQUAL("bc1q9cy7s7nmzah0m6mt2ftmu6x723esjxqkkl4wsw", EncodeDestination(dest_bech32));
1709 auto txs_bech32 = BIP322Txs::Create(dest_bech32, message, mvr);
1710 if (!txs_bech32 || mvr != MessageVerificationResult::OK) {
1711 BOOST_FAIL("Failed to create BIP-322 txs for bech32 address");
1712 }
1713
1714 // TODO: BECH32M
1715 }
1716
1717 BOOST_AUTO_TEST_CASE(message_verify)
1718 {
1719 BOOST_CHECK_EQUAL(
1720 MessageVerify(
1721 "invalid address",
1722 "AA==",
1723 "message too"),
1724 MessageVerificationResult::ERR_INVALID_ADDRESS);
1725
1726 BOOST_CHECK_EQUAL(
1727 MessageVerify(
1728 "3B5fQsEXEaV8v6U3ejYc8XaKXAkyQj2MjV",
1729 "AA==",
1730 "message too"),
1731 MessageVerificationResult::ERR_INVALID /* ERR_ADDRESS_NO_KEY */);
1732
1733 BOOST_CHECK_EQUAL(
1734 MessageVerify(
1735 "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
1736 "invalid signature, not in base64 encoding",
1737 "message should be irrelevant"),
1738 MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
1739
1740 BOOST_CHECK_EQUAL(
1741 MessageVerify(
1742 "1KqbBpLy5FARmTPD4VZnDDpYjkUvkr82Pm",
1743 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1744 "message should be irrelevant"),
1745 MessageVerificationResult::ERR_INVALID /* ERR_PUBKEY_NOT_RECOVERED */);
1746
1747 BOOST_CHECK_EQUAL(
1748 MessageVerify(
1749 "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
1750 "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
1751 "I never signed this"),
1752 MessageVerificationResult::ERR_NOT_SIGNED);
1753
1754 BOOST_CHECK_EQUAL(
1755 MessageVerify(
1756 "15CRxFdyRpGZLW9w8HnHvVduizdL5jKNbs",
1757 "IPojfrX2dfPnH26UegfbGQQLrdK844DlHq5157/P6h57WyuS/Qsl+h/WSVGDF4MUi4rWSswW38oimDYfNNUBUOk=",
1758 "Trust no one"),
1759 MessageVerificationResult::OK);
1760
1761 BOOST_CHECK_EQUAL(
1762 MessageVerify(
1763 "11canuhp9X2NocwCq7xNrQYTmUgZAnLK3",
1764 "IIcaIENoYW5jZWxsb3Igb24gYnJpbmsgb2Ygc2Vjb25kIGJhaWxvdXQgZm9yIGJhbmtzIAaHRtbCeDZINyavx14=",
1765 "Trust me"),
1766 MessageVerificationResult::OK);
1767
1768 // BIP-322 tests
1769
1770 // privkey: L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k
1771
1772 BOOST_CHECK_EQUAL(
1773 MessageVerify(
1774 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1775 "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1776 ""),
1777 MessageVerificationResult::OK);
1778
1779 BOOST_CHECK_EQUAL(
1780 MessageVerify(
1781 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1782 "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1783 "Hello World"),
1784 MessageVerificationResult::OK);
1785
1786 // BIP322 signature created using buidl-python library with same parameters as test on line 2596
1787 BOOST_CHECK_EQUAL(
1788 MessageVerify(
1789 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1790 "AkgwRQIhAOzyynlqt93lOKJr+wmmxIens//zPzl9tqIOua93wO6MAiBi5n5EyAcPScOjf1lAqIUIQtr3zKNeavYabHyR8eGhowEhAsfxIAMZZEKUPYWI4BruhAQjzFT8FSFSajuFwrDL1Yhy",
1791 "Hello World"),
1792 MessageVerificationResult::OK);
1793
1794 // 2-of-3 p2sh multisig BIP322 signature (created with the buidl-python library)
1795 // Keys are defined as (HDRootWIF, bip322_path)
1796 // Key1 (L4DksdGZ4KQJfcLHD5Dv25fu8Rxyv7hHi2RjZR4TYzr8c6h9VNrp, m/45'/0/0/1)
1797 // Key2 (KzSRqnCVwjzY8id2X5oHEJWXkSHwKUYaAXusjwgkES8BuQPJnPNu, m/45'/0/0/3)
1798 // Key3 (L1zt9Rw7HrU7jaguMbVzhiX8ffuVkmMis5wLHddXYuHWYf8u8uRj, m/45'/0/0/6)
1799 // BIP322 includes signs from Key2 and Key3
1800 BOOST_CHECK_EQUAL(
1801 MessageVerify(
1802 "3LnYoUkFrhyYP3V7rq3mhpwALz1XbCY9Uq",
1803 "AAAAAAHNcfHaNfl8f/+ZC2gTr8aF+0KgppYjKM94egaNm/u1ZAAAAAD8AEcwRAIhAJ6hdj61vLDP+aFa30qUZQmrbBfE0kiOObYvt5nqPSxsAh9IrOKFwflfPRUcQ/5e0REkdFHVP2GGdUsMgDet+sNlAUcwRAIgH3eW/VyFDoXvCasd8qxgwj5NDVo0weXvM6qyGXLCR5YCIEwjbEV6fS6RWP6QsKOcMwvlGr1/SgdCC6pW4eH87/YgAUxpUiECKJfGy28imLcuAeNBLHCNv3NRP5jnJwFDNRXCYNY/vJ4hAv1RQtaZs7+vKqQeWl2rb/jd/gMxkEjUnjZdDGPDZkMLIQL65cH2X5O7LujjTLDL2l8Pxy0Y2UUR99u1qCfjdz7dklOuAAAAAAEAAAAAAAAAAAFqAAAAAA==",
1804 "This will be a p2sh 2-of-3 multisig BIP 322 signed message"),
1805 MessageVerificationResult::OK);
1806
1807 // 3-of-3 p2wsh multisig BIP322 signature (created with the buidl-python library)
1808 // Keys are defined as (HDRootWIF, bip322_path)
1809 // Key1 (L4DksdGZ4KQJfcLHD5Dv25fu8Rxyv7hHi2RjZR4TYzr8c6h9VNrp, m/45'/0/0/6)
1810 // Key2 (KzSRqnCVwjzY8id2X5oHEJWXkSHwKUYaAXusjwgkES8BuQPJnPNu, m/45'/0/0/9)
1811 // Key3 (L1zt9Rw7HrU7jaguMbVzhiX8ffuVkmMis5wLHddXYuHWYf8u8uRj, m/45'/0/0/11)
1812 BOOST_CHECK_EQUAL(
1813 MessageVerify(
1814 "bc1qlqtuzpmazp2xmcutlwv0qvggdvem8vahkc333usey4gskug8nutsz53msw", "BQBIMEUCIQDQoXvGKLH58exuujBOta+7+GN7vi0lKwiQxzBpuNuXuAIgIE0XYQlFDOfxbegGYYzlf+tqegleAKE6SXYIa1U+uCcBRzBEAiATegywVl6GWrG9jJuPpNwtgHKyVYCX2yfuSSDRFATAaQIgTLlU6reLQsSIrQSF21z3PtUO2yAUseUWGZqRUIE7VKoBSDBFAiEAgxtpidsU0Z4u/+5RB9cyeQtoCW5NcreLJmWXZ8kXCZMCIBR1sXoEinhZE4CF9P9STGIcMvCuZjY6F5F0XTVLj9SjAWlTIQP3dyWvTZjUENWJowMWBsQrrXCUs20Gu5YF79CG5Ga0XSEDwqI5GVBOuFkFzQOGH5eTExSAj2Z/LDV/hbcvAPQdlJMhA17FuuJd+4wGuj+ZbVxEsFapTKAOwyhfw9qpch52JKxbU64=",
1815 "This will be a p2wsh 3-of-3 multisig BIP 322 signed message"),
1816 MessageVerificationResult::OK);
1817
1818 // Single key p2tr BIP322 signature (created with the buidl-python library)
1819 // PrivateKeyWIF L3VFeEujGtevx9w18HD1fhRbCH67Az2dpCymeRE1SoPK6XQtaN2k
1820 BOOST_CHECK_EQUAL(
1821 MessageVerify(
1822 "bc1ppv609nr0vr25u07u95waq5lucwfm6tde4nydujnu8npg4q75mr5sxq8lt3",
1823 "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==",
1824 "Hello World"),
1825 MessageVerificationResult::OK);
1826
1827 // Same p2tr BIP322 signature as above (created with the buidl-python library)
1828 // Signature should not verify against the message
1829 BOOST_CHECK_EQUAL(
1830 MessageVerify(
1831 "bc1ppv609nr0vr25u07u95waq5lucwfm6tde4nydujnu8npg4q75mr5sxq8lt3",
1832 "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==",
1833 "Hello World - This should fail"),
1834 MessageVerificationResult::ERR_INVALID);
1835
1836 // wrong address
1837
1838 BOOST_CHECK_EQUAL(
1839 MessageVerify(
1840 "bc1qkecg9ly2xwxqgdy9egpuy87qc9x26smpts562s",
1841 "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1842 ""),
1843 MessageVerificationResult::ERR_INVALID);
1844
1845 BOOST_CHECK_EQUAL(
1846 MessageVerify(
1847 "bc1qkecg9ly2xwxqgdy9egpuy87qc9x26smpts562s",
1848 "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1849 "Hello World"),
1850 MessageVerificationResult::ERR_INVALID);
1851
1852 // wrong signature / message (signatures swapped)
1853
1854 BOOST_CHECK_EQUAL(
1855 MessageVerify(
1856 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1857 "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1858 ""),
1859 MessageVerificationResult::ERR_INVALID);
1860
1861 BOOST_CHECK_EQUAL(
1862 MessageVerify(
1863 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1864 "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1865 "Hello World"),
1866 MessageVerificationResult::ERR_INVALID);
1867
1868 // invalid address
1869
1870 BOOST_CHECK_EQUAL(
1871 MessageVerify(
1872 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx1l",
1873 "AkcwRAIgM2gBAQqvZX15ZiysmKmQpDrG83avLIT492QBzLnQIxYCIBaTpOaD20qRlEylyxFSeEA2ba9YOixpX8z46TSDtS40ASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=",
1874 ""),
1875 MessageVerificationResult::ERR_INVALID_ADDRESS);
1876
1877 // malformed signature
1878
1879 BOOST_CHECK_EQUAL(
1880 MessageVerify(
1881 "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l",
1882 "AkcwRAIgClVQ8S9yX1h8YThlGElD9lOrQbOwbFDjkYb0ebfiq+oCIDHgb/X9WNalNNtqTXb465ufbv9JuLxcJf8qi7DP6yOXASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI",
1883 ""),
1884 MessageVerificationResult::ERR_MALFORMED_SIGNATURE);
1885 }
1886
1887 BOOST_AUTO_TEST_CASE(message_hash)
1888 {
1889 const std::string unsigned_tx = "...";
1890 const std::string prefixed_message =
1891 std::string(1, (char)MESSAGE_MAGIC.length()) +
1892 MESSAGE_MAGIC +
1893 std::string(1, (char)unsigned_tx.length()) +
1894 unsigned_tx;
1895
1896 const uint256 signature_hash = Hash(unsigned_tx);
1897 const uint256 message_hash1 = Hash(prefixed_message);
1898 const uint256 message_hash2 = MessageHash(unsigned_tx, MessageSignatureFormat::LEGACY);
1899
1900 BOOST_CHECK_EQUAL(message_hash1, message_hash2);
1901 BOOST_CHECK_NE(message_hash1, signature_hash);
1902
1903 // BIP-322 tests
1904
1905 const uint256 signature_hash_0x = MessageHash("", MessageSignatureFormat::FULL);
1906 const uint256 signature_hash_Hello_World = MessageHash("Hello World", MessageSignatureFormat::FULL);
1907
1908 std::vector<unsigned char> vec(signature_hash_0x.begin(), signature_hash_0x.end());
1909 BOOST_CHECK_EQUAL("c90c269c4f8fcbe6880f72a721ddfbf1914268a794cbb21cfafee13770ae19f1", HexStr(vec));
1910 vec = std::vector<unsigned char>(signature_hash_Hello_World.begin(), signature_hash_Hello_World.end());
1911 BOOST_CHECK_EQUAL("f0eb03b1a75ac6d9847f55c624a99169b5dccba2a31f5b23bea77ba270de0a7a", HexStr(vec));
1912 }
1913
1914 BOOST_AUTO_TEST_CASE(remove_prefix)
1915 {
1916 BOOST_CHECK_EQUAL(RemovePrefix("./common/system.h", "./"), "common/system.h");
1917 BOOST_CHECK_EQUAL(RemovePrefixView("foo", "foo"), "");
1918 BOOST_CHECK_EQUAL(RemovePrefix("foo", "fo"), "o");
1919 BOOST_CHECK_EQUAL(RemovePrefixView("foo", "f"), "oo");
1920 BOOST_CHECK_EQUAL(RemovePrefix("foo", ""), "foo");
1921 BOOST_CHECK_EQUAL(RemovePrefixView("fo", "foo"), "fo");
1922 BOOST_CHECK_EQUAL(RemovePrefix("f", "foo"), "f");
1923 BOOST_CHECK_EQUAL(RemovePrefixView("", "foo"), "");
1924 BOOST_CHECK_EQUAL(RemovePrefix("", ""), "");
1925 }
1926
1927 BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
1928 {
1929 auto noop = ByteUnit::NOOP;
1930
1931 // no multiplier
1932 BOOST_CHECK_EQUAL(ParseByteUnits("1", noop).value(), 1);
1933 BOOST_CHECK_EQUAL(ParseByteUnits("0", noop).value(), 0);
1934
1935 BOOST_CHECK_EQUAL(ParseByteUnits("1k", noop).value(), 1000ULL);
1936 BOOST_CHECK_EQUAL(ParseByteUnits("1K", noop).value(), 1ULL << 10);
1937
1938 BOOST_CHECK_EQUAL(ParseByteUnits("2m", noop).value(), 2'000'000ULL);
1939 BOOST_CHECK_EQUAL(ParseByteUnits("2M", noop).value(), 2ULL << 20);
1940
1941 BOOST_CHECK_EQUAL(ParseByteUnits("3g", noop).value(), 3'000'000'000ULL);
1942 BOOST_CHECK_EQUAL(ParseByteUnits("3G", noop).value(), 3ULL << 30);
1943
1944 BOOST_CHECK_EQUAL(ParseByteUnits("4t", noop).value(), 4'000'000'000'000ULL);
1945 BOOST_CHECK_EQUAL(ParseByteUnits("4T", noop).value(), 4ULL << 40);
1946
1947 // check default multiplier
1948 BOOST_CHECK_EQUAL(ParseByteUnits("5", ByteUnit::K).value(), 5ULL << 10);
1949
1950 // NaN
1951 BOOST_CHECK(!ParseByteUnits("", noop));
1952 BOOST_CHECK(!ParseByteUnits("foo", noop));
1953
1954 // whitespace
1955 BOOST_CHECK(!ParseByteUnits("123m ", noop));
1956 BOOST_CHECK(!ParseByteUnits(" 123m", noop));
1957
1958 // no +-
1959 BOOST_CHECK(!ParseByteUnits("-123m", noop));
1960 BOOST_CHECK(!ParseByteUnits("+123m", noop));
1961
1962 // zero padding
1963 BOOST_CHECK_EQUAL(ParseByteUnits("020M", noop).value(), 20ULL << 20);
1964
1965 // fractions not allowed
1966 BOOST_CHECK(!ParseByteUnits("0.5T", noop));
1967
1968 // overflow
1969 BOOST_CHECK(!ParseByteUnits("18446744073709551615g", noop));
1970
1971 // invalid unit
1972 BOOST_CHECK(!ParseByteUnits("1x", noop));
1973 }
1974
1975 BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
1976 {
1977 fs::path tmpfolder = m_args.GetDataDirBase();
1978 fs::path tmpfile = tmpfolder / "read_binary.dat";
1979 std::string expected_text;
1980 for (int i = 0; i < 30; i++) {
1981 expected_text += "0123456789";
1982 }
1983 {
1984 std::ofstream file{tmpfile};
1985 file << expected_text;
1986 }
1987 {
1988 // read all contents in file
1989 auto [valid, text] = ReadBinaryFile(tmpfile);
1990 BOOST_CHECK(valid);
1991 BOOST_CHECK_EQUAL(text, expected_text);
1992 }
1993 {
1994 // read half contents in file
1995 auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
1996 BOOST_CHECK(valid);
1997 BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
1998 }
1999 {
2000 // read from non-existent file
2001 fs::path invalid_file = tmpfolder / "invalid_binary.dat";
2002 auto [valid, text] = ReadBinaryFile(invalid_file);
2003 BOOST_CHECK(!valid);
2004 BOOST_CHECK(text.empty());
2005 }
2006 }
2007
2008 BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
2009 {
2010 fs::path tmpfolder = m_args.GetDataDirBase();
2011 fs::path tmpfile = tmpfolder / "write_binary.dat";
2012 std::string expected_text = "limenka";
2013 auto valid = WriteBinaryFile(tmpfile, expected_text);
2014 std::string actual_text;
2015 std::ifstream file{tmpfile};
2016 file >> actual_text;
2017 BOOST_CHECK(valid);
2018 BOOST_CHECK_EQUAL(actual_text, expected_text);
2019 }
2020
2021 BOOST_AUTO_TEST_CASE(clearshrink_test)
2022 {
2023 {
2024 std::vector<uint8_t> v = {1, 2, 3};
2025 ClearShrink(v);
2026 BOOST_CHECK_EQUAL(v.size(), 0);
2027 BOOST_CHECK_EQUAL(v.capacity(), 0);
2028 }
2029
2030 {
2031 std::vector<bool> v = {false, true, false, false, true, true};
2032 ClearShrink(v);
2033 BOOST_CHECK_EQUAL(v.size(), 0);
2034 BOOST_CHECK_EQUAL(v.capacity(), 0);
2035 }
2036
2037 {
2038 std::deque<int> v = {1, 3, 3, 7};
2039 ClearShrink(v);
2040 BOOST_CHECK_EQUAL(v.size(), 0);
2041 // std::deque has no capacity() we can observe.
2042 }
2043 }
2044
2045 template <typename T>
2046 void TestCheckedLeftShift()
2047 {
2048 constexpr auto MAX{std::numeric_limits<T>::max()};
2049
2050 // Basic operations
2051 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(0, 1), 0);
2052 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(0, 127), 0);
2053 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(1, 1), 2);
2054 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(2, 2), 8);
2055 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(MAX >> 1, 1), MAX - 1);
2056
2057 // Max left shift
2058 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(1, std::numeric_limits<T>::digits - 1), MAX / 2 + 1);
2059
2060 // Overflow cases
2061 BOOST_CHECK(!CheckedLeftShift<T>((MAX >> 1) + 1, 1));
2062 BOOST_CHECK(!CheckedLeftShift<T>(MAX, 1));
2063 BOOST_CHECK(!CheckedLeftShift<T>(1, std::numeric_limits<T>::digits));
2064 BOOST_CHECK(!CheckedLeftShift<T>(1, std::numeric_limits<T>::digits + 1));
2065
2066 if constexpr (std::is_signed_v<T>) {
2067 constexpr auto MIN{std::numeric_limits<T>::min()};
2068 // Negative input
2069 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(-1, 1), -2);
2070 BOOST_CHECK_EQUAL(CheckedLeftShift<T>((MIN >> 2), 1), MIN / 2);
2071 BOOST_CHECK_EQUAL(CheckedLeftShift<T>((MIN >> 1) + 1, 1), MIN + 2);
2072 BOOST_CHECK_EQUAL(CheckedLeftShift<T>(MIN >> 1, 1), MIN);
2073 // Overflow negative
2074 BOOST_CHECK(!CheckedLeftShift<T>((MIN >> 1) - 1, 1));
2075 BOOST_CHECK(!CheckedLeftShift<T>(MIN >> 1, 2));
2076 BOOST_CHECK(!CheckedLeftShift<T>(-1, 100));
2077 }
2078 }
2079
2080 template <typename T>
2081 void TestSaturatingLeftShift()
2082 {
2083 constexpr auto MAX{std::numeric_limits<T>::max()};
2084
2085 // Basic operations
2086 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(0, 1), 0);
2087 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(0, 127), 0);
2088 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, 1), 2);
2089 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(2, 2), 8);
2090 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MAX >> 1, 1), MAX - 1);
2091
2092 // Max left shift
2093 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits - 1), MAX / 2 + 1);
2094
2095 // Saturation cases
2096 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MAX >> 1) + 1, 1), MAX);
2097 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MAX, 1), MAX);
2098 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits), MAX);
2099 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(1, std::numeric_limits<T>::digits + 1), MAX);
2100
2101 if constexpr (std::is_signed_v<T>) {
2102 constexpr auto MIN{std::numeric_limits<T>::min()};
2103 // Negative input
2104 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(-1, 1), -2);
2105 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 2), 1), MIN / 2);
2106 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 1) + 1, 1), MIN + 2);
2107 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MIN >> 1, 1), MIN);
2108 // Saturation negative
2109 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>((MIN >> 1) - 1, 1), MIN);
2110 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(MIN >> 1, 2), MIN);
2111 BOOST_CHECK_EQUAL(SaturatingLeftShift<T>(-1, 100), MIN);
2112 }
2113 }
2114
2115 BOOST_AUTO_TEST_CASE(checked_left_shift_test)
2116 {
2117 TestCheckedLeftShift<uint8_t>();
2118 TestCheckedLeftShift<int8_t>();
2119 TestCheckedLeftShift<size_t>();
2120 TestCheckedLeftShift<uint64_t>();
2121 TestCheckedLeftShift<int64_t>();
2122 }
2123
2124 BOOST_AUTO_TEST_CASE(saturating_left_shift_test)
2125 {
2126 TestSaturatingLeftShift<uint8_t>();
2127 TestSaturatingLeftShift<int8_t>();
2128 TestSaturatingLeftShift<size_t>();
2129 TestSaturatingLeftShift<uint64_t>();
2130 TestSaturatingLeftShift<int64_t>();
2131 }
2132
2133 template <class Int, auto bytes>
2134 concept BraceInitializesTo = requires { Int{bytes}; };
2135
2136 BOOST_AUTO_TEST_CASE(mib_string_literal_test)
2137 {
2138 // Basic equivalences and simple arithmetic operations
2139 BOOST_CHECK_EQUAL(0_MiB, 0);
2140 BOOST_CHECK_EQUAL(1_MiB, 1 << 20);
2141 BOOST_CHECK_EQUAL(1_MiB, 1024 * 1024);
2142 BOOST_CHECK_EQUAL(1_MiB, 0x100000U);
2143 BOOST_CHECK_EQUAL(1_MiB, 1048576U);
2144 BOOST_CHECK_EQUAL(2ULL * 1_MiB, 2ULL << 20);
2145 BOOST_CHECK_EQUAL((3_MiB + 123) / double(1_MiB), (3_MiB + 123) / 1024.0 / 1024.0);
2146
2147 // Specific codebase values
2148 BOOST_CHECK_EQUAL(4_MiB, 1 << 22);
2149 BOOST_CHECK_EQUAL(8_MiB, 1 << 23);
2150 BOOST_CHECK_EQUAL(16_MiB, 0x1000000U);
2151 BOOST_CHECK_EQUAL(16_MiB, 1 << 24);
2152 BOOST_CHECK_EQUAL(32_MiB, 0x2000000U);
2153 BOOST_CHECK_EQUAL(32_MiB, 32U << 20);
2154 BOOST_CHECK_EQUAL(50_MiB / 1_MiB, 50U);
2155 BOOST_CHECK_EQUAL(50_MiB, 52428800U);
2156 BOOST_CHECK_EQUAL(128_MiB, 0x8000000U);
2157 BOOST_CHECK_EQUAL(550_MiB, 550ULL * 1024 * 1024);
2158
2159 // 4095 MiB fits in uint32_t bytes. 4096 MiB requires the uint64_t return type.
2160 static_assert(BraceInitializesTo<uint32_t, 4095_MiB>);
2161 static_assert(!BraceInitializesTo<uint32_t, 4096_MiB>);
2162 static_assert(BraceInitializesTo<uint64_t, 4096_MiB>);
2163 BOOST_CHECK_EQUAL(4095_MiB, uint32_t{4095} << 20);
2164 BOOST_CHECK_EQUAL(4096_MiB, uint64_t{4096} << 20);
2165 }
2166
2167 BOOST_AUTO_TEST_CASE(gib_string_literal_test)
2168 {
2169 // Basic equivalences and simple arithmetic operations
2170 BOOST_CHECK_EQUAL(0_GiB, 0);
2171 BOOST_CHECK_EQUAL(1_GiB, 1 << 30);
2172 BOOST_CHECK_EQUAL(1_GiB, 1024 * 1024 * 1024);
2173 BOOST_CHECK_EQUAL(1_GiB, 0x40000000U);
2174 BOOST_CHECK_EQUAL(1_GiB, 1073741824U);
2175 BOOST_CHECK_EQUAL(1_GiB, 1_MiB * 1024);
2176 BOOST_CHECK_EQUAL(1_GiB, 1024_MiB);
2177 BOOST_CHECK_EQUAL((1_GiB + 123) / double(1_GiB), (1_GiB + 123) / 1024.0 / 1024.0 / 1024.0);
2178 BOOST_CHECK_EQUAL(2ULL * 1_GiB, 2ULL << 30);
2179 BOOST_CHECK_EQUAL(4 * uint64_t{1_GiB}, uint64_t{4} << 30);
2180 BOOST_CHECK_EQUAL(2_GiB, 2048_MiB);
2181 BOOST_CHECK_EQUAL(3_GiB / 1_GiB, 3U);
2182 BOOST_CHECK_EQUAL(3_GiB, 3U << 30);
2183
2184 // 3 GiB fits in uint32_t bytes. 4 GiB requires the uint64_t return type.
2185 static_assert(BraceInitializesTo<uint32_t, 3_GiB>);
2186 static_assert(!BraceInitializesTo<uint32_t, 4_GiB>);
2187 static_assert(BraceInitializesTo<uint64_t, 4_GiB>);
2188 BOOST_CHECK_EQUAL(3_GiB, uint32_t{3} << 30);
2189 BOOST_CHECK_EQUAL(4_GiB, uint64_t{4} << 30);
2190
2191 // Specific codebase values
2192 BOOST_CHECK_EQUAL(4_GiB, 4096_MiB);
2193 BOOST_CHECK_EQUAL(8_GiB, 8192_MiB);
2194 BOOST_CHECK_EQUAL(16_GiB, 16384_MiB);
2195 BOOST_CHECK_EQUAL(32_GiB, 32768_MiB);
2196 }
2197
2198 BOOST_AUTO_TEST_CASE(is_space_byte_range_test)
2199 {
2200 std::vector expected(256, false);
2201 for (auto c : std::string_view(" \f\n\r\t\v")) expected[c] = true;
2202
2203 for (auto i{0U}; i < expected.size(); ++i) {
2204 auto c = static_cast<char>(i);
2205 BOOST_CHECK_MESSAGE(IsSpace(c) == expected[i], "IsSpace test failed for char value: " << i);
2206 }
2207 }
2208
2209 static std::string CheckModifyRWConfigFile(std::map<std::string, std::string>& settings_to_change, const std::string& current_config_file)
2210 {
2211 std::istringstream stream_in(current_config_file);
2212 std::ostringstream stream_out;
2213 try {
2214 ModifyRWConfigStream(stream_in, stream_out, settings_to_change);
2215 } catch (...) {
2216 settings_to_change.clear();
2217 throw;
2218 }
2219 settings_to_change.clear();
2220 return stream_out.str();
2221 }
2222
2223 BOOST_AUTO_TEST_CASE(test_ModifyRWConfigFile)
2224 {
2225 std::map<std::string, std::string> cs;
2226
2227 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b"), "a=b");
2228
2229 cs["a"] = "c";
2230 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b"), "a=c");
2231 BOOST_CHECK(cs.empty());
2232
2233 // Multi-char name/value
2234 cs["ab"] = "cd";
2235 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "ab=bc"), "ab=cd");
2236
2237 // Preserved final newline
2238 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n"), "a=b\n");
2239 cs["a"] = "c";
2240 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n"), "a=c\n");
2241
2242 // Preserved final tab
2243 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t"), "a=b\t");
2244 cs["a"] = "c";
2245 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t"), "a=c\t");
2246
2247 // Preserved final space
2248 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b "), "a=b ");
2249 cs["a"] = "c";
2250 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b "), "a=c ");
2251
2252 // Preserved final crnl
2253 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\r\n"), "a=b\r\n");
2254 cs["a"] = "c";
2255 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\r\n"), "a=c\r\n");
2256
2257 // Empty file
2258 cs["a"] = "c";
2259 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, ""), "a=c\n");
2260
2261 // Ignore k=v in comment
2262 cs["a"] = "c";
2263 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "#a=b"), "#a=b\na=c\n");
2264
2265 // Preserved comment
2266 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t# c"), "a=b\t# c");
2267
2268 // Commented out commented value
2269 cs["a"] = "c";
2270 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\t# c"), "a=c\n#a=b\t# c");
2271
2272 // Preserved whitespace before name
2273 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, " \t \ta=b"), " \t \ta=b");
2274 cs["a"] = "c";
2275 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, " \t \ta=b"), " \t \ta=c");
2276
2277 // Preserved whitespace after name
2278 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a \t \t=b"), "a \t \t=b");
2279 cs["a"] = "c";
2280 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a \t \t=b"), "a \t \t=c");
2281
2282 // Preserved whitespace before value
2283 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a= \t \tb"), "a= \t \tb");
2284 cs["a"] = "c";
2285 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a= \t \tb"), "a= \t \tc");
2286
2287 // Modifying value between others
2288 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=bc\nd=e");
2289 cs["ab"] = "x";
2290 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=x\nd=e");
2291
2292 // Blank key/value
2293 cs["ab"] = "";
2294 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=\nd=e");
2295 cs[""] = "x";
2296 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nd=e"), "a=b\nab=bc\nd=e\n=x\n");
2297
2298 // Blank line in source
2299 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\nab=bc\n\nd=e"), "a=b\n\nab=bc\n\nd=e");
2300 cs["ab"] = "x";
2301 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\nab=bc\n\nd=e"), "a=b\n\nab=x\n\nd=e");
2302
2303 // Duplicate keys in the source
2304 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nf=x\nab=zx\nd=e"), "a=b\nab=bc\nf=x\nab=zx\nd=e");
2305 cs["ab"] = "x";
2306 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nf=x\nab=zx\nd=e"), "a=b\nab=x\nf=x\nab=zx\nd=e");
2307
2308 // Comment out entire file if invalid input line
2309 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e"), "[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e");
2310 cs["ab"] = "x";
2311 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e"), "ab=x\n[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e");
2312 cs["ab"] = "x";
2313 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=bc\nGARBAGE\nd=e\n"), "ab=x\n[INVALID]\n# Error parsing line 3: GARBAGE\n#a=b\n#ab=bc\n#GARBAGE\n#d=e\n");
2314
2315 // Whitespace inside values
2316 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=b\t \t c\nd=e"), "a=b\nab=b\t \t c\nd=e");
2317 cs["ab"] = "x \t \tx";
2318 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\nab=b\t \t c\nd=e"), "a=b\nab=x \t \tx\nd=e");
2319
2320 // Newline inside name/value
2321 cs["a"] = "x\nx";
2322 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2323 cs["a"] = "x\rx";
2324 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2325 cs["a\nb"] = "x";
2326 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2327 cs["a\rb"] = "x";
2328 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2329
2330 // Whitespace leading/trailing name/value
2331 cs["a"] = " x";
2332 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2333 cs["a"] = "\tx";
2334 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2335 cs[" a"] = "x";
2336 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2337 cs["\ta"] = "x";
2338 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2339 cs["a"] = "x ";
2340 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2341 cs["a"] = "x\t";
2342 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2343 cs["a "] = "x";
2344 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2345 cs["a\t"] = "x";
2346 BOOST_REQUIRE_THROW(CheckModifyRWConfigFile(cs, ""), std::invalid_argument);
2347
2348 // Ignore groups
2349 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nd=e"), "a=b\n[group]\nab=bc\nd=e");
2350 cs["ab"] = "x";
2351 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nd=e"), "a=b\nab=x\n[group]\nab=bc\nd=e");
2352 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\t [group] \t#c\nab=bc\nd=e"), "a=b\n\t [group] \t#c\nab=bc\nd=e");
2353 cs["ab"] = "x";
2354 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n\t [group] \t#c\nab=bc\nd=e"), "a=b\nab=x\n\t [group] \t#c\nab=bc\nd=e");
2355
2356 // Comment out entire file if invalid input line, even after a group
2357 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nGARBAGE\nd=e"), "[INVALID]\n# Error parsing line 4: GARBAGE\n#a=b\n#[group]\n#ab=bc\n#GARBAGE\n#d=e");
2358 cs["ab"] = "x";
2359 BOOST_CHECK_EQUAL(CheckModifyRWConfigFile(cs, "a=b\n[group]\nab=bc\nGARBAGE\nd=e"), "ab=x\n[INVALID]\n# Error parsing line 4: GARBAGE\n#a=b\n#[group]\n#ab=bc\n#GARBAGE\n#d=e");
2360 }
2361
2362 BOOST_AUTO_TEST_CASE(ceil_div_test)
2363 {
2364 // Return type is effectively the wider of the two types.
2365 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, uint32_t{1})), uint32_t>));
2366 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, uint64_t{1})), uint64_t>));
2367 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint64_t{0}, uint32_t{1})), uint64_t>));
2368 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, uint32_t{1})), size_t>));
2369 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint32_t{0}, size_t{1})), size_t>));
2370 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, size_t{1})), size_t>));
2371 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(size_t{0}, uint64_t{1})), uint64_t>));
2372 BOOST_CHECK((std::is_same_v<decltype(CeilDiv(uint64_t{0}, size_t{1})), uint64_t>));
2373
2374 // Basic ceiling division: exact divisions and rounding up.
2375 BOOST_CHECK_EQUAL(CeilDiv(0ULL, 1ULL), 0ULL);
2376 BOOST_CHECK_EQUAL(CeilDiv(1ULL, 1ULL), 1ULL);
2377 BOOST_CHECK_EQUAL(CeilDiv(2ULL, 2ULL), 1ULL);
2378 BOOST_CHECK_EQUAL(CeilDiv(3ULL, 2ULL), 2ULL);
2379 BOOST_CHECK_EQUAL(CeilDiv(5ULL, 3ULL), 2ULL);
2380
2381 // Works with size_t.
2382 BOOST_CHECK_EQUAL(CeilDiv(size_t{0}, size_t{1}), size_t{0});
2383 BOOST_CHECK_EQUAL(CeilDiv(size_t{3}, size_t{2}), size_t{2});
2384
2385 // Works with uint32_t.
2386 BOOST_CHECK_EQUAL(CeilDiv(0U, 1U), 0U);
2387 BOOST_CHECK_EQUAL(CeilDiv(3U, 2U), 2U);
2388
2389 // CeilDiv avoids overflow at max values.
2390 constexpr uint64_t max_u64{std::numeric_limits<uint64_t>::max()};
2391 BOOST_CHECK_EQUAL(CeilDiv(max_u64, 2ULL), (max_u64 / 2) + 1);
2392
2393 // Mixed types: size_t dividend with uint32_t divisor.
2394 constexpr size_t max_u32_as_size{std::numeric_limits<uint32_t>::max()};
2395 BOOST_CHECK_EQUAL(CeilDiv(max_u32_as_size, uint32_t{2}), (max_u32_as_size / 2) + 1);
2396 }
2397
2398 BOOST_AUTO_TEST_CASE(ceil_div_zero_divisor_test)
2399 {
2400 test_only_CheckFailuresAreExceptionsNotAborts check_failures;
2401 BOOST_CHECK_THROW((void)CeilDiv(1ULL, 0ULL), NonFatalCheckError);
2402 BOOST_CHECK_THROW((void)CeilDiv(size_t{1}, size_t{0}), NonFatalCheckError);
2403 }
2404
2405 BOOST_AUTO_TEST_SUITE_END()
2406