1 // Formatting library for C++ - module tests
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
8 // Copyright (c) 2021 - present, Daniela Engert
13 // hide some implementation bugs in msvc
14 // that are not essential to users of the module.
15 # define FMT_HIDE_MODULE_BUGS
26 #include <string_view>
27 #include <system_error>
29 #if (__has_include(<fcntl.h>) || defined(__APPLE__) || \
30 defined(__linux__)) && \
31 (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
33 # define FMT_USE_FCNTL 1
35 # define FMT_USE_FCNTL 0
37 #if defined(_WIN32) && !defined(__MINGW32__)
38 # define FMT_POSIX(call) _##call
40 # define FMT_POSIX(call) call
45 // check for macros leaking from BMI
46 static bool macro_leaked
=
47 #if defined(FMT_CORE_H_) || defined(FMT_FORMAT_H_)
53 #define FMT_OS_H_ // don't pull in os.h, neither directly nor indirectly
54 #include "gtest-extra.h"
56 // an implicitly exported namespace must be visible [module.interface]/2.2
57 TEST(module_test
, namespace) {
59 using namespace fmt::literals
;
64 bool oops_detail_namespace_is_visible
;
68 bool namespace_detail_invisible() {
69 #if defined(FMT_HIDE_MODULE_BUGS) && defined(_MSC_FULL_VER) && \
70 _MSC_FULL_VER <= 193700000
71 // bug in msvc up to at least 17.7:
73 // the namespace is visible even when it is neither
74 // implicitly nor explicitly exported
77 using namespace detail
;
78 // this fails to compile if fmt::detail is visible
79 return !oops_detail_namespace_is_visible
;
84 // the non-exported namespace 'detail' must be invisible [module.interface]/2
85 TEST(module_test
, detail_namespace
) {
86 EXPECT_TRUE(fmt::namespace_detail_invisible());
89 // macros must not be imported from a *named* module [cpp.import]/5.1
90 TEST(module_test
, macros
) {
91 #if defined(FMT_HIDE_MODULE_BUGS) && defined(_MSC_FULL_VER) && \
92 _MSC_FULL_VER <= 192930130
93 // bug in msvc up to 16.11-pre2:
94 // include-guard macros leak from BMI
95 // and even worse: they cannot be #undef-ined
98 EXPECT_FALSE(macro_leaked
);
101 // The following is less about functional testing (that's done elsewhere)
102 // but rather visibility of all client-facing overloads, reachability of
103 // non-exported entities, name lookup and overload resolution within
104 // template instantitions.
105 // Exercise all exported entities of the API at least once.
106 // Instantiate as many code paths as possible.
108 TEST(module_test
, to_string
) {
109 EXPECT_EQ("42", fmt::to_string(42));
110 EXPECT_EQ("42", fmt::to_string(42.0));
112 EXPECT_EQ(L
"42", fmt::to_wstring(42));
113 EXPECT_EQ(L
"42", fmt::to_wstring(42.0));
116 TEST(module_test
, format
) {
117 EXPECT_EQ("42", fmt::format("{:}", 42));
118 EXPECT_EQ("-42", fmt::format("{0}", -42.0));
120 EXPECT_EQ(L
"42", fmt::format(L
"{:}", 42));
121 EXPECT_EQ(L
"-42", fmt::format(L
"{0}", -42.0));
124 TEST(module_test
, format_to
) {
126 fmt::format_to(std::back_inserter(s
), "{}", 42);
129 char buffer
[4] = {0};
130 fmt::format_to(buffer
, "{}", 42);
131 EXPECT_EQ("42", std::string_view(buffer
));
133 fmt::memory_buffer mb
;
134 fmt::format_to(std::back_inserter(mb
), "{}", 42);
135 EXPECT_EQ("42", std::string_view(buffer
));
138 fmt::format_to(std::back_inserter(w
), L
"{}", 42);
141 wchar_t wbuffer
[4] = {0};
142 fmt::format_to(wbuffer
, L
"{}", 42);
143 EXPECT_EQ(L
"42", std::wstring_view(wbuffer
));
145 fmt::wmemory_buffer wb
;
146 fmt::format_to(std::back_inserter(wb
), L
"{}", 42);
147 EXPECT_EQ(L
"42", std::wstring_view(wbuffer
));
150 TEST(module_test
, formatted_size
) {
151 EXPECT_EQ(2u, fmt::formatted_size("{}", 42));
152 EXPECT_EQ(2u, fmt::formatted_size(L
"{}", 42));
155 TEST(module_test
, format_to_n
) {
157 auto result
= fmt::format_to_n(std::back_inserter(s
), 1, "{}", 42);
158 EXPECT_EQ(2u, result
.size
);
159 char buffer
[4] = {0};
160 fmt::format_to_n(buffer
, 3, "{}", 12345);
163 auto wresult
= fmt::format_to_n(std::back_inserter(w
), 1, L
"{}", 42);
164 EXPECT_EQ(2u, wresult
.size
);
165 wchar_t wbuffer
[4] = {0};
166 fmt::format_to_n(wbuffer
, 3, L
"{}", 12345);
169 TEST(module_test
, format_args
) {
170 auto no_args
= fmt::format_args();
171 EXPECT_FALSE(no_args
.get(1));
173 fmt::basic_format_args args
= fmt::make_format_args(42);
174 EXPECT_TRUE(args
.max_size() > 0);
175 auto arg0
= args
.get(0);
177 decltype(arg0
) arg_none
;
178 EXPECT_FALSE(arg_none
);
179 EXPECT_TRUE(arg0
.type() != arg_none
.type());
182 TEST(module_test
, wformat_args
) {
183 auto no_args
= fmt::wformat_args();
184 EXPECT_FALSE(no_args
.get(1));
185 fmt::basic_format_args args
= fmt::make_wformat_args(42);
186 EXPECT_TRUE(args
.get(0));
189 TEST(module_test
, dynamic_format_args
) {
190 fmt::dynamic_format_arg_store
<fmt::format_context
> dyn_store
;
191 dyn_store
.push_back(fmt::arg("a42", 42));
192 fmt::basic_format_args args
= dyn_store
;
193 EXPECT_FALSE(args
.get(3));
194 EXPECT_TRUE(args
.get(fmt::string_view("a42")));
196 fmt::dynamic_format_arg_store
<fmt::wformat_context
> wdyn_store
;
197 wdyn_store
.push_back(fmt::arg(L
"a42", 42));
198 fmt::basic_format_args wargs
= wdyn_store
;
199 EXPECT_FALSE(wargs
.get(3));
200 EXPECT_TRUE(wargs
.get(fmt::wstring_view(L
"a42")));
203 TEST(module_test
, vformat
) {
204 EXPECT_EQ("42", fmt::vformat("{}", fmt::make_format_args(42)));
206 fmt::vformat(fmt::wstring_view(L
"{}"), fmt::make_wformat_args(42)));
209 TEST(module_test
, vformat_to
) {
210 auto store
= fmt::make_format_args(42);
212 fmt::vformat_to(std::back_inserter(s
), "{}", store
);
215 char buffer
[4] = {0};
216 fmt::vformat_to(buffer
, "{:}", store
);
217 EXPECT_EQ("42", std::string_view(buffer
));
219 auto wstore
= fmt::make_wformat_args(42);
221 fmt::vformat_to(std::back_inserter(w
), L
"{}", wstore
);
224 wchar_t wbuffer
[4] = {0};
225 fmt::vformat_to(wbuffer
, L
"{:}", wstore
);
226 EXPECT_EQ(L
"42", std::wstring_view(wbuffer
));
229 TEST(module_test
, vformat_to_n
) {
230 auto store
= fmt::make_format_args(12345);
232 auto result
= fmt::vformat_to_n(std::back_inserter(s
), 1, "{}", store
);
233 char buffer
[4] = {0};
234 fmt::vformat_to_n(buffer
, 3, "{:}", store
);
236 auto wstore
= fmt::make_wformat_args(12345);
238 auto wresult
= fmt::vformat_to_n(std::back_inserter(w
), 1,
239 fmt::wstring_view(L
"{}"), wstore
);
240 wchar_t wbuffer
[4] = {0};
241 fmt::vformat_to_n(wbuffer
, 3, fmt::wstring_view(L
"{:}"), wstore
);
244 std::string
as_string(std::wstring_view text
) {
245 return {reinterpret_cast<const char*>(text
.data()),
246 text
.size() * sizeof(text
[0])};
249 TEST(module_test
, print
) {
250 EXPECT_WRITE(stdout
, fmt::print("{}µ", 42), "42µ");
251 EXPECT_WRITE(stderr
, fmt::print(stderr
, "{}µ", 4.2), "4.2µ");
252 EXPECT_WRITE(stdout
, fmt::print(L
"{}µ", 42), as_string(L
"42µ"));
253 EXPECT_WRITE(stderr
, fmt::print(stderr
, L
"{}µ", 4.2), as_string(L
"4.2µ"));
256 TEST(module_test
, vprint
) {
257 EXPECT_WRITE(stdout
, fmt::vprint("{:}µ", fmt::make_format_args(42)), "42µ");
258 EXPECT_WRITE(stderr
, fmt::vprint(stderr
, "{}", fmt::make_format_args(4.2)),
260 EXPECT_WRITE(stdout
, fmt::vprint(L
"{:}µ", fmt::make_wformat_args(42)),
262 EXPECT_WRITE(stderr
, fmt::vprint(stderr
, L
"{}", fmt::make_wformat_args(42)),
266 TEST(module_test
, named_args
) {
267 EXPECT_EQ("42", fmt::format("{answer}", fmt::arg("answer", 42)));
268 EXPECT_EQ(L
"42", fmt::format(L
"{answer}", fmt::arg(L
"answer", 42)));
271 TEST(module_test
, literals
) {
272 using namespace fmt::literals
;
273 EXPECT_EQ("42", fmt::format("{answer}", "answer"_a
= 42));
274 EXPECT_EQ(L
"42", fmt::format(L
"{answer}", L
"answer"_a
= 42));
277 TEST(module_test
, locale
) {
278 auto store
= fmt::make_format_args(4.2);
279 const auto classic
= std::locale::classic();
280 EXPECT_EQ("4.2", fmt::format(classic
, "{:L}", 4.2));
281 EXPECT_EQ("4.2", fmt::vformat(classic
, "{:L}", store
));
283 fmt::vformat_to(std::back_inserter(s
), classic
, "{:L}", store
);
285 EXPECT_EQ("4.2", fmt::format("{:L}", 4.2));
287 auto wstore
= fmt::make_wformat_args(4.2);
288 EXPECT_EQ(L
"4.2", fmt::format(classic
, L
"{:L}", 4.2));
289 EXPECT_EQ(L
"4.2", fmt::vformat(classic
, L
"{:L}", wstore
));
291 fmt::vformat_to(std::back_inserter(w
), classic
, L
"{:L}", wstore
);
292 EXPECT_EQ(L
"4.2", w
);
293 EXPECT_EQ(L
"4.2", fmt::format(L
"{:L}", 4.2));
296 TEST(module_test
, string_view
) {
297 fmt::string_view
nsv("fmt");
298 EXPECT_EQ("fmt", nsv
);
299 EXPECT_TRUE(fmt::string_view("fmt") == nsv
);
301 fmt::wstring_view
wsv(L
"fmt");
302 EXPECT_EQ(L
"fmt", wsv
);
303 EXPECT_TRUE(fmt::wstring_view(L
"fmt") == wsv
);
306 TEST(module_test
, memory_buffer
) {
307 fmt::basic_memory_buffer
<char, fmt::inline_buffer_size
> buffer
;
308 fmt::format_to(std::back_inserter(buffer
), "{}", "42");
309 EXPECT_EQ("42", to_string(buffer
));
310 fmt::memory_buffer
nbuffer(std::move(buffer
));
311 EXPECT_EQ("42", to_string(nbuffer
));
312 buffer
= std::move(nbuffer
);
313 EXPECT_EQ("42", to_string(buffer
));
315 EXPECT_EQ(0u, to_string(nbuffer
).size());
317 fmt::wmemory_buffer wbuffer
;
318 EXPECT_EQ(0u, to_string(wbuffer
).size());
321 TEST(module_test
, is_char
) {
322 EXPECT_TRUE(fmt::is_char
<char>());
323 EXPECT_TRUE(fmt::is_char
<wchar_t>());
324 EXPECT_TRUE(fmt::is_char
<char8_t
>());
325 EXPECT_TRUE(fmt::is_char
<char16_t
>());
326 EXPECT_TRUE(fmt::is_char
<char32_t
>());
327 EXPECT_FALSE(fmt::is_char
<signed char>());
330 TEST(module_test
, ptr
) {
331 uintptr_t answer
= 42;
332 auto p
= std::bit_cast
<int*>(answer
);
333 EXPECT_EQ("0x2a", fmt::to_string(fmt::ptr(p
)));
334 std::unique_ptr
<int> up(p
);
335 EXPECT_EQ("0x2a", fmt::to_string(fmt::ptr(up
)));
337 auto sp
= std::make_shared
<int>(0);
339 EXPECT_EQ(fmt::to_string(fmt::ptr(p
)), fmt::to_string(fmt::ptr(sp
)));
342 TEST(module_test
, errors
) {
343 auto store
= fmt::make_format_args(42);
344 EXPECT_THROW(throw fmt::format_error("oops"), std::exception
);
345 EXPECT_THROW(throw fmt::vsystem_error(0, "{}", store
), std::system_error
);
346 EXPECT_THROW(throw fmt::system_error(0, "{}", 42), std::system_error
);
348 fmt::memory_buffer buffer
;
349 fmt::format_system_error(buffer
, 0, "oops");
350 auto oops
= to_string(buffer
);
351 EXPECT_TRUE(oops
.size() > 0);
352 EXPECT_WRITE(stderr
, fmt::report_system_error(0, "oops"), oops
+ '\n');
355 EXPECT_THROW(throw fmt::vwindows_error(0, "{}", store
), std::system_error
);
356 EXPECT_THROW(throw fmt::windows_error(0, "{}", 42), std::system_error
);
357 output_redirect
redirect(stderr
);
358 fmt::report_windows_error(0, "oops");
359 EXPECT_TRUE(redirect
.restore_and_read().size() > 0);
363 TEST(module_test
, error_code
) {
364 EXPECT_EQ("generic:42",
365 fmt::format("{0}", std::error_code(42, std::generic_category())));
366 EXPECT_EQ("system:42",
367 fmt::format("{0}", std::error_code(42, fmt::system_category())));
368 EXPECT_EQ(L
"generic:42",
369 fmt::format(L
"{0}", std::error_code(42, std::generic_category())));
372 TEST(module_test
, format_int
) {
373 fmt::format_int
sanswer(42);
374 EXPECT_EQ("42", fmt::string_view(sanswer
.data(), sanswer
.size()));
375 fmt::format_int
uanswer(42u);
376 EXPECT_EQ("42", fmt::string_view(uanswer
.data(), uanswer
.size()));
379 struct test_formatter
: fmt::formatter
<char> {
380 bool check() { return true; }
383 TEST(module_test
, formatter
) { EXPECT_TRUE(test_formatter
{}.check()); }
385 TEST(module_test
, join
) {
386 int arr
[3] = {1, 2, 3};
387 std::vector
<double> vec
{1.0, 2.0, 3.0};
388 std::initializer_list
<int> il
{1, 2, 3};
389 auto sep
= fmt::string_view(", ");
390 EXPECT_EQ("1, 2, 3", to_string(fmt::join(arr
+ 0, arr
+ 3, sep
)));
391 EXPECT_EQ("1, 2, 3", to_string(fmt::join(arr
, sep
)));
392 EXPECT_EQ("1, 2, 3", to_string(fmt::join(vec
.begin(), vec
.end(), sep
)));
393 EXPECT_EQ("1, 2, 3", to_string(fmt::join(vec
, sep
)));
394 EXPECT_EQ("1, 2, 3", to_string(fmt::join(il
, sep
)));
396 auto wsep
= fmt::wstring_view(L
", ");
397 EXPECT_EQ(L
"1, 2, 3", fmt::format(L
"{}", fmt::join(arr
+ 0, arr
+ 3, wsep
)));
398 EXPECT_EQ(L
"1, 2, 3", fmt::format(L
"{}", fmt::join(arr
, wsep
)));
399 EXPECT_EQ(L
"1, 2, 3", fmt::format(L
"{}", fmt::join(il
, wsep
)));
402 TEST(module_test
, time
) {
403 auto time_now
= std::time(nullptr);
404 EXPECT_TRUE(fmt::localtime(time_now
).tm_year
> 120);
405 EXPECT_TRUE(fmt::gmtime(time_now
).tm_year
> 120);
406 auto chrono_now
= std::chrono::system_clock::now();
407 EXPECT_TRUE(fmt::gmtime(chrono_now
).tm_year
> 120);
410 TEST(module_test
, time_point
) {
411 auto now
= std::chrono::system_clock::now();
412 std::string_view
past("2021-05-20 10:30:15");
413 EXPECT_TRUE(past
< fmt::format("{:%Y-%m-%d %H:%M:%S}", now
));
414 std::wstring_view
wpast(L
"2021-05-20 10:30:15");
415 EXPECT_TRUE(wpast
< fmt::format(L
"{:%Y-%m-%d %H:%M:%S}", now
));
418 TEST(module_test
, time_duration
) {
419 using us
= std::chrono::duration
<double, std::micro
>;
420 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds
{42}));
421 EXPECT_EQ("4.2µs", fmt::format("{:3.1}", us
{4.234}));
422 EXPECT_EQ("4.2µs", fmt::format(std::locale::classic(), "{:L}", us
{4.2}));
424 EXPECT_EQ(L
"42s", fmt::format(L
"{}", std::chrono::seconds
{42}));
425 EXPECT_EQ(L
"4.2µs", fmt::format(L
"{:3.1}", us
{4.234}));
426 EXPECT_EQ(L
"4.2µs", fmt::format(std::locale::classic(), L
"{:L}", us
{4.2}));
429 TEST(module_test
, weekday
) {
430 EXPECT_EQ("Mon", fmt::format(std::locale::classic(), "{}", fmt::weekday(1)));
433 TEST(module_test
, printf
) {
434 EXPECT_WRITE(stdout
, fmt::printf("%f", 42.123456), "42.123456");
435 EXPECT_WRITE(stdout
, fmt::printf("%d", 42), "42");
436 EXPECT_WRITE(stdout
, fmt::printf(L
"%f", 42.123456), as_string(L
"42.123456"));
437 EXPECT_WRITE(stdout
, fmt::printf(L
"%d", 42), as_string(L
"42"));
440 TEST(module_test
, fprintf
) {
441 EXPECT_WRITE(stderr
, fmt::fprintf(stderr
, "%d", 42), "42");
442 EXPECT_WRITE(stderr
, fmt::fprintf(stderr
, L
"%d", 42), as_string(L
"42"));
445 TEST(module_test
, sprintf
) {
446 EXPECT_EQ("42", fmt::sprintf("%d", 42));
447 EXPECT_EQ(L
"42", fmt::sprintf(L
"%d", 42));
450 TEST(module_test
, vprintf
) {
451 EXPECT_WRITE(stdout
, fmt::vprintf("%d", fmt::make_printf_args(42)), "42");
452 EXPECT_WRITE(stdout
, fmt::vprintf(L
"%d", fmt::make_wprintf_args(42)),
456 TEST(module_test
, vfprintf
) {
457 auto args
= fmt::make_printf_args(42);
458 EXPECT_WRITE(stderr
, fmt::vfprintf(stderr
, "%d", args
), "42");
459 auto wargs
= fmt::make_wprintf_args(42);
460 EXPECT_WRITE(stderr
, fmt::vfprintf(stderr
, L
"%d", wargs
), as_string(L
"42"));
463 TEST(module_test
, vsprintf
) {
464 EXPECT_EQ("42", fmt::vsprintf("%d", fmt::make_printf_args(42)));
465 EXPECT_EQ(L
"42", fmt::vsprintf(L
"%d", fmt::make_wprintf_args(42)));
468 TEST(module_test
, color
) {
469 auto fg_check
= fg(fmt::rgb(255, 200, 30));
470 auto bg_check
= bg(fmt::color::dark_slate_gray
) | fmt::emphasis::italic
;
471 auto emphasis_check
= fmt::emphasis::underline
| fmt::emphasis::bold
;
472 EXPECT_EQ("\x1B[30m42\x1B[0m",
473 fmt::format(fg(fmt::terminal_color::black
), "{}", 42));
474 EXPECT_EQ(L
"\x1B[30m42\x1B[0m",
475 fmt::format(fg(fmt::terminal_color::black
), L
"{}", 42));
478 TEST(module_test
, cstring_view
) {
480 EXPECT_EQ(s
, fmt::cstring_view(s
).c_str());
482 EXPECT_EQ(w
, fmt::wcstring_view(w
).c_str());
485 TEST(module_test
, buffered_file
) {
486 EXPECT_TRUE(fmt::buffered_file
{}.get() == nullptr);
489 TEST(module_test
, output_file
) {
491 fmt::println("\033[0;33m[=disabled=] {}\033[0;0m",
492 "Clang 16.0 emits multiple copies of vtables");
494 fmt::ostream out
= fmt::output_file("module-test", fmt::buffer_size
= 1);
499 struct custom_context
{
500 using char_type
= char;
501 using parse_context_type
= fmt::format_parse_context
;
504 TEST(module_test
, custom_context
) {
505 fmt::basic_format_arg
<custom_context
> custom_arg
;
506 EXPECT_TRUE(!custom_arg
);
509 TEST(module_test
, compile_format_string
) {
510 using namespace fmt::literals
;
512 fmt::println("\033[0;33m[=disabled=] {}\033[0;0m",
513 "Clang 16.0 fails to import user-defined literals");
515 EXPECT_EQ("42", fmt::format("{0:x}"_cf
, 0x42));
516 EXPECT_EQ(L
"42", fmt::format(L
"{:}"_cf
, 42));
517 EXPECT_EQ("4.2", fmt::format("{arg:3.1f}"_cf
, "arg"_a
= 4.2));
518 EXPECT_EQ(L
" 42", fmt::format(L
"{arg:>3}"_cf
, L
"arg"_a
= L
"42"));