| 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_TIME_TIME_SYN_FORMATTER_TESTS_H |
| 10 | #define TEST_STD_TIME_TIME_SYN_FORMATTER_TESTS_H |
| 11 | |
| 12 | #include "assert_macros.h" |
| 13 | #include "concat_macros.h" |
| 14 | #include "make_string.h" |
| 15 | #include "string_literal.h" |
| 16 | #include "test_format_string.h" |
| 17 | #include "test_macros.h" |
| 18 | |
| 19 | #include <algorithm> |
| 20 | #include <cassert> |
| 21 | #include <iostream> |
| 22 | #include <set> |
| 23 | #include <string> |
| 24 | #include <string_view> |
| 25 | |
| 26 | #define STR(S) MAKE_STRING(CharT, S) |
| 27 | #define SV(S) MAKE_STRING_VIEW(CharT, S) |
| 28 | |
| 29 | #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
| 30 | template <class CharT> |
| 31 | using format_context = std::conditional_t<std::same_as<CharT, char>, std::format_context, std::wformat_context>; |
| 32 | #else |
| 33 | template <class CharT> |
| 34 | using format_context = std::format_context; |
| 35 | #endif |
| 36 | |
| 37 | template <class CharT, class... Args> |
| 38 | void check(std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { |
| 39 | std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...); |
| 40 | TEST_REQUIRE(out == expected, |
| 41 | TEST_WRITE_CONCATENATED( |
| 42 | "\nFormat string " , fmt.get(), "\nExpected output " , expected, "\nActual output " , out, '\n')); |
| 43 | } |
| 44 | |
| 45 | template <class CharT, class... Args> |
| 46 | void check(const std::locale& loc, |
| 47 | std::basic_string_view<CharT> expected, |
| 48 | test_format_string<CharT, Args...> fmt, |
| 49 | Args&&... args) { |
| 50 | std::basic_string<CharT> out = std::format(loc, fmt, std::forward<Args>(args)...); |
| 51 | TEST_REQUIRE(out == expected, |
| 52 | TEST_WRITE_CONCATENATED( |
| 53 | "\nFormat string " , fmt.get(), "\nExpected output " , expected, "\nActual output " , out, '\n')); |
| 54 | } |
| 55 | |
| 56 | template <class CharT, class... Args> |
| 57 | void check_exception([[maybe_unused]] std::string_view what, |
| 58 | [[maybe_unused]] std::basic_string_view<CharT> fmt, |
| 59 | [[maybe_unused]] const Args&... args) { |
| 60 | TEST_VALIDATE_EXCEPTION( |
| 61 | std::format_error, |
| 62 | [&]([[maybe_unused]] const std::format_error& e) { |
| 63 | TEST_LIBCPP_REQUIRE( |
| 64 | e.what() == what, |
| 65 | TEST_WRITE_CONCATENATED( |
| 66 | "\nFormat string " , fmt, "\nExpected exception " , what, "\nActual exception " , e.what(), '\n')); |
| 67 | }, |
| 68 | TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<format_context<CharT>>(args...))); |
| 69 | } |
| 70 | |
| 71 | template <class CharT, class T> |
| 72 | void check_invalid_type(const std::set<std::basic_string_view<CharT>>& valid_types, |
| 73 | std::string_view what, |
| 74 | std::basic_string<CharT> type, |
| 75 | const T& arg) { |
| 76 | std::basic_string<CharT> fmt{STR("{:%" ) + type + STR("}" )}; |
| 77 | |
| 78 | if (valid_types.contains(std::basic_string_view<CharT>{type})) { |
| 79 | #ifndef TEST_HAS_NO_EXCEPTIONS |
| 80 | try { |
| 81 | #endif |
| 82 | TEST_IGNORE_NODISCARD std::vformat( |
| 83 | std::basic_string_view<CharT>{fmt}, std::make_format_args<format_context<CharT>>(arg)); |
| 84 | #ifndef TEST_HAS_NO_EXCEPTIONS |
| 85 | } catch (const std::format_error& e) { |
| 86 | (void)e; |
| 87 | if constexpr (std::same_as<CharT, char>) |
| 88 | std::cerr << "\nFormat string " << fmt << "\nUnexpected exception " << e.what() << '\n'; |
| 89 | assert(false); |
| 90 | } |
| 91 | #endif |
| 92 | } else { |
| 93 | check_exception(what, std::basic_string_view<CharT>{fmt}, arg); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | template <class CharT, class T> |
| 98 | void check_invalid_types(const std::set<std::basic_string_view<CharT>>& valid_types, const T& arg) { |
| 99 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("a" ), arg); |
| 100 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("A" ), arg); |
| 101 | check_invalid_type(valid_types, "The supplied date time doesn't contain a month" , STR("b" ), arg); |
| 102 | check_invalid_type(valid_types, "The supplied date time doesn't contain a month" , STR("B" ), arg); |
| 103 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date and time" , STR("c" ), arg); |
| 104 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("C" ), arg); |
| 105 | check_invalid_type(valid_types, "The supplied date time doesn't contain a day" , STR("d" ), arg); |
| 106 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("D" ), arg); |
| 107 | check_invalid_type(valid_types, "The supplied date time doesn't contain a day" , STR("e" ), arg); |
| 108 | // E - the modifier is checked separately |
| 109 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("f" ), arg); |
| 110 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("F" ), arg); |
| 111 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("g" ), arg); |
| 112 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("G" ), arg); |
| 113 | check_invalid_type(valid_types, "The supplied date time doesn't contain a month" , STR("h" ), arg); |
| 114 | check_invalid_type(valid_types, "The supplied date time doesn't contain an hour" , STR("H" ), arg); |
| 115 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("i" ), arg); |
| 116 | check_invalid_type(valid_types, "The supplied date time doesn't contain an hour" , STR("I" ), arg); |
| 117 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date or duration" , STR("j" ), arg); |
| 118 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("J" ), arg); |
| 119 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("k" ), arg); |
| 120 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("K" ), arg); |
| 121 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("l" ), arg); |
| 122 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("L" ), arg); |
| 123 | check_invalid_type(valid_types, "The supplied date time doesn't contain a month" , STR("m" ), arg); |
| 124 | check_invalid_type(valid_types, "The supplied date time doesn't contain a minute" , STR("M" ), arg); |
| 125 | // n - valid |
| 126 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("N" ), arg); |
| 127 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("o" ), arg); |
| 128 | // O - the modifier is checked separately |
| 129 | check_invalid_type(valid_types, "The supplied date time doesn't contain an hour" , STR("p" ), arg); |
| 130 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("P" ), arg); |
| 131 | check_invalid_type(valid_types, "The supplied date time doesn't contain a duration" , STR("q" ), arg); |
| 132 | check_invalid_type(valid_types, "The supplied date time doesn't contain a duration" , STR("Q" ), arg); |
| 133 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time" , STR("r" ), arg); |
| 134 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time" , STR("R" ), arg); |
| 135 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("s" ), arg); |
| 136 | check_invalid_type(valid_types, "The supplied date time doesn't contain a second" , STR("S" ), arg); |
| 137 | // t - valid |
| 138 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time" , STR("T" ), arg); |
| 139 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("u" ), arg); |
| 140 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("U" ), arg); |
| 141 | check_invalid_type(valid_types, "The date time type specifier is invalid" , STR("v" ), arg); |
| 142 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("V" ), arg); |
| 143 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("w" ), arg); |
| 144 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("W" ), arg); |
| 145 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("x" ), arg); |
| 146 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time" , STR("X" ), arg); |
| 147 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("y" ), arg); |
| 148 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("y" ), arg); |
| 149 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone" , STR("z" ), arg); |
| 150 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone" , STR("Z" ), arg); |
| 151 | |
| 152 | // *** E modifier |
| 153 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ea" ), arg); |
| 154 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EA" ), arg); |
| 155 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eb" ), arg); |
| 156 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EB" ), arg); |
| 157 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date and time" , STR("Ec" ), arg); |
| 158 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("EC" ), arg); |
| 159 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ed" ), arg); |
| 160 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("ED" ), arg); |
| 161 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ee" ), arg); |
| 162 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EE" ), arg); |
| 163 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ef" ), arg); |
| 164 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EF" ), arg); |
| 165 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eg" ), arg); |
| 166 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EG" ), arg); |
| 167 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eh" ), arg); |
| 168 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EH" ), arg); |
| 169 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ei" ), arg); |
| 170 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EI" ), arg); |
| 171 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ej" ), arg); |
| 172 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EJ" ), arg); |
| 173 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ek" ), arg); |
| 174 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EK" ), arg); |
| 175 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("El" ), arg); |
| 176 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EL" ), arg); |
| 177 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Em" ), arg); |
| 178 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EM" ), arg); |
| 179 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("En" ), arg); |
| 180 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EN" ), arg); |
| 181 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eo" ), arg); |
| 182 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EO" ), arg); |
| 183 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ep" ), arg); |
| 184 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EP" ), arg); |
| 185 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eq" ), arg); |
| 186 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EQ" ), arg); |
| 187 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Er" ), arg); |
| 188 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("ER" ), arg); |
| 189 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Es" ), arg); |
| 190 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("ES" ), arg); |
| 191 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Et" ), arg); |
| 192 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("ET" ), arg); |
| 193 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Eu" ), arg); |
| 194 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EU" ), arg); |
| 195 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ev" ), arg); |
| 196 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EV" ), arg); |
| 197 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("Ew" ), arg); |
| 198 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EW" ), arg); |
| 199 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("Ex" ), arg); |
| 200 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time" , STR("EX" ), arg); |
| 201 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("Ey" ), arg); |
| 202 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("EY" ), arg); |
| 203 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone" , STR("Ez" ), arg); |
| 204 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("EZ" ), arg); |
| 205 | check_invalid_type(valid_types, "The date time type specifier for modifier E is invalid" , STR("E%" ), arg); |
| 206 | |
| 207 | // *** O modifier |
| 208 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oa" ), arg); |
| 209 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OA" ), arg); |
| 210 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ob" ), arg); |
| 211 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OB" ), arg); |
| 212 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oc" ), arg); |
| 213 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OC" ), arg); |
| 214 | check_invalid_type(valid_types, "The supplied date time doesn't contain a day" , STR("Od" ), arg); |
| 215 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OD" ), arg); |
| 216 | check_invalid_type(valid_types, "The supplied date time doesn't contain a day" , STR("Oe" ), arg); |
| 217 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OE" ), arg); |
| 218 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Of" ), arg); |
| 219 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OF" ), arg); |
| 220 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Og" ), arg); |
| 221 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OG" ), arg); |
| 222 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oh" ), arg); |
| 223 | check_invalid_type(valid_types, "The supplied date time doesn't contain an hour" , STR("OH" ), arg); |
| 224 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oi" ), arg); |
| 225 | check_invalid_type(valid_types, "The supplied date time doesn't contain an hour" , STR("OI" ), arg); |
| 226 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oj" ), arg); |
| 227 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OJ" ), arg); |
| 228 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ok" ), arg); |
| 229 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OK" ), arg); |
| 230 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ol" ), arg); |
| 231 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OL" ), arg); |
| 232 | check_invalid_type(valid_types, "The supplied date time doesn't contain a month" , STR("Om" ), arg); |
| 233 | check_invalid_type(valid_types, "The supplied date time doesn't contain a minute" , STR("OM" ), arg); |
| 234 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("On" ), arg); |
| 235 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("ON" ), arg); |
| 236 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oo" ), arg); |
| 237 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OO" ), arg); |
| 238 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Op" ), arg); |
| 239 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OP" ), arg); |
| 240 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Oq" ), arg); |
| 241 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OQ" ), arg); |
| 242 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Or" ), arg); |
| 243 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OR" ), arg); |
| 244 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Os" ), arg); |
| 245 | check_invalid_type(valid_types, "The supplied date time doesn't contain a second" , STR("OS" ), arg); |
| 246 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ot" ), arg); |
| 247 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OT" ), arg); |
| 248 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("Ou" ), arg); |
| 249 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("OU" ), arg); |
| 250 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ov" ), arg); |
| 251 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("OV" ), arg); |
| 252 | check_invalid_type(valid_types, "The supplied date time doesn't contain a weekday" , STR("Ow" ), arg); |
| 253 | check_invalid_type(valid_types, "The supplied date time doesn't contain a date" , STR("OW" ), arg); |
| 254 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("Ox" ), arg); |
| 255 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OX" ), arg); |
| 256 | check_invalid_type(valid_types, "The supplied date time doesn't contain a year" , STR("Oy" ), arg); |
| 257 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OY" ), arg); |
| 258 | check_invalid_type(valid_types, "The supplied date time doesn't contain a time zone" , STR("Oz" ), arg); |
| 259 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("OZ" ), arg); |
| 260 | check_invalid_type(valid_types, "The date time type specifier for modifier O is invalid" , STR("O%" ), arg); |
| 261 | } |
| 262 | |
| 263 | #endif // TEST_STD_TIME_TIME_SYN_FORMATTER_TESTS_H |
| 264 | |