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 28 template <class CharT, class TestFunction, class ExceptionTest> 29 void 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 137 template <class TestFunction, class ExceptionTest> 138 void 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 // 245 template <class CharT, class TestFunction, class ExceptionTest> 246 void 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 341 template <class CharT, class TestFunction, class ExceptionTest> 342 void 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 356 template <class CharT, class TestFunction, class ExceptionTest> 357 void 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 452 template <class CharT, class TestFunction, class ExceptionTest> 453 void 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 464 template <class CharT, class TestFunction, class ExceptionTest> 465 void 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 566 template <class CharT, class TestFunction, class ExceptionTest> 567 void 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 666 template <class CharT, class TestFunction, class ExceptionTest> 667 void 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 768 template <class CharT, class TestFunction, class ExceptionTest> 769 void 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 824 class adaptor { 825 using adaptee = std::map<int, int>; 826 827 public: 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 837 private: 838 adaptee data_; 839 }; 840 841 static_assert(std::format_kind<adaptor> == std::range_format::map); 842 843 template <class CharT, class TestFunction, class ExceptionTest> 844 void 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 852 template <class CharT, class TestFunction, class ExceptionTest> 853 void 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