xref: /aosp_15_r20/external/fmtlib/test/xchar-test.cc (revision 5c90c05cd622c0a81b57953a4d343e0e489f2e08)
1*5c90c05cSAndroid Build Coastguard Worker // Formatting library for C++ - formatting library tests
2*5c90c05cSAndroid Build Coastguard Worker //
3*5c90c05cSAndroid Build Coastguard Worker // Copyright (c) 2012 - present, Victor Zverovich
4*5c90c05cSAndroid Build Coastguard Worker // All rights reserved.
5*5c90c05cSAndroid Build Coastguard Worker //
6*5c90c05cSAndroid Build Coastguard Worker // For the license information refer to format.h.
7*5c90c05cSAndroid Build Coastguard Worker 
8*5c90c05cSAndroid Build Coastguard Worker #include "fmt/xchar.h"
9*5c90c05cSAndroid Build Coastguard Worker 
10*5c90c05cSAndroid Build Coastguard Worker #include <algorithm>
11*5c90c05cSAndroid Build Coastguard Worker #include <complex>
12*5c90c05cSAndroid Build Coastguard Worker #include <cwchar>
13*5c90c05cSAndroid Build Coastguard Worker #include <vector>
14*5c90c05cSAndroid Build Coastguard Worker 
15*5c90c05cSAndroid Build Coastguard Worker #include "fmt/chrono.h"
16*5c90c05cSAndroid Build Coastguard Worker #include "fmt/color.h"
17*5c90c05cSAndroid Build Coastguard Worker #include "fmt/ostream.h"
18*5c90c05cSAndroid Build Coastguard Worker #include "fmt/ranges.h"
19*5c90c05cSAndroid Build Coastguard Worker #include "fmt/std.h"
20*5c90c05cSAndroid Build Coastguard Worker #include "gtest-extra.h"  // Contains
21*5c90c05cSAndroid Build Coastguard Worker #include "util.h"         // get_locale
22*5c90c05cSAndroid Build Coastguard Worker 
23*5c90c05cSAndroid Build Coastguard Worker using fmt::detail::max_value;
24*5c90c05cSAndroid Build Coastguard Worker using testing::Contains;
25*5c90c05cSAndroid Build Coastguard Worker 
26*5c90c05cSAndroid Build Coastguard Worker #if defined(__MINGW32__) && !defined(_UCRT)
27*5c90c05cSAndroid Build Coastguard Worker // Only C89 conversion specifiers when using MSVCRT instead of UCRT
28*5c90c05cSAndroid Build Coastguard Worker #  define FMT_HAS_C99_STRFTIME 0
29*5c90c05cSAndroid Build Coastguard Worker #else
30*5c90c05cSAndroid Build Coastguard Worker #  define FMT_HAS_C99_STRFTIME 1
31*5c90c05cSAndroid Build Coastguard Worker #endif
32*5c90c05cSAndroid Build Coastguard Worker 
33*5c90c05cSAndroid Build Coastguard Worker struct non_string {};
34*5c90c05cSAndroid Build Coastguard Worker 
35*5c90c05cSAndroid Build Coastguard Worker template <typename T> class has_to_string_view_test : public testing::Test {};
36*5c90c05cSAndroid Build Coastguard Worker 
37*5c90c05cSAndroid Build Coastguard Worker using string_char_types = testing::Types<char, wchar_t, char16_t, char32_t>;
38*5c90c05cSAndroid Build Coastguard Worker TYPED_TEST_SUITE(has_to_string_view_test, string_char_types);
39*5c90c05cSAndroid Build Coastguard Worker 
40*5c90c05cSAndroid Build Coastguard Worker template <typename Char>
41*5c90c05cSAndroid Build Coastguard Worker struct derived_from_string_view : fmt::basic_string_view<Char> {};
42*5c90c05cSAndroid Build Coastguard Worker 
TYPED_TEST(has_to_string_view_test,has_to_string_view)43*5c90c05cSAndroid Build Coastguard Worker TYPED_TEST(has_to_string_view_test, has_to_string_view) {
44*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<TypeParam*>::value);
45*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<const TypeParam*>::value);
46*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<TypeParam[2]>::value);
47*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<const TypeParam[2]>::value);
48*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(
49*5c90c05cSAndroid Build Coastguard Worker       fmt::detail::has_to_string_view<std::basic_string<TypeParam>>::value);
50*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<
51*5c90c05cSAndroid Build Coastguard Worker               fmt::basic_string_view<TypeParam>>::value);
52*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(fmt::detail::has_to_string_view<
53*5c90c05cSAndroid Build Coastguard Worker               derived_from_string_view<TypeParam>>::value);
54*5c90c05cSAndroid Build Coastguard Worker   using fmt_string_view = fmt::detail::std_string_view<TypeParam>;
55*5c90c05cSAndroid Build Coastguard Worker   EXPECT_TRUE(std::is_empty<fmt_string_view>::value !=
56*5c90c05cSAndroid Build Coastguard Worker               fmt::detail::has_to_string_view<fmt_string_view>::value);
57*5c90c05cSAndroid Build Coastguard Worker   EXPECT_FALSE(fmt::detail::has_to_string_view<non_string>::value);
58*5c90c05cSAndroid Build Coastguard Worker }
59*5c90c05cSAndroid Build Coastguard Worker 
60*5c90c05cSAndroid Build Coastguard Worker // std::is_constructible is broken in MSVC until version 2015.
61*5c90c05cSAndroid Build Coastguard Worker #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1900
62*5c90c05cSAndroid Build Coastguard Worker struct explicitly_convertible_to_wstring_view {
operator fmt::wstring_viewexplicitly_convertible_to_wstring_view63*5c90c05cSAndroid Build Coastguard Worker   explicit operator fmt::wstring_view() const { return L"foo"; }
64*5c90c05cSAndroid Build Coastguard Worker };
65*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,format_explicitly_convertible_to_wstring_view)66*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, format_explicitly_convertible_to_wstring_view) {
67*5c90c05cSAndroid Build Coastguard Worker   // Types explicitly convertible to wstring_view are not formattable by
68*5c90c05cSAndroid Build Coastguard Worker   // default because it may introduce ODR violations.
69*5c90c05cSAndroid Build Coastguard Worker   static_assert(
70*5c90c05cSAndroid Build Coastguard Worker       !fmt::is_formattable<explicitly_convertible_to_wstring_view>::value, "");
71*5c90c05cSAndroid Build Coastguard Worker }
72*5c90c05cSAndroid Build Coastguard Worker #endif
73*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,format)74*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, format) {
75*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"42", fmt::format(L"{}", 42));
76*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"4.2", fmt::format(L"{}", 4.2));
77*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"abc", fmt::format(L"{}", L"abc"));
78*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"z", fmt::format(L"{}", L'z'));
79*5c90c05cSAndroid Build Coastguard Worker   EXPECT_THROW(fmt::format(fmt::runtime(L"{:*\x343E}"), 42), fmt::format_error);
80*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"true", fmt::format(L"{}", true));
81*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"a", fmt::format(L"{0}", L'a'));
82*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"Cyrillic letter \x42e",
83*5c90c05cSAndroid Build Coastguard Worker             fmt::format(L"Cyrillic letter {}", L'\x42e'));
84*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"abc1", fmt::format(L"{}c{}", L"ab", 1));
85*5c90c05cSAndroid Build Coastguard Worker }
86*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,is_formattable)87*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, is_formattable) {
88*5c90c05cSAndroid Build Coastguard Worker   static_assert(!fmt::is_formattable<const wchar_t*>::value, "");
89*5c90c05cSAndroid Build Coastguard Worker }
90*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,compile_time_string)91*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, compile_time_string) {
92*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(fmt::wformat_string<int>(L"{}"), 42), L"42");
93*5c90c05cSAndroid Build Coastguard Worker #if defined(FMT_USE_STRING_VIEW) && FMT_CPLUSPLUS >= 201703L
94*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42), L"42");
95*5c90c05cSAndroid Build Coastguard Worker #endif
96*5c90c05cSAndroid Build Coastguard Worker }
97*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,format_to)98*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, format_to) {
99*5c90c05cSAndroid Build Coastguard Worker   auto buf = std::vector<wchar_t>();
100*5c90c05cSAndroid Build Coastguard Worker   fmt::format_to(std::back_inserter(buf), L"{}{}", 42, L'\0');
101*5c90c05cSAndroid Build Coastguard Worker   EXPECT_STREQ(buf.data(), L"42");
102*5c90c05cSAndroid Build Coastguard Worker }
103*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,compile_time_string_format_to)104*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, compile_time_string_format_to) {
105*5c90c05cSAndroid Build Coastguard Worker   std::wstring ws;
106*5c90c05cSAndroid Build Coastguard Worker   fmt::format_to(std::back_inserter(ws), FMT_STRING(L"{}"), 42);
107*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"42", ws);
108*5c90c05cSAndroid Build Coastguard Worker }
109*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,vformat_to)110*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, vformat_to) {
111*5c90c05cSAndroid Build Coastguard Worker   int n = 42;
112*5c90c05cSAndroid Build Coastguard Worker   auto args = fmt::make_wformat_args(n);
113*5c90c05cSAndroid Build Coastguard Worker   auto w = std::wstring();
114*5c90c05cSAndroid Build Coastguard Worker   fmt::vformat_to(std::back_inserter(w), L"{}", args);
115*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"42", w);
116*5c90c05cSAndroid Build Coastguard Worker }
117*5c90c05cSAndroid Build Coastguard Worker 
118*5c90c05cSAndroid Build Coastguard Worker namespace test {
119*5c90c05cSAndroid Build Coastguard Worker struct struct_as_wstring_view {};
format_as(struct_as_wstring_view)120*5c90c05cSAndroid Build Coastguard Worker auto format_as(struct_as_wstring_view) -> fmt::wstring_view { return L"foo"; }
121*5c90c05cSAndroid Build Coastguard Worker }  // namespace test
122*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,format_as)123*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, format_as) {
124*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", test::struct_as_wstring_view()), L"foo");
125*5c90c05cSAndroid Build Coastguard Worker }
126*5c90c05cSAndroid Build Coastguard Worker 
TEST(format_test,wide_format_to_n)127*5c90c05cSAndroid Build Coastguard Worker TEST(format_test, wide_format_to_n) {
128*5c90c05cSAndroid Build Coastguard Worker   wchar_t buffer[4];
129*5c90c05cSAndroid Build Coastguard Worker   buffer[3] = L'x';
130*5c90c05cSAndroid Build Coastguard Worker   auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
131*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(5u, result.size);
132*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(buffer + 3, result.out);
133*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
134*5c90c05cSAndroid Build Coastguard Worker   buffer[0] = L'x';
135*5c90c05cSAndroid Build Coastguard Worker   buffer[1] = L'x';
136*5c90c05cSAndroid Build Coastguard Worker   buffer[2] = L'x';
137*5c90c05cSAndroid Build Coastguard Worker   result = fmt::format_to_n(buffer, 3, L"{}", L'A');
138*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(1u, result.size);
139*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(buffer + 1, result.out);
140*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4));
141*5c90c05cSAndroid Build Coastguard Worker   result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C');
142*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(3u, result.size);
143*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(buffer + 3, result.out);
144*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
145*5c90c05cSAndroid Build Coastguard Worker }
146*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,named_arg_udl)147*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, named_arg_udl) {
148*5c90c05cSAndroid Build Coastguard Worker   using namespace fmt::literals;
149*5c90c05cSAndroid Build Coastguard Worker   auto udl_a =
150*5c90c05cSAndroid Build Coastguard Worker       fmt::format(L"{first}{second}{first}{third}", L"first"_a = L"abra",
151*5c90c05cSAndroid Build Coastguard Worker                   L"second"_a = L"cad", L"third"_a = 99);
152*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(
153*5c90c05cSAndroid Build Coastguard Worker       fmt::format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"),
154*5c90c05cSAndroid Build Coastguard Worker                   fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
155*5c90c05cSAndroid Build Coastguard Worker       udl_a);
156*5c90c05cSAndroid Build Coastguard Worker }
157*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,print)158*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, print) {
159*5c90c05cSAndroid Build Coastguard Worker   // Check that the wide print overload compiles.
160*5c90c05cSAndroid Build Coastguard Worker   if (fmt::detail::const_check(false)) {
161*5c90c05cSAndroid Build Coastguard Worker     fmt::print(L"test");
162*5c90c05cSAndroid Build Coastguard Worker     fmt::println(L"test");
163*5c90c05cSAndroid Build Coastguard Worker   }
164*5c90c05cSAndroid Build Coastguard Worker }
165*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,join)166*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, join) {
167*5c90c05cSAndroid Build Coastguard Worker   int v[3] = {1, 2, 3};
168*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"({})", fmt::join(v, v + 3, L", ")), L"(1, 2, 3)");
169*5c90c05cSAndroid Build Coastguard Worker   auto t = std::tuple<wchar_t, int, float>('a', 1, 2.0f);
170*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"({})", fmt::join(t, L", ")), L"(a, 1, 2)");
171*5c90c05cSAndroid Build Coastguard Worker }
172*5c90c05cSAndroid Build Coastguard Worker 
173*5c90c05cSAndroid Build Coastguard Worker enum streamable_enum {};
174*5c90c05cSAndroid Build Coastguard Worker 
operator <<(std::wostream & os,streamable_enum)175*5c90c05cSAndroid Build Coastguard Worker std::wostream& operator<<(std::wostream& os, streamable_enum) {
176*5c90c05cSAndroid Build Coastguard Worker   return os << L"streamable_enum";
177*5c90c05cSAndroid Build Coastguard Worker }
178*5c90c05cSAndroid Build Coastguard Worker 
179*5c90c05cSAndroid Build Coastguard Worker namespace fmt {
180*5c90c05cSAndroid Build Coastguard Worker template <>
181*5c90c05cSAndroid Build Coastguard Worker struct formatter<streamable_enum, wchar_t> : basic_ostream_formatter<wchar_t> {
182*5c90c05cSAndroid Build Coastguard Worker };
183*5c90c05cSAndroid Build Coastguard Worker }  // namespace fmt
184*5c90c05cSAndroid Build Coastguard Worker 
185*5c90c05cSAndroid Build Coastguard Worker enum unstreamable_enum {};
format_as(unstreamable_enum e)186*5c90c05cSAndroid Build Coastguard Worker auto format_as(unstreamable_enum e) -> int { return e; }
187*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,enum)188*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, enum) {
189*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"streamable_enum", fmt::format(L"{}", streamable_enum()));
190*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
191*5c90c05cSAndroid Build Coastguard Worker }
192*5c90c05cSAndroid Build Coastguard Worker 
193*5c90c05cSAndroid Build Coastguard Worker struct streamable_and_unformattable {};
194*5c90c05cSAndroid Build Coastguard Worker 
operator <<(std::wostream & os,streamable_and_unformattable)195*5c90c05cSAndroid Build Coastguard Worker auto operator<<(std::wostream& os, streamable_and_unformattable)
196*5c90c05cSAndroid Build Coastguard Worker     -> std::wostream& {
197*5c90c05cSAndroid Build Coastguard Worker   return os << L"foo";
198*5c90c05cSAndroid Build Coastguard Worker }
199*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,streamed)200*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, streamed) {
201*5c90c05cSAndroid Build Coastguard Worker   EXPECT_FALSE(fmt::is_formattable<streamable_and_unformattable>());
202*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", fmt::streamed(streamable_and_unformattable())),
203*5c90c05cSAndroid Build Coastguard Worker             L"foo");
204*5c90c05cSAndroid Build Coastguard Worker }
205*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,sign_not_truncated)206*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, sign_not_truncated) {
207*5c90c05cSAndroid Build Coastguard Worker   wchar_t format_str[] = {
208*5c90c05cSAndroid Build Coastguard Worker       L'{', L':',
209*5c90c05cSAndroid Build Coastguard Worker       '+' | static_cast<wchar_t>(1 << fmt::detail::num_bits<char>()), L'}', 0};
210*5c90c05cSAndroid Build Coastguard Worker   EXPECT_THROW(fmt::format(fmt::runtime(format_str), 42), fmt::format_error);
211*5c90c05cSAndroid Build Coastguard Worker }
212*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,chrono)213*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, chrono) {
214*5c90c05cSAndroid Build Coastguard Worker   auto tm = std::tm();
215*5c90c05cSAndroid Build Coastguard Worker   tm.tm_year = 116;
216*5c90c05cSAndroid Build Coastguard Worker   tm.tm_mon = 3;
217*5c90c05cSAndroid Build Coastguard Worker   tm.tm_mday = 25;
218*5c90c05cSAndroid Build Coastguard Worker   tm.tm_hour = 11;
219*5c90c05cSAndroid Build Coastguard Worker   tm.tm_min = 22;
220*5c90c05cSAndroid Build Coastguard Worker   tm.tm_sec = 33;
221*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm),
222*5c90c05cSAndroid Build Coastguard Worker             "The date is 2016-04-25 11:22:33.");
223*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"42s", fmt::format(L"{}", std::chrono::seconds(42)));
224*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{:%F}", tm), L"2016-04-25");
225*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{:%T}", tm), L"11:22:33");
226*5c90c05cSAndroid Build Coastguard Worker }
227*5c90c05cSAndroid Build Coastguard Worker 
system_wcsftime(const std::wstring & format,const std::tm * timeptr,std::locale * locptr=nullptr)228*5c90c05cSAndroid Build Coastguard Worker std::wstring system_wcsftime(const std::wstring& format, const std::tm* timeptr,
229*5c90c05cSAndroid Build Coastguard Worker                              std::locale* locptr = nullptr) {
230*5c90c05cSAndroid Build Coastguard Worker   auto loc = locptr ? *locptr : std::locale::classic();
231*5c90c05cSAndroid Build Coastguard Worker   auto& facet = std::use_facet<std::time_put<wchar_t>>(loc);
232*5c90c05cSAndroid Build Coastguard Worker   std::wostringstream os;
233*5c90c05cSAndroid Build Coastguard Worker   os.imbue(loc);
234*5c90c05cSAndroid Build Coastguard Worker   facet.put(os, os, L' ', timeptr, format.c_str(),
235*5c90c05cSAndroid Build Coastguard Worker             format.c_str() + format.size());
236*5c90c05cSAndroid Build Coastguard Worker #ifdef _WIN32
237*5c90c05cSAndroid Build Coastguard Worker   // Workaround a bug in older versions of Universal CRT.
238*5c90c05cSAndroid Build Coastguard Worker   auto str = os.str();
239*5c90c05cSAndroid Build Coastguard Worker   if (str == L"-0000") str = L"+0000";
240*5c90c05cSAndroid Build Coastguard Worker   return str;
241*5c90c05cSAndroid Build Coastguard Worker #else
242*5c90c05cSAndroid Build Coastguard Worker   return os.str();
243*5c90c05cSAndroid Build Coastguard Worker #endif
244*5c90c05cSAndroid Build Coastguard Worker }
245*5c90c05cSAndroid Build Coastguard Worker 
TEST(chrono_test_wchar,time_point)246*5c90c05cSAndroid Build Coastguard Worker TEST(chrono_test_wchar, time_point) {
247*5c90c05cSAndroid Build Coastguard Worker   auto t1 = std::chrono::time_point_cast<std::chrono::seconds>(
248*5c90c05cSAndroid Build Coastguard Worker       std::chrono::system_clock::now());
249*5c90c05cSAndroid Build Coastguard Worker 
250*5c90c05cSAndroid Build Coastguard Worker   std::vector<std::wstring> spec_list = {
251*5c90c05cSAndroid Build Coastguard Worker       L"%%",  L"%n",  L"%t",  L"%Y",  L"%EY", L"%y",  L"%Oy", L"%Ey", L"%C",
252*5c90c05cSAndroid Build Coastguard Worker       L"%EC", L"%G",  L"%g",  L"%b",  L"%h",  L"%B",  L"%m",  L"%Om", L"%U",
253*5c90c05cSAndroid Build Coastguard Worker       L"%OU", L"%W",  L"%OW", L"%V",  L"%OV", L"%j",  L"%d",  L"%Od", L"%e",
254*5c90c05cSAndroid Build Coastguard Worker       L"%Oe", L"%a",  L"%A",  L"%w",  L"%Ow", L"%u",  L"%Ou", L"%H",  L"%OH",
255*5c90c05cSAndroid Build Coastguard Worker       L"%I",  L"%OI", L"%M",  L"%OM", L"%S",  L"%OS", L"%x",  L"%Ex", L"%X",
256*5c90c05cSAndroid Build Coastguard Worker       L"%EX", L"%D",  L"%F",  L"%R",  L"%T",  L"%p"};
257*5c90c05cSAndroid Build Coastguard Worker #ifndef _WIN32
258*5c90c05cSAndroid Build Coastguard Worker   // Disabled on Windows, because these formats is not consistent among
259*5c90c05cSAndroid Build Coastguard Worker   // platforms.
260*5c90c05cSAndroid Build Coastguard Worker   spec_list.insert(spec_list.end(), {L"%c", L"%Ec", L"%r"});
261*5c90c05cSAndroid Build Coastguard Worker #elif !FMT_HAS_C99_STRFTIME
262*5c90c05cSAndroid Build Coastguard Worker   // Only C89 conversion specifiers when using MSVCRT instead of UCRT
263*5c90c05cSAndroid Build Coastguard Worker   spec_list = {L"%%", L"%Y", L"%y", L"%b", L"%B", L"%m", L"%U",
264*5c90c05cSAndroid Build Coastguard Worker                L"%W", L"%j", L"%d", L"%a", L"%A", L"%w", L"%H",
265*5c90c05cSAndroid Build Coastguard Worker                L"%I", L"%M", L"%S", L"%x", L"%X", L"%p"};
266*5c90c05cSAndroid Build Coastguard Worker #endif
267*5c90c05cSAndroid Build Coastguard Worker   spec_list.push_back(L"%Y-%m-%d %H:%M:%S");
268*5c90c05cSAndroid Build Coastguard Worker 
269*5c90c05cSAndroid Build Coastguard Worker   for (const auto& spec : spec_list) {
270*5c90c05cSAndroid Build Coastguard Worker     auto t = std::chrono::system_clock::to_time_t(t1);
271*5c90c05cSAndroid Build Coastguard Worker     auto tm = *std::gmtime(&t);
272*5c90c05cSAndroid Build Coastguard Worker 
273*5c90c05cSAndroid Build Coastguard Worker     auto sys_output = system_wcsftime(spec, &tm);
274*5c90c05cSAndroid Build Coastguard Worker 
275*5c90c05cSAndroid Build Coastguard Worker     auto fmt_spec = fmt::format(L"{{:{}}}", spec);
276*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
277*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
278*5c90c05cSAndroid Build Coastguard Worker   }
279*5c90c05cSAndroid Build Coastguard Worker 
280*5c90c05cSAndroid Build Coastguard Worker   // Timezone formatters tests makes sense for localtime.
281*5c90c05cSAndroid Build Coastguard Worker #if FMT_HAS_C99_STRFTIME
282*5c90c05cSAndroid Build Coastguard Worker   spec_list = {L"%z", L"%Z"};
283*5c90c05cSAndroid Build Coastguard Worker #else
284*5c90c05cSAndroid Build Coastguard Worker   spec_list = {L"%Z"};
285*5c90c05cSAndroid Build Coastguard Worker #endif
286*5c90c05cSAndroid Build Coastguard Worker   for (const auto& spec : spec_list) {
287*5c90c05cSAndroid Build Coastguard Worker     auto t = std::chrono::system_clock::to_time_t(t1);
288*5c90c05cSAndroid Build Coastguard Worker     auto tm = *std::localtime(&t);
289*5c90c05cSAndroid Build Coastguard Worker 
290*5c90c05cSAndroid Build Coastguard Worker     auto sys_output = system_wcsftime(spec, &tm);
291*5c90c05cSAndroid Build Coastguard Worker 
292*5c90c05cSAndroid Build Coastguard Worker     auto fmt_spec = fmt::format(L"{{:{}}}", spec);
293*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
294*5c90c05cSAndroid Build Coastguard Worker 
295*5c90c05cSAndroid Build Coastguard Worker     if (spec == L"%z") {
296*5c90c05cSAndroid Build Coastguard Worker       sys_output.insert(sys_output.end() - 2, 1, L':');
297*5c90c05cSAndroid Build Coastguard Worker       EXPECT_EQ(sys_output, fmt::format(L"{:%Ez}", tm));
298*5c90c05cSAndroid Build Coastguard Worker       EXPECT_EQ(sys_output, fmt::format(L"{:%Oz}", tm));
299*5c90c05cSAndroid Build Coastguard Worker     }
300*5c90c05cSAndroid Build Coastguard Worker   }
301*5c90c05cSAndroid Build Coastguard Worker 
302*5c90c05cSAndroid Build Coastguard Worker   // Separate tests for UTC, since std::time_put can use local time and ignoring
303*5c90c05cSAndroid Build Coastguard Worker   // the timezone in std::tm (if it presents on platform).
304*5c90c05cSAndroid Build Coastguard Worker   if (fmt::detail::has_member_data_tm_zone<std::tm>::value) {
305*5c90c05cSAndroid Build Coastguard Worker     auto t = std::chrono::system_clock::to_time_t(t1);
306*5c90c05cSAndroid Build Coastguard Worker     auto tm = *std::gmtime(&t);
307*5c90c05cSAndroid Build Coastguard Worker 
308*5c90c05cSAndroid Build Coastguard Worker     std::vector<std::wstring> tz_names = {L"GMT", L"UTC"};
309*5c90c05cSAndroid Build Coastguard Worker     EXPECT_THAT(tz_names, Contains(fmt::format(L"{:%Z}", t1)));
310*5c90c05cSAndroid Build Coastguard Worker     EXPECT_THAT(tz_names, Contains(fmt::format(L"{:%Z}", tm)));
311*5c90c05cSAndroid Build Coastguard Worker   }
312*5c90c05cSAndroid Build Coastguard Worker 
313*5c90c05cSAndroid Build Coastguard Worker   if (fmt::detail::has_member_data_tm_gmtoff<std::tm>::value) {
314*5c90c05cSAndroid Build Coastguard Worker     auto t = std::chrono::system_clock::to_time_t(t1);
315*5c90c05cSAndroid Build Coastguard Worker     auto tm = *std::gmtime(&t);
316*5c90c05cSAndroid Build Coastguard Worker 
317*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+0000", fmt::format(L"{:%z}", t1));
318*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+0000", fmt::format(L"{:%z}", tm));
319*5c90c05cSAndroid Build Coastguard Worker 
320*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+00:00", fmt::format(L"{:%Ez}", t1));
321*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+00:00", fmt::format(L"{:%Ez}", tm));
322*5c90c05cSAndroid Build Coastguard Worker 
323*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+00:00", fmt::format(L"{:%Oz}", t1));
324*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(L"+00:00", fmt::format(L"{:%Oz}", tm));
325*5c90c05cSAndroid Build Coastguard Worker   }
326*5c90c05cSAndroid Build Coastguard Worker }
327*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,color)328*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, color) {
329*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), L"rgb(255,20,30) wide"),
330*5c90c05cSAndroid Build Coastguard Worker             L"\x1b[38;2;255;020;030mrgb(255,20,30) wide\x1b[0m");
331*5c90c05cSAndroid Build Coastguard Worker }
332*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,ostream)333*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, ostream) {
334*5c90c05cSAndroid Build Coastguard Worker #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 409
335*5c90c05cSAndroid Build Coastguard Worker   {
336*5c90c05cSAndroid Build Coastguard Worker     std::wostringstream wos;
337*5c90c05cSAndroid Build Coastguard Worker     fmt::print(wos, L"Don't {}!", L"panic");
338*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(wos.str(), L"Don't panic!");
339*5c90c05cSAndroid Build Coastguard Worker   }
340*5c90c05cSAndroid Build Coastguard Worker 
341*5c90c05cSAndroid Build Coastguard Worker   {
342*5c90c05cSAndroid Build Coastguard Worker     std::wostringstream wos;
343*5c90c05cSAndroid Build Coastguard Worker     fmt::println(wos, L"Don't {}!", L"panic");
344*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(wos.str(), L"Don't panic!\n");
345*5c90c05cSAndroid Build Coastguard Worker   }
346*5c90c05cSAndroid Build Coastguard Worker #endif
347*5c90c05cSAndroid Build Coastguard Worker }
348*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,format_map)349*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, format_map) {
350*5c90c05cSAndroid Build Coastguard Worker   auto m = std::map<std::wstring, int>{{L"one", 1}, {L"t\"wo", 2}};
351*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", m), L"{\"one\": 1, \"t\\\"wo\": 2}");
352*5c90c05cSAndroid Build Coastguard Worker }
353*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,escape_string)354*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, escape_string) {
355*5c90c05cSAndroid Build Coastguard Worker   using vec = std::vector<std::wstring>;
356*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", vec{L"\n\r\t\"\\"}), L"[\"\\n\\r\\t\\\"\\\\\"]");
357*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", vec{L"понедельник"}), L"[\"понедельник\"]");
358*5c90c05cSAndroid Build Coastguard Worker }
359*5c90c05cSAndroid Build Coastguard Worker 
TEST(xchar_test,to_wstring)360*5c90c05cSAndroid Build Coastguard Worker TEST(xchar_test, to_wstring) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
361*5c90c05cSAndroid Build Coastguard Worker 
362*5c90c05cSAndroid Build Coastguard Worker #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
363*5c90c05cSAndroid Build Coastguard Worker 
364*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct numpunct : std::numpunct<Char> {
365*5c90c05cSAndroid Build Coastguard Worker  protected:
do_decimal_pointnumpunct366*5c90c05cSAndroid Build Coastguard Worker   Char do_decimal_point() const override { return '?'; }
do_groupingnumpunct367*5c90c05cSAndroid Build Coastguard Worker   std::string do_grouping() const override { return "\03"; }
do_thousands_sepnumpunct368*5c90c05cSAndroid Build Coastguard Worker   Char do_thousands_sep() const override { return '~'; }
369*5c90c05cSAndroid Build Coastguard Worker };
370*5c90c05cSAndroid Build Coastguard Worker 
371*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct no_grouping : std::numpunct<Char> {
372*5c90c05cSAndroid Build Coastguard Worker  protected:
do_decimal_pointno_grouping373*5c90c05cSAndroid Build Coastguard Worker   Char do_decimal_point() const override { return '.'; }
do_groupingno_grouping374*5c90c05cSAndroid Build Coastguard Worker   std::string do_grouping() const override { return ""; }
do_thousands_sepno_grouping375*5c90c05cSAndroid Build Coastguard Worker   Char do_thousands_sep() const override { return ','; }
376*5c90c05cSAndroid Build Coastguard Worker };
377*5c90c05cSAndroid Build Coastguard Worker 
378*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct special_grouping : std::numpunct<Char> {
379*5c90c05cSAndroid Build Coastguard Worker  protected:
do_decimal_pointspecial_grouping380*5c90c05cSAndroid Build Coastguard Worker   Char do_decimal_point() const override { return '.'; }
do_groupingspecial_grouping381*5c90c05cSAndroid Build Coastguard Worker   std::string do_grouping() const override { return "\03\02"; }
do_thousands_sepspecial_grouping382*5c90c05cSAndroid Build Coastguard Worker   Char do_thousands_sep() const override { return ','; }
383*5c90c05cSAndroid Build Coastguard Worker };
384*5c90c05cSAndroid Build Coastguard Worker 
385*5c90c05cSAndroid Build Coastguard Worker template <typename Char> struct small_grouping : std::numpunct<Char> {
386*5c90c05cSAndroid Build Coastguard Worker  protected:
do_decimal_pointsmall_grouping387*5c90c05cSAndroid Build Coastguard Worker   Char do_decimal_point() const override { return '.'; }
do_groupingsmall_grouping388*5c90c05cSAndroid Build Coastguard Worker   std::string do_grouping() const override { return "\01"; }
do_thousands_sepsmall_grouping389*5c90c05cSAndroid Build Coastguard Worker   Char do_thousands_sep() const override { return ','; }
390*5c90c05cSAndroid Build Coastguard Worker };
391*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,localized_double)392*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, localized_double) {
393*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale(std::locale(), new numpunct<char>());
394*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:L}", 1.23), "1?23");
395*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:Lf}", 1.23), "1?230000");
396*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:L}", 1234.5), "1~234?5");
397*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:L}", 12000.0), "12~000");
398*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:8L}", 1230.0), "   1~230");
399*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:15.6Lf}", 0.1), "       0?100000");
400*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:15.6Lf}", 1.0), "       1?000000");
401*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(loc, "{:15.6Lf}", 1e3), "   1~000?000000");
402*5c90c05cSAndroid Build Coastguard Worker }
403*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,format)404*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, format) {
405*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale(std::locale(), new numpunct<char>());
406*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1234567", fmt::format(std::locale(), "{:L}", 1234567));
407*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1~234~567", fmt::format(loc, "{:L}", 1234567));
408*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("-1~234~567", fmt::format(loc, "{:L}", -1234567));
409*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("-256", fmt::format(loc, "{:L}", -256));
410*5c90c05cSAndroid Build Coastguard Worker   auto n = 1234567;
411*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1~234~567", fmt::vformat(loc, "{:L}", fmt::make_format_args(n)));
412*5c90c05cSAndroid Build Coastguard Worker   auto s = std::string();
413*5c90c05cSAndroid Build Coastguard Worker   fmt::format_to(std::back_inserter(s), loc, "{:L}", 1234567);
414*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1~234~567", s);
415*5c90c05cSAndroid Build Coastguard Worker 
416*5c90c05cSAndroid Build Coastguard Worker   auto no_grouping_loc = std::locale(std::locale(), new no_grouping<char>());
417*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1234567", fmt::format(no_grouping_loc, "{:L}", 1234567));
418*5c90c05cSAndroid Build Coastguard Worker 
419*5c90c05cSAndroid Build Coastguard Worker   auto special_grouping_loc =
420*5c90c05cSAndroid Build Coastguard Worker       std::locale(std::locale(), new special_grouping<char>());
421*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:L}", 12345678));
422*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("12,345", fmt::format(special_grouping_loc, "{:L}", 12345));
423*5c90c05cSAndroid Build Coastguard Worker 
424*5c90c05cSAndroid Build Coastguard Worker   auto small_grouping_loc =
425*5c90c05cSAndroid Build Coastguard Worker       std::locale(std::locale(), new small_grouping<char>());
426*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
427*5c90c05cSAndroid Build Coastguard Worker             fmt::format(small_grouping_loc, "{:L}", max_value<uint32_t>()));
428*5c90c05cSAndroid Build Coastguard Worker }
429*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,format_default_align)430*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, format_default_align) {
431*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale({}, new special_grouping<char>());
432*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("  12,345", fmt::format(loc, "{:8L}", 12345));
433*5c90c05cSAndroid Build Coastguard Worker }
434*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,format_plus)435*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, format_plus) {
436*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale({}, new special_grouping<char>());
437*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ("+100", fmt::format(loc, "{:+L}", 100));
438*5c90c05cSAndroid Build Coastguard Worker }
439*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,wformat)440*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, wformat) {
441*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale(std::locale(), new numpunct<wchar_t>());
442*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:L}", 1234567));
443*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1~234~567", fmt::format(loc, L"{:L}", 1234567));
444*5c90c05cSAndroid Build Coastguard Worker   int n = 1234567;
445*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1~234~567",
446*5c90c05cSAndroid Build Coastguard Worker             fmt::vformat(loc, L"{:L}", fmt::make_wformat_args(n)));
447*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1234567", fmt::format(std::locale("C"), L"{:L}", 1234567));
448*5c90c05cSAndroid Build Coastguard Worker 
449*5c90c05cSAndroid Build Coastguard Worker   auto no_grouping_loc = std::locale(std::locale(), new no_grouping<wchar_t>());
450*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1234567", fmt::format(no_grouping_loc, L"{:L}", 1234567));
451*5c90c05cSAndroid Build Coastguard Worker 
452*5c90c05cSAndroid Build Coastguard Worker   auto special_grouping_loc =
453*5c90c05cSAndroid Build Coastguard Worker       std::locale(std::locale(), new special_grouping<wchar_t>());
454*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"1,23,45,678",
455*5c90c05cSAndroid Build Coastguard Worker             fmt::format(special_grouping_loc, L"{:L}", 12345678));
456*5c90c05cSAndroid Build Coastguard Worker 
457*5c90c05cSAndroid Build Coastguard Worker   auto small_grouping_loc =
458*5c90c05cSAndroid Build Coastguard Worker       std::locale(std::locale(), new small_grouping<wchar_t>());
459*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(L"4,2,9,4,9,6,7,2,9,5",
460*5c90c05cSAndroid Build Coastguard Worker             fmt::format(small_grouping_loc, L"{:L}", max_value<uint32_t>()));
461*5c90c05cSAndroid Build Coastguard Worker }
462*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,int_formatter)463*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, int_formatter) {
464*5c90c05cSAndroid Build Coastguard Worker   auto loc = std::locale(std::locale(), new special_grouping<char>());
465*5c90c05cSAndroid Build Coastguard Worker   auto f = fmt::formatter<int>();
466*5c90c05cSAndroid Build Coastguard Worker   auto parse_ctx = fmt::format_parse_context("L");
467*5c90c05cSAndroid Build Coastguard Worker   f.parse(parse_ctx);
468*5c90c05cSAndroid Build Coastguard Worker   auto buf = fmt::memory_buffer();
469*5c90c05cSAndroid Build Coastguard Worker   fmt::basic_format_context<fmt::appender, char> format_ctx(
470*5c90c05cSAndroid Build Coastguard Worker       fmt::appender(buf), {}, fmt::detail::locale_ref(loc));
471*5c90c05cSAndroid Build Coastguard Worker   f.format(12345, format_ctx);
472*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::to_string(buf), "12,345");
473*5c90c05cSAndroid Build Coastguard Worker }
474*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,chrono_weekday)475*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, chrono_weekday) {
476*5c90c05cSAndroid Build Coastguard Worker   auto loc = get_locale("es_ES.UTF-8", "Spanish_Spain.1252");
477*5c90c05cSAndroid Build Coastguard Worker   auto loc_old = std::locale::global(loc);
478*5c90c05cSAndroid Build Coastguard Worker   auto sat = fmt::weekday(6);
479*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", sat), L"Sat");
480*5c90c05cSAndroid Build Coastguard Worker   if (loc != std::locale::classic()) {
481*5c90c05cSAndroid Build Coastguard Worker     // L'\341' is 'á'.
482*5c90c05cSAndroid Build Coastguard Worker     auto saturdays =
483*5c90c05cSAndroid Build Coastguard Worker         std::vector<std::wstring>{L"s\341b", L"s\341.", L"s\341b."};
484*5c90c05cSAndroid Build Coastguard Worker     EXPECT_THAT(saturdays, Contains(fmt::format(loc, L"{:L}", sat)));
485*5c90c05cSAndroid Build Coastguard Worker   }
486*5c90c05cSAndroid Build Coastguard Worker   std::locale::global(loc_old);
487*5c90c05cSAndroid Build Coastguard Worker }
488*5c90c05cSAndroid Build Coastguard Worker 
TEST(locale_test,sign)489*5c90c05cSAndroid Build Coastguard Worker TEST(locale_test, sign) {
490*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(std::locale(), L"{:L}", -50), L"-50");
491*5c90c05cSAndroid Build Coastguard Worker }
492*5c90c05cSAndroid Build Coastguard Worker 
TEST(std_test_xchar,complex)493*5c90c05cSAndroid Build Coastguard Worker TEST(std_test_xchar, complex) {
494*5c90c05cSAndroid Build Coastguard Worker   auto s = fmt::format(L"{}", std::complex<double>(1, 2));
495*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(s, L"(1+2i)");
496*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{:.2f}", std::complex<double>(1, 2)),
497*5c90c05cSAndroid Build Coastguard Worker             L"(1.00+2.00i)");
498*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{:8}", std::complex<double>(1, 2)), L"(1+2i)  ");
499*5c90c05cSAndroid Build Coastguard Worker }
500*5c90c05cSAndroid Build Coastguard Worker 
TEST(std_test_xchar,optional)501*5c90c05cSAndroid Build Coastguard Worker TEST(std_test_xchar, optional) {
502*5c90c05cSAndroid Build Coastguard Worker #  ifdef __cpp_lib_optional
503*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", std::optional{L'C'}), L"optional(\'C\')");
504*5c90c05cSAndroid Build Coastguard Worker   EXPECT_EQ(fmt::format(L"{}", std::optional{std::wstring{L"wide string"}}),
505*5c90c05cSAndroid Build Coastguard Worker             L"optional(\"wide string\")");
506*5c90c05cSAndroid Build Coastguard Worker #  endif
507*5c90c05cSAndroid Build Coastguard Worker }
508*5c90c05cSAndroid Build Coastguard Worker 
509*5c90c05cSAndroid Build Coastguard Worker #endif  // FMT_STATIC_THOUSANDS_SEPARATOR
510