xref: /aosp_15_r20/external/fmtlib/test/module-test.cc (revision 5c90c05cd622c0a81b57953a4d343e0e489f2e08)
1 // Formatting library for C++ - module 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 // Copyright (c) 2021 - present, Daniela Engert
9 // All Rights Reserved
10 // {fmt} module.
11 
12 #ifdef _MSC_FULL_VER
13 // hide some implementation bugs in msvc
14 // that are not essential to users of the module.
15 #  define FMT_HIDE_MODULE_BUGS
16 #endif
17 
18 #include <bit>
19 #include <chrono>
20 #include <exception>
21 #include <iterator>
22 #include <locale>
23 #include <memory>
24 #include <ostream>
25 #include <string>
26 #include <string_view>
27 #include <system_error>
28 
29 #if (__has_include(<fcntl.h>) || defined(__APPLE__) || \
30      defined(__linux__)) &&                              \
31     (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
32 #  include <fcntl.h>
33 #  define FMT_USE_FCNTL 1
34 #else
35 #  define FMT_USE_FCNTL 0
36 #endif
37 #if defined(_WIN32) && !defined(__MINGW32__)
38 #  define FMT_POSIX(call) _##call
39 #else
40 #  define FMT_POSIX(call) call
41 #endif
42 
43 import fmt;
44 
45 // check for macros leaking from BMI
46 static bool macro_leaked =
47 #if defined(FMT_CORE_H_) || defined(FMT_FORMAT_H_)
48     true;
49 #else
50     false;
51 #endif
52 
53 #define FMT_OS_H_  // don't pull in os.h, neither directly nor indirectly
54 #include "gtest-extra.h"
55 
56 // an implicitly exported namespace must be visible [module.interface]/2.2
TEST(module_test,namespace)57 TEST(module_test, namespace) {
58   using namespace fmt;
59   using namespace fmt::literals;
60   ASSERT_TRUE(true);
61 }
62 
63 namespace detail {
64 bool oops_detail_namespace_is_visible;
65 }
66 
67 namespace fmt {
namespace_detail_invisible()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:
72 
73   // the namespace is visible even when it is neither
74   // implicitly nor explicitly exported
75   return true;
76 #else
77   using namespace detail;
78   // this fails to compile if fmt::detail is visible
79   return !oops_detail_namespace_is_visible;
80 #endif
81 }
82 }  // namespace fmt
83 
84 // the non-exported namespace 'detail' must be invisible [module.interface]/2
TEST(module_test,detail_namespace)85 TEST(module_test, detail_namespace) {
86   EXPECT_TRUE(fmt::namespace_detail_invisible());
87 }
88 
89 // macros must not be imported from a *named* module  [cpp.import]/5.1
TEST(module_test,macros)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
96   macro_leaked = false;
97 #endif
98   EXPECT_FALSE(macro_leaked);
99 }
100 
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.
107 
TEST(module_test,to_string)108 TEST(module_test, to_string) {
109   EXPECT_EQ("42", fmt::to_string(42));
110   EXPECT_EQ("42", fmt::to_string(42.0));
111 
112   EXPECT_EQ(L"42", fmt::to_wstring(42));
113   EXPECT_EQ(L"42", fmt::to_wstring(42.0));
114 }
115 
TEST(module_test,format)116 TEST(module_test, format) {
117   EXPECT_EQ("42", fmt::format("{:}", 42));
118   EXPECT_EQ("-42", fmt::format("{0}", -42.0));
119 
120   EXPECT_EQ(L"42", fmt::format(L"{:}", 42));
121   EXPECT_EQ(L"-42", fmt::format(L"{0}", -42.0));
122 }
123 
TEST(module_test,format_to)124 TEST(module_test, format_to) {
125   std::string s;
126   fmt::format_to(std::back_inserter(s), "{}", 42);
127   EXPECT_EQ("42", s);
128 
129   char buffer[4] = {0};
130   fmt::format_to(buffer, "{}", 42);
131   EXPECT_EQ("42", std::string_view(buffer));
132 
133   fmt::memory_buffer mb;
134   fmt::format_to(std::back_inserter(mb), "{}", 42);
135   EXPECT_EQ("42", std::string_view(buffer));
136 
137   std::wstring w;
138   fmt::format_to(std::back_inserter(w), L"{}", 42);
139   EXPECT_EQ(L"42", w);
140 
141   wchar_t wbuffer[4] = {0};
142   fmt::format_to(wbuffer, L"{}", 42);
143   EXPECT_EQ(L"42", std::wstring_view(wbuffer));
144 
145   fmt::wmemory_buffer wb;
146   fmt::format_to(std::back_inserter(wb), L"{}", 42);
147   EXPECT_EQ(L"42", std::wstring_view(wbuffer));
148 }
149 
TEST(module_test,formatted_size)150 TEST(module_test, formatted_size) {
151   EXPECT_EQ(2u, fmt::formatted_size("{}", 42));
152   EXPECT_EQ(2u, fmt::formatted_size(L"{}", 42));
153 }
154 
TEST(module_test,format_to_n)155 TEST(module_test, format_to_n) {
156   std::string s;
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);
161 
162   std::wstring w;
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);
167 }
168 
TEST(module_test,format_args)169 TEST(module_test, format_args) {
170   auto no_args = fmt::format_args();
171   EXPECT_FALSE(no_args.get(1));
172 
173   fmt::basic_format_args args = fmt::make_format_args(42);
174   EXPECT_TRUE(args.max_size() > 0);
175   auto arg0 = args.get(0);
176   EXPECT_TRUE(arg0);
177   decltype(arg0) arg_none;
178   EXPECT_FALSE(arg_none);
179   EXPECT_TRUE(arg0.type() != arg_none.type());
180 }
181 
TEST(module_test,wformat_args)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));
187 }
188 
TEST(module_test,dynamic_format_args)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")));
195 
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")));
201 }
202 
TEST(module_test,vformat)203 TEST(module_test, vformat) {
204   EXPECT_EQ("42", fmt::vformat("{}", fmt::make_format_args(42)));
205   EXPECT_EQ(L"42",
206             fmt::vformat(fmt::wstring_view(L"{}"), fmt::make_wformat_args(42)));
207 }
208 
TEST(module_test,vformat_to)209 TEST(module_test, vformat_to) {
210   auto store = fmt::make_format_args(42);
211   std::string s;
212   fmt::vformat_to(std::back_inserter(s), "{}", store);
213   EXPECT_EQ("42", s);
214 
215   char buffer[4] = {0};
216   fmt::vformat_to(buffer, "{:}", store);
217   EXPECT_EQ("42", std::string_view(buffer));
218 
219   auto wstore = fmt::make_wformat_args(42);
220   std::wstring w;
221   fmt::vformat_to(std::back_inserter(w), L"{}", wstore);
222   EXPECT_EQ(L"42", w);
223 
224   wchar_t wbuffer[4] = {0};
225   fmt::vformat_to(wbuffer, L"{:}", wstore);
226   EXPECT_EQ(L"42", std::wstring_view(wbuffer));
227 }
228 
TEST(module_test,vformat_to_n)229 TEST(module_test, vformat_to_n) {
230   auto store = fmt::make_format_args(12345);
231   std::string s;
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);
235 
236   auto wstore = fmt::make_wformat_args(12345);
237   std::wstring w;
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);
242 }
243 
as_string(std::wstring_view text)244 std::string as_string(std::wstring_view text) {
245   return {reinterpret_cast<const char*>(text.data()),
246           text.size() * sizeof(text[0])};
247 }
248 
TEST(module_test,print)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µ"));
254 }
255 
TEST(module_test,vprint)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)),
259                "4.2");
260   EXPECT_WRITE(stdout, fmt::vprint(L"{:}µ", fmt::make_wformat_args(42)),
261                as_string(L"42µ"));
262   EXPECT_WRITE(stderr, fmt::vprint(stderr, L"{}", fmt::make_wformat_args(42)),
263                as_string(L"42"));
264 }
265 
TEST(module_test,named_args)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)));
269 }
270 
TEST(module_test,literals)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));
275 }
276 
TEST(module_test,locale)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));
282   std::string s;
283   fmt::vformat_to(std::back_inserter(s), classic, "{:L}", store);
284   EXPECT_EQ("4.2", s);
285   EXPECT_EQ("4.2", fmt::format("{:L}", 4.2));
286 
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));
290   std::wstring w;
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));
294 }
295 
TEST(module_test,string_view)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);
300 
301   fmt::wstring_view wsv(L"fmt");
302   EXPECT_EQ(L"fmt", wsv);
303   EXPECT_TRUE(fmt::wstring_view(L"fmt") == wsv);
304 }
305 
TEST(module_test,memory_buffer)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));
314   nbuffer.clear();
315   EXPECT_EQ(0u, to_string(nbuffer).size());
316 
317   fmt::wmemory_buffer wbuffer;
318   EXPECT_EQ(0u, to_string(wbuffer).size());
319 }
320 
TEST(module_test,is_char)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>());
328 }
329 
TEST(module_test,ptr)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)));
336   up.release();
337   auto sp = std::make_shared<int>(0);
338   p = sp.get();
339   EXPECT_EQ(fmt::to_string(fmt::ptr(p)), fmt::to_string(fmt::ptr(sp)));
340 }
341 
TEST(module_test,errors)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);
347 
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');
353 
354 #ifdef _WIN32
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);
360 #endif
361 }
362 
TEST(module_test,error_code)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())));
370 }
371 
TEST(module_test,format_int)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()));
377 }
378 
379 struct test_formatter : fmt::formatter<char> {
checktest_formatter380   bool check() { return true; }
381 };
382 
TEST(module_test,formatter)383 TEST(module_test, formatter) { EXPECT_TRUE(test_formatter{}.check()); }
384 
TEST(module_test,join)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)));
395 
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)));
400 }
401 
TEST(module_test,time)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);
408 }
409 
TEST(module_test,time_point)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));
416 }
417 
TEST(module_test,time_duration)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}));
423 
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}));
427 }
428 
TEST(module_test,weekday)429 TEST(module_test, weekday) {
430   EXPECT_EQ("Mon", fmt::format(std::locale::classic(), "{}", fmt::weekday(1)));
431 }
432 
TEST(module_test,printf)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"));
438 }
439 
TEST(module_test,fprintf)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"));
443 }
444 
TEST(module_test,sprintf)445 TEST(module_test, sprintf) {
446   EXPECT_EQ("42", fmt::sprintf("%d", 42));
447   EXPECT_EQ(L"42", fmt::sprintf(L"%d", 42));
448 }
449 
TEST(module_test,vprintf)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)),
453                as_string(L"42"));
454 }
455 
TEST(module_test,vfprintf)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"));
461 }
462 
TEST(module_test,vsprintf)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)));
466 }
467 
TEST(module_test,color)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));
476 }
477 
TEST(module_test,cstring_view)478 TEST(module_test, cstring_view) {
479   auto s = "fmt";
480   EXPECT_EQ(s, fmt::cstring_view(s).c_str());
481   auto w = L"fmt";
482   EXPECT_EQ(w, fmt::wcstring_view(w).c_str());
483 }
484 
TEST(module_test,buffered_file)485 TEST(module_test, buffered_file) {
486   EXPECT_TRUE(fmt::buffered_file{}.get() == nullptr);
487 }
488 
TEST(module_test,output_file)489 TEST(module_test, output_file) {
490 #ifdef __clang__
491   fmt::println("\033[0;33m[=disabled=] {}\033[0;0m",
492                "Clang 16.0 emits multiple copies of vtables");
493 #else
494   fmt::ostream out = fmt::output_file("module-test", fmt::buffer_size = 1);
495   out.close();
496 #endif
497 }
498 
499 struct custom_context {
500   using char_type = char;
501   using parse_context_type = fmt::format_parse_context;
502 };
503 
TEST(module_test,custom_context)504 TEST(module_test, custom_context) {
505   fmt::basic_format_arg<custom_context> custom_arg;
506   EXPECT_TRUE(!custom_arg);
507 }
508 
TEST(module_test,compile_format_string)509 TEST(module_test, compile_format_string) {
510   using namespace fmt::literals;
511 #ifdef __clang__
512   fmt::println("\033[0;33m[=disabled=] {}\033[0;0m",
513                "Clang 16.0 fails to import user-defined literals");
514 #else
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"));
519 #endif
520 }
521