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_FMTSTR_FORMAT_FUNCTIONS_TESTS_H
9#define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTSTR_FORMAT_FUNCTIONS_TESTS_H
10
11#include <array>
12#include <format>
13#include <list>
14
15#include "format.functions.common.h"
16#include "make_string.h"
17#include "platform_support.h" // locale name macros
18#include "test_macros.h"
19
20//
21// Types
22//
23
24template <class Container>
25class test_range_format_string {
26public:
27 explicit test_range_format_string(Container str) : str_(std::move(str)) {}
28
29 typename Container::const_iterator begin() const { return str_.begin(); }
30 typename Container::const_iterator end() const { return str_.end(); }
31
32private:
33 Container str_;
34};
35
36template <class Container>
37constexpr std::range_format std::format_kind<test_range_format_string<Container>> = std::range_format::string;
38
39template <class Container>
40class test_range_format_debug_string {
41public:
42 explicit test_range_format_debug_string(Container str) : str_(std::move(str)) {}
43
44 typename Container::const_iterator begin() const { return str_.begin(); }
45 typename Container::const_iterator end() const { return str_.end(); }
46
47private:
48 Container str_;
49};
50
51template <class Container>
52constexpr std::range_format std::format_kind<test_range_format_debug_string<Container>> =
53 std::range_format::debug_string;
54
55//
56// String
57//
58
59template <class CharT, class TestFunction, class ExceptionTest>
60void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
61 check(SV("hello"), SV("{}"), input);
62 check(SV("hello^42"), SV("{}^42"), input);
63 check(SV("hello^42"), SV("{:}^42"), input);
64
65 // *** align-fill & width ***
66 check(SV("hello "), SV("{:10}"), input);
67 check(SV("hello*****"), SV("{:*<10}"), input);
68 check(SV("__hello___"), SV("{:_^10}"), input);
69 check(SV(":::::hello"), SV("{::>10}"), input);
70
71 check(SV("hello "), SV("{:{}}"), input, 10);
72 check(SV("hello*****"), SV("{:*<{}}"), input, 10);
73 check(SV("__hello___"), SV("{:_^{}}"), input, 10);
74 check(SV(":::::hello"), SV("{::>{}}"), input, 10);
75
76 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
77 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
78
79 // *** sign ***
80 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
81
82 // *** alternate form ***
83 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
84
85 // *** zero-padding ***
86 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
87
88 // *** precision ***
89 check(SV("hel"), SV("{:.3}"), input);
90 check(SV("hel"), SV("{:.{}}"), input, 3);
91
92 check(SV("hel "), SV("{:5.3}"), input);
93 check(SV("hel "), SV("{:{}.{}}"), input, 5, 3);
94
95 // *** locale-specific form ***
96 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
97
98 // *** type ***
99 check(SV("hello"), SV("{:s}"), input);
100 check(SV("\"hello\""), SV("{:?}"), input);
101 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s?"))
102 check_exception("The type option contains an invalid value for a string formatting argument", fmt, input);
103}
104
105template <class CharT, class TestFunction, class ExceptionTest>
106void test_string(TestFunction check, ExceptionTest check_exception) {
107 // libc++ uses different containers for contiguous and non-contiguous ranges.
108 std::basic_string<CharT> input = STR("hello");
109 test_string<CharT>(check, check_exception, test_range_format_string<std::basic_string<CharT>>{input});
110 test_string<CharT>(check, check_exception, test_range_format_string<std::basic_string_view<CharT>>{input});
111 test_string<CharT>(
112 check, check_exception, test_range_format_string<std::list<CharT>>{std::list<CharT>{input.begin(), input.end()}});
113}
114
115//
116// String range
117//
118
119template <class CharT, class TestFunction, class ExceptionTest>
120void test_range_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
121 check(SV(R"([Hello, world])"), SV("{}"), input);
122 check(SV(R"([Hello, world]^42)"), SV("{}^42"), input);
123 check(SV(R"([Hello, world]^42)"), SV("{:}^42"), input);
124
125 // ***** underlying has no format-spec
126
127 // *** align-fill & width ***
128 check(SV(R"([Hello, world] )"), SV("{:19}"), input);
129 check(SV(R"([Hello, world]*****)"), SV("{:*<19}"), input);
130 check(SV(R"(__[Hello, world]___)"), SV("{:_^19}"), input);
131 check(SV(R"(#####[Hello, world])"), SV("{:#>19}"), input);
132
133 check(SV(R"([Hello, world] )"), SV("{:{}}"), input, 19);
134 check(SV(R"([Hello, world]*****)"), SV("{:*<{}}"), input, 19);
135 check(SV(R"(__[Hello, world]___)"), SV("{:_^{}}"), input, 19);
136 check(SV(R"(#####[Hello, world])"), SV("{:#>{}}"), input, 19);
137
138 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
139 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
140
141 // *** sign ***
142 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
143
144 // *** alternate form ***
145 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
146
147 // *** zero-padding ***
148 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
149
150 // *** precision ***
151 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
152
153 // *** locale-specific form ***
154 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
155
156 // *** n
157 check(SV(R"(_Hello, world_)"), SV("{:_^14n}"), input);
158
159 // *** type ***
160 check_exception("Type m requires a pair or a tuple with two elements", SV("{:m}"), input);
161 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
162 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
163
164 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
165 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
166
167 // ***** Only underlying has a format-spec
168 check(SV(R"([Hello , world ])"), SV("{::8}"), input);
169 check(SV(R"([Hello***, world***])"), SV("{::*<8}"), input);
170 check(SV(R"([_Hello__, _world__])"), SV("{::_^8}"), input);
171 check(SV(R"([:::Hello, :::world])"), SV("{:::>8}"), input);
172
173 check(SV(R"([Hello , world ])"), SV("{::{}}"), input, 8);
174 check(SV(R"([Hello***, world***])"), SV("{::*<{}}"), input, 8);
175 check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
176 check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
177
178 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
179 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
180
181 // *** sign ***
182 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
183
184 // *** alternate form ***
185 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
186
187 // *** zero-padding ***
188 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
189
190 // *** precision ***
191 check(SV(R"([Hel, wor])"), SV("{::.3}"), input);
192
193 check(SV(R"([Hel, wor])"), SV("{::.{}}"), input, 3);
194
195 check_exception("The precision option does not contain a value or an argument index", SV("{::.}"), input);
196
197 // *** locale-specific form ***
198 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
199
200 // *** type ***
201 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s?"))
202 check_exception("The type option contains an invalid value for a string formatting argument", fmt, input);
203
204 // ***** Both have a format-spec
205 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
206 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
207 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
208
209 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
210 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
211 check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
212
213 check_exception(
214 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}::>8}"), input);
215 check_exception(
216 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}::>{}}"), input, 25);
217}
218
219template <class CharT, class TestFunction, class ExceptionTest>
220void test_range_string(TestFunction check, ExceptionTest check_exception) {
221 // libc++ uses different containers for contiguous and non-contiguous ranges.
222 std::array input{STR("Hello"), STR("world")};
223 test_range_string<CharT>(
224 check,
225 check_exception,
226 std::array{test_range_format_string<std::basic_string<CharT>>{input[0]},
227 test_range_format_string<std::basic_string<CharT>>{input[1]}});
228 test_range_string<CharT>(
229 check,
230 check_exception,
231 std::array{test_range_format_string<std::basic_string_view<CharT>>{input[0]},
232 test_range_format_string<std::basic_string_view<CharT>>{input[1]}});
233 test_range_string<CharT>(
234 check,
235 check_exception,
236 std::array{test_range_format_string<std::list<CharT>>{std::list<CharT>{input[0].begin(), input[0].end()}},
237 test_range_format_string<std::list<CharT>>{std::list<CharT>{input[1].begin(), input[1].end()}}});
238 test_range_string<CharT>(
239 check,
240 check_exception,
241 std::list{test_range_format_string<std::list<CharT>>{std::list<CharT>{input[0].begin(), input[0].end()}},
242 test_range_format_string<std::list<CharT>>{std::list<CharT>{input[1].begin(), input[1].end()}}});
243}
244
245//
246// Debug string
247//
248
249template <class CharT, class TestFunction, class ExceptionTest>
250void test_debug_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
251 check(SV("\"hello\""), SV("{}"), input);
252 check(SV("\"hello\"^42"), SV("{}^42"), input);
253 check(SV("\"hello\"^42"), SV("{:}^42"), input);
254
255 // *** align-fill & width ***
256 check(SV("\"hello\" "), SV("{:12}"), input);
257 check(SV("\"hello\"*****"), SV("{:*<12}"), input);
258 check(SV("__\"hello\"___"), SV("{:_^12}"), input);
259 check(SV(":::::\"hello\""), SV("{::>12}"), input);
260
261 check(SV("\"hello\" "), SV("{:{}}"), input, 12);
262 check(SV("\"hello\"*****"), SV("{:*<{}}"), input, 12);
263 check(SV("__\"hello\"___"), SV("{:_^{}}"), input, 12);
264 check(SV(":::::\"hello\""), SV("{::>{}}"), input, 12);
265
266 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
267 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
268
269 // *** sign ***
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(SV("\"he"), SV("{:.3}"), input);
280 check(SV("\"he"), SV("{:.{}}"), input, 3);
281
282 check(SV("\"he "), SV("{:5.3}"), input);
283 check(SV("\"he "), SV("{:{}.{}}"), input, 5, 3);
284
285 // *** locale-specific form ***
286 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
287
288 // *** type ***
289 check(SV("\"hello\""), SV("{:s}"), input); // escape overrides the type option s
290 check(SV("\"hello\""), SV("{:?}"), input);
291 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s?"))
292 check_exception("The type option contains an invalid value for a string formatting argument", fmt, input);
293}
294
295template <class CharT, class TestFunction, class ExceptionTest>
296void test_debug_string(TestFunction check, ExceptionTest check_exception) {
297 // libc++ uses different containers for contiguous and non-contiguous ranges.
298 std::basic_string<CharT> input = STR("hello");
299 test_debug_string<CharT>(check, check_exception, test_range_format_debug_string<std::basic_string<CharT>>{input});
300 test_debug_string<CharT>(
301 check, check_exception, test_range_format_debug_string<std::basic_string_view<CharT>>{input});
302 test_debug_string<CharT>(
303 check,
304 check_exception,
305 test_range_format_debug_string<std::list<CharT>>{std::list<CharT>{input.begin(), input.end()}});
306}
307
308//
309// Debug string range
310//
311
312template <class CharT, class TestFunction, class ExceptionTest>
313void test_range_debug_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
314 // ***** underlying has no format-spec
315
316 // *** align-fill & width ***
317 check(SV(R"(["Hello", "world"] )"), SV("{:23}"), input);
318 check(SV(R"(["Hello", "world"]*****)"), SV("{:*<23}"), input);
319 check(SV(R"(__["Hello", "world"]___)"), SV("{:_^23}"), input);
320 check(SV(R"(#####["Hello", "world"])"), SV("{:#>23}"), input);
321
322 check(SV(R"(["Hello", "world"] )"), SV("{:{}}"), input, 23);
323 check(SV(R"(["Hello", "world"]*****)"), SV("{:*<{}}"), input, 23);
324 check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
325 check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
326
327 check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
328 check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
329
330 // *** sign ***
331 check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
332
333 // *** alternate form ***
334 check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
335
336 // *** zero-padding ***
337 check_exception("The width option should not have a leading zero", SV("{:0}"), input);
338
339 // *** precision ***
340 check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);
341
342 // *** locale-specific form ***
343 check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);
344
345 // *** n
346 check(SV(R"(_"Hello", "world"_)"), SV("{:_^18n}"), input);
347
348 // *** type ***
349 check_exception("Type m requires a pair or a tuple with two elements", SV("{:m}"), input);
350 check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
351 check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);
352
353 for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
354 check_exception("The format specifier should consume the input or end with a '}'", fmt, input);
355
356 // ***** Only underlying has a format-spec
357 check(SV(R"(["Hello" , "world" ])"), SV("{::10}"), input);
358 check(SV(R"(["Hello"***, "world"***])"), SV("{::*<10}"), input);
359 check(SV(R"([_"Hello"__, _"world"__])"), SV("{::_^10}"), input);
360 check(SV(R"([:::"Hello", :::"world"])"), SV("{:::>10}"), input);
361
362 check(SV(R"(["Hello" , "world" ])"), SV("{::{}}"), input, 10);
363 check(SV(R"(["Hello"***, "world"***])"), SV("{::*<{}}"), input, 10);
364 check(SV(R"([_"Hello"__, _"world"__])"), SV("{::_^{}}"), input, 10);
365 check(SV(R"([:::"Hello", :::"world"])"), SV("{:::>{}}"), input, 10);
366
367 check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
368 check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
369
370 // *** sign ***
371 check_exception("The format specifier should consume the input or end with a '}'", SV("{::-}"), input);
372
373 // *** alternate form ***
374 check_exception("The format specifier should consume the input or end with a '}'", SV("{::#}"), input);
375
376 // *** zero-padding ***
377 check_exception("The width option should not have a leading zero", SV("{::05}"), input);
378
379 // *** precision ***
380 check(SV(R"(["He, "wo])"), SV("{::.3}"), input);
381
382 check(SV(R"(["He, "wo])"), SV("{::.{}}"), input, 3);
383
384 check_exception("The precision option does not contain a value or an argument index", SV("{::.}"), input);
385
386 // *** locale-specific form ***
387 check_exception("The format specifier should consume the input or end with a '}'", SV("{::L}"), input);
388
389 // *** type ***
390 for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s?"))
391 check_exception("The type option contains an invalid value for a string formatting argument", fmt, input);
392
393 // ***** Both have a format-spec
394 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^29::>10}"), input);
395 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^{}::>10}"), input, 29);
396 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^{}::>{}}"), input, 29, 10);
397
398 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^29::>10}"), input);
399 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^{}::>10}"), input, 29);
400 check(SV(R"(^^[:::"Hello", :::"world"]^^^)"), SV("{:^^{}::>{}}"), input, 29, 10);
401
402 check_exception(
403 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}::>10}"), input);
404 check_exception(
405 "The argument index value is too large for the number of arguments supplied", SV("{:^^{}::>{}}"), input, 29);
406}
407
408template <class CharT, class TestFunction, class ExceptionTest>
409void test_range_debug_string(TestFunction check, ExceptionTest check_exception) {
410 // libc++ uses different containers for contiguous and non-contiguous ranges.
411 std::array input{STR("Hello"), STR("world")};
412 test_range_debug_string<CharT>(
413 check,
414 check_exception,
415 std::array{test_range_format_debug_string<std::basic_string<CharT>>{input[0]},
416 test_range_format_debug_string<std::basic_string<CharT>>{input[1]}});
417 test_range_debug_string<CharT>(
418 check,
419 check_exception,
420 std::array{test_range_format_debug_string<std::basic_string_view<CharT>>{input[0]},
421 test_range_format_debug_string<std::basic_string_view<CharT>>{input[1]}});
422 test_range_debug_string<CharT>(
423 check,
424 check_exception,
425 std::array{test_range_format_debug_string<std::list<CharT>>{std::list<CharT>{input[0].begin(), input[0].end()}},
426 test_range_format_debug_string<std::list<CharT>>{std::list<CharT>{input[1].begin(), input[1].end()}}});
427 test_range_debug_string<CharT>(
428 check,
429 check_exception,
430 std::list{test_range_format_debug_string<std::list<CharT>>{std::list<CharT>{input[0].begin(), input[0].end()}},
431 test_range_format_debug_string<std::list<CharT>>{std::list<CharT>{input[1].begin(), input[1].end()}}});
432}
433
434//
435// Driver
436//
437
438template <class CharT, class TestFunction, class ExceptionTest>
439void format_tests(TestFunction check, ExceptionTest check_exception) {
440 test_string<CharT>(check, check_exception);
441 test_range_string<CharT>(check, check_exception);
442
443 test_debug_string<CharT>(check, check_exception);
444 test_range_debug_string<CharT>(check, check_exception);
445}
446
447#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTSTR_FORMAT_FUNCTIONS_TESTS_H
448

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