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 25 template <class Container> 26 class test_range_format_string { 27 public: 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 33 private: 34 Container str_; 35 }; 36 37 template <class Container> 38 constexpr std::range_format std::format_kind<test_range_format_string<Container>> = std::range_format::string; 39 40 template <class Container> 41 class test_range_format_debug_string { 42 public: 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 48 private: 49 Container str_; 50 }; 51 52 template <class Container> 53 constexpr std::range_format std::format_kind<test_range_format_debug_string<Container>> = 54 std::range_format::debug_string; 55 56 // 57 // String 58 // 59 60 template <class CharT, class TestFunction, class ExceptionTest> 61 void 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 106 template <class CharT, class TestFunction, class ExceptionTest> 107 void 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 120 template <class CharT, class TestFunction, class ExceptionTest> 121 void 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 220 template <class CharT, class TestFunction, class ExceptionTest> 221 void 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 250 template <class CharT, class TestFunction, class ExceptionTest> 251 void 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 296 template <class CharT, class TestFunction, class ExceptionTest> 297 void 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 313 template <class CharT, class TestFunction, class ExceptionTest> 314 void 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 409 template <class CharT, class TestFunction, class ExceptionTest> 410 void 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 439 template <class CharT, class TestFunction, class ExceptionTest> 440 void 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