diff --git a/libcxx/test/std/utilities/format/format.functions/format.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format.locale.pass.cpp @@ -47,11 +47,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/format.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format.pass.cpp @@ -56,11 +56,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h --- a/libcxx/test/std/utilities/format/format.functions/format_tests.h +++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h @@ -17,126 +17,15 @@ #include #include -#include "make_string.h" #include "string_literal.h" #include "test_macros.h" +#include "format.functions.common.h" // In this file the following template types are used: // TestFunction must be callable as check(expected-result, string-to-format, args-to-format...) // ExceptionTest must be callable as check_exception(expected-exception, string-to-format, args-to-format...) -#define STR(S) MAKE_STRING(CharT, S) -#define SV(S) MAKE_STRING_VIEW(CharT, S) -#define CSTR(S) MAKE_CSTRING(CharT, S) - -template -struct context {}; - -template <> -struct context { - using type = std::format_context; -}; - -#ifndef TEST_HAS_NO_WIDE_CHARACTERS -template <> -struct context { - using type = std::wformat_context; -}; -#endif - -template -using context_t = typename context::type; - -// A user-defined type used to test the handle formatter. -enum class status : uint16_t { foo = 0xAAAA, bar = 0x5555, foobar = 0xAA55 }; - -// The formatter for a user-defined type used to test the handle formatter. -template -struct std::formatter { - int type = 0; - - constexpr auto parse(basic_format_parse_context& parse_ctx) -> decltype(parse_ctx.begin()) { - auto begin = parse_ctx.begin(); - auto end = parse_ctx.end(); - if (begin == end) - return begin; - - switch (*begin) { - case CharT('x'): - break; - case CharT('X'): - type = 1; - break; - case CharT('s'): - type = 2; - break; - case CharT('}'): - return begin; - default: - throw_format_error("The format-spec type has a type not supported for a status argument"); - } - - ++begin; - if (begin != end && *begin != CharT('}')) - throw_format_error("The format-spec should consume the input or end with a '}'"); - - return begin; - } - - template - auto format(status s, basic_format_context& ctx) const -> decltype(ctx.out()) { - const char* names[] = {"foo", "bar", "foobar"}; - char buffer[7]; - const char* begin = names[0]; - const char* end = names[0]; - switch (type) { - case 0: - begin = buffer; - buffer[0] = '0'; - buffer[1] = 'x'; - end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; - buffer[6] = '\0'; - break; - - case 1: - begin = buffer; - buffer[0] = '0'; - buffer[1] = 'X'; - end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; - std::transform(static_cast(&buffer[2]), end, &buffer[2], [](char c) { - return static_cast(std::toupper(c)); }); - buffer[6] = '\0'; - break; - - case 2: - switch (s) { - case status::foo: - begin = names[0]; - break; - case status::bar: - begin = names[1]; - break; - case status::foobar: - begin = names[2]; - break; - } - end = begin + strlen(begin); - break; - } - - return std::copy(begin, end, ctx.out()); - } - -private: - void throw_format_error(const char* s) { -#ifndef TEST_HAS_NO_EXCEPTIONS - throw std::format_error(s); -#else - (void)s; - std::abort(); -#endif - } -}; +enum class execution_modus { partial, full }; template std::vector> invalid_types(std::string_view valid) { @@ -2722,7 +2611,7 @@ check(std::basic_string_view{fill + str}, SV("{:*>{}}"), str, minimum + str.size()); } -template +template void format_tests(TestFunction check, ExceptionTest check_exception) { // *** Test escaping *** @@ -2797,8 +2686,10 @@ CharT('A'), CharT('Z'), CharT('!')); - format_test_char(check, check_exception); - format_test_char_as_integer(check, check_exception); + if constexpr (modus == execution_modus::full) { + format_test_char(check, check_exception); + format_test_char_as_integer(check, check_exception); + } // *** Test string format argument *** { @@ -2820,13 +2711,16 @@ std::basic_string_view data = buffer; check(SV("hello world"), SV("hello {}"), data); } - format_string_tests(check, check_exception); + if constexpr (modus == execution_modus::full) + format_string_tests(check, check_exception); // *** Test Boolean format argument *** check(SV("hello false true"), SV("hello {} {}"), false, true); - format_test_bool(check, check_exception); - format_test_bool_as_integer(check, check_exception); + if constexpr (modus == execution_modus::full) { + format_test_bool(check, check_exception); + format_test_bool_as_integer(check, check_exception); + } // *** Test signed integral format argument *** check(SV("hello 42"), SV("hello {}"), static_cast(42)); @@ -2837,7 +2731,8 @@ #ifndef TEST_HAS_NO_INT128 check(SV("hello 42"), SV("hello {}"), static_cast<__int128_t>(42)); #endif - format_test_signed_integer(check, check_exception); + if constexpr (modus == execution_modus::full) + format_test_signed_integer(check, check_exception); // ** Test unsigned integral format argument *** check(SV("hello 42"), SV("hello {}"), static_cast(42)); @@ -2848,25 +2743,29 @@ #ifndef TEST_HAS_NO_INT128 check(SV("hello 42"), SV("hello {}"), static_cast<__uint128_t>(42)); #endif - format_test_unsigned_integer(check, check_exception); + if constexpr (modus == execution_modus::full) + format_test_unsigned_integer(check, check_exception); // *** Test floating point format argument *** check(SV("hello 42"), SV("hello {}"), static_cast(42)); check(SV("hello 42"), SV("hello {}"), static_cast(42)); check(SV("hello 42"), SV("hello {}"), static_cast(42)); - format_test_floating_point(check, check_exception); + if constexpr (modus == execution_modus::full) + format_test_floating_point(check, check_exception); // *** Test pointer formater argument *** check(SV("hello 0x0"), SV("hello {}"), nullptr); check(SV("hello 0x42"), SV("hello {}"), reinterpret_cast(0x42)); check(SV("hello 0x42"), SV("hello {}"), reinterpret_cast(0x42)); - format_test_pointer(check, check_exception); + if constexpr (modus == execution_modus::full) + format_test_pointer(check, check_exception); // *** Test handle formatter argument *** format_test_handle(check, check_exception); // *** Test the interal buffer optimizations *** - format_test_buffer_optimizations(check); + if constexpr (modus == execution_modus::full) + format_test_buffer_optimizations(check); } #ifndef TEST_HAS_NO_WIDE_CHARACTERS @@ -2877,4 +2776,4 @@ } #endif -#endif +#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H diff --git a/libcxx/test/std/utilities/format/format.functions/format_to.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format_to.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format_to.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format_to.locale.pass.cpp @@ -70,11 +70,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/format_to.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format_to.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format_to.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format_to.pass.cpp @@ -66,11 +66,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/format_to_n.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format_to_n.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format_to_n.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format_to_n.locale.pass.cpp @@ -106,11 +106,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/format_to_n.pass.cpp b/libcxx/test/std/utilities/format/format.functions/format_to_n.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/format_to_n.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/format_to_n.pass.cpp @@ -100,11 +100,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/formatted_size.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/formatted_size.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/formatted_size.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/formatted_size.locale.pass.cpp @@ -44,11 +44,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/formatted_size.pass.cpp b/libcxx/test/std/utilities/format/format.functions/formatted_size.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/formatted_size.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/formatted_size.pass.cpp @@ -41,11 +41,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp @@ -48,11 +48,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp @@ -22,6 +22,7 @@ #include "test_macros.h" #include "format_tests.h" #include "string_literal.h" + auto test = []( std::basic_string_view expected, std::basic_string_view fmt, Args&&... args) constexpr { std::basic_string out = std::vformat(fmt, std::make_format_args>(args...)); @@ -46,11 +47,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp @@ -77,11 +77,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp @@ -74,11 +74,11 @@ }; int main(int, char**) { - format_tests(test, test_exception); + format_tests(test, test_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS format_tests_char_to_wchar_t(test); - format_tests(test, test_exception); + format_tests(test, test_exception); #endif return 0; diff --git a/libcxx/test/support/format.functions.common.h b/libcxx/test/support/format.functions.common.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/format.functions.common.h @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_SUPPORT_FORMAT_FUNCTIONS_COMMON_H +#define TEST_SUPPORT_FORMAT_FUNCTIONS_COMMON_H + +// Contains the common part of the formatter tests for different papers. + +#include + +#include "make_string.h" + +#define STR(S) MAKE_STRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) +#define CSTR(S) MAKE_CSTRING(CharT, S) + +template +struct context {}; + +template <> +struct context { + using type = std::format_context; +}; + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +template <> +struct context { + using type = std::wformat_context; +}; +#endif + +template +using context_t = typename context::type; + +// A user-defined type used to test the handle formatter. +enum class status : uint16_t { foo = 0xAAAA, bar = 0x5555, foobar = 0xAA55 }; + +// The formatter for a user-defined type used to test the handle formatter. +template +struct std::formatter { + int type = 0; + + constexpr auto parse(basic_format_parse_context& parse_ctx) -> decltype(parse_ctx.begin()) { + auto begin = parse_ctx.begin(); + auto end = parse_ctx.end(); + if (begin == end) + return begin; + + switch (*begin) { + case CharT('x'): + break; + case CharT('X'): + type = 1; + break; + case CharT('s'): + type = 2; + break; + case CharT('}'): + return begin; + default: + throw_format_error("The format-spec type has a type not supported for a status argument"); + } + + ++begin; + if (begin != end && *begin != CharT('}')) + throw_format_error("The format-spec should consume the input or end with a '}'"); + + return begin; + } + + template + auto format(status s, basic_format_context& ctx) const -> decltype(ctx.out()) { + const char* names[] = {"foo", "bar", "foobar"}; + char buffer[7]; + const char* begin = names[0]; + const char* end = names[0]; + switch (type) { + case 0: + begin = buffer; + buffer[0] = '0'; + buffer[1] = 'x'; + end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; + buffer[6] = '\0'; + break; + + case 1: + begin = buffer; + buffer[0] = '0'; + buffer[1] = 'X'; + end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; + std::transform(static_cast(&buffer[2]), end, &buffer[2], [](char c) { + return static_cast(std::toupper(c)); }); + buffer[6] = '\0'; + break; + + case 2: + switch (s) { + case status::foo: + begin = names[0]; + break; + case status::bar: + begin = names[1]; + break; + case status::foobar: + begin = names[2]; + break; + } + end = begin + strlen(begin); + break; + } + + return std::copy(begin, end, ctx.out()); + } + +private: + void throw_format_error(const char* s) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::format_error(s); +#else + (void)s; + std::abort(); +#endif + } +}; + +#endif // TEST_SUPPORT_FORMAT_FUNCTIONS_COMMON_H