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 #ifndef TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
9 #define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
10
11 #include <algorithm>
12 #include <array>
13 #include <charconv>
14 #include <concepts>
15 #include <deque>
16 #include <format>
17 #include <list>
18 #include <ranges>
19 #include <span>
20 #include <tuple>
21 #include <vector>
22
23 #include "format.functions.common.h"
24 #include "make_string.h"
25 #include "platform_support.h" // locale name macros
26 #include "test_iterators.h"
27 #include "test_macros.h"
28
29 //
30 // Char
31 //
32
33 template <class CharT, class TestFunction, class ExceptionTest>
test_char_default(TestFunction check,ExceptionTest check_exception,auto && input)34 void test_char_default(TestFunction check, ExceptionTest check_exception, auto&& input) {
35 // Note when no range-underlying-spec is present the char is escaped,
36 check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{}"), input);
37
38 // when one is present there is no escaping,
39 check(SV("[H, e, l, l, o]"), SV("{::}"), input);
40 // unless forced by the type specifier.
41 check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{::?}"), input);
42
43 // ***** underlying has no format-spec
44
45 // *** align-fill & width ***
46 check(SV("['H', 'e', 'l', 'l', 'o'] "), SV("{:30}"), input);
47 check(SV("['H', 'e', 'l', 'l', 'o']*****"), SV("{:*<30}"), input);
48 check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^30}"), input);
49 check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>30}"), input);
50
51 check(SV("['H', 'e', 'l', 'l', 'o'] "), SV("{:{}}"), input, 30);
52 check(SV("['H', 'e', 'l', 'l', 'o']*****"), SV("{:*<{}}"), input, 30);
53 check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^{}}"), input, 30);
54 check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>{}}"), input, 30);
55
56 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
57 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
58 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
59
60 // *** sign ***
61 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
62 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
63 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
64
65 // *** alternate form ***
66 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
67
68 // *** zero-padding ***
69 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
70
71 // *** precision ***
72 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
73
74 // *** locale-specific form ***
75 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
76
77 // *** n
78 check(SV("__'H', 'e', 'l', 'l', 'o'___"), SV("{:_^28n}"), input);
79
80 // *** type ***
81 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
82 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
83 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
84
85 // ***** Only underlying has a format-spec
86 check(SV("[H , e , l , l , o ]"), SV("{::4}"), input);
87 check(SV("[H***, e***, l***, l***, o***]"), SV("{::*<4}"), input);
88 check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^4}"), input);
89 check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>4}"), input);
90
91 check(SV("[H , e , l , l , o ]"), SV("{::{}}"), input, 4);
92 check(SV("[H***, e***, l***, l***, o***]"), SV("{::*<{}}"), input, 4);
93 check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^{}}"), input, 4);
94 check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>{}}"), input, 4);
95
96 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
97 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
98
99 // *** sign ***
100 check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
101 check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
102 check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
103
104 check(SV("[72, 101, 108, 108, 111]"), SV("{::-d}"), input);
105 check(SV("[+72, +101, +108, +108, +111]"), SV("{::+d}"), input);
106 check(SV("[ 72, 101, 108, 108, 111]"), SV("{:: d}"), input);
107
108 // *** alternate form ***
109 check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
110
111 check(SV("[0x48, 0x65, 0x6c, 0x6c, 0x6f]"), SV("{::#x}"), input);
112
113 // *** zero-padding ***
114 check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
115
116 check(SV("[00110, 00145, 00154, 00154, 00157]"), SV("{::05o}"), input);
117
118 // *** precision ***
119 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
120
121 // *** locale-specific form ***
122 check(SV("[H, e, l, l, o]"), SV("{::L}"), input);
123
124 // *** type ***
125 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
126 check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
127
128 // ***** Both have a format-spec
129 check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^25::>2}"), input);
130 check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^{}::>2}"), input, 25);
131 check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^{}::>{}}"), input, 25, 2);
132
133 check_exception("Argument index out of bounds", SV("{:^^{}::>2}"), input);
134 check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 25);
135 }
136
137 template <class CharT, class TestFunction, class ExceptionTest>
test_char_string(TestFunction check,ExceptionTest check_exception,auto && input)138 void test_char_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
139 check(SV("Hello"), SV("{:s}"), input);
140
141 // ***** underlying has no format-spec
142
143 // *** align-fill & width ***
144 check(SV("Hello "), SV("{:8s}"), input);
145 check(SV("Hello***"), SV("{:*<8s}"), input);
146 check(SV("_Hello__"), SV("{:_^8s}"), input);
147 check(SV("###Hello"), SV("{:#>8s}"), input);
148
149 check(SV("Hello "), SV("{:{}s}"), input, 8);
150 check(SV("Hello***"), SV("{:*<{}s}"), input, 8);
151 check(SV("_Hello__"), SV("{:_^{}s}"), input, 8);
152 check(SV("###Hello"), SV("{:#>{}s}"), input, 8);
153
154 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<s}"), input);
155 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<s}"), input);
156 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<s}"), input);
157
158 // *** sign ***
159 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-s}"), input);
160 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+s}"), input);
161 check_exception("The format-spec should consume the input or end with a '}'", SV("{: s}"), input);
162
163 // *** alternate form ***
164 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#s}"), input);
165
166 // *** zero-padding ***
167 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0s}"), input);
168
169 // *** precision ***
170 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.s}"), input);
171
172 // *** locale-specific form ***
173 check_exception("The format-spec should consume the input or end with a '}'", SV("{:Ls}"), input);
174
175 // *** n
176 check_exception("The n option and type s can't be used together", SV("{:ns}"), input);
177
178 // *** type ***
179 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
180
181 // ***** Only underlying has a format-spec
182 check_exception("Type s and an underlying format specification can't be used together", SV("{:s:}"), input);
183 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
184 check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
185
186 // ***** Both have a format-spec
187 check_exception("Type s and an underlying format specification can't be used together", SV("{:5s:5}"), input);
188 }
189
190 template <class CharT, class TestFunction, class ExceptionTest>
test_char_escaped_string(TestFunction check,ExceptionTest check_exception,auto && input)191 void test_char_escaped_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
192 check(SV(R"("\"Hello'")"), SV("{:?s}"), input);
193
194 // ***** underlying has no format-spec
195
196 // *** align-fill & width ***
197 check(SV(R"("\"Hello'" )"), SV("{:13?s}"), input);
198 check(SV(R"("\"Hello'"***)"), SV("{:*<13?s}"), input);
199 check(SV(R"(_"\"Hello'"__)"), SV("{:_^13?s}"), input);
200 check(SV(R"(###"\"Hello'")"), SV("{:#>13?s}"), input);
201
202 check(SV(R"("\"Hello'" )"), SV("{:{}?s}"), input, 13);
203 check(SV(R"("\"Hello'"***)"), SV("{:*<{}?s}"), input, 13);
204 check(SV(R"(_"\"Hello'"__)"), SV("{:_^{}?s}"), input, 13);
205 check(SV(R"(###"\"Hello'")"), SV("{:#>{}?s}"), input, 13);
206
207 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<?s}"), input);
208 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<?s}"), input);
209 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<?s}"), input);
210
211 // *** sign ***
212 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-?s}"), input);
213 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+?s}"), input);
214 check_exception("The format-spec should consume the input or end with a '}'", SV("{: ?s}"), input);
215
216 // *** alternate form ***
217 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#?s}"), input);
218
219 // *** zero-padding ***
220 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0?s}"), input);
221
222 // *** precision ***
223 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.?s}"), input);
224
225 // *** locale-specific form ***
226 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L?s}"), input);
227
228 // *** n
229 check_exception("The n option and type ?s can't be used together", SV("{:n?s}"), input);
230
231 // *** type ***
232 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
233
234 // ***** Only underlying has a format-spec
235 check_exception("Type ?s and an underlying format specification can't be used together", SV("{:?s:}"), input);
236
237 // ***** Both have a format-spec
238 check_exception("Type ?s and an underlying format specification can't be used together", SV("{:5?s:5}"), input);
239 }
240
241 template <class CharT, class TestFunction, class ExceptionTest>
test_char(TestFunction check,ExceptionTest check_exception)242 void test_char(TestFunction check, ExceptionTest check_exception) {
243 test_char_default<CharT>(
244 check, check_exception, std::array{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
245
246 // This tests two different implementations in libc++. A basic_string_view
247 // formatter if the range is contiguous, a basic_string otherwise.
248 test_char_escaped_string<CharT>(
249 check,
250 check_exception,
251 std::array{CharT('"'), CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o'), CharT('\'')});
252 test_char_escaped_string<CharT>(
253 check,
254 check_exception,
255 std::list{CharT('"'), CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o'), CharT('\'')});
256
257 // This tests two different implementations in libc++. A basic_string_view
258 // formatter if the range is contiguous, a basic_string otherwise.
259 test_char_string<CharT>(
260 check, check_exception, std::array{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
261 test_char_string<CharT>(
262 check, check_exception, std::list{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
263 }
264
265 //
266 // char -> wchar_t
267 //
268
269 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
270 template <class TestFunction, class ExceptionTest>
271 void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
272 test_char_default<wchar_t>(check, check_exception, std::array{'H', 'e', 'l', 'l', 'o'});
273
274 // The types s and ?s may only be used when using range_formatter<T, charT>
275 // where the types T and charT are the same. This means this can't be used for
276 // range_formatter<wchar_t, char> even when formatter<wchar_t, char> has a
277 // debug-enabled specialization.
278
279 using CharT = wchar_t;
280 check_exception("The range-format-spec type s requires formatting a character type",
281 SV("{:s}"),
282 std::array{'H', 'e', 'l', 'l', 'o'});
283 check_exception("The range-format-spec type ?s requires formatting a character type",
284 SV("{:?s}"),
285 std::array{'H', 'e', 'l', 'l', 'o'});
286 }
287 #endif
288
289 //
290 // Bool
291 //
292
293 template <class CharT, class TestFunction, class ExceptionTest>
test_bool(TestFunction check,ExceptionTest check_exception)294 void test_bool(TestFunction check, ExceptionTest check_exception) {
295 std::array input{true, true, false};
296
297 check(SV("[true, true, false]"), SV("{}"), input);
298
299 // ***** underlying has no format-spec
300
301 // *** align-fill & width ***
302 check(SV("[true, true, false] "), SV("{:24}"), input);
303 check(SV("[true, true, false]*****"), SV("{:*<24}"), input);
304 check(SV("__[true, true, false]___"), SV("{:_^24}"), input);
305 check(SV("#####[true, true, false]"), SV("{:#>24}"), input);
306
307 check(SV("[true, true, false] "), SV("{:{}}"), input, 24);
308 check(SV("[true, true, false]*****"), SV("{:*<{}}"), input, 24);
309 check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
310 check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
311
312 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
313 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
314 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
315
316 // *** sign ***
317 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
318 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
319 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
320
321 // *** alternate form ***
322 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
323
324 // *** zero-padding ***
325 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
326
327 // *** precision ***
328 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
329
330 // *** locale-specific form ***
331 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
332
333 // *** n
334 check(SV("__true, true, false___"), SV("{:_^22n}"), input);
335
336 // *** type ***
337 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
338 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
339 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
340 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
341 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
342
343 // ***** Only underlying has a format-spec
344 check(SV("[true , true , false ]"), SV("{::7}"), input);
345 check(SV("[true***, true***, false**]"), SV("{::*<7}"), input);
346 check(SV("[_true__, _true__, _false_]"), SV("{::_^7}"), input);
347 check(SV("[:::true, :::true, ::false]"), SV("{:::>7}"), input);
348
349 check(SV("[true , true , false ]"), SV("{::{}}"), input, 7);
350 check(SV("[true***, true***, false**]"), SV("{::*<{}}"), input, 7);
351 check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
352 check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
353
354 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
355 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
356
357 // *** sign ***
358 check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
359 check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
360 check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
361
362 check(SV("[1, 1, 0]"), SV("{::-d}"), input);
363 check(SV("[+1, +1, +0]"), SV("{::+d}"), input);
364 check(SV("[ 1, 1, 0]"), SV("{:: d}"), input);
365
366 // *** alternate form ***
367 check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
368
369 check(SV("[0x1, 0x1, 0x0]"), SV("{::#x}"), input);
370
371 // *** zero-padding ***
372 check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
373
374 check(SV("[00001, 00001, 00000]"), SV("{::05o}"), input);
375
376 // *** precision ***
377 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
378
379 // *** locale-specific form ***
380 check(SV("[true, true, false]"), SV("{::L}"), input);
381
382 // *** type ***
383 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBdosxX"))
384 check_exception("The format-spec type has a type not supported for a bool argument", fmt, input);
385
386 // ***** Both have a format-spec
387 check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^32::>7}"), input);
388 check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>7}"), input, 32);
389 check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>{}}"), input, 32, 7);
390
391 check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
392 check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 32);
393 }
394
395 //
396 // Integral
397 //
398
399 template <class CharT, class TestFunction, class ExceptionTest>
test_int(TestFunction check,ExceptionTest check_exception,auto && input)400 void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
401 check(SV("[1, 2, 42, -42]"), SV("{}"), input);
402
403 // ***** underlying has no format-spec
404
405 // *** align-fill & width ***
406 check(SV("[1, 2, 42, -42] "), SV("{:20}"), input);
407 check(SV("[1, 2, 42, -42]*****"), SV("{:*<20}"), input);
408 check(SV("__[1, 2, 42, -42]___"), SV("{:_^20}"), input);
409 check(SV("#####[1, 2, 42, -42]"), SV("{:#>20}"), input);
410
411 check(SV("[1, 2, 42, -42] "), SV("{:{}}"), input, 20);
412 check(SV("[1, 2, 42, -42]*****"), SV("{:*<{}}"), input, 20);
413 check(SV("__[1, 2, 42, -42]___"), SV("{:_^{}}"), input, 20);
414 check(SV("#####[1, 2, 42, -42]"), SV("{:#>{}}"), input, 20);
415
416 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
417 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
418 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
419
420 // *** sign ***
421 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
422 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
423 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
424
425 // *** alternate form ***
426 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
427
428 // *** zero-padding ***
429 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
430
431 // *** precision ***
432 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
433
434 // *** locale-specific form ***
435 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
436
437 // *** n
438 check(SV("__1, 2, 42, -42___"), SV("{:_^18n}"), input);
439
440 // *** type ***
441 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
442 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
443 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
444 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
445 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
446
447 // ***** Only underlying has a format-spec
448 check(SV("[ 1, 2, 42, -42]"), SV("{::5}"), input);
449 check(SV("[1****, 2****, 42***, -42**]"), SV("{::*<5}"), input);
450 check(SV("[__1__, __2__, _42__, _-42_]"), SV("{::_^5}"), input);
451 check(SV("[::::1, ::::2, :::42, ::-42]"), SV("{:::>5}"), input);
452
453 check(SV("[ 1, 2, 42, -42]"), SV("{::{}}"), input, 5);
454 check(SV("[1****, 2****, 42***, -42**]"), SV("{::*<{}}"), input, 5);
455 check(SV("[__1__, __2__, _42__, _-42_]"), SV("{::_^{}}"), input, 5);
456 check(SV("[::::1, ::::2, :::42, ::-42]"), SV("{:::>{}}"), input, 5);
457
458 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
459 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
460
461 // *** sign ***
462 check(SV("[1, 2, 42, -42]"), SV("{::-}"), input);
463 check(SV("[+1, +2, +42, -42]"), SV("{::+}"), input);
464 check(SV("[ 1, 2, 42, -42]"), SV("{:: }"), input);
465
466 // *** alternate form ***
467 check(SV("[0x1, 0x2, 0x2a, -0x2a]"), SV("{::#x}"), input);
468
469 // *** zero-padding ***
470 check(SV("[00001, 00002, 00042, -0042]"), SV("{::05}"), input);
471 check(SV("[00001, 00002, 0002a, -002a]"), SV("{::05x}"), input);
472 check(SV("[0x001, 0x002, 0x02a, -0x2a]"), SV("{::#05x}"), input);
473
474 // *** precision ***
475 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
476
477 // *** locale-specific form ***
478 check(SV("[1, 2, 42, -42]"), SV("{::L}"), input); // does nothing in this test, but is accepted.
479
480 // *** type ***
481 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX"))
482 check_exception("The format-spec type has a type not supported for an integer argument", fmt, input);
483
484 // ***** Both have a format-spec
485 check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^33::>5}"), input);
486 check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^{}::>5}"), input, 33);
487 check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
488
489 check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
490 check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 33);
491 }
492
493 template <class CharT, class TestFunction, class ExceptionTest>
test_int(TestFunction check,ExceptionTest check_exception)494 void test_int(TestFunction check, ExceptionTest check_exception) {
495 test_int<CharT>(check, check_exception, std::array{1, 2, 42, -42});
496 test_int<CharT>(check, check_exception, std::list{1, 2, 42, -42});
497 test_int<CharT>(check, check_exception, std::vector{1, 2, 42, -42});
498 std::array input{1, 2, 42, -42};
499 test_int<CharT>(check, check_exception, std::span{input});
500 }
501
502 //
503 // Floating point
504 //
505
506 template <class CharT, class TestFunction, class ExceptionTest>
test_floating_point(TestFunction check,ExceptionTest check_exception,auto && input)507 void test_floating_point(TestFunction check, ExceptionTest check_exception, auto&& input) {
508 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{}"), input);
509
510 // ***** underlying has no format-spec
511
512 // *** align-fill & width ***
513 check(SV("[-42.5, 0, 1.25, 42.5] "), SV("{:27}"), input);
514 check(SV("[-42.5, 0, 1.25, 42.5]*****"), SV("{:*<27}"), input);
515 check(SV("__[-42.5, 0, 1.25, 42.5]___"), SV("{:_^27}"), input);
516 check(SV("#####[-42.5, 0, 1.25, 42.5]"), SV("{:#>27}"), input);
517
518 check(SV("[-42.5, 0, 1.25, 42.5] "), SV("{:{}}"), input, 27);
519 check(SV("[-42.5, 0, 1.25, 42.5]*****"), SV("{:*<{}}"), input, 27);
520 check(SV("__[-42.5, 0, 1.25, 42.5]___"), SV("{:_^{}}"), input, 27);
521 check(SV("#####[-42.5, 0, 1.25, 42.5]"), SV("{:#>{}}"), input, 27);
522
523 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
524 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
525 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
526
527 // *** sign ***
528 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
529 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
530 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
531
532 // *** alternate form ***
533 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
534
535 // *** zero-padding ***
536 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
537
538 // *** precision ***
539 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
540
541 // *** locale-specific form ***
542 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
543
544 // *** n
545 check(SV("__-42.5, 0, 1.25, 42.5___"), SV("{:_^25n}"), input);
546
547 // *** type ***
548 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
549 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
550 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
551 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
552 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
553
554 // ***** Only underlying has a format-spec
555 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::5}"), input);
556 check(SV("[-42.5, 0****, 1.25*, 42.5*]"), SV("{::*<5}"), input);
557 check(SV("[-42.5, __0__, 1.25_, 42.5_]"), SV("{::_^5}"), input);
558 check(SV("[-42.5, ::::0, :1.25, :42.5]"), SV("{:::>5}"), input);
559
560 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::{}}"), input, 5);
561 check(SV("[-42.5, 0****, 1.25*, 42.5*]"), SV("{::*<{}}"), input, 5);
562 check(SV("[-42.5, __0__, 1.25_, 42.5_]"), SV("{::_^{}}"), input, 5);
563 check(SV("[-42.5, ::::0, :1.25, :42.5]"), SV("{:::>{}}"), input, 5);
564
565 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
566 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
567
568 // *** sign ***
569 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::-}"), input);
570 check(SV("[-42.5, +0, +1.25, +42.5]"), SV("{::+}"), input);
571 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{:: }"), input);
572
573 // *** alternate form ***
574 check(SV("[-42.5, 0., 1.25, 42.5]"), SV("{::#}"), input);
575
576 // *** zero-padding ***
577 check(SV("[-42.5, 00000, 01.25, 042.5]"), SV("{::05}"), input);
578 check(SV("[-42.5, 0000., 01.25, 042.5]"), SV("{::#05}"), input);
579
580 // *** precision ***
581 check(SV("[-42, 0, 1.2, 42]"), SV("{::.2}"), input);
582 check(SV("[-42.500, 0.000, 1.250, 42.500]"), SV("{::.3f}"), input);
583
584 check(SV("[-42, 0, 1.2, 42]"), SV("{::.{}}"), input, 2);
585 check(SV("[-42.500, 0.000, 1.250, 42.500]"), SV("{::.{}f}"), input, 3);
586
587 check_exception("The format-spec precision field doesn't contain a value or arg-id", SV("{::.}"), input);
588
589 // *** locale-specific form ***
590 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::L}"), input); // does not require locales present
591 #ifndef TEST_HAS_NO_LOCALIZATION
592 // TODO FMT Enable with locale testing active
593 # if 0
594 std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
595 check(SV("[-42,5, 0, 1,25, 42,5]"), SV("{::L}"), input);
596
597 std::locale::global(std::locale(LOCALE_en_US_UTF_8));
598 check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::L}"), input);
599
600 std::locale::global(std::locale::classic());
601 # endif
602 #endif // TEST_HAS_NO_LOCALIZATION
603
604 // *** type ***
605 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("aAeEfFgG"))
606 check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, input);
607
608 // ***** Both have a format-spec
609 check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^33::>5}"), input);
610 check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^{}::>5}"), input, 33);
611 check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
612
613 check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^33::>5.2}"), input);
614 check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>5.2}"), input, 33);
615 check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>{}.2}"), input, 33, 5);
616 check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>{}.{}}"), input, 33, 5, 2);
617
618 check_exception("Argument index out of bounds", SV("{:^^{}::>5.2}"), input);
619 check_exception("Argument index out of bounds", SV("{:^^{}::>{}.2}"), input, 33);
620 check_exception("Argument index out of bounds", SV("{:^^{}::>{}.{}}"), input, 33, 5);
621 }
622
623 template <class CharT, class TestFunction, class ExceptionTest>
test_floating_point(TestFunction check,ExceptionTest check_exception)624 void test_floating_point(TestFunction check, ExceptionTest check_exception) {
625 test_floating_point<CharT>(check, check_exception, std::array{-42.5f, 0.0f, 1.25f, 42.5f});
626 test_floating_point<CharT>(check, check_exception, std::vector{-42.5, 0.0, 1.25, 42.5});
627
628 std::array input{-42.5l, 0.0l, 1.25l, 42.5l};
629 test_floating_point<CharT>(check, check_exception, std::span{input});
630 }
631
632 //
633 // Pointer
634 //
635
636 template <class CharT, class TestFunction, class ExceptionTest>
test_pointer(TestFunction check,ExceptionTest check_exception,auto && input)637 void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
638 check(SV("[0x0]"), SV("{}"), input);
639
640 // ***** underlying has no format-spec
641
642 // *** align-fill & width ***
643 check(SV("[0x0] "), SV("{:10}"), input);
644 check(SV("[0x0]*****"), SV("{:*<10}"), input);
645 check(SV("__[0x0]___"), SV("{:_^10}"), input);
646 check(SV("#####[0x0]"), SV("{:#>10}"), input);
647
648 check(SV("[0x0] "), SV("{:{}}"), input, 10);
649 check(SV("[0x0]*****"), SV("{:*<{}}"), input, 10);
650 check(SV("__[0x0]___"), SV("{:_^{}}"), input, 10);
651 check(SV("#####[0x0]"), SV("{:#>{}}"), input, 10);
652
653 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
654 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
655 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
656
657 // *** sign ***
658 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
659
660 // *** alternate form ***
661 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
662
663 // *** zero-padding ***
664 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
665
666 // *** precision ***
667 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
668
669 // *** locale-specific form ***
670 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
671
672 // *** n
673 check(SV("_0x0_"), SV("{:_^5n}"), input);
674
675 // *** type ***
676 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
677 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
678 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
679 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
680 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
681
682 // ***** Only underlying has a format-spec
683 check(SV("[ 0x0]"), SV("{::5}"), input);
684 check(SV("[0x0**]"), SV("{::*<5}"), input);
685 check(SV("[_0x0_]"), SV("{::_^5}"), input);
686 check(SV("[::0x0]"), SV("{:::>5}"), input);
687
688 check(SV("[ 0x0]"), SV("{::{}}"), input, 5);
689 check(SV("[0x0**]"), SV("{::*<{}}"), input, 5);
690 check(SV("[_0x0_]"), SV("{::_^{}}"), input, 5);
691 check(SV("[::0x0]"), SV("{:::>{}}"), input, 5);
692
693 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
694 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
695
696 // *** sign ***
697 check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
698
699 // *** alternate form ***
700 check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
701
702 // *** zero-padding ***
703 check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
704
705 // *** precision ***
706 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
707
708 // *** locale-specific form ***
709 check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
710
711 // *** type ***
712 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("p"))
713 check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
714
715 // ***** Both have a format-spec
716 check(SV("^^[::0x0]^^^"), SV("{:^^12::>5}"), input);
717 check(SV("^^[::0x0]^^^"), SV("{:^^{}::>5}"), input, 12);
718 check(SV("^^[::0x0]^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
719
720 check(SV("^^[::0x0]^^^"), SV("{:^^12::>5}"), input);
721 check(SV("^^[::0x0]^^^"), SV("{:^^{}::>5}"), input, 12);
722 check(SV("^^[::0x0]^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
723
724 check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
725 check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 12);
726 }
727
728 template <class CharT, class TestFunction, class ExceptionTest>
test_pointer(TestFunction check,ExceptionTest check_exception)729 void test_pointer(TestFunction check, ExceptionTest check_exception) {
730 test_pointer<CharT>(check, check_exception, std::array{nullptr});
731 test_pointer<CharT>(check, check_exception, std::array{static_cast<const void*>(0)});
732 test_pointer<CharT>(check, check_exception, std::array{static_cast<void*>(0)});
733 }
734
735 //
736 // String
737 //
738
739 template <class CharT, class TestFunction, class ExceptionTest>
test_string(TestFunction check,ExceptionTest check_exception,auto && input)740 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
741 check(SV(R"(["Hello", "world"])"), SV("{}"), input);
742
743 // ***** underlying has no format-spec
744
745 // *** align-fill & width ***
746 check(SV(R"(["Hello", "world"] )"), SV("{:23}"), input);
747 check(SV(R"(["Hello", "world"]*****)"), SV("{:*<23}"), input);
748 check(SV(R"(__["Hello", "world"]___)"), SV("{:_^23}"), input);
749 check(SV(R"(#####["Hello", "world"])"), SV("{:#>23}"), input);
750
751 check(SV(R"(["Hello", "world"] )"), SV("{:{}}"), input, 23);
752 check(SV(R"(["Hello", "world"]*****)"), SV("{:*<{}}"), input, 23);
753 check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
754 check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
755
756 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
757 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
758 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
759
760 // *** sign ***
761 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
762
763 // *** alternate form ***
764 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
765
766 // *** zero-padding ***
767 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
768
769 // *** precision ***
770 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
771
772 // *** locale-specific form ***
773 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
774
775 // *** n
776 check(SV(R"(_"Hello", "world"_)"), SV("{:_^18n}"), input);
777
778 // *** type ***
779 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
780 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
781 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
782 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
783 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
784
785 // ***** Only underlying has a format-spec
786 check(SV(R"([Hello , world ])"), SV("{::8}"), input);
787 check(SV(R"([Hello***, world***])"), SV("{::*<8}"), input);
788 check(SV(R"([_Hello__, _world__])"), SV("{::_^8}"), input);
789 check(SV(R"([:::Hello, :::world])"), SV("{:::>8}"), input);
790
791 check(SV(R"([Hello , world ])"), SV("{::{}}"), input, 8);
792 check(SV(R"([Hello***, world***])"), SV("{::*<{}}"), input, 8);
793 check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
794 check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
795
796 check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
797 check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
798
799 // *** sign ***
800 check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
801
802 // *** alternate form ***
803 check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
804
805 // *** zero-padding ***
806 check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
807
808 // *** precision ***
809 check(SV(R"([Hel, wor])"), SV("{::.3}"), input);
810
811 check(SV(R"([Hel, wor])"), SV("{::.{}}"), input, 3);
812
813 check_exception("The format-spec precision field doesn't contain a value or arg-id", SV("{::.}"), input);
814
815 // *** locale-specific form ***
816 check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
817
818 // *** type ***
819 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s?"))
820 check_exception("The format-spec type has a type not supported for a string argument", fmt, input);
821
822 // ***** Both have a format-spec
823 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
824 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
825 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
826
827 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
828 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
829 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
830
831 check_exception("Argument index out of bounds", SV("{:^^{}::>8}"), input);
832 check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 25);
833 }
834
835 template <class CharT, class TestFunction, class ExceptionTest>
test_string(TestFunction check,ExceptionTest check_exception)836 void test_string(TestFunction check, ExceptionTest check_exception) {
837 test_string<CharT>(check, check_exception, std::array{CSTR("Hello"), CSTR("world")});
838 test_string<CharT>(check, check_exception, std::array{STR("Hello"), STR("world")});
839 test_string<CharT>(check, check_exception, std::array{SV("Hello"), SV("world")});
840 }
841
842 //
843 // Handle
844 //
845
846 template <class CharT, class TestFunction, class ExceptionTest>
test_status(TestFunction check,ExceptionTest check_exception)847 void test_status(TestFunction check, ExceptionTest check_exception) {
848 std::array input{status::foo, status::bar, status::foobar};
849
850 check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{}"), input);
851
852 // ***** underlying has no format-spec
853
854 // *** align-fill & width ***
855 check(SV("[0xaaaa, 0x5555, 0xaa55] "), SV("{:29}"), input);
856 check(SV("[0xaaaa, 0x5555, 0xaa55]*****"), SV("{:*<29}"), input);
857 check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^29}"), input);
858 check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>29}"), input);
859
860 check(SV("[0xaaaa, 0x5555, 0xaa55] "), SV("{:{}}"), input, 29);
861 check(SV("[0xaaaa, 0x5555, 0xaa55]*****"), SV("{:*<{}}"), input, 29);
862 check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^{}}"), input, 29);
863 check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>{}}"), input, 29);
864
865 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
866 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
867 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
868
869 // *** sign ***
870 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
871 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
872 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
873
874 // *** alternate form ***
875 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
876
877 // *** zero-padding ***
878 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
879
880 // *** precision ***
881 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
882
883 // *** locale-specific form ***
884 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
885
886 // *** n
887 check(SV("__0xaaaa, 0x5555, 0xaa55___"), SV("{:_^27n}"), input);
888
889 // *** type ***
890 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
891 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
892 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
893 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
894 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
895
896 // ***** Only underlying has a format-spec
897 check_exception("The format-spec type has a type not supported for a status argument", SV("{::*<7}"), input);
898 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("sxX"))
899 check_exception("The format-spec type has a type not supported for a status argument", fmt, input);
900
901 check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{::x}"), input);
902 check(SV("[0XAAAA, 0X5555, 0XAA55]"), SV("{::X}"), input);
903 check(SV("[foo, bar, foobar]"), SV("{::s}"), input);
904
905 // ***** Both have a format-spec
906 check(SV("^^[0XAAAA, 0X5555, 0XAA55]^^^"), SV("{:^^29:X}"), input);
907 check(SV("^^[0XAAAA, 0X5555, 0XAA55]^^^"), SV("{:^^{}:X}"), input, 29);
908
909 check_exception("Argument index out of bounds", SV("{:^^{}:X}"), input);
910 }
911
912 //
913 // Pair
914 //
915
916 template <class CharT, class TestFunction, class ExceptionTest>
test_pair_tuple(TestFunction check,ExceptionTest check_exception,auto && input)917 void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& input) {
918 // [format.range.formatter]/3
919 // For range_formatter<T, charT>, the format-spec in a
920 // range-underlying-spec, if any, is interpreted by formatter<T, charT>.
921 //
922 // template<class ParseContext>
923 // constexpr typename ParseContext::iterator
924 // parse(ParseContext& ctx);
925 // [format.tuple]/7
926 // ... if e.set_debug_format() is a valid expression, calls
927 // e.set_debug_format().
928 // So when there is no range-underlying-spec, there is no need to call parse
929 // thus the char element is not escaped.
930 // TODO FMT P2733 addresses this issue.
931 check(SV("[(1, 'a'), (42, '*')]"), SV("{}"), input);
932
933 // ***** underlying has no format-spec
934
935 // *** align-fill & width ***
936 check(SV("[(1, 'a'), (42, '*')] "), SV("{:26}"), input);
937 check(SV("[(1, 'a'), (42, '*')]*****"), SV("{:*<26}"), input);
938 check(SV("__[(1, 'a'), (42, '*')]___"), SV("{:_^26}"), input);
939 check(SV("#####[(1, 'a'), (42, '*')]"), SV("{:#>26}"), input);
940
941 check(SV("[(1, 'a'), (42, '*')] "), SV("{:{}}"), input, 26);
942 check(SV("[(1, 'a'), (42, '*')]*****"), SV("{:*<{}}"), input, 26);
943 check(SV("__[(1, 'a'), (42, '*')]___"), SV("{:_^{}}"), input, 26);
944 check(SV("#####[(1, 'a'), (42, '*')]"), SV("{:#>{}}"), input, 26);
945
946 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
947 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
948 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
949
950 // *** sign ***
951 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
952 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
953 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
954
955 // *** alternate form ***
956 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
957
958 // *** zero-padding ***
959 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
960
961 // *** precision ***
962 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
963
964 // *** locale-specific form ***
965 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
966
967 // *** n
968 check(SV("__(1, 'a'), (42, '*')___"), SV("{:_^24n}"), input);
969 check(SV("__(1, 'a'), (42, '*')___"), SV("{:_^24nm}"), input); // m should have no effect
970
971 // *** type ***
972 check(SV("__{(1, 'a'), (42, '*')}___"), SV("{:_^26m}"), input);
973 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
974 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
975 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
976 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
977
978 // ***** Only underlying has a format-spec
979 check(SV("[(1, 'a') , (42, '*') ]"), SV("{::11}"), input);
980 check(SV("[(1, 'a')***, (42, '*')**]"), SV("{::*<11}"), input);
981 check(SV("[_(1, 'a')__, _(42, '*')_]"), SV("{::_^11}"), input);
982 check(SV("[###(1, 'a'), ##(42, '*')]"), SV("{::#>11}"), input);
983
984 check(SV("[(1, 'a') , (42, '*') ]"), SV("{::{}}"), input, 11);
985 check(SV("[(1, 'a')***, (42, '*')**]"), SV("{::*<{}}"), input, 11);
986 check(SV("[_(1, 'a')__, _(42, '*')_]"), SV("{::_^{}}"), input, 11);
987 check(SV("[###(1, 'a'), ##(42, '*')]"), SV("{::#>{}}"), input, 11);
988
989 check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
990 check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
991 check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
992
993 // *** sign ***
994 check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
995 check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
996 check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
997
998 // *** alternate form ***
999 check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1000
1001 // *** zero-padding ***
1002 check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1003
1004 // *** precision ***
1005 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1006
1007 // *** locale-specific form ***
1008 check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1009
1010 // *** type ***
1011 check(SV("[1: 'a', 42: '*']"), SV("{::m}"), input);
1012 check(SV("[1, 'a', 42, '*']"), SV("{::n}"), input);
1013 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
1014 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1015
1016 // ***** Both have a format-spec
1017 check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^31:#>11}"), input);
1018 check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^31:#>11}"), input);
1019 check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^{}:#>11}"), input, 31);
1020 check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^{}:#>{}}"), input, 31, 11);
1021
1022 check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1023 check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 31);
1024
1025 check(SV("1: 'a', 42: '*'"), SV("{:n:m}"), input);
1026 check(SV("1, 'a', 42, '*'"), SV("{:n:n}"), input);
1027 check(SV("{1: 'a', 42: '*'}"), SV("{:m:m}"), input);
1028 check(SV("{1, 'a', 42, '*'}"), SV("{:m:n}"), input);
1029 }
1030
1031 template <class CharT, class TestFunction, class ExceptionTest>
test_pair_tuple(TestFunction check,ExceptionTest check_exception)1032 void test_pair_tuple(TestFunction check, ExceptionTest check_exception) {
1033 test_pair_tuple<CharT>(
1034 check, check_exception, std::array{std::make_pair(1, CharT('a')), std::make_pair(42, CharT('*'))});
1035 test_pair_tuple<CharT>(
1036 check, check_exception, std::array{std::make_tuple(1, CharT('a')), std::make_tuple(42, CharT('*'))});
1037 }
1038
1039 //
1040 // Tuple 1
1041 //
1042
1043 template <class CharT, class TestFunction, class ExceptionTest>
test_tuple_int(TestFunction check,ExceptionTest check_exception)1044 void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
1045 std::array input{std::make_tuple(42), std::make_tuple(99)};
1046
1047 check(SV("[(42), (99)]"), SV("{}"), input);
1048
1049 // ***** underlying has no format-spec
1050
1051 // *** align-fill & width ***
1052 check(SV("[(42), (99)] "), SV("{:17}"), input);
1053 check(SV("[(42), (99)]*****"), SV("{:*<17}"), input);
1054 check(SV("__[(42), (99)]___"), SV("{:_^17}"), input);
1055 check(SV("#####[(42), (99)]"), SV("{:#>17}"), input);
1056
1057 check(SV("[(42), (99)] "), SV("{:{}}"), input, 17);
1058 check(SV("[(42), (99)]*****"), SV("{:*<{}}"), input, 17);
1059 check(SV("__[(42), (99)]___"), SV("{:_^{}}"), input, 17);
1060 check(SV("#####[(42), (99)]"), SV("{:#>{}}"), input, 17);
1061
1062 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
1063 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
1064 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
1065
1066 // *** sign ***
1067 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
1068 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
1069 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
1070
1071 // *** alternate form ***
1072 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
1073
1074 // *** zero-padding ***
1075 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
1076
1077 // *** precision ***
1078 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
1079
1080 // *** locale-specific form ***
1081 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
1082
1083 // *** n
1084 check(SV("__(42), (99)___"), SV("{:_^15n}"), input);
1085
1086 // *** type ***
1087 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
1088 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
1089 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
1090 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
1091 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1092
1093 // ***** Only underlying has a format-spec
1094 check(SV("[(42) , (99) ]"), SV("{::7}"), input);
1095 check(SV("[(42)***, (99)***]"), SV("{::*<7}"), input);
1096 check(SV("[_(42)__, _(99)__]"), SV("{::_^7}"), input);
1097 check(SV("[###(42), ###(99)]"), SV("{::#>7}"), input);
1098
1099 check(SV("[(42) , (99) ]"), SV("{::{}}"), input, 7);
1100 check(SV("[(42)***, (99)***]"), SV("{::*<{}}"), input, 7);
1101 check(SV("[_(42)__, _(99)__]"), SV("{::_^{}}"), input, 7);
1102 check(SV("[###(42), ###(99)]"), SV("{::#>{}}"), input, 7);
1103
1104 check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
1105 check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
1106 check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
1107
1108 // *** sign ***
1109 check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
1110 check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
1111 check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
1112
1113 // *** alternate form ***
1114 check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1115
1116 // *** zero-padding ***
1117 check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1118
1119 // *** precision ***
1120 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1121
1122 // *** locale-specific form ***
1123 check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1124
1125 // *** type ***
1126 check(SV("[42, 99]"), SV("{::n}"), input);
1127 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
1128 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1129
1130 // ***** Both have a format-spec
1131 check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^23:#>7}"), input);
1132 check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^23:#>7}"), input);
1133 check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^{}:#>7}"), input, 23);
1134 check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^{}:#>{}}"), input, 23, 7);
1135
1136 check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1137 check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 23);
1138 }
1139
1140 //
1141 // Tuple 3
1142 //
1143
1144 template <class CharT, class TestFunction, class ExceptionTest>
test_tuple_int_int_int(TestFunction check,ExceptionTest check_exception)1145 void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
1146 std::array input{std::make_tuple(42, 99, 0), std::make_tuple(1, 10, 100)};
1147
1148 check(SV("[(42, 99, 0), (1, 10, 100)]"), SV("{}"), input);
1149
1150 // ***** underlying has no format-spec
1151
1152 // *** align-fill & width ***
1153 check(SV("[(42, 99, 0), (1, 10, 100)] "), SV("{:32}"), input);
1154 check(SV("[(42, 99, 0), (1, 10, 100)]*****"), SV("{:*<32}"), input);
1155 check(SV("__[(42, 99, 0), (1, 10, 100)]___"), SV("{:_^32}"), input);
1156 check(SV("#####[(42, 99, 0), (1, 10, 100)]"), SV("{:#>32}"), input);
1157
1158 check(SV("[(42, 99, 0), (1, 10, 100)] "), SV("{:{}}"), input, 32);
1159 check(SV("[(42, 99, 0), (1, 10, 100)]*****"), SV("{:*<{}}"), input, 32);
1160 check(SV("__[(42, 99, 0), (1, 10, 100)]___"), SV("{:_^{}}"), input, 32);
1161 check(SV("#####[(42, 99, 0), (1, 10, 100)]"), SV("{:#>{}}"), input, 32);
1162
1163 check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
1164 check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
1165 check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
1166
1167 // *** sign ***
1168 check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
1169 check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
1170 check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
1171
1172 // *** alternate form ***
1173 check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
1174
1175 // *** zero-padding ***
1176 check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
1177
1178 // *** precision ***
1179 check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
1180
1181 // *** locale-specific form ***
1182 check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
1183
1184 // *** n
1185 check(SV("__(42, 99, 0), (1, 10, 100)___"), SV("{:_^30n}"), input);
1186
1187 // *** type ***
1188 check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
1189 check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
1190 check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
1191 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
1192 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1193
1194 // ***** Only underlying has a format-spec
1195 check(SV("[(42, 99, 0) , (1, 10, 100) ]"), SV("{::14}"), input);
1196 check(SV("[(42, 99, 0)***, (1, 10, 100)**]"), SV("{::*<14}"), input);
1197 check(SV("[_(42, 99, 0)__, _(1, 10, 100)_]"), SV("{::_^14}"), input);
1198 check(SV("[###(42, 99, 0), ##(1, 10, 100)]"), SV("{::#>14}"), input);
1199
1200 check(SV("[(42, 99, 0) , (1, 10, 100) ]"), SV("{::{}}"), input, 14);
1201 check(SV("[(42, 99, 0)***, (1, 10, 100)**]"), SV("{::*<{}}"), input, 14);
1202 check(SV("[_(42, 99, 0)__, _(1, 10, 100)_]"), SV("{::_^{}}"), input, 14);
1203 check(SV("[###(42, 99, 0), ##(1, 10, 100)]"), SV("{::#>{}}"), input, 14);
1204
1205 check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
1206 check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
1207 check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
1208
1209 // *** sign ***
1210 check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
1211 check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
1212 check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
1213
1214 // *** alternate form ***
1215 check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1216
1217 // *** zero-padding ***
1218 check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1219
1220 // *** precision ***
1221 check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1222
1223 // *** locale-specific form ***
1224 check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1225
1226 // *** type ***
1227 check(SV("[42, 99, 0, 1, 10, 100]"), SV("{::n}"), input);
1228 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s"))
1229 check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1230
1231 // ***** Both have a format-spec
1232 check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^37:#>14}"), input);
1233 check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^37:#>14}"), input);
1234 check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^{}:#>14}"), input, 37);
1235 check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^{}:#>{}}"), input, 37, 14);
1236
1237 check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1238 check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 37);
1239 }
1240
1241 //
1242 // Ranges
1243 //
1244
1245 template <class CharT, class TestFunction, class ExceptionTest>
test_with_ranges(TestFunction check,ExceptionTest check_exception,auto && iter)1246 void test_with_ranges(TestFunction check, ExceptionTest check_exception, auto&& iter) {
1247 std::ranges::subrange range{std::move(iter), std::default_sentinel};
1248 test_int<CharT>(check, check_exception, std::move(range));
1249 }
1250
1251 template <class CharT, class TestFunction, class ExceptionTest>
test_with_ranges(TestFunction check,ExceptionTest check_exception)1252 void test_with_ranges(TestFunction check, ExceptionTest check_exception) {
1253 std::array input{1, 2, 42, -42};
1254 test_with_ranges<CharT>(
1255 check, check_exception, std::counted_iterator{cpp20_input_iterator<int*>(input.data()), input.size()});
1256 test_with_ranges<CharT>(
1257 check, check_exception, std::counted_iterator{forward_iterator<int*>(input.data()), input.size()});
1258 test_with_ranges<CharT>(
1259 check, check_exception, std::counted_iterator{bidirectional_iterator<int*>(input.data()), input.size()});
1260 test_with_ranges<CharT>(
1261 check, check_exception, std::counted_iterator{random_access_iterator<int*>(input.data()), input.size()});
1262 test_with_ranges<CharT>(
1263 check, check_exception, std::counted_iterator{contiguous_iterator<int*>(input.data()), input.size()});
1264 }
1265
1266 //
1267 // Adaptor
1268 //
1269
1270 template <class CharT>
1271 class non_contiguous {
1272 // A deque iterator is random access, but not contiguous.
1273 using adaptee = std::deque<CharT>;
1274
1275 public:
1276 using iterator = typename adaptee::iterator;
1277 using pointer = typename adaptee::pointer;
1278
begin()1279 iterator begin() { return data_.begin(); }
end()1280 iterator end() { return data_.end(); }
1281
non_contiguous(adaptee && data)1282 explicit non_contiguous(adaptee&& data) : data_(std::move(data)) {}
1283
1284 private:
1285 adaptee data_;
1286 };
1287
1288 template <class CharT>
1289 class contiguous {
1290 // A vector iterator is contiguous.
1291 using adaptee = std::vector<CharT>;
1292
1293 public:
1294 using iterator = typename adaptee::iterator;
1295 using pointer = typename adaptee::pointer;
1296
begin()1297 iterator begin() { return data_.begin(); }
end()1298 iterator end() { return data_.end(); }
1299
contiguous(adaptee && data)1300 explicit contiguous(adaptee&& data) : data_(std::move(data)) {}
1301
1302 private:
1303 adaptee data_;
1304 };
1305
1306 // This tests two different implementations in libc++. A basic_string_view
1307 // formatter if the range is contiguous, a basic_string otherwise.
1308 template <class CharT, class TestFunction, class ExceptionTest>
test_adaptor(TestFunction check,ExceptionTest check_exception)1309 void test_adaptor(TestFunction check, ExceptionTest check_exception) {
1310 static_assert(std::format_kind<non_contiguous<CharT>> == std::range_format::sequence);
1311 static_assert(std::ranges::sized_range<non_contiguous<CharT>>);
1312 static_assert(!std::ranges::contiguous_range<non_contiguous<CharT>>);
1313 test_char_string<CharT>(
1314 check,
1315 check_exception,
1316 non_contiguous<CharT>{std::deque{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')}});
1317
1318 static_assert(std::format_kind<contiguous<CharT>> == std::range_format::sequence);
1319 static_assert(std::ranges::sized_range<contiguous<CharT>>);
1320 static_assert(std::ranges::contiguous_range<contiguous<CharT>>);
1321 test_char_string<CharT>(check,
1322 check_exception,
1323 contiguous<CharT>{std::vector{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')}});
1324 }
1325
1326 //
1327 // Driver
1328 //
1329
1330 template <class CharT, class TestFunction, class ExceptionTest>
format_tests(TestFunction check,ExceptionTest check_exception)1331 void format_tests(TestFunction check, ExceptionTest check_exception) {
1332 test_char<CharT>(check, check_exception);
1333 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1334 if (std::same_as<CharT, wchar_t>) // avoid testing twice
1335 test_char_to_wchar(check, check_exception);
1336 #endif
1337 test_bool<CharT>(check, check_exception);
1338 test_int<CharT>(check, check_exception);
1339 test_floating_point<CharT>(check, check_exception);
1340 test_pointer<CharT>(check, check_exception);
1341 test_string<CharT>(check, check_exception);
1342
1343 test_status<CharT>(check, check_exception); // Has its own handler with its own parser
1344
1345 test_pair_tuple<CharT>(check, check_exception);
1346 test_tuple_int<CharT>(check, check_exception);
1347 test_tuple_int_int_int<CharT>(check, check_exception);
1348
1349 test_with_ranges<CharT>(check, check_exception);
1350
1351 test_adaptor<CharT>(check, check_exception);
1352 }
1353
1354 #endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
1355