xref: /llvm-project/libcxx/test/std/utilities/format/format.functions/escaped_output.unicode.pass.cpp (revision f0fc8c4878ed3ed60bd7536f97ef2673eb691ae7)
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
5 //
6 //===----------------------------------------------------------------------===//
7 
8 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9 // UNSUPPORTED: libcpp-has-no-incomplete-format
10 
11 // This version runs the test when the platform has Unicode support.
12 // UNSUPPORTED: libcpp-has-no-unicode
13 
14 // TODO FMT Investigate Windows and AIX issues.
15 // UNSUPPORTED: msvc, target={{.+}}-windows-gnu
16 // UNSUPPORTED: LIBCXX-AIX-FIXME
17 
18 // TODO FMT Fix this test using GCC, it currently crashes.
19 // UNSUPPORTED: gcc-12
20 
21 // TODO FMT This test should not require std::to_chars(floating-point)
22 // XFAIL: availability-fp_to_chars-missing
23 
24 // <format>
25 
26 // This test the debug string type for the formatter specializations for char
27 // and string types. This tests Unicode strings.
28 
29 #include <format>
30 
31 #include <cassert>
32 #include <concepts>
33 #include <iterator>
34 #include <list>
35 #include <vector>
36 
37 #include "test_macros.h"
38 #include "make_string.h"
39 #include "test_format_string.h"
40 #include "assert_macros.h"
41 #include "concat_macros.h"
42 
43 #ifndef TEST_HAS_NO_LOCALIZATION
44 #  include <iostream>
45 #endif
46 
47 #define SV(S) MAKE_STRING_VIEW(CharT, S)
48 
49 auto test_format = []<class CharT, class... Args>(
50                        std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
51   {
52     std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
53     TEST_REQUIRE(out == expected,
54                  TEST_WRITE_CONCATENATED(
55                      "\nFormat string   ", fmt.get(), "\nExpected output ", expected, "\nActual output   ", out, '\n'));
56   }
57 #ifndef TEST_HAS_NO_LOCALIZATION
58   {
59     std::basic_string<CharT> out = std::format(std::locale(), fmt, std::forward<Args>(args)...);
60     assert(out == expected);
61   }
62 #endif // TEST_HAS_NO_LOCALIZATION
63 };
64 
65 auto test_format_to =
66     []<class CharT, class... Args>(
67         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
68       {
69         std::basic_string<CharT> out(expected.size(), CharT(' '));
70         auto it = std::format_to(out.begin(), fmt, std::forward<Args>(args)...);
71         assert(it == out.end());
72         assert(out == expected);
73       }
74 #ifndef TEST_HAS_NO_LOCALIZATION
75       {
76         std::basic_string<CharT> out(expected.size(), CharT(' '));
77         auto it = std::format_to(out.begin(), std::locale(), fmt, std::forward<Args>(args)...);
78         assert(it == out.end());
79         assert(out == expected);
80       }
81 #endif // TEST_HAS_NO_LOCALIZATION
82       {
83         std::list<CharT> out;
84         std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
85         assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
86       }
87       {
88         std::vector<CharT> out;
89         std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
90         assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
91       }
92       {
93         assert(expected.size() < 4096 && "Update the size of the buffer.");
94         CharT out[4096];
95         CharT* it = std::format_to(out, fmt, std::forward<Args>(args)...);
96         assert(std::distance(out, it) == int(expected.size()));
97         // Convert to std::string since output contains '\0' for boolean tests.
98         assert(std::basic_string<CharT>(out, it) == expected);
99       }
100     };
101 
102 auto test_formatted_size =
103     []<class CharT, class... Args>(
104         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
105       {
106         std::size_t size = std::formatted_size(fmt, std::forward<Args>(args)...);
107         assert(size == expected.size());
108       }
109 #ifndef TEST_HAS_NO_LOCALIZATION
110       {
111         std::size_t size = std::formatted_size(std::locale(), fmt, std::forward<Args>(args)...);
112         assert(size == expected.size());
113       }
114 #endif // TEST_HAS_NO_LOCALIZATION
115     };
116 
117 auto test_format_to_n =
118     []<class CharT, class... Args>(
119         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
120       {
121         std::size_t n = expected.size();
122         std::basic_string<CharT> out(n, CharT(' '));
123         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
124         assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
125         assert(result.out == out.end());
126         assert(out == expected);
127       }
128 #ifndef TEST_HAS_NO_LOCALIZATION
129       {
130         std::size_t n = expected.size();
131         std::basic_string<CharT> out(n, CharT(' '));
132         std::format_to_n_result result =
133             std::format_to_n(out.begin(), n, std::locale(), fmt, std::forward<Args>(args)...);
134         assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
135         assert(result.out == out.end());
136         assert(out == expected);
137       }
138 #endif // TEST_HAS_NO_LOCALIZATION
139       {
140         std::ptrdiff_t n = 0;
141         std::basic_string<CharT> out;
142         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
143         assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
144         assert(result.out == out.end());
145         assert(out.empty());
146       }
147       {
148         std::ptrdiff_t n = expected.size() / 2;
149         std::basic_string<CharT> out(n, CharT(' '));
150         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
151         assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
152         assert(result.out == out.end());
153         assert(out == expected.substr(0, n));
154       }
155     };
156 
157 template <class CharT>
158 void test_char() {
159   // *** P2286 examples ***
160   test_format(SV("['\\'', '\"']"), SV("[{:?}, {:?}]"), CharT('\''), CharT('"'));
161 
162   // *** Specical cases ***
163   test_format(SV("'\\t'"), SV("{:?}"), CharT('\t'));
164   test_format(SV("'\\n'"), SV("{:?}"), CharT('\n'));
165   test_format(SV("'\\r'"), SV("{:?}"), CharT('\r'));
166   test_format(SV("'\\\\'"), SV("{:?}"), CharT('\\'));
167 
168   test_format(SV("'\\\''"), SV("{:?}"), CharT('\''));
169   test_format(SV("'\"'"), SV("{:?}"), CharT('"')); // only special for string
170 
171   test_format(SV("' '"), SV("{:?}"), CharT(' '));
172 
173   // *** Printable ***
174   test_format(SV("'a'"), SV("{:?}"), CharT('a'));
175   test_format(SV("'b'"), SV("{:?}"), CharT('b'));
176   test_format(SV("'c'"), SV("{:?}"), CharT('c'));
177 
178   // *** Non-printable ***
179 
180   // Control
181   test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0'));
182   test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f'));
183 
184   // Ill-formed
185   if constexpr (sizeof(CharT) == 1)
186     test_format(SV("'\\x{80}'"), SV("{:?}"), CharT('\x80'));
187 
188 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
189   if constexpr (sizeof(CharT) > 1) {
190     using V = std::basic_string_view<CharT>;
191 
192     // Unicode fitting in a 16-bit wchar_t
193 
194     // *** Non-printable ***
195 
196     // Space_Separator
197     test_format(V{L"'\\u{a0}'"}, L"{:?}", L'\xa0');     // NO-BREAK SPACE
198     test_format(V{L"'\\u{3000}'"}, L"{:?}", L'\x3000'); // IDEOGRAPHIC SPACE
199 
200     // Line_Separator
201     test_format(V{L"'\\u{2028}'"}, L"{:?}", L'\x2028'); // LINE SEPARATOR
202 
203     // Paragraph_Separator
204     test_format(V{L"'\\u{2029}'"}, L"{:?}", L'\x2029'); // PARAGRAPH SEPARATOR
205 
206     // Format
207     test_format(V{L"'\\u{ad}'"}, L"{:?}", L'\xad');     // SOFT HYPHEN
208     test_format(V{L"'\\u{600}'"}, L"{:?}", L'\x600');   // ARABIC NUMBER SIGN
209     test_format(V{L"'\\u{feff}'"}, L"{:?}", L'\xfeff'); // ZERO WIDTH NO-BREAK SPACE
210 
211     // Incomplete surrogate pair in UTF-16
212     test_format(V{L"'\\x{d800}'"}, L"{:?}", L'\xd800'); // <surrogate-D800>
213     test_format(V{L"'\\x{dfff}'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF>
214 
215     // Private_Use
216     test_format(V{L"'\\u{e000}'"}, L"{:?}", L'\xe000'); // <private-use-E000>
217     test_format(V{L"'\\u{f8ff}'"}, L"{:?}", L'\xf8ff'); // <private-use-F8FF>
218 
219     // Unassigned
220     test_format(V{L"'\\u{378}'"}, L"{:?}", L'\x378');   // <reserved-0378>
221     test_format(V{L"'\\u{1774}'"}, L"{:?}", L'\x1774'); // <reserved-1774>
222     test_format(V{L"'\\u{ffff}'"}, L"{:?}", L'\xffff'); // <noncharacter-FFFF>
223 
224     // Grapheme Extended
225     test_format(V{L"'\\u{300}'"}, L"{:?}", L'\x300');   // COMBINING GRAVE ACCENT
226     test_format(V{L"'\\u{fe20}'"}, L"{:?}", L'\xfe20'); // VARIATION SELECTOR-1
227   }
228 #  ifndef TEST_SHORT_WCHAR
229   if constexpr (sizeof(CharT) > 2) {
230     static_assert(sizeof(CharT) == 4, "add support for unexpected size");
231     // Unicode fitting in a 32-bit wchar_t
232 
233     constexpr wchar_t x  = 0x1ffff;
234     constexpr std::uint32_t y = 0x1ffff;
235     static_assert(x == y);
236 
237     using V = std::basic_string_view<CharT>;
238 
239     // *** Non-printable ***
240     // Format
241     test_format(V{L"'\\u{110bd}'"}, L"{:?}", L'\x110bd'); // KAITHI NUMBER SIGN
242     test_format(V{L"'\\u{e007f}'"}, L"{:?}", L'\xe007f'); // CANCEL TAG
243 
244     // Private_Use
245     test_format(V{L"'\\u{f0000}'"}, L"{:?}", L'\xf0000'); // <private-use-F0000>
246     test_format(V{L"'\\u{ffffd}'"}, L"{:?}", L'\xffffd'); // <private-use-FFFFD>
247 
248     test_format(V{L"'\\u{100000}'"}, L"{:?}", L'\x100000'); // <private-use-100000>
249     test_format(V{L"'\\u{10fffd}'"}, L"{:?}", L'\x10fffd'); // <private-use-10FFFD>
250 
251     // Unassigned
252     test_format(V{L"'\\u{1000c}'"}, L"{:?}", L'\x1000c');   // <reserved-1000c>
253     test_format(V{L"'\\u{fffff}'"}, L"{:?}", L'\xfffff');   // <noncharacter-FFFFF>
254     test_format(V{L"'\\u{10fffe}'"}, L"{:?}", L'\x10fffe'); // <noncharacter-10FFFE>
255 
256     // Grapheme Extended
257     test_format(V{L"'\\u{101fd}'"}, L"{:?}", L'\x101fd'); // COMBINING OLD PERMIC LETTER AN
258     test_format(V{L"'\\u{e0100}'"}, L"{:?}", L'\xe0100'); // VARIATION SELECTOR-17
259 
260     // Ill-formed
261     test_format(V{L"'\\x{110000}'"}, L"{:?}", L'\x110000');
262     test_format(V{L"'\\x{ffffffff}'"}, L"{:?}", L'\xffffffff');
263   }
264 #  endif // TEST_SHORT_WCHAR
265 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
266 }
267 
268 template <class CharT>
269 void test_string() {
270   // *** P2286 examples ***
271   test_format(SV("[h\tllo]"), SV("[{}]"), SV("h\tllo"));
272   test_format(SV(R"(["h\tllo"])"), SV("[{:?}]"), SV("h\tllo"));
273   test_format(SV(R"(["Спасибо, Виктор ♥!"])"), SV("[{:?}]"), SV("Спасибо, Виктор ♥!"));
274 
275   test_format(SV(R"(["\u{0} \n \t \u{2} \u{1b}"])"), SV("[{:?}]"), SV("\0 \n \t \x02 \x1b"));
276 
277   if constexpr (sizeof(CharT) == 1) {
278     // Ill-formend UTF-8
279     test_format(SV(R"(["\x{c3}"])"), SV("[{:?}]"), "\xc3");
280     test_format(SV(R"(["\x{c3}("])"), SV("[{:?}]"), "\xc3\x28");
281 
282     /* U+0000..U+0007F 1 code unit range, encoded in 2 code units. */
283     test_format(SV(R"(["\x{c0}\x{80}"])"), SV("[{:?}]"), "\xc0\x80"); // U+0000
284     test_format(SV(R"(["\x{c1}\x{bf}"])"), SV("[{:?}]"), "\xc1\xbf"); // U+007F
285     test_format(SV(R"(["\u{80}"])"), SV("[{:?}]"), "\xc2\x80");       // U+0080 first valid (General_Category=Control)
286 
287     /* U+0000..U+07FFF 1 and 2 code unit range, encoded in 3 code units. */
288     test_format(SV(R"(["\x{e0}\x{80}\x{80}"])"), SV("[{:?}]"), "\xe0\x80\x80"); // U+0000
289     test_format(SV(R"(["\x{e0}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xe0\x81\xbf"); // U+007F
290     test_format(SV(R"(["\x{e0}\x{82}\x{80}"])"), SV("[{:?}]"), "\xe0\x82\x80"); // U+0080
291     test_format(SV(R"(["\x{e0}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xe0\x9f\xbf"); // U+07FF
292     test_format(SV("[\"\u0800\"]"), SV("[{:?}]"), "\xe0\xa0\x80");              // U+0800 first valid
293 
294 #if 0
295 	// This code point is in the Hangul Jamo Extended-B block and at the time of writing
296 	// it's unassigned. When it comes defined, this branch might become true.
297     test_format(SV("[\"\ud7ff\"]"), SV("[{:?}]"), "\xed\x9f\xbf");              // U+D7FF last valid
298 #else
299     /* U+D800..D+DFFFF surrogate range */
300     test_format(SV(R"(["\u{d7ff}"])"), SV("[{:?}]"), "\xed\x9f\xbf");           // U+D7FF last valid
301 #endif
302     test_format(SV(R"(["\x{ed}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xed\xa0\x80"); // U+D800
303     test_format(SV(R"(["\x{ed}\x{af}\x{bf}"])"), SV("[{:?}]"), "\xed\xaf\xbf"); // U+DBFF
304     test_format(SV(R"(["\x{ed}\x{bf}\x{80}"])"), SV("[{:?}]"), "\xed\xbf\x80"); // U+DC00
305     test_format(SV(R"(["\x{ed}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xed\xbf\xbf"); // U+DFFF
306     test_format(SV(R"(["\u{e000}"])"), SV("[{:?}]"), "\xee\x80\x80");           // U+E000 first valid
307                                                                                 // (in the Private Use Area block)
308 
309     /* U+0000..U+FFFF 1, 2, and 3 code unit range */
310     test_format(SV(R"(["\x{f0}\x{80}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x80\x80"); // U+0000
311     test_format(SV(R"(["\x{f0}\x{80}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x81\xbf"); // U+007F
312     test_format(SV(R"(["\x{f0}\x{80}\x{82}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x82\x80"); // U+0080
313     test_format(SV(R"(["\x{f0}\x{80}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x9f\xbf"); // U+07FF
314     test_format(SV(R"(["\x{f0}\x{80}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\xa0\x80"); // U+0800
315     test_format(SV(R"(["\x{f0}\x{8f}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf0\x8f\xbf\xbf"); // U+FFFF
316     test_format(SV("[\"\U00010000\"]"), SV("[{:?}]"), "\xf0\x90\x80\x80");                // U+10000 first valid
317 
318     /* U+10FFFF..U+1FFFFF invalid range */
319     test_format(SV(R"(["\u{10ffff}"])"), SV("[{:?}]"), "\xf4\x8f\xbf\xbf"); // U+10FFFF last valid
320                                                                             // (in Supplementary Private Use Area-B)
321     test_format(SV(R"(["\x{f4}\x{90}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf4\x90\x80\x80"); // U+110000
322     test_format(SV(R"(["\x{f4}\x{bf}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf4\xbf\xbf\xbf"); // U+11FFFF
323   } else {
324     // Valid UTF-16 and UTF-32
325     test_format(SV("[\"\u00c3\"]"), SV("[{:?}]"), L"\xc3"); // LATIN CAPITAL LETTER A WITH TILDE
326     test_format(SV("[\"\u00c3(\"]"), SV("[{:?}]"), L"\xc3\x28");
327   }
328 
329   test_format(SV(R"(["����\u{200d}♂\u{fe0f}"])"), SV("[{:?}]"), SV("����‍♂️"));
330 
331   // *** Specical cases ***
332   test_format(SV(R"("\t\n\r\\'\" ")"), SV("{:?}"), SV("\t\n\r\\'\" "));
333 
334   // *** Printable ***
335   test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg"));
336 
337   // *** Non-printable ***
338 
339   // Control
340   test_format(SV(R"("\u{0}\u{1f}")"), SV("{:?}"), SV("\0\x1f"));
341 
342   // Ill-formed
343   if constexpr (sizeof(CharT) == 1)
344     test_format(SV(R"("\x{80}")"), SV("{:?}"), SV("\x80"));
345 
346 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
347   if constexpr (sizeof(CharT) > 1) {
348     using V = std::basic_string_view<CharT>;
349 
350     // Unicode fitting in a 16-bit wchar_t
351 
352     // *** Non-printable ***
353 
354     // Space_Separator
355     test_format(V{LR"("\u{a0}\u{3000}")"}, L"{:?}", L"\xa0\x3000");
356 
357     // Line_Separator
358     test_format(V{LR"("\u{2028}")"}, L"{:?}", L"\x2028"); // LINE SEPARATOR
359 
360     // Paragraph_Separator
361     test_format(V{LR"("\u{2029}")"}, L"{:?}", L"\x2029"); // PARAGRAPH SEPARATOR
362 
363     // Format
364     test_format(V{LR"("\u{ad}\u{600}\u{feff}")"}, L"{:?}", L"\xad\x600\xfeff");
365 
366     // Incomplete surrogate pair in UTF-16
367     test_format(V{LR"("\x{d800}")"}, L"{:?}", L"\xd800");
368 
369     // Private_Use
370     test_format(V{LR"("\u{e000}\u{f8ff}")"}, L"{:?}", L"\xe000\xf8ff");
371 
372     // Unassigned
373     test_format(V{LR"("\u{378}\u{1774}\u{ffff}")"}, L"{:?}", L"\x378\x1774\xffff");
374 
375     // Grapheme Extended
376     test_format(V{LR"("\u{300}\u{fe20}")"}, L"{:?}", L"\x300\xfe20");
377   }
378 #  ifndef TEST_SHORT_WCHAR
379   if constexpr (sizeof(CharT) > 2) {
380     static_assert(sizeof(CharT) == 4, "add support for unexpected size");
381     // Unicode fitting in a 32-bit wchar_t
382 
383     constexpr wchar_t x  = 0x1ffff;
384     constexpr std::uint32_t y = 0x1ffff;
385     static_assert(x == y);
386 
387     using V = std::basic_string_view<CharT>;
388 
389     // *** Non-printable ***
390     // Format
391     test_format(V{LR"("\u{110bd}\u{e007f}")"}, L"{:?}", L"\x110bd\xe007f");
392 
393     // Private_Use
394     test_format(V{LR"("\u{f0000}\u{ffffd}\u{100000}\u{10fffd}")"}, L"{:?}", L"\xf0000\xffffd\x100000\x10fffd");
395 
396     // Unassigned
397     test_format(V{LR"("\u{1000c}\u{fffff}\u{10fffe}")"}, L"{:?}", L"\x1000c\xfffff\x10fffe");
398 
399     // Grapheme Extended
400     test_format(V{LR"("\u{101fd}\u{e0100}")"}, L"{:?}", L"\x101fd\xe0100");
401 
402     // Ill-formed
403     test_format(V{LR"("\x{110000}\x{ffffffff}")"}, L"{:?}", L"\x110000\xffffffff");
404   }
405 #  endif // TEST_SHORT_WCHAR
406 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
407 }
408 
409 template <class CharT, class TestFunction>
410 void test_format_functions(TestFunction check) {
411   // *** align-fill & width ***
412   check(SV(R"(***"hellö")"), SV("{:*>10?}"), SV("hellö")); // ö is LATIN SMALL LETTER O WITH DIAERESIS
413   check(SV(R"(*"hellö"**)"), SV("{:*^10?}"), SV("hellö"));
414   check(SV(R"("hellö"***)"), SV("{:*<10?}"), SV("hellö"));
415 
416   check(SV(R"("hello\u{308}")"), SV("{:*>10?}"), SV("hello\u0308"));
417   check(SV(R"(***"hello\u{308}")"), SV("{:*>17?}"), SV("hello\u0308"));
418   check(SV(R"(*"hello\u{308}"**)"), SV("{:*^17?}"), SV("hello\u0308"));
419   check(SV(R"("hello\u{308}"***)"), SV("{:*<17?}"), SV("hello\u0308"));
420 
421   check(SV(R"("hello ����\u{200d}♂\u{fe0f}")"), SV("{:*>10?}"), SV("hello ����‍♂️"));
422   check(SV(R"(***"hello ����\u{200d}♂\u{fe0f}")"), SV("{:*>30?}"), SV("hello ����‍♂️"));
423   check(SV(R"(*"hello ����\u{200d}♂\u{fe0f}"**)"), SV("{:*^30?}"), SV("hello ����‍♂️"));
424   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"***)"), SV("{:*<30?}"), SV("hello ����‍♂️"));
425 
426   // *** width ***
427   check(SV(R"("hellö"   )"), SV("{:10?}"), SV("hellö"));
428   check(SV(R"("hello\u{308}"   )"), SV("{:17?}"), SV("hello\u0308"));
429   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"   )"), SV("{:30?}"), SV("hello ����‍♂️"));
430 
431   // *** precision ***
432   check(SV(R"("hell)"), SV("{:.5?}"), SV("hellö"));
433   check(SV(R"("hellö)"), SV("{:.6?}"), SV("hellö"));
434   check(SV(R"("hellö")"), SV("{:.7?}"), SV("hellö"));
435 
436   check(SV(R"("hello )"), SV("{:.7?}"), SV("hello ����‍♂️"));
437   check(SV(R"("hello )"), SV("{:.8?}"), SV("hello ����‍♂️")); // shrug is two columns
438   check(SV(R"("hello ����)"), SV("{:.9?}"), SV("hello ����‍♂️"));
439   check(SV(R"("hello ����\)"), SV("{:.10?}"), SV("hello ����‍♂️"));
440   check(SV(R"("hello ����\u{200d})"), SV("{:.17?}"), SV("hello ����‍♂️"));
441   check(SV(R"("hello ����\u{200d}♂)"), SV("{:.18?}"), SV("hello ����‍♂️"));
442   check(SV(R"("hello ����\u{200d}♂\)"), SV("{:.19?}"), SV("hello ����‍♂️"));
443   check(SV(R"("hello ����\u{200d}♂\u{fe0f}")"), SV("{:.28?}"), SV("hello ����‍♂️"));
444 
445   // *** width & precision ***
446   check(SV(R"("hell#########################)"), SV("{:#<30.5?}"), SV("hellö"));
447   check(SV(R"("hellö########################)"), SV("{:#<30.6?}"), SV("hellö"));
448   check(SV(R"("hellö"#######################)"), SV("{:#<30.7?}"), SV("hellö"));
449 
450   check(SV(R"("hello #######################)"), SV("{:#<30.7?}"), SV("hello ����‍♂️"));
451   check(SV(R"("hello #######################)"), SV("{:#<30.8?}"), SV("hello ����‍♂️"));
452   check(SV(R"("hello ����#####################)"), SV("{:#<30.9?}"), SV("hello ����‍♂️"));
453   check(SV(R"("hello ����\####################)"), SV("{:#<30.10?}"), SV("hello ����‍♂️"));
454   check(SV(R"("hello ����\u{200d}#############)"), SV("{:#<30.17?}"), SV("hello ����‍♂️"));
455   check(SV(R"("hello ����\u{200d}♂############)"), SV("{:#<30.18?}"), SV("hello ����‍♂️"));
456   check(SV(R"("hello ����\u{200d}♂\###########)"), SV("{:#<30.19?}"), SV("hello ����‍♂️"));
457   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"###)"), SV("{:#<30.28?}"), SV("hello ����‍♂️"));
458 }
459 
460 template <class CharT>
461 void test() {
462   test_char<CharT>();
463   test_string<CharT>();
464 
465   test_format_functions<CharT>(test_format);
466   test_format_functions<CharT>(test_format_to);
467   test_format_functions<CharT>(test_formatted_size);
468   test_format_functions<CharT>(test_format_to_n);
469 }
470 
471 static void test_ill_formed_utf8() {
472   using namespace std::literals;
473 
474   // Too few code units
475   test_format(R"("\x{df}")"sv, "{:?}", "\xdf");
476   test_format(R"("\x{ef}")"sv, "{:?}", "\xef");
477   test_format(R"("\x{ef}\x{bf}")"sv, "{:?}", "\xef\xbf");
478   test_format(R"("\x{f7}")"sv, "{:?}", "\xf7");
479   test_format(R"("\x{f7}\x{bf}")"sv, "{:?}", "\xf7\xbf");
480   test_format(R"("\x{f7}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf");
481 
482   // Invalid continuation byte
483   test_format(R"("\x{df}a")"sv,
484               "{:?}",
485               "\xdf"
486               "a");
487   test_format(R"("\x{ef}a")"sv,
488               "{:?}",
489               "\xef"
490               "a");
491   test_format(R"("\x{ef}\x{bf}a")"sv,
492               "{:?}",
493               "\xef\xbf"
494               "a");
495   test_format(R"("\x{f7}a")"sv,
496               "{:?}",
497               "\xf7"
498               "a");
499   test_format(R"("\x{f7}\x{bf}a")"sv,
500               "{:?}",
501               "\xf7\xbf"
502               "a");
503   test_format(R"("\x{f7}\x{bf}\x{bf}a")"sv,
504               "{:?}",
505               "\xf7\xbf\xbf"
506               "a");
507 
508   // Code unit out of range
509   test_format(R"("\u{10ffff}")"sv, "{:?}", "\xf4\x8f\xbf\xbf");               // last valid code point
510   test_format(R"("\x{f4}\x{90}\x{80}\x{80}")"sv, "{:?}", "\xf4\x90\x80\x80"); // first invalid code point
511   test_format(R"("\x{f5}\x{b1}\x{b2}\x{b3}")"sv, "{:?}", "\xf5\xb1\xb2\xb3");
512   test_format(R"("\x{f7}\x{bf}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf\xbf"); // largest encoded code point
513 }
514 
515 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
516 #  ifdef _LIBCPP_SHORT_WCHAR
517 static void test_ill_formed_utf16() {
518   using namespace std::literals;
519 
520   // Too few code units
521   test_format(LR"("\x{d800}")"sv, L"{:?}", L"\xd800");
522   test_format(LR"("\x{dbff}")"sv, L"{:?}", L"\xdbff");
523 
524   // Start with low surrogate pair
525   test_format(LR"("\x{dc00}a")"sv,
526               L"{:?}",
527               L"\xdc00"
528               "a");
529   test_format(LR"("\x{dfff}a")"sv,
530               L"{:?}",
531               L"\xdfff"
532               "a");
533 
534   // Only high surrogate pair
535   test_format(LR"("\x{d800}a")"sv,
536               L"{:?}",
537               L"\xd800"
538               "a");
539   test_format(LR"("\x{dbff}a")"sv,
540               L"{:?}",
541               L"\xdbff"
542               "a");
543 }
544 #  else // _LIBCPP_SHORT_WCHAR
545 static void test_ill_formed_utf32() {
546   using namespace std::literals;
547 
548   test_format(LR"("\u{10ffff}")"sv, L"{:?}", L"\x10ffff");     // last valid code point
549   test_format(LR"("\x{110000}")"sv, L"{:?}", L"\x110000");     // first invalid code point
550   test_format(LR"("\x{ffffffff}")"sv, L"{:?}", L"\xffffffff"); // largest encoded code point
551 }
552 
553 #  endif // _LIBCPP_SHORT_WCHAR
554 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
555 
556 int main(int, char**) {
557   test<char>();
558 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
559   test<wchar_t>();
560 #endif
561 
562   test_ill_formed_utf8();
563 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
564 #  ifdef _LIBCPP_SHORT_WCHAR
565   test_ill_formed_utf16();
566   assert(false);
567 #  else  // _LIBCPP_SHORT_WCHAR
568   test_ill_formed_utf32();
569 #  endif // _LIBCPP_SHORT_WCHAR
570 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
571 
572   return 0;
573 }
574