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_FMTMAP_FORMAT_FUNCTIONS_TESTS_H
9#define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTMAP_FORMAT_FUNCTIONS_TESTS_H
10
11#include <algorithm>
12#include <format>
13#include <map>
14#include <unordered_map>
15
16#include "format.functions.common.h"
17#include "make_string.h"
18#include "platform_support.h" // locale name macros
19#include "test_macros.h"
20
21//
22// Char
23//
24
25template <class CharT, class TestFunction, class ExceptionTest>
26void test_char(TestFunction check, ExceptionTest check_exception) {
27 std::map<CharT, CharT> input{{CharT('a'), CharT('A')}, {CharT('c'), CharT('C')}, {CharT('b'), CharT('B')}};
28
29 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{}"), input);
30 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{}^42"), input);
31 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{:}^42"), input);
32
33 // ***** underlying has no format-spec
34
35 // *** align-fill & width ***
36 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'} "), SV("{:35}"), input);
37 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}*****"), SV("{:*<35}"), input);
38 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^35}"), input);
39 check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>35}"), input);
40
41 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'} "), SV("{:{}}"), input, 35);
42 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}*****"), SV("{:*<{}}"), input, 35);
43 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^{}}"), input, 35);
44 check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>{}}"), input, 35);
45
46 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
47 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
48
49 // *** sign ***
50 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
51 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
52 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
53
54 // *** alternate form ***
55 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
56
57 // *** zero-padding ***
58 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
59
60 // *** precision ***
61 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
62
63 // *** locale-specific form ***
64 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
65
66 // *** n
67 check(SV("__'a': 'A', 'b': 'B', 'c': 'C'___"), SV("{:_^33n}"), input);
68
69 // *** type ***
70 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^35m}"), input); // the m type does the same as the default.
71 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
72 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
73
74 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
75 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
76
77 // ***** Only underlying has a format-spec
78
79 check(SV("{'a': 'A' , 'b': 'B' , 'c': 'C' }"), SV("{::13}"), input);
80 check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<13}"), input);
81 check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^13}"), input);
82 check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>13}"), input);
83
84 check(SV("{'a': 'A' , 'b': 'B' , 'c': 'C' }"), SV("{::{}}"), input, 13);
85 check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<{}}"), input, 13);
86 check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
87 check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
88
89 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
90 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
91
92 // *** sign ***
93 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
94 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
95 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
96
97 // *** alternate form ***
98 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
99
100 // *** zero-padding ***
101 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
102
103 // *** precision ***
104 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
105
106 // *** locale-specific form ***
107 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
108
109 // *** type ***
110 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::m}"), input);
111 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::n}"), input);
112 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
113 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
114
115 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
116 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
117
118 // ***** Both have a format-spec
119 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^44:#>11}"), input);
120 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>11}"), input, 44);
121 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>{}}"), input, 44, 11);
122
123 check_exception(
124 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>11}"), input);
125 check_exception(
126 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 44);
127}
128
129//
130// char -> wchar_t
131//
132
133#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
134template <class TestFunction, class ExceptionTest>
135void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
136 std::map<char, char> input{{'a', 'A'}, {'c', 'C'}, {'b', 'B'}};
137
138 using CharT = wchar_t;
139 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{}"), input);
140 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{}^42"), input);
141 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{:}^42"), input);
142
143 // ***** underlying has no format-spec
144
145 // *** align-fill & width ***
146 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'} "), SV("{:35}"), input);
147 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}*****"), SV("{:*<35}"), input);
148 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^35}"), input);
149 check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>35}"), input);
150
151 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'} "), SV("{:{}}"), input, 35);
152 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}*****"), SV("{:*<{}}"), input, 35);
153 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^{}}"), input, 35);
154 check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>{}}"), input, 35);
155
156 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
157 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
158
159 // *** sign ***
160 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
161 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
162 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
163
164 // *** alternate form ***
165 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
166
167 // *** zero-padding ***
168 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
169
170 // *** precision ***
171 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
172
173 // *** locale-specific form ***
174 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
175
176 // *** n
177 check(SV("__'a': 'A', 'b': 'B', 'c': 'C'___"), SV("{:_^33n}"), input);
178
179 // *** type ***
180 check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^35m}"), input); // the m type does the same as the default.
181 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
182 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
183
184 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
185 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
186
187 // ***** Only underlying has a format-spec
188 check(SV("{'a': 'A' , 'b': 'B' , 'c': 'C' }"), SV("{::13}"), input);
189 check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<13}"), input);
190 check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^13}"), input);
191 check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>13}"), input);
192
193 check(SV("{'a': 'A' , 'b': 'B' , 'c': 'C' }"), SV("{::{}}"), input, 13);
194 check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<{}}"), input, 13);
195 check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
196 check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
197
198 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
199 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
200
201 // *** sign ***
202 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
203 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
204 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
205
206 // *** alternate form ***
207 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
208
209 // *** zero-padding ***
210 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
211
212 // *** precision ***
213 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
214
215 // *** locale-specific form ***
216 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
217
218 // *** type ***
219 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::m}"), input);
220 check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::n}"), input);
221 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
222 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
223
224 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
225 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
226
227 // ***** Both have a format-spec
228 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^44:#>11}"), input);
229 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>11}"), input, 44);
230 check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>{}}"), input, 44, 11);
231
232 check_exception(
233 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>11}"), input);
234 check_exception(
235 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 44);
236}
237#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
238
239//
240// Bool
241//
242template <class CharT, class TestFunction, class ExceptionTest>
243void test_bool(TestFunction check, ExceptionTest check_exception) {
244 // duplicates are stored in order of insertion
245 std::multimap<bool, int> input{{true, 42}, {false, 0}, {true, 1}};
246
247 check(SV("{false: 0, true: 42, true: 1}"), SV("{}"), input);
248 check(SV("{false: 0, true: 42, true: 1}^42"), SV("{}^42"), input);
249 check(SV("{false: 0, true: 42, true: 1}^42"), SV("{:}^42"), input);
250
251 // ***** underlying has no format-spec
252
253 // *** align-fill & width ***
254 check(SV("{false: 0, true: 42, true: 1} "), SV("{:34}"), input);
255 check(SV("{false: 0, true: 42, true: 1}*****"), SV("{:*<34}"), input);
256 check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^34}"), input);
257 check(SV("#####{false: 0, true: 42, true: 1}"), SV("{:#>34}"), input);
258
259 check(SV("{false: 0, true: 42, true: 1} "), SV("{:{}}"), input, 34);
260 check(SV("{false: 0, true: 42, true: 1}*****"), SV("{:*<{}}"), input, 34);
261 check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^{}}"), input, 34);
262 check(SV("#####{false: 0, true: 42, true: 1}"), SV("{:#>{}}"), input, 34);
263
264 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
265 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
266
267 // *** sign ***
268 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
269 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
270 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
271
272 // *** alternate form ***
273 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
274
275 // *** zero-padding ***
276 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
277
278 // *** precision ***
279 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
280
281 // *** locale-specific form ***
282 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
283
284 // *** n
285 check(SV("__false: 0, true: 42, true: 1___"), SV("{:_^32n}"), input);
286
287 // *** type ***
288 check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^34m}"), input); // the m type does the same as the default.
289 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
290 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
291
292 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
293 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
294
295 // ***** Only underlying has a format-spec
296 check(SV("{false: 0 , true: 42 , true: 1 }"), SV("{::10}"), input);
297 check(SV("{false: 0**, true: 42**, true: 1***}"), SV("{::*<10}"), input);
298 check(SV("{_false: 0_, _true: 42_, _true: 1__}"), SV("{::_^10}"), input);
299 check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>10}"), input);
300
301 check(SV("{false: 0 , true: 42 , true: 1 }"), SV("{::{}}"), input, 10);
302 check(SV("{false: 0**, true: 42**, true: 1***}"), SV("{::*<{}}"), input, 10);
303 check(SV("{_false: 0_, _true: 42_, _true: 1__}"), SV("{::_^{}}"), input, 10);
304 check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>{}}"), input, 10);
305
306 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
307 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
308
309 // *** sign ***
310 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
311 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
312 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
313
314 // *** alternate form ***
315 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
316
317 // *** zero-padding ***
318 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
319
320 // *** precision ***
321 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
322
323 // *** locale-specific form ***
324 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
325
326 // *** type ***
327 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
328 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
329
330 // ***** Both have a format-spec
331 check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^41:#>10}"), input);
332 check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^{}:#>10}"), input, 41);
333 check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^{}:#>{}}"), input, 41, 10);
334
335 check_exception(
336 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>10}"), input);
337 check_exception(
338 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 41);
339}
340
341//
342// Integral
343//
344
345template <class CharT, class TestFunction, class ExceptionTest>
346void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
347 check(SV("{-42: 42, 1: -1, 42: -42}"), SV("{}"), input);
348 check(SV("{-42: 42, 1: -1, 42: -42}^42"), SV("{}^42"), input);
349 check(SV("{-42: 42, 1: -1, 42: -42}^42"), SV("{:}^42"), input);
350
351 // ***** underlying has no format-spec
352
353 // *** align-fill & width ***
354 check(SV("{-42: 42, 1: -1, 42: -42} "), SV("{:30}"), input);
355 check(SV("{-42: 42, 1: -1, 42: -42}*****"), SV("{:*<30}"), input);
356 check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^30}"), input);
357 check(SV("#####{-42: 42, 1: -1, 42: -42}"), SV("{:#>30}"), input);
358
359 check(SV("{-42: 42, 1: -1, 42: -42} "), SV("{:{}}"), input, 30);
360 check(SV("{-42: 42, 1: -1, 42: -42}*****"), SV("{:*<{}}"), input, 30);
361 check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^{}}"), input, 30);
362 check(SV("#####{-42: 42, 1: -1, 42: -42}"), SV("{:#>{}}"), input, 30);
363
364 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
365 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
366
367 // *** sign ***
368 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
369 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
370 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
371
372 // *** alternate form ***
373 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
374
375 // *** zero-padding ***
376 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
377
378 // *** precision ***
379 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
380
381 // *** locale-specific form ***
382 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
383
384 // *** n
385 check(SV("__-42: 42, 1: -1, 42: -42___"), SV("{:_^28n}"), input);
386
387 // *** type ***
388 check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^30m}"), input); // the m type does the same as the default.
389 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
390 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
391
392 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
393 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
394
395 // ***** Only underlying has a format-spec
396 check(SV("{-42: 42 , 1: -1 , 42: -42 }"), SV("{::10}"), input);
397 check(SV("{-42: 42***, 1: -1*****, 42: -42***}"), SV("{::*<10}"), input);
398 check(SV("{_-42: 42__, __1: -1___, _42: -42__}"), SV("{::_^10}"), input);
399 check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>10}"), input);
400
401 check(SV("{-42: 42 , 1: -1 , 42: -42 }"), SV("{::{}}"), input, 10);
402 check(SV("{-42: 42***, 1: -1*****, 42: -42***}"), SV("{::*<{}}"), input, 10);
403 check(SV("{_-42: 42__, __1: -1___, _42: -42__}"), SV("{::_^{}}"), input, 10);
404 check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>{}}"), input, 10);
405
406 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
407 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
408
409 // *** sign ***
410 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
411 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
412 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
413
414 // *** alternate form ***
415 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
416
417 // *** zero-padding ***
418 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
419
420 // *** precision ***
421 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
422
423 // *** locale-specific form ***
424 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
425
426 // *** type ***
427 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
428 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
429
430 // ***** Both have a format-spec
431 check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^41:#>10}"), input);
432 check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^{}:#>10}"), input, 41);
433 check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^{}:#>{}}"), input, 41, 10);
434
435 check_exception(
436 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>10}"), input);
437 check_exception(
438 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 41);
439}
440
441template <class CharT, class TestFunction, class ExceptionTest>
442void test_int(TestFunction check, ExceptionTest check_exception) {
443 test_int<CharT>(check, check_exception, std::map<int, int>{{1, -1}, {42, -42}, {-42, 42}});
444}
445
446//
447// Floating point
448//
449
450template <class CharT, class TestFunction, class ExceptionTest>
451void test_floating_point(TestFunction check, ExceptionTest check_exception) {
452 std::map<double, double> input{{1.0, -1.0}, {-42, 42}};
453
454 check(SV("{-42: 42, 1: -1}"), SV("{}"), input);
455 check(SV("{-42: 42, 1: -1}^42"), SV("{}^42"), input);
456 check(SV("{-42: 42, 1: -1}^42"), SV("{:}^42"), input);
457
458 // ***** underlying has no format-spec
459
460 // *** align-fill & width ***
461 check(SV("{-42: 42, 1: -1} "), SV("{:21}"), input);
462 check(SV("{-42: 42, 1: -1}*****"), SV("{:*<21}"), input);
463 check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21}"), input);
464 check(SV("#####{-42: 42, 1: -1}"), SV("{:#>21}"), input);
465
466 check(SV("{-42: 42, 1: -1} "), SV("{:{}}"), input, 21);
467 check(SV("{-42: 42, 1: -1}*****"), SV("{:*<{}}"), input, 21);
468 check(SV("__{-42: 42, 1: -1}___"), SV("{:_^{}}"), input, 21);
469 check(SV("#####{-42: 42, 1: -1}"), SV("{:#>{}}"), input, 21);
470
471 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
472 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
473
474 // *** sign ***
475 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
476 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
477 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
478
479 // *** alternate form ***
480 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
481
482 // *** zero-padding ***
483 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
484
485 // *** precision ***
486 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
487
488 // *** locale-specific form ***
489 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
490
491 // *** n
492 check(SV("__-42: 42, 1: -1___"), SV("{:_^19n}"), input);
493
494 // *** type ***
495 check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21m}"), input); // the m type does the same as the default.
496 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
497 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
498
499 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
500 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
501
502 // ***** Only underlying has a format-spec
503 check(SV("{-42: 42 , 1: -1 }"), SV("{::10}"), input);
504 check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<10}"), input);
505 check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^10}"), input);
506 check(SV("{###-42: 42, #####1: -1}"), SV("{::#>10}"), input);
507
508 check(SV("{-42: 42 , 1: -1 }"), SV("{::{}}"), input, 10);
509 check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<{}}"), input, 10);
510 check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^{}}"), input, 10);
511 check(SV("{###-42: 42, #####1: -1}"), SV("{::#>{}}"), input, 10);
512
513 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
514 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
515
516 // *** sign ***
517 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
518 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
519 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
520
521 // *** alternate form ***
522 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
523
524 // *** zero-padding ***
525 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
526
527 // *** precision ***
528 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
529
530 // *** locale-specific form ***
531 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
532
533 // *** type ***
534 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
535 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
536
537 // ***** Both have a format-spec
538 check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^29:#>10}"), input);
539 check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>10}"), input, 29);
540 check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>{}}"), input, 29, 10);
541
542 check_exception(
543 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>10}"), input);
544 check_exception(
545 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 29);
546}
547
548//
549// Pointer
550//
551
552template <class CharT, class TestFunction, class ExceptionTest>
553void test_pointer(TestFunction check, ExceptionTest check_exception) {
554 std::unordered_map<const void*, std::nullptr_t> input{{0, 0}};
555
556 check(SV("{0x0: 0x0}"), SV("{}"), input);
557 check(SV("{0x0: 0x0}^42"), SV("{}^42"), input);
558 check(SV("{0x0: 0x0}^42"), SV("{:}^42"), input);
559
560 // ***** underlying has no format-spec
561
562 // *** align-fill & width ***
563 check(SV("{0x0: 0x0} "), SV("{:15}"), input);
564 check(SV("{0x0: 0x0}*****"), SV("{:*<15}"), input);
565 check(SV("__{0x0: 0x0}___"), SV("{:_^15}"), input);
566 check(SV("#####{0x0: 0x0}"), SV("{:#>15}"), input);
567
568 check(SV("{0x0: 0x0} "), SV("{:{}}"), input, 15);
569 check(SV("{0x0: 0x0}*****"), SV("{:*<{}}"), input, 15);
570 check(SV("__{0x0: 0x0}___"), SV("{:_^{}}"), input, 15);
571 check(SV("#####{0x0: 0x0}"), SV("{:#>{}}"), input, 15);
572
573 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
574 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
575
576 // *** sign ***
577 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
578
579 // *** alternate form ***
580 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
581
582 // *** zero-padding ***
583 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
584
585 // *** precision ***
586 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
587
588 // *** locale-specific form ***
589 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
590
591 // *** n
592 check(SV("__0x0: 0x0___"), SV("{:_^13n}"), input);
593
594 // *** type ***
595 check(SV("__{0x0: 0x0}___"), SV("{:_^15m}"), input); // the m type does the same as the default.
596 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
597 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
598
599 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
600 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
601
602 // ***** Only underlying has a format-spec
603 check(SV("{0x0: 0x0 }"), SV("{::13}"), input);
604 check(SV("{0x0: 0x0*****}"), SV("{::*<13}"), input);
605 check(SV("{__0x0: 0x0___}"), SV("{::_^13}"), input);
606 check(SV("{#####0x0: 0x0}"), SV("{::#>13}"), input);
607
608 check(SV("{0x0: 0x0 }"), SV("{::{}}"), input, 13);
609 check(SV("{0x0: 0x0*****}"), SV("{::*<{}}"), input, 13);
610 check(SV("{__0x0: 0x0___}"), SV("{::_^{}}"), input, 13);
611 check(SV("{#####0x0: 0x0}"), SV("{::#>{}}"), input, 13);
612
613 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
614 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
615
616 // *** sign ***
617 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
618 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
619 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
620
621 // *** alternate form ***
622 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
623
624 // *** zero-padding ***
625 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
626
627 // *** precision ***
628 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
629
630 // *** locale-specific form ***
631 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
632
633 // *** type ***
634 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
635 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
636
637 // ***** Both have a format-spec
638 check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^18:#>11}"), input);
639 check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^{}:#>11}"), input, 18);
640 check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^{}:#>{}}"), input, 18, 11);
641
642 check_exception(
643 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>11}"), input);
644 check_exception(
645 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 18);
646}
647
648//
649// String
650//
651
652template <class CharT, class TestFunction, class ExceptionTest>
653void test_string(TestFunction check, ExceptionTest check_exception) {
654 std::map<std::basic_string<CharT>, std::basic_string<CharT>> input{
655 {STR("hello"), STR("HELLO")}, {STR("world"), STR("WORLD")}};
656
657 check(SV(R"({"hello": "HELLO", "world": "WORLD"})"), SV("{}"), input);
658 check(SV(R"({"hello": "HELLO", "world": "WORLD"}^42)"), SV("{}^42"), input);
659 check(SV(R"({"hello": "HELLO", "world": "WORLD"}^42)"), SV("{:}^42"), input);
660
661 // ***** underlying has no format-spec
662
663 // *** align-fill & width ***
664 check(SV(R"({"hello": "HELLO", "world": "WORLD"} )"), SV("{:41}"), input);
665 check(SV(R"({"hello": "HELLO", "world": "WORLD"}*****)"), SV("{:*<41}"), input);
666 check(SV(R"(__{"hello": "HELLO", "world": "WORLD"}___)"), SV("{:_^41}"), input);
667 check(SV(R"(#####{"hello": "HELLO", "world": "WORLD"})"), SV("{:#>41}"), input);
668
669 check(SV(R"({"hello": "HELLO", "world": "WORLD"} )"), SV("{:{}}"), input, 41);
670 check(SV(R"({"hello": "HELLO", "world": "WORLD"}*****)"), SV("{:*<{}}"), input, 41);
671 check(SV(R"(__{"hello": "HELLO", "world": "WORLD"}___)"), SV("{:_^{}}"), input, 41);
672 check(SV(R"(#####{"hello": "HELLO", "world": "WORLD"})"), SV("{:#>{}}"), input, 41);
673
674 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
675 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
676
677 // *** sign ***
678 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
679
680 // *** alternate form ***
681 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
682
683 // *** zero-padding ***
684 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
685
686 // *** precision ***
687 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
688
689 // *** locale-specific form ***
690 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
691
692 // *** n
693 check(SV(R"(__"hello": "HELLO", "world": "WORLD"___)"), SV("{:_^39n}"), input);
694
695 // *** type ***
696 check(SV(R"(__{"hello": "HELLO", "world": "WORLD"}___)"), SV("{:_^41m}"), input);
697 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
698 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
699
700 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
701 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
702
703 // ***** Only underlying has a format-spec
704 check(SV(R"({"hello": "HELLO" , "world": "WORLD" })"), SV("{::21}"), input);
705 check(SV(R"({"hello": "HELLO"*****, "world": "WORLD"*****})"), SV("{::*<21}"), input);
706 check(SV(R"({__"hello": "HELLO"___, __"world": "WORLD"___})"), SV("{::_^21}"), input);
707 check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>21}"), input);
708
709 check(SV(R"({"hello": "HELLO" , "world": "WORLD" })"), SV("{::{}}"), input, 21);
710 check(SV(R"({"hello": "HELLO"*****, "world": "WORLD"*****})"), SV("{::*<{}}"), input, 21);
711 check(SV(R"({__"hello": "HELLO"___, __"world": "WORLD"___})"), SV("{::_^{}}"), input, 21);
712 check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>{}}"), input, 21);
713
714 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
715 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
716
717 // *** sign ***
718 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
719 check_exception("The format specifier should consume the input or end with a '}'", SV("{::+}"), input);
720 check_exception("The format specifier should consume the input or end with a '}'", SV("{:: }"), input);
721
722 // *** alternate form ***
723 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
724
725 // *** zero-padding ***
726 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
727
728 // *** precision ***
729 check_exception("The format specifier should consume the input or end with a '}'", SV("{::.}"), input);
730
731 // *** locale-specific form ***
732 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
733
734 // *** type ***
735 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
736 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
737
738 // ***** Both have a format-spec
739
740 check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^51:#>21}"), input);
741 check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^{}:#>21}"), input, 51);
742 check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^{}:#>{}}"), input, 51, 21);
743
744 check_exception(
745 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>21}"), input);
746 check_exception(
747 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>{}}"), input, 51);
748}
749
750//
751// Handle
752//
753
754template <class CharT, class TestFunction, class ExceptionTest>
755void test_status(TestFunction check, ExceptionTest check_exception) {
756 std::unordered_multimap<status, status> input{{status::foobar, status::foo}, {status::foobar, status::bar}};
757
758 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{}"), input);
759 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}^42"), SV("{}^42"), input);
760 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}^42"), SV("{:}^42"), input);
761
762 // ***** underlying has no format-spec
763
764 // *** align-fill & width ***
765 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555} "), SV("{:37}"), input);
766 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}*****"), SV("{:*<37}"), input);
767 check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^37}"), input);
768 check(SV("#####{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{:#>37}"), input);
769
770 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555} "), SV("{:{}}"), input, 37);
771 check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}*****"), SV("{:*<{}}"), input, 37);
772 check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^{}}"), input, 37);
773 check(SV("#####{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{:#>{}}"), input, 37);
774
775 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
776 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
777
778 // *** sign ***
779 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
780 check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);
781 check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);
782
783 // *** alternate form ***
784 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
785
786 // *** zero-padding ***
787 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
788
789 // *** precision ***
790 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
791
792 // *** locale-specific form ***
793 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
794
795 // *** n
796 check(SV("__0xaa55: 0xaaaa, 0xaa55: 0x5555___"), SV("{:_^35n}"), input);
797
798 // *** type ***
799 check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^37}"), input); // the m type does the same as the default.
800 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
801 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
802
803 // Underlying can't have a format-spec
804}
805
806//
807// Adaptor
808//
809
810class adaptor {
811 using adaptee = std::map<int, int>;
812
813public:
814 using key_type = typename adaptee::key_type;
815 using mapped_type = typename adaptee::mapped_type;
816 using iterator = typename adaptee::iterator;
817
818 iterator begin() { return data_.begin(); }
819 iterator end() { return data_.end(); }
820
821 explicit adaptor(std::map<int, int>&& data) : data_(std::move(data)) {}
822
823private:
824 adaptee data_;
825};
826
827static_assert(std::format_kind<adaptor> == std::range_format::map);
828
829template <class CharT, class TestFunction, class ExceptionTest>
830void test_adaptor(TestFunction check, ExceptionTest check_exception) {
831 test_int<CharT>(check, check_exception, adaptor{std::map<int, int>{{1, -1}, {42, -42}, {-42, 42}}});
832}
833
834//
835// Driver
836//
837
838template <class CharT, class TestFunction, class ExceptionTest>
839void format_tests(TestFunction check, ExceptionTest check_exception) {
840 test_char<CharT>(check, check_exception);
841#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
842 if (std::same_as<CharT, wchar_t>) // avoid testing twice
843 test_char_to_wchar(check, check_exception);
844#endif
845 test_bool<CharT>(check, check_exception);
846 test_int<CharT>(check, check_exception);
847 test_floating_point<CharT>(check, check_exception);
848 test_pointer<CharT>(check, check_exception);
849 test_string<CharT>(check, check_exception);
850
851 test_status<CharT>(check, check_exception);
852
853 test_adaptor<CharT>(check, check_exception);
854}
855
856#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTMAP_FORMAT_FUNCTIONS_TESTS_H
857

source code of libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h