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