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