1 // Formatting library for C++ - formatting library implementation tests
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
10 #include "test-assert.h"
12 // Include format.cc instead of format.h to test implementation.
13 #include "../src/format.cc"
14 #include "fmt/color.h"
15 #include "fmt/printf.h"
21 #include "gtest-extra.h"
27 #if FMT_HAS_CPP_ATTRIBUTE(noreturn)
28 # define FMT_NORETURN [[noreturn]]
33 using fmt::internal::fp
;
35 template <bool is_iec559
>
36 void test_construct_from_double() {
37 fmt::print("warning: double is not IEC559, skipping FP tests\n");
41 void test_construct_from_double
<true>() {
43 EXPECT_EQ(v
.f
, 0x13ae147ae147aeu
);
47 TEST(FPTest
, ConstructFromDouble
) {
48 test_construct_from_double
<std::numeric_limits
<double>::is_iec559
>();
51 TEST(FPTest
, Normalize
) {
52 auto v
= fp(0xbeef, 42);
54 EXPECT_EQ(0xbeef000000000000, v
.f
);
58 TEST(FPTest
, ComputeBoundariesSubnormal
) {
59 auto v
= fp(0xbeef, 42);
61 v
.compute_boundaries(lower
, upper
);
62 EXPECT_EQ(0xbeee800000000000, lower
.f
);
63 EXPECT_EQ(-6, lower
.e
);
64 EXPECT_EQ(0xbeef800000000000, upper
.f
);
65 EXPECT_EQ(-6, upper
.e
);
68 TEST(FPTest
, ComputeBoundaries
) {
69 auto v
= fp(0x10000000000000, 42);
71 v
.compute_boundaries(lower
, upper
);
72 EXPECT_EQ(0x7ffffffffffffe00, lower
.f
);
73 EXPECT_EQ(31, lower
.e
);
74 EXPECT_EQ(0x8000000000000400, upper
.f
);
75 EXPECT_EQ(31, upper
.e
);
78 TEST(FPTest
, Subtract
) {
79 auto v
= fp(123, 1) - fp(102, 1);
84 TEST(FPTest
, Multiply
) {
85 auto v
= fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
86 EXPECT_EQ(v
.f
, 123u * 56u);
87 EXPECT_EQ(v
.e
, 4 + 7 + 64);
88 v
= fp(123ULL << 32, 4) * fp(567ULL << 31, 8);
89 EXPECT_EQ(v
.f
, (123 * 567 + 1u) / 2);
90 EXPECT_EQ(v
.e
, 4 + 8 + 64);
93 TEST(FPTest
, GetCachedPower
) {
94 typedef std::numeric_limits
<double> limits
;
95 for (auto exp
= limits::min_exponent
; exp
<= limits::max_exponent
; ++exp
) {
97 auto fp
= fmt::internal::get_cached_power(exp
, dec_exp
);
100 EXPECT_LE(fp
.e
, exp
+ dec_exp_step
* log2(10));
101 EXPECT_DOUBLE_EQ(pow(10, dec_exp
), ldexp(fp
.f
, fp
.e
));
105 TEST(FPTest
, Grisu2FormatCompilesWithNonIEEEDouble
) {
106 fmt::memory_buffer buf
;
107 grisu2_format(4.2f
, buf
, fmt::core_format_specs());
110 template <typename T
>
111 struct ValueExtractor
: fmt::internal::function
<T
> {
112 T
operator()(T value
) {
116 template <typename U
>
117 FMT_NORETURN T
operator()(U
) {
118 throw std::runtime_error(fmt::format("invalid type {}", typeid(U
).name()));
122 TEST(FormatTest
, ArgConverter
) {
123 long long value
= std::numeric_limits
<long long>::max();
124 auto arg
= fmt::internal::make_arg
<fmt::format_context
>(value
);
125 visit(fmt::internal::arg_converter
<long long, fmt::format_context
>(arg
, 'd'),
127 EXPECT_EQ(value
, visit(ValueExtractor
<long long>(), arg
));
130 TEST(FormatTest
, FormatNegativeNaN
) {
131 double nan
= std::numeric_limits
<double>::quiet_NaN();
132 if (std::signbit(-nan
))
133 EXPECT_EQ("-nan", fmt::format("{}", -nan
));
135 fmt::print("Warning: compiler doesn't handle negative NaN correctly");
138 TEST(FormatTest
, StrError
) {
139 char *message
= FMT_NULL
;
140 char buffer
[BUFFER_SIZE
];
141 EXPECT_ASSERT(fmt::safe_strerror(EDOM
, message
= FMT_NULL
, 0),
143 EXPECT_ASSERT(fmt::safe_strerror(EDOM
, message
= buffer
, 0),
146 #if defined(_GNU_SOURCE) && !defined(__COVERITY__)
147 // Use invalid error code to make sure that safe_strerror returns an error
148 // message in the buffer rather than a pointer to a static string.
151 int error_code
= EDOM
;
154 int result
= fmt::safe_strerror(error_code
, message
= buffer
, BUFFER_SIZE
);
155 EXPECT_EQ(result
, 0);
156 std::size_t message_size
= std::strlen(message
);
157 EXPECT_GE(BUFFER_SIZE
- 1u, message_size
);
158 EXPECT_EQ(get_system_error(error_code
), message
);
160 // safe_strerror never uses buffer on MinGW.
162 result
= fmt::safe_strerror(error_code
, message
= buffer
, message_size
);
163 EXPECT_EQ(ERANGE
, result
);
164 result
= fmt::safe_strerror(error_code
, message
= buffer
, 1);
165 EXPECT_EQ(buffer
, message
); // Message should point to buffer.
166 EXPECT_EQ(ERANGE
, result
);
167 EXPECT_STREQ("", message
);
171 TEST(FormatTest
, FormatErrorCode
) {
172 std::string msg
= "error 42", sep
= ": ";
174 fmt::memory_buffer buffer
;
175 format_to(buffer
, "garbage");
176 fmt::format_error_code(buffer
, 42, "test");
177 EXPECT_EQ("test: " + msg
, to_string(buffer
));
180 fmt::memory_buffer buffer
;
182 fmt::inline_buffer_size
- msg
.size() - sep
.size() + 1, 'x');
183 fmt::format_error_code(buffer
, 42, prefix
);
184 EXPECT_EQ(msg
, to_string(buffer
));
186 int codes
[] = {42, -1};
187 for (std::size_t i
= 0, n
= sizeof(codes
) / sizeof(*codes
); i
< n
; ++i
) {
188 // Test maximum buffer size.
189 msg
= fmt::format("error {}", codes
[i
]);
190 fmt::memory_buffer buffer
;
192 fmt::inline_buffer_size
- msg
.size() - sep
.size(), 'x');
193 fmt::format_error_code(buffer
, codes
[i
], prefix
);
194 EXPECT_EQ(prefix
+ sep
+ msg
, to_string(buffer
));
195 std::size_t size
= fmt::inline_buffer_size
;
196 EXPECT_EQ(size
, buffer
.size());
198 // Test with a message that doesn't fit into the buffer.
200 fmt::format_error_code(buffer
, codes
[i
], prefix
);
201 EXPECT_EQ(msg
, to_string(buffer
));
205 TEST(FormatTest
, CountCodePoints
) {
206 EXPECT_EQ(4, fmt::internal::count_code_points(fmt::u8string_view("ёжик")));
209 TEST(ColorsTest
, Colors
) {
210 EXPECT_WRITE(stdout
, fmt::print(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
211 "\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
212 EXPECT_WRITE(stdout
, fmt::print(fg(fmt::color::blue
), "blue"),
213 "\x1b[38;2;000;000;255mblue\x1b[0m");
216 fmt::print(fg(fmt::color::blue
) | bg(fmt::color::red
), "two color"),
217 "\x1b[38;2;000;000;255m\x1b[48;2;255;000;000mtwo color\x1b[0m");
218 EXPECT_WRITE(stdout
, fmt::print(fmt::emphasis::bold
, "bold"),
219 "\x1b[1mbold\x1b[0m");
220 EXPECT_WRITE(stdout
, fmt::print(fmt::emphasis::italic
, "italic"),
221 "\x1b[3mitalic\x1b[0m");
222 EXPECT_WRITE(stdout
, fmt::print(fmt::emphasis::underline
, "underline"),
223 "\x1b[4munderline\x1b[0m");
225 fmt::print(fmt::emphasis::strikethrough
, "strikethrough"),
226 "\x1b[9mstrikethrough\x1b[0m");
229 fmt::print(fg(fmt::color::blue
) | fmt::emphasis::bold
, "blue/bold"),
230 "\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m");
231 EXPECT_WRITE(stderr
, fmt::print(stderr
, fmt::emphasis::bold
, "bold error"),
232 "\x1b[1mbold error\x1b[0m");
233 EXPECT_WRITE(stderr
, fmt::print(stderr
, fg(fmt::color::blue
), "blue log"),
234 "\x1b[38;2;000;000;255mblue log\x1b[0m");
235 EXPECT_WRITE(stdout
, fmt::print(fmt::text_style(), "hi"), "hi");