Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / format / format.functions / escaped_output.ascii.pass.cpp
blobfdf644f505113b9a1a811371d73a6c1ff37513a0
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 //===----------------------------------------------------------------------===//
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
17 // <format>
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.
22 #include <cassert>
23 #include <concepts>
24 #include <iterator>
25 #include <list>
26 #include <vector>
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
35 # include <iostream>
36 #endif
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
56 auto test_format_to =
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
74 std::list<CharT> out;
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.");
85 CharT out[4096];
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());
136 assert(out.empty());
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>
149 void test_char() {
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(' '));
164 // *** Printable ***
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 ***
171 // Control
172 test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0'));
173 test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f'));
175 // Ill-formed
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 ***
187 // Space_Separator
188 test_format(V{L"'\xa0'"}, L"{:?}", L'\xa0'); // NO-BREAK SPACE
189 test_format(V{L"'\x3000'"}, L"{:?}", L'\x3000'); // IDEOGRAPHIC SPACE
191 // Line_Separator
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
197 // Format
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>
206 } else {
207 test_format(V{L"'\xd800'"}, L"{:?}", L'\xd800'); // <surrogate-D800>
208 test_format(V{L"'\xdfff'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF>
211 // Private_Use
212 test_format(V{L"'\xe000'"}, L"{:?}", L'\xe000'); // <private-use-E000>
213 test_format(V{L"'\xf8ff'"}, L"{:?}", L'\xf8ff'); // <private-use-F8FF>
215 // Unassigned
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>
220 // Grapheme Extended
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 ***
236 // Format
237 test_format(V{L"'\x110bd'"}, L"{:?}", L'\x110bd'); // KAITHI NUMBER SIGN
238 test_format(V{L"'\xe007f'"}, L"{:?}", L'\xe007f'); // CANCEL TAG
240 // Private_Use
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>
247 // Unassigned
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>
252 // Grapheme Extended
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
256 // Ill-formed
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>
265 void test_string() {
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"));
277 } else {
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\\'\" "));
288 // *** Printable ***
289 test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg"));
291 // *** Non-printable ***
293 // Control
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ö")"),
308 SV("{:*>{}?}"),
309 SV("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);
319 // *** width ***
320 check(SV(R"("hello" )"), SV("{:10?}"), SV("hello"));
322 // *** precision ***
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>
334 void test() {
335 test_char<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**) {
346 test<char>();
347 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
348 test<wchar_t>();
349 #endif
351 return 0;