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

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