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