]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // Formatting library for C++ - formatting library implementation tests |
2 | // | |
3 | // Copyright (c) 2012 - present, Victor Zverovich | |
4 | // All rights reserved. | |
5 | // | |
6 | // For the license information refer to format.h. | |
7 | ||
8 | #define FMT_NOEXCEPT | |
9 | #undef FMT_SHARED | |
10 | #include "test-assert.h" | |
11 | ||
12 | // Include format.cc instead of format.h to test implementation. | |
11fdf7f2 TL |
13 | #include <algorithm> |
14 | #include <cstring> | |
15 | ||
f67539c2 TL |
16 | #include "../src/format.cc" |
17 | #include "fmt/printf.h" | |
11fdf7f2 TL |
18 | #include "gmock.h" |
19 | #include "gtest-extra.h" | |
20 | #include "util.h" | |
21 | ||
11fdf7f2 TL |
22 | #undef max |
23 | ||
f67539c2 TL |
24 | using fmt::detail::bigint; |
25 | using fmt::detail::fp; | |
26 | using fmt::detail::max_value; | |
eafe8130 | 27 | |
f67539c2 TL |
28 | static_assert(!std::is_copy_constructible<bigint>::value, ""); |
29 | static_assert(!std::is_copy_assignable<bigint>::value, ""); | |
11fdf7f2 | 30 | |
f67539c2 TL |
31 | TEST(BigIntTest, Construct) { |
32 | EXPECT_EQ("", fmt::format("{}", bigint())); | |
33 | EXPECT_EQ("42", fmt::format("{}", bigint(0x42))); | |
34 | EXPECT_EQ("123456789abcedf0", fmt::format("{}", bigint(0x123456789abcedf0))); | |
11fdf7f2 TL |
35 | } |
36 | ||
f67539c2 TL |
37 | TEST(BigIntTest, Compare) { |
38 | bigint n1(42); | |
39 | bigint n2(42); | |
40 | EXPECT_EQ(compare(n1, n2), 0); | |
41 | n2 <<= 32; | |
42 | EXPECT_LT(compare(n1, n2), 0); | |
43 | bigint n3(43); | |
44 | EXPECT_LT(compare(n1, n3), 0); | |
45 | EXPECT_GT(compare(n3, n1), 0); | |
46 | bigint n4(42 * 0x100000001); | |
47 | EXPECT_LT(compare(n2, n4), 0); | |
48 | EXPECT_GT(compare(n4, n2), 0); | |
11fdf7f2 TL |
49 | } |
50 | ||
f67539c2 TL |
51 | TEST(BigIntTest, AddCompare) { |
52 | EXPECT_LT( | |
53 | add_compare(bigint(0xffffffff), bigint(0xffffffff), bigint(1) <<= 64), 0); | |
54 | EXPECT_LT(add_compare(bigint(1) <<= 32, bigint(1), bigint(1) <<= 96), 0); | |
55 | EXPECT_GT(add_compare(bigint(1) <<= 32, bigint(0), bigint(0xffffffff)), 0); | |
56 | EXPECT_GT(add_compare(bigint(0), bigint(1) <<= 32, bigint(0xffffffff)), 0); | |
57 | EXPECT_GT(add_compare(bigint(42), bigint(1), bigint(42)), 0); | |
58 | EXPECT_GT(add_compare(bigint(0xffffffff), bigint(1), bigint(0xffffffff)), 0); | |
59 | EXPECT_LT(add_compare(bigint(10), bigint(10), bigint(22)), 0); | |
60 | EXPECT_LT(add_compare(bigint(0x100000010), bigint(0x100000010), | |
61 | bigint(0x300000010)), | |
62 | 0); | |
63 | EXPECT_GT(add_compare(bigint(0x1ffffffff), bigint(0x100000002), | |
64 | bigint(0x300000000)), | |
65 | 0); | |
66 | EXPECT_EQ(add_compare(bigint(0x1ffffffff), bigint(0x100000002), | |
67 | bigint(0x300000001)), | |
68 | 0); | |
69 | EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002), | |
70 | bigint(0x300000002)), | |
71 | 0); | |
72 | EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002), | |
73 | bigint(0x300000003)), | |
74 | 0); | |
11fdf7f2 TL |
75 | } |
76 | ||
f67539c2 TL |
77 | TEST(BigIntTest, ShiftLeft) { |
78 | bigint n(0x42); | |
79 | n <<= 0; | |
80 | EXPECT_EQ("42", fmt::format("{}", n)); | |
81 | n <<= 1; | |
82 | EXPECT_EQ("84", fmt::format("{}", n)); | |
83 | n <<= 25; | |
84 | EXPECT_EQ("108000000", fmt::format("{}", n)); | |
85 | } | |
86 | ||
87 | TEST(BigIntTest, Multiply) { | |
88 | bigint n(0x42); | |
89 | EXPECT_THROW(n *= 0, assertion_failure); | |
90 | n *= 1; | |
91 | EXPECT_EQ("42", fmt::format("{}", n)); | |
92 | n *= 2; | |
93 | EXPECT_EQ("84", fmt::format("{}", n)); | |
94 | n *= 0x12345678; | |
95 | EXPECT_EQ("962fc95e0", fmt::format("{}", n)); | |
96 | bigint bigmax(max_value<uint32_t>()); | |
97 | bigmax *= max_value<uint32_t>(); | |
98 | EXPECT_EQ("fffffffe00000001", fmt::format("{}", bigmax)); | |
99 | bigmax.assign(max_value<uint64_t>()); | |
100 | bigmax *= max_value<uint64_t>(); | |
101 | EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", bigmax)); | |
102 | } | |
103 | ||
104 | TEST(BigIntTest, Accumulator) { | |
105 | fmt::detail::accumulator acc; | |
106 | EXPECT_EQ(acc.lower, 0); | |
107 | EXPECT_EQ(acc.upper, 0); | |
108 | acc.upper = 12; | |
109 | acc.lower = 34; | |
110 | EXPECT_EQ(static_cast<uint32_t>(acc), 34); | |
111 | acc += 56; | |
112 | EXPECT_EQ(acc.lower, 90); | |
113 | acc += fmt::detail::max_value<uint64_t>(); | |
114 | EXPECT_EQ(acc.upper, 13); | |
115 | EXPECT_EQ(acc.lower, 89); | |
116 | acc >>= 32; | |
117 | EXPECT_EQ(acc.upper, 0); | |
118 | EXPECT_EQ(acc.lower, 13 * 0x100000000); | |
119 | } | |
120 | ||
121 | TEST(BigIntTest, Square) { | |
122 | bigint n0(0); | |
123 | n0.square(); | |
124 | EXPECT_EQ("0", fmt::format("{}", n0)); | |
125 | bigint n1(0x100); | |
126 | n1.square(); | |
127 | EXPECT_EQ("10000", fmt::format("{}", n1)); | |
128 | bigint n2(0xfffffffff); | |
129 | n2.square(); | |
130 | EXPECT_EQ("ffffffffe000000001", fmt::format("{}", n2)); | |
131 | bigint n3(max_value<uint64_t>()); | |
132 | n3.square(); | |
133 | EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", n3)); | |
134 | bigint n4; | |
135 | n4.assign_pow10(10); | |
136 | EXPECT_EQ("2540be400", fmt::format("{}", n4)); | |
137 | } | |
138 | ||
139 | TEST(BigIntTest, DivModAssignZeroDivisor) { | |
140 | bigint zero(0); | |
141 | EXPECT_THROW(bigint(0).divmod_assign(zero), assertion_failure); | |
142 | EXPECT_THROW(bigint(42).divmod_assign(zero), assertion_failure); | |
143 | } | |
144 | ||
145 | TEST(BigIntTest, DivModAssignSelf) { | |
146 | bigint n(100); | |
147 | EXPECT_THROW(n.divmod_assign(n), assertion_failure); | |
148 | } | |
149 | ||
150 | TEST(BigIntTest, DivModAssignUnaligned) { | |
151 | // (42 << 340) / pow(10, 100): | |
152 | bigint n1(42); | |
153 | n1 <<= 340; | |
154 | bigint n2; | |
155 | n2.assign_pow10(100); | |
156 | int result = n1.divmod_assign(n2); | |
157 | EXPECT_EQ(result, 9406); | |
158 | EXPECT_EQ("10f8353019583bfc29ffc8f564e1b9f9d819dbb4cf783e4507eca1539220p96", | |
159 | fmt::format("{}", n1)); | |
160 | } | |
161 | ||
162 | TEST(BigIntTest, DivModAssign) { | |
163 | // 100 / 10: | |
164 | bigint n1(100); | |
165 | int result = n1.divmod_assign(bigint(10)); | |
166 | EXPECT_EQ(result, 10); | |
167 | EXPECT_EQ("0", fmt::format("{}", n1)); | |
168 | // pow(10, 100) / (42 << 320): | |
169 | n1.assign_pow10(100); | |
170 | result = n1.divmod_assign(bigint(42) <<= 320); | |
171 | EXPECT_EQ(result, 111); | |
172 | EXPECT_EQ("13ad2594c37ceb0b2784c4ce0bf38ace408e211a7caab24308a82e8f10p96", | |
173 | fmt::format("{}", n1)); | |
174 | // 42 / 100: | |
175 | bigint n2(42); | |
176 | n1.assign_pow10(2); | |
177 | result = n2.divmod_assign(n1); | |
178 | EXPECT_EQ(result, 0); | |
179 | EXPECT_EQ("2a", fmt::format("{}", n2)); | |
180 | } | |
181 | ||
182 | template <bool is_iec559> void run_double_tests() { | |
183 | fmt::print("warning: double is not IEC559, skipping FP tests\n"); | |
184 | } | |
185 | ||
186 | template <> void run_double_tests<true>() { | |
187 | // Construct from double. | |
188 | EXPECT_EQ(fp(1.23), fp(0x13ae147ae147aeu, -52)); | |
189 | ||
190 | // Compute boundaries: | |
191 | fp value; | |
192 | // Normalized & not power of 2 - equidistant boundaries: | |
193 | auto b = value.assign_with_boundaries(1.23); | |
194 | EXPECT_EQ(value, fp(0x0013ae147ae147ae, -52)); | |
195 | EXPECT_EQ(b.lower, 0x9d70a3d70a3d6c00); | |
196 | EXPECT_EQ(b.upper, 0x9d70a3d70a3d7400); | |
197 | // Normalized power of 2 - lower boundary is closer: | |
198 | b = value.assign_with_boundaries(1.9807040628566084e+28); // 2**94 | |
199 | EXPECT_EQ(value, fp(0x0010000000000000, 42)); | |
200 | EXPECT_EQ(b.lower, 0x7ffffffffffffe00); | |
201 | EXPECT_EQ(b.upper, 0x8000000000000400); | |
202 | // Smallest normalized double - equidistant boundaries: | |
203 | b = value.assign_with_boundaries(2.2250738585072014e-308); | |
204 | EXPECT_EQ(value, fp(0x0010000000000000, -1074)); | |
205 | EXPECT_EQ(b.lower, 0x7ffffffffffffc00); | |
206 | EXPECT_EQ(b.upper, 0x8000000000000400); | |
207 | // Subnormal - equidistant boundaries: | |
208 | b = value.assign_with_boundaries(4.9406564584124654e-324); | |
209 | EXPECT_EQ(value, fp(0x0000000000000001, -1074)); | |
210 | EXPECT_EQ(b.lower, 0x4000000000000000); | |
211 | EXPECT_EQ(b.upper, 0xc000000000000000); | |
11fdf7f2 TL |
212 | } |
213 | ||
f67539c2 TL |
214 | TEST(FPTest, DoubleTests) { |
215 | run_double_tests<std::numeric_limits<double>::is_iec559>(); | |
11fdf7f2 TL |
216 | } |
217 | ||
f67539c2 TL |
218 | TEST(FPTest, Normalize) { |
219 | const auto v = fp(0xbeef, 42); | |
220 | auto normalized = normalize(v); | |
221 | EXPECT_EQ(0xbeef000000000000, normalized.f); | |
222 | EXPECT_EQ(-6, normalized.e); | |
11fdf7f2 TL |
223 | } |
224 | ||
f67539c2 TL |
225 | TEST(FPTest, ComputeFloatBoundaries) { |
226 | struct { | |
227 | double x, lower, upper; | |
228 | } tests[] = { | |
229 | // regular | |
230 | {1.5f, 1.4999999403953552, 1.5000000596046448}, | |
231 | // boundary | |
232 | {1.0f, 0.9999999701976776, 1.0000000596046448}, | |
233 | // min normal | |
234 | {1.1754944e-38f, 1.1754942807573643e-38, 1.1754944208872107e-38}, | |
235 | // max subnormal | |
236 | {1.1754942e-38f, 1.1754941406275179e-38, 1.1754942807573643e-38}, | |
237 | // min subnormal | |
238 | {1e-45f, 7.006492321624085e-46, 2.1019476964872256e-45}, | |
239 | }; | |
240 | for (auto test : tests) { | |
241 | fp vlower = normalize(fp(test.lower)); | |
242 | fp vupper = normalize(fp(test.upper)); | |
243 | vlower.f >>= vupper.e - vlower.e; | |
244 | vlower.e = vupper.e; | |
245 | fp value; | |
246 | auto b = value.assign_float_with_boundaries(test.x); | |
247 | EXPECT_EQ(vlower.f, b.lower); | |
248 | EXPECT_EQ(vupper.f, b.upper); | |
249 | } | |
11fdf7f2 TL |
250 | } |
251 | ||
252 | TEST(FPTest, Multiply) { | |
253 | auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7); | |
254 | EXPECT_EQ(v.f, 123u * 56u); | |
255 | EXPECT_EQ(v.e, 4 + 7 + 64); | |
256 | v = fp(123ULL << 32, 4) * fp(567ULL << 31, 8); | |
257 | EXPECT_EQ(v.f, (123 * 567 + 1u) / 2); | |
258 | EXPECT_EQ(v.e, 4 + 8 + 64); | |
259 | } | |
260 | ||
261 | TEST(FPTest, GetCachedPower) { | |
262 | typedef std::numeric_limits<double> limits; | |
263 | for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) { | |
264 | int dec_exp = 0; | |
f67539c2 | 265 | auto fp = fmt::detail::get_cached_power(exp, dec_exp); |
11fdf7f2 TL |
266 | EXPECT_LE(exp, fp.e); |
267 | int dec_exp_step = 8; | |
268 | EXPECT_LE(fp.e, exp + dec_exp_step * log2(10)); | |
f67539c2 | 269 | EXPECT_DOUBLE_EQ(pow(10, dec_exp), ldexp(static_cast<double>(fp.f), fp.e)); |
11fdf7f2 TL |
270 | } |
271 | } | |
272 | ||
9f95a23c | 273 | TEST(FPTest, GetRoundDirection) { |
f67539c2 TL |
274 | using fmt::detail::get_round_direction; |
275 | using fmt::detail::round_direction; | |
276 | EXPECT_EQ(round_direction::down, get_round_direction(100, 50, 0)); | |
277 | EXPECT_EQ(round_direction::up, get_round_direction(100, 51, 0)); | |
278 | EXPECT_EQ(round_direction::down, get_round_direction(100, 40, 10)); | |
279 | EXPECT_EQ(round_direction::up, get_round_direction(100, 60, 10)); | |
280 | for (size_t i = 41; i < 60; ++i) | |
281 | EXPECT_EQ(round_direction::unknown, get_round_direction(100, i, 10)); | |
282 | uint64_t max = max_value<uint64_t>(); | |
9f95a23c TL |
283 | EXPECT_THROW(get_round_direction(100, 100, 0), assertion_failure); |
284 | EXPECT_THROW(get_round_direction(100, 0, 100), assertion_failure); | |
285 | EXPECT_THROW(get_round_direction(100, 0, 50), assertion_failure); | |
286 | // Check that remainder + error doesn't overflow. | |
f67539c2 | 287 | EXPECT_EQ(round_direction::up, get_round_direction(max, max - 1, 2)); |
9f95a23c | 288 | // Check that 2 * (remainder + error) doesn't overflow. |
f67539c2 | 289 | EXPECT_EQ(round_direction::unknown, |
9f95a23c TL |
290 | get_round_direction(max, max / 2 + 1, max / 2)); |
291 | // Check that remainder - error doesn't overflow. | |
f67539c2 | 292 | EXPECT_EQ(round_direction::unknown, get_round_direction(100, 40, 41)); |
9f95a23c | 293 | // Check that 2 * (remainder - error) doesn't overflow. |
f67539c2 | 294 | EXPECT_EQ(round_direction::up, get_round_direction(max, max - 1, 1)); |
9f95a23c TL |
295 | } |
296 | ||
297 | TEST(FPTest, FixedHandler) { | |
f67539c2 | 298 | struct handler : fmt::detail::fixed_handler { |
9f95a23c | 299 | char buffer[10]; |
f67539c2 | 300 | handler(int prec = 0) : fmt::detail::fixed_handler() { |
9f95a23c TL |
301 | buf = buffer; |
302 | precision = prec; | |
303 | } | |
304 | }; | |
305 | int exp = 0; | |
306 | handler().on_digit('0', 100, 99, 0, exp, false); | |
307 | EXPECT_THROW(handler().on_digit('0', 100, 100, 0, exp, false), | |
308 | assertion_failure); | |
f67539c2 | 309 | namespace digits = fmt::detail::digits; |
9f95a23c TL |
310 | EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, exp, false), digits::done); |
311 | // Check that divisor - error doesn't overflow. | |
312 | EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, exp, false), digits::error); | |
313 | // Check that 2 * error doesn't overflow. | |
f67539c2 | 314 | uint64_t max = max_value<uint64_t>(); |
9f95a23c TL |
315 | EXPECT_EQ(handler(1).on_digit('0', max, 10, max - 1, exp, false), |
316 | digits::error); | |
317 | } | |
318 | ||
f67539c2 | 319 | TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) { |
eafe8130 | 320 | fmt::memory_buffer buf; |
f67539c2 | 321 | format_float(0.42, -1, fmt::detail::float_specs(), buf); |
eafe8130 TL |
322 | } |
323 | ||
f67539c2 | 324 | template <typename T> struct value_extractor { |
9f95a23c | 325 | T operator()(T value) { return value; } |
11fdf7f2 | 326 | |
9f95a23c | 327 | template <typename U> FMT_NORETURN T operator()(U) { |
11fdf7f2 TL |
328 | throw std::runtime_error(fmt::format("invalid type {}", typeid(U).name())); |
329 | } | |
f67539c2 TL |
330 | |
331 | #if FMT_USE_INT128 | |
332 | // Apple Clang does not define typeid for __int128_t and __uint128_t. | |
333 | FMT_NORETURN T operator()(fmt::detail::int128_t) { | |
334 | throw std::runtime_error("invalid type __int128_t"); | |
335 | } | |
336 | ||
337 | FMT_NORETURN T operator()(fmt::detail::uint128_t) { | |
338 | throw std::runtime_error("invalid type __uint128_t"); | |
339 | } | |
340 | #endif | |
11fdf7f2 TL |
341 | }; |
342 | ||
343 | TEST(FormatTest, ArgConverter) { | |
f67539c2 TL |
344 | long long value = max_value<long long>(); |
345 | auto arg = fmt::detail::make_arg<fmt::format_context>(value); | |
9f95a23c | 346 | fmt::visit_format_arg( |
f67539c2 | 347 | fmt::detail::arg_converter<long long, fmt::format_context>(arg, 'd'), |
9f95a23c | 348 | arg); |
f67539c2 | 349 | EXPECT_EQ(value, fmt::visit_format_arg(value_extractor<long long>(), arg)); |
11fdf7f2 TL |
350 | } |
351 | ||
352 | TEST(FormatTest, FormatNegativeNaN) { | |
353 | double nan = std::numeric_limits<double>::quiet_NaN(); | |
eafe8130 | 354 | if (std::signbit(-nan)) |
11fdf7f2 TL |
355 | EXPECT_EQ("-nan", fmt::format("{}", -nan)); |
356 | else | |
357 | fmt::print("Warning: compiler doesn't handle negative NaN correctly"); | |
358 | } | |
359 | ||
360 | TEST(FormatTest, StrError) { | |
f67539c2 | 361 | char* message = nullptr; |
11fdf7f2 | 362 | char buffer[BUFFER_SIZE]; |
f67539c2 | 363 | EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = nullptr, 0), |
eafe8130 | 364 | "invalid buffer"); |
f67539c2 | 365 | EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = buffer, 0), |
11fdf7f2 TL |
366 | "invalid buffer"); |
367 | buffer[0] = 'x'; | |
368 | #if defined(_GNU_SOURCE) && !defined(__COVERITY__) | |
369 | // Use invalid error code to make sure that safe_strerror returns an error | |
370 | // message in the buffer rather than a pointer to a static string. | |
371 | int error_code = -1; | |
372 | #else | |
373 | int error_code = EDOM; | |
374 | #endif | |
375 | ||
f67539c2 TL |
376 | int result = |
377 | fmt::detail::safe_strerror(error_code, message = buffer, BUFFER_SIZE); | |
eafe8130 | 378 | EXPECT_EQ(result, 0); |
f67539c2 | 379 | size_t message_size = std::strlen(message); |
11fdf7f2 TL |
380 | EXPECT_GE(BUFFER_SIZE - 1u, message_size); |
381 | EXPECT_EQ(get_system_error(error_code), message); | |
382 | ||
383 | // safe_strerror never uses buffer on MinGW. | |
f67539c2 TL |
384 | #if !defined(__MINGW32__) && !defined(__sun) |
385 | result = | |
386 | fmt::detail::safe_strerror(error_code, message = buffer, message_size); | |
11fdf7f2 | 387 | EXPECT_EQ(ERANGE, result); |
f67539c2 | 388 | result = fmt::detail::safe_strerror(error_code, message = buffer, 1); |
11fdf7f2 TL |
389 | EXPECT_EQ(buffer, message); // Message should point to buffer. |
390 | EXPECT_EQ(ERANGE, result); | |
391 | EXPECT_STREQ("", message); | |
392 | #endif | |
393 | } | |
394 | ||
395 | TEST(FormatTest, FormatErrorCode) { | |
396 | std::string msg = "error 42", sep = ": "; | |
397 | { | |
398 | fmt::memory_buffer buffer; | |
399 | format_to(buffer, "garbage"); | |
f67539c2 | 400 | fmt::detail::format_error_code(buffer, 42, "test"); |
11fdf7f2 TL |
401 | EXPECT_EQ("test: " + msg, to_string(buffer)); |
402 | } | |
403 | { | |
404 | fmt::memory_buffer buffer; | |
9f95a23c TL |
405 | std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size() + 1, |
406 | 'x'); | |
f67539c2 | 407 | fmt::detail::format_error_code(buffer, 42, prefix); |
11fdf7f2 TL |
408 | EXPECT_EQ(msg, to_string(buffer)); |
409 | } | |
410 | int codes[] = {42, -1}; | |
f67539c2 | 411 | for (size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) { |
11fdf7f2 TL |
412 | // Test maximum buffer size. |
413 | msg = fmt::format("error {}", codes[i]); | |
414 | fmt::memory_buffer buffer; | |
9f95a23c | 415 | std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x'); |
f67539c2 | 416 | fmt::detail::format_error_code(buffer, codes[i], prefix); |
11fdf7f2 | 417 | EXPECT_EQ(prefix + sep + msg, to_string(buffer)); |
f67539c2 | 418 | size_t size = fmt::inline_buffer_size; |
11fdf7f2 TL |
419 | EXPECT_EQ(size, buffer.size()); |
420 | buffer.resize(0); | |
421 | // Test with a message that doesn't fit into the buffer. | |
422 | prefix += 'x'; | |
f67539c2 | 423 | fmt::detail::format_error_code(buffer, codes[i], prefix); |
11fdf7f2 TL |
424 | EXPECT_EQ(msg, to_string(buffer)); |
425 | } | |
426 | } | |
427 | ||
428 | TEST(FormatTest, CountCodePoints) { | |
f67539c2 TL |
429 | EXPECT_EQ(4, |
430 | fmt::detail::count_code_points( | |
431 | fmt::basic_string_view<fmt::detail::char8_type>( | |
432 | reinterpret_cast<const fmt::detail::char8_type*>("ёжик")))); | |
433 | } | |
434 | ||
435 | // Tests fmt::detail::count_digits for integer type Int. | |
436 | template <typename Int> void test_count_digits() { | |
437 | for (Int i = 0; i < 10; ++i) EXPECT_EQ(1u, fmt::detail::count_digits(i)); | |
438 | for (Int i = 1, n = 1, end = max_value<Int>() / 10; n <= end; ++i) { | |
439 | n *= 10; | |
440 | EXPECT_EQ(i, fmt::detail::count_digits(n - 1)); | |
441 | EXPECT_EQ(i + 1, fmt::detail::count_digits(n)); | |
442 | } | |
443 | } | |
444 | ||
445 | TEST(UtilTest, CountDigits) { | |
446 | test_count_digits<uint32_t>(); | |
447 | test_count_digits<uint64_t>(); | |
448 | } | |
449 | ||
450 | TEST(UtilTest, WriteFallbackUIntPtr) { | |
451 | std::string s; | |
452 | fmt::detail::write_ptr<char>( | |
453 | std::back_inserter(s), | |
454 | fmt::detail::fallback_uintptr(reinterpret_cast<void*>(0xface)), nullptr); | |
455 | EXPECT_EQ(s, "0xface"); | |
11fdf7f2 | 456 | } |