]> git.proxmox.com Git - ceph.git/blame - ceph/src/fmt/test/format-impl-test.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / fmt / test / format-impl-test.cc
CommitLineData
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
24using fmt::detail::bigint;
25using fmt::detail::fp;
26using fmt::detail::max_value;
eafe8130 27
f67539c2
TL
28static_assert(!std::is_copy_constructible<bigint>::value, "");
29static_assert(!std::is_copy_assignable<bigint>::value, "");
11fdf7f2 30
f67539c2
TL
31TEST(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
37TEST(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
51TEST(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
77TEST(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
87TEST(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
104TEST(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
121TEST(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
139TEST(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
145TEST(BigIntTest, DivModAssignSelf) {
146 bigint n(100);
147 EXPECT_THROW(n.divmod_assign(n), assertion_failure);
148}
149
150TEST(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
162TEST(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
182template <bool is_iec559> void run_double_tests() {
183 fmt::print("warning: double is not IEC559, skipping FP tests\n");
184}
185
186template <> 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
214TEST(FPTest, DoubleTests) {
215 run_double_tests<std::numeric_limits<double>::is_iec559>();
11fdf7f2
TL
216}
217
f67539c2
TL
218TEST(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
225TEST(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
252TEST(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
261TEST(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 273TEST(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
297TEST(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 319TEST(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 324template <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
343TEST(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
352TEST(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
360TEST(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
395TEST(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
428TEST(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.
436template <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
445TEST(UtilTest, CountDigits) {
446 test_count_digits<uint32_t>();
447 test_count_digits<uint64_t>();
448}
449
450TEST(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}