brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.4 KiB · d8ed015 Raw
375 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef TEST_STD_UTILITIES_FORMAT_FORMAT_TUPLE_FORMAT_TESTS_H10#define TEST_STD_UTILITIES_FORMAT_FORMAT_TUPLE_FORMAT_TESTS_H11 12#include <concepts>13#include <format>14#include <tuple>15 16#include "format.functions.common.h"17 18enum class color { black, red, gold };19 20template <class CharT>21struct std::formatter<color, CharT> : std::formatter<basic_string_view<CharT>, CharT> {22  static constexpr basic_string_view<CharT> color_names[] = {SV("black"), SV("red"), SV("gold")};23  auto format(color c, auto& ctx) const {24    return formatter<basic_string_view<CharT>, CharT>::format(color_names[static_cast<int>(c)], ctx);25  }26};27 28//29// Generic tests for a tuple and pair with two elements.30//31template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>32void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {33  check(SV("(42, 99)"), SV("{}"), input);34  check(SV("(42, 99)^42"), SV("{}^42"), input);35  check(SV("(42, 99)^42"), SV("{:}^42"), input);36 37  // *** align-fill & width ***38  check(SV("(42, 99)     "), SV("{:13}"), input);39  check(SV("(42, 99)*****"), SV("{:*<13}"), input);40  check(SV("__(42, 99)___"), SV("{:_^13}"), input);41  check(SV("#####(42, 99)"), SV("{:#>13}"), input);42 43  check(SV("(42, 99)     "), SV("{:{}}"), input, 13);44  check(SV("(42, 99)*****"), SV("{:*<{}}"), input, 13);45  check(SV("__(42, 99)___"), SV("{:_^{}}"), input, 13);46  check(SV("#####(42, 99)"), SV("{:#>{}}"), input, 13);47 48  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);49  check_exception("The fill option contains an invalid value", SV("{:{<}"), input);50 51  // *** sign ***52  check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);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 56  // *** alternate form ***57  check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);58 59  // *** zero-padding ***60  check_exception("The width option should not have a leading zero", SV("{:0}"), input);61 62  // *** precision ***63  check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);64 65  // *** locale-specific form ***66  check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);67 68  // *** type ***69  check(SV("__42: 99___"), SV("{:_^11m}"), input);70  check(SV("__42, 99___"), SV("{:_^11n}"), input);71 72  for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {73    check_exception("The format specifier should consume the input or end with a '}'",74                    std::basic_string_view{STR("{:") + c + STR("}")},75                    input);76  }77}78 79template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>80void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {81  check(SV("(42, \"hello\")"), SV("{}"), input);82  check(SV("(42, \"hello\")^42"), SV("{}^42"), input);83  check(SV("(42, \"hello\")^42"), SV("{:}^42"), input);84 85  // *** align-fill & width ***86  check(SV("(42, \"hello\")     "), SV("{:18}"), input);87  check(SV("(42, \"hello\")*****"), SV("{:*<18}"), input);88  check(SV("__(42, \"hello\")___"), SV("{:_^18}"), input);89  check(SV("#####(42, \"hello\")"), SV("{:#>18}"), input);90 91  check(SV("(42, \"hello\")     "), SV("{:{}}"), input, 18);92  check(SV("(42, \"hello\")*****"), SV("{:*<{}}"), input, 18);93  check(SV("__(42, \"hello\")___"), SV("{:_^{}}"), input, 18);94  check(SV("#####(42, \"hello\")"), SV("{:#>{}}"), input, 18);95 96  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);97  check_exception("The fill option contains an invalid value", SV("{:{<}"), input);98 99  // *** sign ***100  check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);101  check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);102  check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);103 104  // *** alternate form ***105  check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);106 107  // *** zero-padding ***108  check_exception("The width option should not have a leading zero", SV("{:0}"), input);109 110  // *** precision ***111  check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);112 113  // *** locale-specific form ***114  check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);115 116  // *** type ***117  check(SV("__42: \"hello\"___"), SV("{:_^16m}"), input);118  check(SV("__42, \"hello\"___"), SV("{:_^16n}"), input);119 120  for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {121    check_exception("The format specifier should consume the input or end with a '}'",122                    std::basic_string_view{STR("{:") + c + STR("}")},123                    input);124  }125}126 127template <class CharT, class TestFunction, class TupleOrPair>128void test_escaping(TestFunction check, TupleOrPair&& input) {129  static_assert(std::same_as<std::remove_cvref_t<decltype(std::get<0>(input))>, CharT>);130  static_assert(std::same_as<std::remove_cvref_t<decltype(std::get<1>(input))>, std::basic_string<CharT>>);131 132  check(SV(R"(('*', ""))"), SV("{}"), input);133 134  // Char135  std::get<0>(input) = CharT('\t');136  check(SV(R"(('\t', ""))"), SV("{}"), input);137  std::get<0>(input) = CharT('\n');138  check(SV(R"(('\n', ""))"), SV("{}"), input);139  std::get<0>(input) = CharT('\0');140  check(SV(R"(('\u{0}', ""))"), SV("{}"), input);141 142  // String143  std::get<0>(input) = CharT('*');144  std::get<1>(input) = SV("hellö");145  check(SV("('*', \"hellö\")"), SV("{}"), input);146}147 148//149// pair tests150//151 152template <class CharT, class TestFunction, class ExceptionTest>153void test_pair_int_int(TestFunction check, ExceptionTest check_exception) {154  test_tuple_or_pair_int_int<CharT>(check, check_exception, std::make_pair(42, 99));155}156 157template <class CharT, class TestFunction, class ExceptionTest>158void test_pair_int_string(TestFunction check, ExceptionTest check_exception) {159  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_pair(42, SV("hello")));160  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_pair(42, STR("hello")));161  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_pair(42, CSTR("hello")));162}163 164//165// tuple tests166//167 168template <class CharT, class TestFunction, class ExceptionTest>169void test_tuple_int(TestFunction check, ExceptionTest check_exception) {170  auto input = std::make_tuple(42);171 172  check(SV("(42)"), SV("{}"), input);173  check(SV("(42)^42"), SV("{}^42"), input);174  check(SV("(42)^42"), SV("{:}^42"), input);175 176  // *** align-fill & width ***177  check(SV("(42)     "), SV("{:9}"), input);178  check(SV("(42)*****"), SV("{:*<9}"), input);179  check(SV("__(42)___"), SV("{:_^9}"), input);180  check(SV("#####(42)"), SV("{:#>9}"), input);181 182  check(SV("(42)     "), SV("{:{}}"), input, 9);183  check(SV("(42)*****"), SV("{:*<{}}"), input, 9);184  check(SV("__(42)___"), SV("{:_^{}}"), input, 9);185  check(SV("#####(42)"), SV("{:#>{}}"), input, 9);186 187  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);188  check_exception("The fill option contains an invalid value", SV("{:{<}"), input);189 190  // *** sign ***191  check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);192  check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);193  check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);194 195  // *** alternate form ***196  check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);197 198  // *** zero-padding ***199  check_exception("The width option should not have a leading zero", SV("{:0}"), input);200 201  // *** precision ***202  check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);203 204  // *** locale-specific form ***205  check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);206 207  // *** type ***208  check_exception("Type m requires a pair or a tuple with two elements", SV("{:m}"), input);209  check(SV("__42___"), SV("{:_^7n}"), input);210 211  for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {212    check_exception("The format specifier should consume the input or end with a '}'",213                    std::basic_string_view{STR("{:") + c + STR("}")},214                    input);215  }216}217 218template <class CharT, class TestFunction, class ExceptionTest>219void test_tuple_int_string_color(TestFunction check, ExceptionTest check_exception) {220  const auto input = std::make_tuple(42, SV("hello"), color::red);221 222  check(SV("(42, \"hello\", \"red\")"), SV("{}"), input);223  check(SV("(42, \"hello\", \"red\")^42"), SV("{}^42"), input);224  check(SV("(42, \"hello\", \"red\")^42"), SV("{:}^42"), input);225 226  // *** align-fill & width ***227  check(SV("(42, \"hello\", \"red\")     "), SV("{:25}"), input);228  check(SV("(42, \"hello\", \"red\")*****"), SV("{:*<25}"), input);229  check(SV("__(42, \"hello\", \"red\")___"), SV("{:_^25}"), input);230  check(SV("#####(42, \"hello\", \"red\")"), SV("{:#>25}"), input);231 232  check(SV("(42, \"hello\", \"red\")     "), SV("{:{}}"), input, 25);233  check(SV("(42, \"hello\", \"red\")*****"), SV("{:*<{}}"), input, 25);234  check(SV("__(42, \"hello\", \"red\")___"), SV("{:_^{}}"), input, 25);235  check(SV("#####(42, \"hello\", \"red\")"), SV("{:#>{}}"), input, 25);236 237  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);238  check_exception("The fill option contains an invalid value", SV("{:{<}"), input);239 240  // *** sign ***241  check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);242  check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);243  check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);244 245  // *** alternate form ***246  check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);247 248  // *** zero-padding ***249  check_exception("The width option should not have a leading zero", SV("{:0}"), input);250 251  // *** precision ***252  check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);253 254  // *** locale-specific form ***255  check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);256 257  // *** type ***258  check_exception("Type m requires a pair or a tuple with two elements", SV("{:m}"), input);259  check(SV("__42, \"hello\", \"red\"___"), SV("{:_^23n}"), input);260 261  for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {262    check_exception("The format specifier should consume the input or end with a '}'",263                    std::basic_string_view{STR("{:") + c + STR("}")},264                    input);265  }266}267 268template <class CharT, class TestFunction, class ExceptionTest>269void test_tuple_int_int(TestFunction check, ExceptionTest check_exception) {270  test_tuple_or_pair_int_int<CharT>(check, check_exception, std::make_tuple(42, 99));271}272 273template <class CharT, class TestFunction, class ExceptionTest>274void test_tuple_int_string(TestFunction check, ExceptionTest check_exception) {275  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_tuple(42, SV("hello")));276  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_tuple(42, STR("hello")));277  test_tuple_or_pair_int_string<CharT>(check, check_exception, std::make_tuple(42, CSTR("hello")));278}279 280//281// nested tests282//283 284template <class CharT, class TestFunction, class ExceptionTest, class Nested>285void test_nested(TestFunction check, ExceptionTest check_exception, Nested&& input) {286  // [format.formatter.spec]/2287  //   A debug-enabled specialization of formatter additionally provides a288  //   public, constexpr, non-static member function set_debug_format()289  //   which modifies the state of the formatter to be as if the type of the290  //   std-format-spec parsed by the last call to parse were ?.291  // pair and tuple are not debug-enabled specializations to the292  // set_debug_format is not propagated. The paper293  //   P2733 Fix handling of empty specifiers in std::format294  // addressed this.295 296  check(SV("(42, (\"hello\", \"red\"))"), SV("{}"), input);297  check(SV("(42, (\"hello\", \"red\"))^42"), SV("{}^42"), input);298  check(SV("(42, (\"hello\", \"red\"))^42"), SV("{:}^42"), input);299 300  // *** align-fill & width ***301  check(SV("(42, (\"hello\", \"red\"))     "), SV("{:27}"), input);302  check(SV("(42, (\"hello\", \"red\"))*****"), SV("{:*<27}"), input);303  check(SV("__(42, (\"hello\", \"red\"))___"), SV("{:_^27}"), input);304  check(SV("#####(42, (\"hello\", \"red\"))"), SV("{:#>27}"), input);305 306  check(SV("(42, (\"hello\", \"red\"))     "), SV("{:{}}"), input, 27);307  check(SV("(42, (\"hello\", \"red\"))*****"), SV("{:*<{}}"), input, 27);308  check(SV("__(42, (\"hello\", \"red\"))___"), SV("{:_^{}}"), input, 27);309  check(SV("#####(42, (\"hello\", \"red\"))"), SV("{:#>{}}"), input, 27);310 311  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);312  check_exception("The fill option contains an invalid value", SV("{:{<}"), input);313 314  // *** sign ***315  check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);316  check_exception("The format specifier should consume the input or end with a '}'", SV("{:+}"), input);317  check_exception("The format specifier should consume the input or end with a '}'", SV("{: }"), input);318 319  // *** alternate form ***320  check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);321 322  // *** zero-padding ***323  check_exception("The width option should not have a leading zero", SV("{:0}"), input);324 325  // *** precision ***326  check_exception("The format specifier should consume the input or end with a '}'", SV("{:.}"), input);327 328  // *** locale-specific form ***329  check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);330 331  // *** type ***332  check(SV("__42: (\"hello\", \"red\")___"), SV("{:_^25m}"), input);333  check(SV("__42, (\"hello\", \"red\")___"), SV("{:_^25n}"), input);334 335  for (CharT c : SV("aAbBcdeEfFgGopPsxX?")) {336    check_exception("The format specifier should consume the input or end with a '}'",337                    std::basic_string_view{STR("{:") + c + STR("}")},338                    input);339  }340}341 342template <class CharT, class TestFunction, class ExceptionTest>343void run_tests(TestFunction check, ExceptionTest check_exception) {344  test_pair_int_int<CharT>(check, check_exception);345  test_pair_int_string<CharT>(check, check_exception);346 347  test_tuple_int<CharT>(check, check_exception);348  test_tuple_int_int<CharT>(check, check_exception);349  test_tuple_int_string<CharT>(check, check_exception);350  test_tuple_int_string_color<CharT>(check, check_exception);351 352  test_nested<CharT>(check, check_exception, std::make_pair(42, std::make_pair(SV("hello"), color::red)));353  test_nested<CharT>(check, check_exception, std::make_pair(42, std::make_tuple(SV("hello"), color::red)));354  test_nested<CharT>(check, check_exception, std::make_tuple(42, std::make_pair(SV("hello"), color::red)));355  test_nested<CharT>(check, check_exception, std::make_tuple(42, std::make_tuple(SV("hello"), color::red)));356 357  test_escaping<CharT>(check, std::make_pair(CharT('*'), STR("")));358  test_escaping<CharT>(check, std::make_tuple(CharT('*'), STR("")));359 360  // Test const ref-qualified types.361  // clang-format off362  check(SV("(42)"), SV("{}"), std::tuple<      int  >{42});363  check(SV("(42)"), SV("{}"), std::tuple<const int  >{42});364 365  int answer = 42;366  check(SV("(42)"), SV("{}"), std::tuple<      int& >{answer});367  check(SV("(42)"), SV("{}"), std::tuple<const int& >{answer});368 369  check(SV("(42)"), SV("{}"), std::tuple<      int&&>{42});370  check(SV("(42)"), SV("{}"), std::tuple<const int&&>{42});371  // clang-format on372}373 374#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_TUPLE_FORMAT_TESTS_H375