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