dynarmic/test/format-impl-test.cc
Lioncash d4c6fa3122 Squashed 'externals/fmt/' changes from 9bdd1596c..cd4af11ef
cd4af11ef Update version
1ebc2f7cc Bump version
f4c997062 Fix changelog
72920ba30 Update changelog
0907c08ae Fix handling of default alignmment with locale (#1801)
37c8f4eaf Don't use 128 bit integers with clang-cl (#1800)
eaaaec999 Workaround a bug in msvc
ccf8561cb Workaround broken numeric_limites, part 2 (#1787)
0cc73ebf7 Report error on missing named argument (#1796)
33efc3c94 Fix handling of iterators in locale-specific formatting (#1782)
b9d749095 Update version
86b63bb71 Bump version
cbf6be960 Update changelog
229ee9b46 Workaround broken numeric_limits (#1725)
2b7a146fa Fix a regression in handling digit separators (#1782)
89d0c7124 Fix compatibility with CMake 3.4 (#1779)
f19b1a521 Update version
5c67fefb2 Fix a changelog entry
1d2a556e1 Fix undefined reference error
04c9b62fb Merge release branch
6be6762e5 Fix date
f1dd2eb3c Bump version
fbf3b943c Workaround a bug in gcc
a29a01d30 Fix docs
9f0b3afb7 Bump version in namespace
86b2f99f8 Fix the docs
c472ff12d Update version
5173a76ba Update version
1614af352 Minor corrections in the changelog
569a9b3a7 Bump version
4e7e3c65a Update docs
0f7a6bfa1 Add a section on std::format compatibility
4faec5a5e Update README.rst
7dbc8ac71 Update changelog
c87dd746f Update changelog
372175caf Revert changelog changes
904754876 Add ClickHouse to the list of projects (#1751)
d30bca64e Revert changelog conversion since GFM is not supported there
d6047cdc4 Update changelog
810241b36 Convert changlog to markdown
661c47473 Rename changelog
7c33059fa Update ChangeLog.rst
9e20883ab Update README.rst
41899d522 Update changelog
f42f45908 Update changelog
2381df654 Update readme
7ae816563 Update README.rst
c56cf3d07 Update changelog and readme
01309a34a Deprecate arg_formatter
a62d06055 Update changelog
23e3a2eee Update changelog
d8e0554b9 Disable numeric formatting by default
1e8eea4f4 Update changelog
44bd5384a Fix formatting
20e19387a Update changelog
56fed7814 FMT_NUMERIC_ALIGN -> FMT_DEPRECATED_NUMERIC_ALIGN
56e63078f Make the n specifier an opt-in
31ce6bc70 Fix a conversion warning with Clang10 on Windows (#1750)
c9c5b90da Fix a typo. Thanks Tracy Chapman from TripleChecker
1f3f84631 Fix a typo
5de62af60 Fix possible infinite recursion in FMT_ASSERT (#1744)
cbddab2fe Use consistent include style
f69b6eaab Add a simple buffered stream with no sync
ba363b3a2 Use digit pairs as in unrolledlut
a6f8e7d86 Update changelog
e753244ab Update changelog
98a7a8b40 Update changelog and disable internal
3135d95fd Don't use non-portable attribute
8630a8f5f Tweak the docs
cc3a88e6b Extract docs from compile.h
79c4b6bd7 Apply clang-format
d130ee070 Document format string compilation
d0f90b5be Spelling fixes
6e080660d Update README.rst
31c3a2426 Spelling fixes
613b3b459 Spelling fixes
978521bb8 Fix a compile error introduced in #1738
4e94c649f Deprecate compile
1a83443e6 Add user-defined type support to compilation
8bef1c3b3 Tweaks for EDG based compilers (Intel, nVidia, MCST/Elbrus, etc).
b287c37c6 Do not use -Wl,--as-needed with emscripten.
2cac8a9d2 Reintroduce UDT support to fmt::to_string and test ADL
9a4cc8842 Add FMT_COMPILE support to format_to
5ddf9ee1b Streamline default FP formatting
0b3a83f7f Update README.rst
5aa5c9873 Added  #define WIN32_LEAN_AND_MEAN before including windows.h (#1729)
397ad1bec Optimize common case
7431165f3 Make to_string bypass format
ee4d4c7fd Inline compiled format
ab2f8484e Finish text::format
e900d735b Re-enable assert in format_decimal
f4de7b684 Fix ambiguity
1f8f5450b Reuse format_decimal
d702a68df Fix formatting of bool with FMT_COMPILE and add more tests
e956a14e9 Use write instead of format_int in to_string
98dcc251e Undo branching reduction
5b8641ddd Undo branching reduction
8c88abde6 Fix sign handling in 'L'
23b976a61 Reduce branching
9edee0e72 Optimize small string parsing
a909d42b7 Fix a warning
16637341b Enable compilation for all types
2d71d7e03 Add a simple format string compilation API
d259fcfb0 Tweak comments
704ed557a Move project in order to solve a CMake warning
8603bd20d Update README.rst
547f12ae6 Fix a warning (#1722)
f904e8a1b c++11 use formatting user-defined types (#1721)
100e8af08 Update README.rst
c11d0f056 Update README.rst
2453ee576 Improve default formatting
47ae52155 MINGW cross compiler fixes
936a1833c Add default_arg_formatter
f2c9cb624 Fix a UB
d3107f855 Cleanup arg_formatter_base
5e7c70e20 Simplify arg_formatter_base
38cc68b3e Inline visitor
6732ea500 Make symbols readable
57ddc77ce Make advance_to a noop for back_insert_iterator
50bad7d62 Optimize format string parsing
8f7a824e4 Inline visit
f11e96870 Optimize format string parsing
09737dd83 Optimize format handler
d9e3d6e6e Move format_handler to detail
795b47a7b Fix a warning (#1712)
95c6ac0cc fix typo which caused the loss of the counting information when using a printf context with a truncating_iterator
21409cfdd Fix warnings
88c8d534e Move digits10 to where they belong and add comments
0f3eaeac0 Fix a warning
344218510 Ignore /doc/node_modules directory
16aec0617 Cleanup arg_formatter_base
1e1193590 Fix format_decimal overloads
0893c9c2e Inline parse_format_string
3245145a4 Remove undocumented buffer_range and output_range
57fc44907 Increase VM disk size
7d22bebb6 Remove uses of buffer_range
8f2b5fe74 Don't install sphinx cache files
f095c67b6 Remove uses of buffer_range
5aabf1f71 Simplify copy_str
19c5b5d15 Simplify arg_formatter
519571ede Simplify arg_formatter_base
ac8dfd841 Improve handling of separators
2c6165a22 Reduce the number of comparisons
28639969e Use memcpy for copying digits
f5fa1dee5 Support custom FMT_INC_DIR in pkgconfig and cmake configs (#1702)
51bf9cfac Fix Mingw support
1a716caf5 Optimize common case
98d4bbf81 Update README.rst
8c8f74a87 fix zero flag for char types and make zero flag ignored if a precision is specified
bc1b89da2 Temporarily revert parsing changes
a7fb321ac Remove a redundant branch
8cadb9650 fix max/min macro (#1697)
297c3b2ed Fix an example (thanks Alexey Kuzmenko)
943532fec Make ostream formatter work with compile-time format strings (#1692)
bd8804019 Update README.rst
f230300ac Knuth is using fmt library (#1691)
a265e25b7 Optimize small string parsing
2aa2526f6 Optimize small string concatenation
8d78045e7 Move void_t to where it's used
7aafa6bc6 Update analytics
c66aae165 Adding sentinel support to fmt::join(). (#1689)
6d66de380 Add c specifier support to integral types (#1652)
6b219a58d fix interaction of space flag and '+' flag, as well as '-' flag and '0' flag (#1687)
eee2023c2 Update signatures
c5ed73aab Add fmt::detail::buffer to the docs (#704)
ea1cd9638 Fix apidoc
d3964d7b1 Merge branch 'master' of github.com:fmtlib/fmt
d18c6723a Update docs
96c18b26c make plus flag for printf not be ignored for char argument (#1683)
ba25baeb9 Apply doc patch to 6.2.1
981b517cc nested replacement fields may omit arg_id (#1681)
922ea924b Make dynamic_format_arg_store reusable and add reserve() (#1677)
e0d98923c Update version
806926537 internal -> detail (#1538)
963ee0831 Simplify named arguments
02a6fe59f Named arguments go brrr
de290f5c4 Ditch internal::arg_map
d0623de51 Bump version
73e335ed3 Make implicit capture explicit for C++20 (#1669)
b4d46e398 Update changelog
a182f7341 Update changelog
68201831a Support named args in dynamic_format_arg_store (#1655). (#1663)
7f723fbcb Consistently namespace qualify size_t
c06851456 Purge basic_writer
2f05054dd Purge basic_writer
f0ce21164 Revert enum change
44639b11f Fix some warnings (#1667)
1c86a99e8 Purge basic_writer
8f511fc12 Make copyfmt not throw (#1666)
59fe455f3 Remove compatibility stubs
b0f47a13e Separate nonfinite formatting
d6cea50d0 Remove deprecated APIs
40bc7163f Move FMT_MAYBE_UNUSED to where it's actually used
080e44d0b Fix inconsistent type detection (#1662)
7e57cace5 Exclude std::abort from compilation when compiling CUDA with Clang (#1661)
7b66e2f21 Inherit arg_formatter_base from basic_writer
bab3f5800 Refactor pointer formatting
9cc7edfdd Move int_writer to the namespace scope
8d9d528bf Improve handling of alignment
8efd1a8ef Improve handling of alignment
a71bc9c82 Use '0' fill with numeric align for consistency with std::format
60d85d598 Suppress ubsan warning
c3099beb6 Cleanup
cbb4cb899 Remove undocumented deprecated APIs
b85e9ac38 Simplify vformat_to
e3710ab97 FMT_CONSTEXPR -> constexpr
d59751f0f Update date formatting example to use threadsafe localtime
d6abb2fa0 Reduce library size
e9fdea90b Update README.rst
44b6584f2 Update README.rst
78f041ab5 build: Fix installation paths
7ca89bf87 Reduce template bloat in write_int
3c114d091 Fix a shadowing warning (#1658)
e2ef12a8c Allow to avoid inclusion of os.cc in fmt target
bca82719a Pass iterator by value
99da38962 Make write_padded non-members
f19d66794 Bump fuzzer allocation limit
3e6984761 Reduce branching in write_padded
9ac1eebd4 Reduce library size
e2ff91067 Replace FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION  with fmt-specific macro (#1650)
f2ed03b91 Fix a warning (#1649)
9dde9f013 Reduce library size
b1af642d1 Reduce library size
4a617f25c Clarify encoding conversion in chrono
6f435f55c Improve compile time by using extern template (#1452)
cb475cb88 Clarify why we don't check argument id
1e1ac6e96 Check dynamic width/precision id at compile time (#1614)
e51c449fe Revert "Check dynamic widht/precision id at compile time (#1614)"
0463665ef Don't access a C string past precision in printf (#1595)
7d748a6f8 Check dynamic widht/precision id at compile time (#1614)
2b75bd7ce Get rid of do_check_format_string
4a1d5931c Simplify udl_formatter with FMT_STRING
811b0f905 Enable compile-time error tests
450e8eed9 Fix markup
b8fbcec1b Clarify formatter reuse
56bc86ffa Suppress bogus MSVC analysis warnings
3f79357ef Fix a recent regression in handling max packed arguments
8a11148f9 Add Facebook Folly to the list of projects
e371e8b68 Tweak readme
813732fed Improve readme formatting
3670d5b3f README: add vectorized.io/redpanda in the list of users
9e2ad7cf6 Add windows terminal to the projects using {fmt}
63479c851 Use a delegating ctor and add inlines
5944fcad3 Remove remaining wchar_t instantiation
e253b371b Don't generate RTTI for allocator
0c86f467b Fix build on ancient gcc
1929df4bc Simplify format_args
a13822181 Always inline arg_data functions
04e0dfd4b Always inline value ctors
04cde756b Simplify checks
c9a57b9a8 Fix incorrect assumptions about nul termination
f46f5ecaf Reenable constexpr _compile on GCC 9
6e8d7e277 Don't use constexpr on Intel compiler (#1628)
567ed03f8 Merge arg overloads and cleanup
c3fa33314 Remove warning in core.h with when compiling with gcc and -Wshadow
84898b462 Remove warning in format.h when compiling with gcc and -Wshadow
538d83fd0 Cleanup named arguments
8a4630686 Improve handling of named arguments
a9d62d3f3 Add check for CompiledFormat to avoid ambiguous call
fdcf7870a Add stack-based named argument storage
5899267c4 Fix a clang-tidy warning
07b4c246e Fix a typo
e99809f29 Fix ostream support in sprintf (#1631)
3cd5179f3 Fixed clang tidy warning -multiple declarations in a single statement reduces readability
7404e33a7 Fix clang warning about explicit ctor
3aab2171e Clean up basic_format_args
7645ca072 Clean up printf
e30d8391e Suppress an MSVC warning (#1622)
8cd8ef03e Simplify warning suppression
bbb6b357c Add floating-point L specifier (#1624)
36ea32640 Suppress a bogus MSVC warning
141a00d64 Define FMT_EXTERN_TEMPLATE_API on export
3860edc5d Bump version
7d01859ef Fix handling of unsigned char strings in printf
63b23e786 Merge branch 'master' of github.com:fmtlib/fmt
4999796c1 Fix the docs
34b3f7b7a Avoid windows issue with min() max() macros
27e3c0fe9 Update signature in the docs

git-subtree-dir: externals/fmt
git-subtree-split: cd4af11efc9c622896a3e4cb599fa28668ca3d05
2020-09-19 14:25:26 -04:00

456 lines
15 KiB
C++

// Formatting library for C++ - formatting library implementation tests
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#define FMT_NOEXCEPT
#undef FMT_SHARED
#include "test-assert.h"
// Include format.cc instead of format.h to test implementation.
#include <algorithm>
#include <cstring>
#include "../src/format.cc"
#include "fmt/printf.h"
#include "gmock.h"
#include "gtest-extra.h"
#include "util.h"
#undef max
using fmt::detail::bigint;
using fmt::detail::fp;
using fmt::detail::max_value;
static_assert(!std::is_copy_constructible<bigint>::value, "");
static_assert(!std::is_copy_assignable<bigint>::value, "");
TEST(BigIntTest, Construct) {
EXPECT_EQ("", fmt::format("{}", bigint()));
EXPECT_EQ("42", fmt::format("{}", bigint(0x42)));
EXPECT_EQ("123456789abcedf0", fmt::format("{}", bigint(0x123456789abcedf0)));
}
TEST(BigIntTest, Compare) {
bigint n1(42);
bigint n2(42);
EXPECT_EQ(compare(n1, n2), 0);
n2 <<= 32;
EXPECT_LT(compare(n1, n2), 0);
bigint n3(43);
EXPECT_LT(compare(n1, n3), 0);
EXPECT_GT(compare(n3, n1), 0);
bigint n4(42 * 0x100000001);
EXPECT_LT(compare(n2, n4), 0);
EXPECT_GT(compare(n4, n2), 0);
}
TEST(BigIntTest, AddCompare) {
EXPECT_LT(
add_compare(bigint(0xffffffff), bigint(0xffffffff), bigint(1) <<= 64), 0);
EXPECT_LT(add_compare(bigint(1) <<= 32, bigint(1), bigint(1) <<= 96), 0);
EXPECT_GT(add_compare(bigint(1) <<= 32, bigint(0), bigint(0xffffffff)), 0);
EXPECT_GT(add_compare(bigint(0), bigint(1) <<= 32, bigint(0xffffffff)), 0);
EXPECT_GT(add_compare(bigint(42), bigint(1), bigint(42)), 0);
EXPECT_GT(add_compare(bigint(0xffffffff), bigint(1), bigint(0xffffffff)), 0);
EXPECT_LT(add_compare(bigint(10), bigint(10), bigint(22)), 0);
EXPECT_LT(add_compare(bigint(0x100000010), bigint(0x100000010),
bigint(0x300000010)),
0);
EXPECT_GT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
bigint(0x300000000)),
0);
EXPECT_EQ(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
bigint(0x300000001)),
0);
EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
bigint(0x300000002)),
0);
EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
bigint(0x300000003)),
0);
}
TEST(BigIntTest, ShiftLeft) {
bigint n(0x42);
n <<= 0;
EXPECT_EQ("42", fmt::format("{}", n));
n <<= 1;
EXPECT_EQ("84", fmt::format("{}", n));
n <<= 25;
EXPECT_EQ("108000000", fmt::format("{}", n));
}
TEST(BigIntTest, Multiply) {
bigint n(0x42);
EXPECT_THROW(n *= 0, assertion_failure);
n *= 1;
EXPECT_EQ("42", fmt::format("{}", n));
n *= 2;
EXPECT_EQ("84", fmt::format("{}", n));
n *= 0x12345678;
EXPECT_EQ("962fc95e0", fmt::format("{}", n));
bigint bigmax(max_value<uint32_t>());
bigmax *= max_value<uint32_t>();
EXPECT_EQ("fffffffe00000001", fmt::format("{}", bigmax));
bigmax.assign(max_value<uint64_t>());
bigmax *= max_value<uint64_t>();
EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", bigmax));
}
TEST(BigIntTest, Accumulator) {
fmt::detail::accumulator acc;
EXPECT_EQ(acc.lower, 0);
EXPECT_EQ(acc.upper, 0);
acc.upper = 12;
acc.lower = 34;
EXPECT_EQ(static_cast<uint32_t>(acc), 34);
acc += 56;
EXPECT_EQ(acc.lower, 90);
acc += fmt::detail::max_value<uint64_t>();
EXPECT_EQ(acc.upper, 13);
EXPECT_EQ(acc.lower, 89);
acc >>= 32;
EXPECT_EQ(acc.upper, 0);
EXPECT_EQ(acc.lower, 13 * 0x100000000);
}
TEST(BigIntTest, Square) {
bigint n0(0);
n0.square();
EXPECT_EQ("0", fmt::format("{}", n0));
bigint n1(0x100);
n1.square();
EXPECT_EQ("10000", fmt::format("{}", n1));
bigint n2(0xfffffffff);
n2.square();
EXPECT_EQ("ffffffffe000000001", fmt::format("{}", n2));
bigint n3(max_value<uint64_t>());
n3.square();
EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", n3));
bigint n4;
n4.assign_pow10(10);
EXPECT_EQ("2540be400", fmt::format("{}", n4));
}
TEST(BigIntTest, DivModAssignZeroDivisor) {
bigint zero(0);
EXPECT_THROW(bigint(0).divmod_assign(zero), assertion_failure);
EXPECT_THROW(bigint(42).divmod_assign(zero), assertion_failure);
}
TEST(BigIntTest, DivModAssignSelf) {
bigint n(100);
EXPECT_THROW(n.divmod_assign(n), assertion_failure);
}
TEST(BigIntTest, DivModAssignUnaligned) {
// (42 << 340) / pow(10, 100):
bigint n1(42);
n1 <<= 340;
bigint n2;
n2.assign_pow10(100);
int result = n1.divmod_assign(n2);
EXPECT_EQ(result, 9406);
EXPECT_EQ("10f8353019583bfc29ffc8f564e1b9f9d819dbb4cf783e4507eca1539220p96",
fmt::format("{}", n1));
}
TEST(BigIntTest, DivModAssign) {
// 100 / 10:
bigint n1(100);
int result = n1.divmod_assign(bigint(10));
EXPECT_EQ(result, 10);
EXPECT_EQ("0", fmt::format("{}", n1));
// pow(10, 100) / (42 << 320):
n1.assign_pow10(100);
result = n1.divmod_assign(bigint(42) <<= 320);
EXPECT_EQ(result, 111);
EXPECT_EQ("13ad2594c37ceb0b2784c4ce0bf38ace408e211a7caab24308a82e8f10p96",
fmt::format("{}", n1));
// 42 / 100:
bigint n2(42);
n1.assign_pow10(2);
result = n2.divmod_assign(n1);
EXPECT_EQ(result, 0);
EXPECT_EQ("2a", fmt::format("{}", n2));
}
template <bool is_iec559> void run_double_tests() {
fmt::print("warning: double is not IEC559, skipping FP tests\n");
}
template <> void run_double_tests<true>() {
// Construct from double.
EXPECT_EQ(fp(1.23), fp(0x13ae147ae147aeu, -52));
// Compute boundaries:
fp value;
// Normalized & not power of 2 - equidistant boundaries:
auto b = value.assign_with_boundaries(1.23);
EXPECT_EQ(value, fp(0x0013ae147ae147ae, -52));
EXPECT_EQ(b.lower, 0x9d70a3d70a3d6c00);
EXPECT_EQ(b.upper, 0x9d70a3d70a3d7400);
// Normalized power of 2 - lower boundary is closer:
b = value.assign_with_boundaries(1.9807040628566084e+28); // 2**94
EXPECT_EQ(value, fp(0x0010000000000000, 42));
EXPECT_EQ(b.lower, 0x7ffffffffffffe00);
EXPECT_EQ(b.upper, 0x8000000000000400);
// Smallest normalized double - equidistant boundaries:
b = value.assign_with_boundaries(2.2250738585072014e-308);
EXPECT_EQ(value, fp(0x0010000000000000, -1074));
EXPECT_EQ(b.lower, 0x7ffffffffffffc00);
EXPECT_EQ(b.upper, 0x8000000000000400);
// Subnormal - equidistant boundaries:
b = value.assign_with_boundaries(4.9406564584124654e-324);
EXPECT_EQ(value, fp(0x0000000000000001, -1074));
EXPECT_EQ(b.lower, 0x4000000000000000);
EXPECT_EQ(b.upper, 0xc000000000000000);
}
TEST(FPTest, DoubleTests) {
run_double_tests<std::numeric_limits<double>::is_iec559>();
}
TEST(FPTest, Normalize) {
const auto v = fp(0xbeef, 42);
auto normalized = normalize(v);
EXPECT_EQ(0xbeef000000000000, normalized.f);
EXPECT_EQ(-6, normalized.e);
}
TEST(FPTest, ComputeFloatBoundaries) {
struct {
double x, lower, upper;
} tests[] = {
// regular
{1.5f, 1.4999999403953552, 1.5000000596046448},
// boundary
{1.0f, 0.9999999701976776, 1.0000000596046448},
// min normal
{1.1754944e-38f, 1.1754942807573643e-38, 1.1754944208872107e-38},
// max subnormal
{1.1754942e-38f, 1.1754941406275179e-38, 1.1754942807573643e-38},
// min subnormal
{1e-45f, 7.006492321624085e-46, 2.1019476964872256e-45},
};
for (auto test : tests) {
fp vlower = normalize(fp(test.lower));
fp vupper = normalize(fp(test.upper));
vlower.f >>= vupper.e - vlower.e;
vlower.e = vupper.e;
fp value;
auto b = value.assign_float_with_boundaries(test.x);
EXPECT_EQ(vlower.f, b.lower);
EXPECT_EQ(vupper.f, b.upper);
}
}
TEST(FPTest, Multiply) {
auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
EXPECT_EQ(v.f, 123u * 56u);
EXPECT_EQ(v.e, 4 + 7 + 64);
v = fp(123ULL << 32, 4) * fp(567ULL << 31, 8);
EXPECT_EQ(v.f, (123 * 567 + 1u) / 2);
EXPECT_EQ(v.e, 4 + 8 + 64);
}
TEST(FPTest, GetCachedPower) {
typedef std::numeric_limits<double> limits;
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
int dec_exp = 0;
auto fp = fmt::detail::get_cached_power(exp, dec_exp);
EXPECT_LE(exp, fp.e);
int dec_exp_step = 8;
EXPECT_LE(fp.e, exp + dec_exp_step * log2(10));
EXPECT_DOUBLE_EQ(pow(10, dec_exp), ldexp(static_cast<double>(fp.f), fp.e));
}
}
TEST(FPTest, GetRoundDirection) {
using fmt::detail::get_round_direction;
using fmt::detail::round_direction;
EXPECT_EQ(round_direction::down, get_round_direction(100, 50, 0));
EXPECT_EQ(round_direction::up, get_round_direction(100, 51, 0));
EXPECT_EQ(round_direction::down, get_round_direction(100, 40, 10));
EXPECT_EQ(round_direction::up, get_round_direction(100, 60, 10));
for (size_t i = 41; i < 60; ++i)
EXPECT_EQ(round_direction::unknown, get_round_direction(100, i, 10));
uint64_t max = max_value<uint64_t>();
EXPECT_THROW(get_round_direction(100, 100, 0), assertion_failure);
EXPECT_THROW(get_round_direction(100, 0, 100), assertion_failure);
EXPECT_THROW(get_round_direction(100, 0, 50), assertion_failure);
// Check that remainder + error doesn't overflow.
EXPECT_EQ(round_direction::up, get_round_direction(max, max - 1, 2));
// Check that 2 * (remainder + error) doesn't overflow.
EXPECT_EQ(round_direction::unknown,
get_round_direction(max, max / 2 + 1, max / 2));
// Check that remainder - error doesn't overflow.
EXPECT_EQ(round_direction::unknown, get_round_direction(100, 40, 41));
// Check that 2 * (remainder - error) doesn't overflow.
EXPECT_EQ(round_direction::up, get_round_direction(max, max - 1, 1));
}
TEST(FPTest, FixedHandler) {
struct handler : fmt::detail::fixed_handler {
char buffer[10];
handler(int prec = 0) : fmt::detail::fixed_handler() {
buf = buffer;
precision = prec;
}
};
int exp = 0;
handler().on_digit('0', 100, 99, 0, exp, false);
EXPECT_THROW(handler().on_digit('0', 100, 100, 0, exp, false),
assertion_failure);
namespace digits = fmt::detail::digits;
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, exp, false), digits::done);
// Check that divisor - error doesn't overflow.
EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, exp, false), digits::error);
// Check that 2 * error doesn't overflow.
uint64_t max = max_value<uint64_t>();
EXPECT_EQ(handler(1).on_digit('0', max, 10, max - 1, exp, false),
digits::error);
}
TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) {
fmt::memory_buffer buf;
format_float(0.42, -1, fmt::detail::float_specs(), buf);
}
template <typename T> struct value_extractor {
T operator()(T value) { return value; }
template <typename U> FMT_NORETURN T operator()(U) {
throw std::runtime_error(fmt::format("invalid type {}", typeid(U).name()));
}
#if FMT_USE_INT128
// Apple Clang does not define typeid for __int128_t and __uint128_t.
FMT_NORETURN T operator()(fmt::detail::int128_t) {
throw std::runtime_error("invalid type __int128_t");
}
FMT_NORETURN T operator()(fmt::detail::uint128_t) {
throw std::runtime_error("invalid type __uint128_t");
}
#endif
};
TEST(FormatTest, ArgConverter) {
long long value = max_value<long long>();
auto arg = fmt::detail::make_arg<fmt::format_context>(value);
fmt::visit_format_arg(
fmt::detail::arg_converter<long long, fmt::format_context>(arg, 'd'),
arg);
EXPECT_EQ(value, fmt::visit_format_arg(value_extractor<long long>(), arg));
}
TEST(FormatTest, FormatNegativeNaN) {
double nan = std::numeric_limits<double>::quiet_NaN();
if (std::signbit(-nan))
EXPECT_EQ("-nan", fmt::format("{}", -nan));
else
fmt::print("Warning: compiler doesn't handle negative NaN correctly");
}
TEST(FormatTest, StrError) {
char* message = nullptr;
char buffer[BUFFER_SIZE];
EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = nullptr, 0),
"invalid buffer");
EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = buffer, 0),
"invalid buffer");
buffer[0] = 'x';
#if defined(_GNU_SOURCE) && !defined(__COVERITY__)
// Use invalid error code to make sure that safe_strerror returns an error
// message in the buffer rather than a pointer to a static string.
int error_code = -1;
#else
int error_code = EDOM;
#endif
int result =
fmt::detail::safe_strerror(error_code, message = buffer, BUFFER_SIZE);
EXPECT_EQ(result, 0);
size_t message_size = std::strlen(message);
EXPECT_GE(BUFFER_SIZE - 1u, message_size);
EXPECT_EQ(get_system_error(error_code), message);
// safe_strerror never uses buffer on MinGW.
#if !defined(__MINGW32__) && !defined(__sun)
result =
fmt::detail::safe_strerror(error_code, message = buffer, message_size);
EXPECT_EQ(ERANGE, result);
result = fmt::detail::safe_strerror(error_code, message = buffer, 1);
EXPECT_EQ(buffer, message); // Message should point to buffer.
EXPECT_EQ(ERANGE, result);
EXPECT_STREQ("", message);
#endif
}
TEST(FormatTest, FormatErrorCode) {
std::string msg = "error 42", sep = ": ";
{
fmt::memory_buffer buffer;
format_to(buffer, "garbage");
fmt::detail::format_error_code(buffer, 42, "test");
EXPECT_EQ("test: " + msg, to_string(buffer));
}
{
fmt::memory_buffer buffer;
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size() + 1,
'x');
fmt::detail::format_error_code(buffer, 42, prefix);
EXPECT_EQ(msg, to_string(buffer));
}
int codes[] = {42, -1};
for (size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) {
// Test maximum buffer size.
msg = fmt::format("error {}", codes[i]);
fmt::memory_buffer buffer;
std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
fmt::detail::format_error_code(buffer, codes[i], prefix);
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
size_t size = fmt::inline_buffer_size;
EXPECT_EQ(size, buffer.size());
buffer.resize(0);
// Test with a message that doesn't fit into the buffer.
prefix += 'x';
fmt::detail::format_error_code(buffer, codes[i], prefix);
EXPECT_EQ(msg, to_string(buffer));
}
}
TEST(FormatTest, CountCodePoints) {
EXPECT_EQ(4,
fmt::detail::count_code_points(
fmt::basic_string_view<fmt::detail::char8_type>(
reinterpret_cast<const fmt::detail::char8_type*>("ёжик"))));
}
// Tests fmt::detail::count_digits for integer type Int.
template <typename Int> void test_count_digits() {
for (Int i = 0; i < 10; ++i) EXPECT_EQ(1u, fmt::detail::count_digits(i));
for (Int i = 1, n = 1, end = max_value<Int>() / 10; n <= end; ++i) {
n *= 10;
EXPECT_EQ(i, fmt::detail::count_digits(n - 1));
EXPECT_EQ(i + 1, fmt::detail::count_digits(n));
}
}
TEST(UtilTest, CountDigits) {
test_count_digits<uint32_t>();
test_count_digits<uint64_t>();
}
TEST(UtilTest, WriteFallbackUIntPtr) {
std::string s;
fmt::detail::write_ptr<char>(
std::back_inserter(s),
fmt::detail::fallback_uintptr(reinterpret_cast<void*>(0xface)), nullptr);
EXPECT_EQ(s, "0xface");
}