| 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 | |