1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===//
8 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11 // TODO FMT This test should not require std::to_chars(floating-point)
12 // XFAIL: availability-fp_to_chars-missing
14 // Force unicode to be disabled.
15 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_HAS_NO_UNICODE
19 // This test the debug string type for the formatter specializations for char
20 // and string types. This tests ASCII strings, the tests assume every char32_t value is valid ASCII.
28 #include "test_macros.h"
29 #include "make_string.h"
30 #include "test_format_string.h"
31 #include "assert_macros.h"
32 #include "concat_macros.h"
34 #ifndef TEST_HAS_NO_LOCALIZATION
38 #define SV(S) MAKE_STRING_VIEW(CharT, S)
40 auto test_format
= []<class CharT
, class... Args
>(
41 std::basic_string_view
<CharT
> expected
, test_format_string
<CharT
, Args
...> fmt
, Args
&&... args
) {
43 std::basic_string
<CharT
> out
= std::format(fmt
, std::forward
<Args
>(args
)...);
44 TEST_REQUIRE(out
== expected
,
45 TEST_WRITE_CONCATENATED(
46 "\nFormat string ", fmt
.get(), "\nExpected output ", expected
, "\nActual output ", out
, '\n'));
48 #ifndef TEST_HAS_NO_LOCALIZATION
50 std::basic_string
<CharT
> out
= std::format(std::locale(), fmt
, std::forward
<Args
>(args
)...);
51 assert(out
== expected
);
53 #endif // TEST_HAS_NO_LOCALIZATION
57 []<class CharT
, class... Args
>(
58 std::basic_string_view
<CharT
> expected
, test_format_string
<CharT
, Args
...> fmt
, Args
&&... args
) {
60 std::basic_string
<CharT
> out(expected
.size(), CharT(' '));
61 auto it
= std::format_to(out
.begin(), fmt
, std::forward
<Args
>(args
)...);
62 assert(it
== out
.end());
63 assert(out
== expected
);
65 #ifndef TEST_HAS_NO_LOCALIZATION
67 std::basic_string
<CharT
> out(expected
.size(), CharT(' '));
68 auto it
= std::format_to(out
.begin(), std::locale(), fmt
, std::forward
<Args
>(args
)...);
69 assert(it
== out
.end());
70 assert(out
== expected
);
72 #endif // TEST_HAS_NO_LOCALIZATION
75 std::format_to(std::back_inserter(out
), fmt
, std::forward
<Args
>(args
)...);
76 assert(std::equal(out
.begin(), out
.end(), expected
.begin(), expected
.end()));
79 std::vector
<CharT
> out
;
80 std::format_to(std::back_inserter(out
), fmt
, std::forward
<Args
>(args
)...);
81 assert(std::equal(out
.begin(), out
.end(), expected
.begin(), expected
.end()));
84 assert(expected
.size() < 4096 && "Update the size of the buffer.");
86 CharT
* it
= std::format_to(out
, fmt
, std::forward
<Args
>(args
)...);
87 assert(std::distance(out
, it
) == int(expected
.size()));
88 // Convert to std::string since output contains '\0' for boolean tests.
89 assert(std::basic_string
<CharT
>(out
, it
) == expected
);
93 auto test_formatted_size
=
94 []<class CharT
, class... Args
>(
95 std::basic_string_view
<CharT
> expected
, test_format_string
<CharT
, Args
...> fmt
, Args
&&... args
) {
97 std::size_t size
= std::formatted_size(fmt
, std::forward
<Args
>(args
)...);
98 assert(size
== expected
.size());
100 #ifndef TEST_HAS_NO_LOCALIZATION
102 std::size_t size
= std::formatted_size(std::locale(), fmt
, std::forward
<Args
>(args
)...);
103 assert(size
== expected
.size());
105 #endif // TEST_HAS_NO_LOCALIZATION
108 auto test_format_to_n
=
109 []<class CharT
, class... Args
>(
110 std::basic_string_view
<CharT
> expected
, test_format_string
<CharT
, Args
...> fmt
, Args
&&... args
) {
112 std::size_t n
= expected
.size();
113 std::basic_string
<CharT
> out(n
, CharT(' '));
114 std::format_to_n_result result
= std::format_to_n(out
.begin(), n
, fmt
, std::forward
<Args
>(args
)...);
115 assert(result
.size
== static_cast<std::ptrdiff_t>(expected
.size()));
116 assert(result
.out
== out
.end());
117 assert(out
== expected
);
119 #ifndef TEST_HAS_NO_LOCALIZATION
121 std::size_t n
= expected
.size();
122 std::basic_string
<CharT
> out(n
, CharT(' '));
123 std::format_to_n_result result
=
124 std::format_to_n(out
.begin(), n
, std::locale(), fmt
, std::forward
<Args
>(args
)...);
125 assert(result
.size
== static_cast<std::ptrdiff_t>(expected
.size()));
126 assert(result
.out
== out
.end());
127 assert(out
== expected
);
129 #endif // TEST_HAS_NO_LOCALIZATION
131 std::ptrdiff_t n
= 0;
132 std::basic_string
<CharT
> out
;
133 std::format_to_n_result result
= std::format_to_n(out
.begin(), n
, fmt
, std::forward
<Args
>(args
)...);
134 assert(result
.size
== static_cast<std::ptrdiff_t>(expected
.size()));
135 assert(result
.out
== out
.end());
139 std::ptrdiff_t n
= expected
.size() / 2;
140 std::basic_string
<CharT
> out(n
, CharT(' '));
141 std::format_to_n_result result
= std::format_to_n(out
.begin(), n
, fmt
, std::forward
<Args
>(args
)...);
142 assert(result
.size
== static_cast<std::ptrdiff_t>(expected
.size()));
143 assert(result
.out
== out
.end());
144 assert(out
== expected
.substr(0, n
));
148 template <class CharT
>
150 // *** P2286 examples ***
151 test_format(SV("['\\'', '\"']"), SV("[{:?}, {:?}]"), CharT('\''), CharT('"'));
153 // *** Specical cases ***
154 test_format(SV("'\\t'"), SV("{:?}"), CharT('\t'));
155 test_format(SV("'\\n'"), SV("{:?}"), CharT('\n'));
156 test_format(SV("'\\r'"), SV("{:?}"), CharT('\r'));
157 test_format(SV("'\\\\'"), SV("{:?}"), CharT('\\'));
159 test_format(SV("'\\\''"), SV("{:?}"), CharT('\''));
160 test_format(SV("'\"'"), SV("{:?}"), CharT('"')); // only special for string
162 test_format(SV("' '"), SV("{:?}"), CharT(' '));
165 test_format(SV("'a'"), SV("{:?}"), CharT('a'));
166 test_format(SV("'b'"), SV("{:?}"), CharT('b'));
167 test_format(SV("'c'"), SV("{:?}"), CharT('c'));
169 // *** Non-printable ***
172 test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0'));
173 test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f'));
176 if constexpr (sizeof(CharT
) == 1)
177 test_format(SV("'\x80'"), SV("{:?}"), CharT('\x80'));
179 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
180 if constexpr (sizeof(CharT
) > 1) {
181 using V
= std::basic_string_view
<CharT
>;
183 // Unicode fitting in a 16-bit wchar_t
185 // *** Non-printable ***
188 test_format(V
{L
"'\xa0'"}, L
"{:?}", L
'\xa0'); // NO-BREAK SPACE
189 test_format(V
{L
"'\x3000'"}, L
"{:?}", L
'\x3000'); // IDEOGRAPHIC SPACE
192 test_format(V
{L
"'\x2028'"}, L
"{:?}", L
'\x2028'); // LINE SEPARATOR
194 // Paragraph_Separator
195 test_format(V
{L
"'\x2029'"}, L
"{:?}", L
'\x2029'); // PARAGRAPH SEPARATOR
198 test_format(V
{L
"'\xad'"}, L
"{:?}", L
'\xad'); // SOFT HYPHEN
199 test_format(V
{L
"'\x600'"}, L
"{:?}", L
'\x600'); // ARABIC NUMBER SIGN
200 test_format(V
{L
"'\xfeff'"}, L
"{:?}", L
'\xfeff'); // ZERO WIDTH NO-BREAK SPACE
202 if constexpr (sizeof(CharT
) == 2) {
203 // Incomplete surrogate pair in UTF-16
204 test_format(V
{L
"'\xd800'"}, L
"{:?}", L
'\xd800'); // <surrogate-D800>
205 test_format(V
{L
"'\xdfff'"}, L
"{:?}", L
'\xdfff'); // <surrogate-DFFF>
207 test_format(V
{L
"'\xd800'"}, L
"{:?}", L
'\xd800'); // <surrogate-D800>
208 test_format(V
{L
"'\xdfff'"}, L
"{:?}", L
'\xdfff'); // <surrogate-DFFF>
212 test_format(V
{L
"'\xe000'"}, L
"{:?}", L
'\xe000'); // <private-use-E000>
213 test_format(V
{L
"'\xf8ff'"}, L
"{:?}", L
'\xf8ff'); // <private-use-F8FF>
216 test_format(V
{L
"'\x378'"}, L
"{:?}", L
'\x378'); // <reserved-0378>
217 test_format(V
{L
"'\x1774'"}, L
"{:?}", L
'\x1774'); // <reserved-1774>
218 test_format(V
{L
"'\xffff'"}, L
"{:?}", L
'\xffff'); // <noncharacter-FFFF>
221 test_format(V
{L
"'\x300'"}, L
"{:?}", L
'\x300'); // COMBINING GRAVE ACCENT
222 test_format(V
{L
"'\xfe20'"}, L
"{:?}", L
'\xfe20'); // VARIATION SELECTOR-1
224 # ifndef TEST_SHORT_WCHAR
225 if constexpr (sizeof(CharT
) > 2) {
226 static_assert(sizeof(CharT
) == 4, "add support for unexpected size");
227 // Unicode fitting in a 32-bit wchar_t
229 constexpr wchar_t x
= 0x1ffff;
230 constexpr std::uint32_t y
= 0x1ffff;
231 static_assert(x
== y
);
233 using V
= std::basic_string_view
<CharT
>;
235 // *** Non-printable ***
237 test_format(V
{L
"'\x110bd'"}, L
"{:?}", L
'\x110bd'); // KAITHI NUMBER SIGN
238 test_format(V
{L
"'\xe007f'"}, L
"{:?}", L
'\xe007f'); // CANCEL TAG
241 test_format(V
{L
"'\xf0000'"}, L
"{:?}", L
'\xf0000'); // <private-use-F0000>
242 test_format(V
{L
"'\xffffd'"}, L
"{:?}", L
'\xffffd'); // <private-use-FFFFD>
244 test_format(V
{L
"'\x100000'"}, L
"{:?}", L
'\x100000'); // <private-use-100000>
245 test_format(V
{L
"'\x10fffd'"}, L
"{:?}", L
'\x10fffd'); // <private-use-10FFFD>
248 test_format(V
{L
"'\x1000c'"}, L
"{:?}", L
'\x1000c'); // <reserved-1000c>
249 test_format(V
{L
"'\xfffff'"}, L
"{:?}", L
'\xfffff'); // <noncharacter-FFFFF>
250 test_format(V
{L
"'\x10fffe'"}, L
"{:?}", L
'\x10fffe'); // <noncharacter-10FFFE>
253 test_format(V
{L
"'\x101fd'"}, L
"{:?}", L
'\x101fd'); // COMBINING OLD PERMIC LETTER AN
254 test_format(V
{L
"'\xe0100'"}, L
"{:?}", L
'\xe0100'); // VARIATION SELECTOR-17
257 test_format(V
{L
"'\x110000'"}, L
"{:?}", L
'\x110000');
258 test_format(V
{L
"'\xffffffff'"}, L
"{:?}", L
'\xffffffff');
260 # endif // TEST_SHORT_WCHAR
261 #endif // TEST_HAS_NO_WIDE_CHARACTERS
264 template <class CharT
>
266 // *** P2286 examples ***
267 test_format(SV("[h\tllo]"), SV("[{}]"), SV("h\tllo"));
268 test_format(SV(R
"(["h
\tllo
"])"), SV("[{:?}]"), SV("h\tllo"));
269 test_format(SV(R
"(["Спасибо
, Виктор ♥
!"])"), SV("[{:?}]"), SV("Спасибо, Виктор ♥!"));
271 test_format(SV(R
"(["\u
{0} \n \t \u
{2} \u
{1b
}"])"), SV("[{:?}]"), SV("\0 \n \t \x02 \x1b"));
273 if constexpr (sizeof(CharT
) == 1) {
274 // Ill-formend UTF-8, but valid as ASCII
275 test_format(SV("[\"\xc3\"]"), SV("[{:?}]"), SV("\xc3"));
276 test_format(SV("[\"\xc3\x28\"]"), SV("[{:?}]"), SV("\xc3\x28"));
278 // Valid UTF-16 and UTF-32
279 test_format(SV("[\"\u00c3\"]"), SV("[{:?}]"), L
"\xc3"); // LATIN CAPITAL LETTER A WITH TILDE
280 test_format(SV("[\"\u00c3(\"]"), SV("[{:?}]"), L
"\xc3\x28");
283 test_format(SV("[\"🤷🏻\u200d♂\ufe0f\"]"), SV("[{:?}]"), SV("🤷🏻♂️"));
285 // *** Specical cases ***
286 test_format(SV(R
"("\t\n\r\\'\" ")"), SV("{:?}"), SV("\t\n\r\\'\" "));
289 test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg
"));
291 // *** Non-printable ***
294 test_format(SV(R"("\u{0}\u{1f}")"), SV("{:?}"), SV("\
0\x1f"));
296 // Ill-formed UTF-8, valid ASCII
297 test_format(SV("\"\x80\""), SV("{:?}"), SV("\x80"));
300 template <class CharT, class TestFunction>
301 void test_format_functions(TestFunction check) {
302 // LATIN SMALL LETTER O WITH DIAERESIS is encoded in two chars or 1 wchar_t
303 // due to the range of the value.
304 // 8 + sizeof(CharT) == 1 is not considered an constant expression
306 // *** align-fill & width ***
307 check(SV(R"(***"hellö")"),
310 sizeof(CharT) == 1 ? 11 : 10); // ö is LATIN SMALL LETTER O WITH DIAERESIS
311 check(SV(R"(*"hellö"**)"), SV("{:*^{}?}"), SV("hellö
"), sizeof(CharT) == 1 ? 11 : 10);
312 check(SV(R"("hellö"***)"), SV("{:*<{}?}"), SV("hellö
"), sizeof(CharT) == 1 ? 11 : 10);
314 check(SV("\"hello
\u0308\""), SV("{:*>{}?}"), SV("hello
\u0308"), sizeof(CharT) == 1 ? 9 : 8);
315 check(SV("***\"hello
\u0308\""), SV("{:*>{}?}"), SV("hello
\u0308"), sizeof(CharT) == 1 ? 12 : 11);
316 check(SV("*\"hello
\u0308\"**"), SV("{:*^{}?}"), SV("hello
\u0308"), sizeof(CharT) == 1 ? 12 : 11);
317 check(SV("\"hello
\u0308\"***"), SV("{:*<{}?}"), SV("hello
\u0308"), sizeof(CharT) == 1 ? 12 : 11);
320 check(SV(R"("hello" )"), SV("{:10?}"), SV("hello
"));
323 check(SV(R"("hell)"), SV("{:.5?}"), SV("hello"));
324 check(SV(R
"("hello
)"), SV("{:.6?}"), SV("hello
"));
325 check(SV(R"("hello")"), SV("{:.7?}"), SV("hello
"));
327 // *** width & precision ***
328 check(SV(R"("hell#########################)"), SV("{:#<30.5?}"), SV("hello"));
329 check(SV(R
"("hello
########################)"), SV("{:#<30.6?}"), SV("hello"));
330 check(SV(R"("hello"#######################)"), SV("{:#<30.7?}"), SV("hello"));
333 template <class CharT>
337 test_string<CharT>();
339 test_format_functions<CharT>(test_format);
340 test_format_functions<CharT>(test_format_to);
341 test_format_functions<CharT>(test_formatted_size);
342 test_format_functions<CharT>(test_format_to_n);
345 int main(int, char**) {
347 #ifndef TEST_HAS_NO_WIDE_CHARACTERS