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

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