Add opt out for built-in types

This commit is contained in:
Victor Zverovich
2024-08-25 09:20:40 -07:00
parent 5a0a37340c
commit 377cf203e3
11 changed files with 149 additions and 81 deletions

View File

@@ -372,15 +372,19 @@ VISIT_TYPE(long, long long);
VISIT_TYPE(unsigned long, unsigned long long);
#endif
#define CHECK_ARG(Char, expected, value) \
{ \
testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
EXPECT_CALL(visitor, visit(expected)); \
using iterator = fmt::basic_appender<Char>; \
auto var = value; \
fmt::detail::make_arg<fmt::basic_format_context<iterator, Char>>(var) \
.visit(visitor); \
}
#if FMT_BUILTIN_TYPES
# define CHECK_ARG(Char, expected, value) \
{ \
testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
EXPECT_CALL(visitor, visit(expected)); \
using iterator = fmt::basic_appender<Char>; \
auto var = value; \
fmt::detail::make_arg<fmt::basic_format_context<iterator, Char>>(var) \
.visit(visitor); \
}
#else
# define CHECK_ARG(Char, expected, value)
#endif
#define CHECK_ARG_SIMPLE(value) \
{ \
@@ -391,10 +395,14 @@ VISIT_TYPE(unsigned long, unsigned long long);
template <typename T> class numeric_arg_test : public testing::Test {};
#if FMT_BUILTIN_TYPES
using test_types =
testing::Types<bool, signed char, unsigned char, short, unsigned short, int,
unsigned, long, unsigned long, long long, unsigned long long,
float, double, long double>;
#else
using test_types = testing::Types<int>;
#endif
TYPED_TEST_SUITE(numeric_arg_test, test_types);
template <typename T, fmt::enable_if_t<std::is_integral<T>::value, int> = 0>
@@ -757,20 +765,12 @@ TEST(base_test, format_to_array) {
EXPECT_TRUE(result.truncated);
EXPECT_EQ("ABCD", fmt::string_view(buffer, 4));
result = fmt::format_to(buffer, "{}", std::string(1000, '*'));
result = fmt::format_to(buffer, "{}", std::string(1000, '*').c_str());
EXPECT_EQ(4, std::distance(&buffer[0], result.out));
EXPECT_TRUE(result.truncated);
EXPECT_EQ("****", fmt::string_view(buffer, 4));
}
#ifdef __cpp_lib_byte
TEST(base_test, format_byte) {
auto s = std::string();
fmt::format_to(std::back_inserter(s), "{}", std::byte(42));
EXPECT_EQ(s, "42");
}
#endif
// Test that check is not found by ADL.
template <typename T> void check(T);
TEST(base_test, adl_check) {

View File

@@ -753,7 +753,7 @@ TEST(chrono_test, weekday) {
std::locale::global(loc);
auto sat = fmt::weekday(6);
auto tm = std::tm();
tm.tm_wday = static_cast<int>(sat.c_encoding());
@@ -795,20 +795,14 @@ TEST(chrono_test, cpp20_duration_subsecond_support) {
"01.234000");
EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}),
"-01.234000");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12345}),
"12.34");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12375}),
"12.37");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12345}), "12.34");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12375}), "12.37");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{-12375}),
"-12.37");
EXPECT_EQ(fmt::format("{:.0%S}", std::chrono::milliseconds{12054}),
"12");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{99999}),
"39.99");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{1000}),
"01.00");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::milliseconds{1}),
"00.001");
EXPECT_EQ(fmt::format("{:.0%S}", std::chrono::milliseconds{12054}), "12");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{99999}), "39.99");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{1000}), "01.00");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::milliseconds{1}), "00.001");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000");
EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123");
@@ -1032,7 +1026,7 @@ TEST(chrono_test, out_of_range) {
TEST(chrono_test, year_month_day) {
auto loc = get_locale("es_ES.UTF-8");
std::locale::global(loc);
auto year = fmt::year(2024);
auto month = fmt::month(1);
auto day = fmt::day(1);

View File

@@ -810,7 +810,7 @@ TEST(format_test, hash_flag) {
EXPECT_EQ(fmt::format("{:#.2g}", 0.5), "0.50");
EXPECT_EQ(fmt::format("{:#.0f}", 0.5), "0.");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#"), 'c'), format_error,
"missing '}' in format string");
"invalid format specifier for char");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#}"), 'c'), format_error,
"invalid format specifier for char");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#}"), "abc"), format_error,
@@ -831,7 +831,7 @@ TEST(format_test, zero_flag) {
EXPECT_EQ(fmt::format("{0:07}", -42.0), "-000042");
EXPECT_EQ(fmt::format("{0:07}", -42.0l), "-000042");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:0"), 'c'), format_error,
"missing '}' in format string");
"invalid format specifier for char");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:05}"), 'c'), format_error,
"invalid format specifier for char");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:05}"), "abc"), format_error,
@@ -878,6 +878,10 @@ TEST(format_test, width) {
EXPECT_EQ(fmt::format("{:>06.0f}", 0.00884311), " 0");
}
auto bad_dynamic_spec_msg = FMT_BUILTIN_TYPES
? "width/precision is out of range"
: "width/precision is not integer";
TEST(format_test, runtime_width) {
auto int_maxer = std::to_string(INT_MAX + 1u);
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{" + int_maxer), 0),
@@ -902,16 +906,16 @@ TEST(format_test, runtime_width) {
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, -1), format_error,
"width/precision is out of range");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1u)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, -1l), format_error,
"width/precision is out of range");
bad_dynamic_spec_msg);
if (fmt::detail::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (value + 1)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
}
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1ul)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, '0'), format_error,
"width/precision is not integer");
@@ -1127,16 +1131,16 @@ TEST(format_test, runtime_precision) {
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, -1),
format_error, "width/precision is out of range");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, (INT_MAX + 1u)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, -1l),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
if (fmt::detail::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, (value + 1)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
}
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, (INT_MAX + 1ul)),
format_error, "width/precision is out of range");
format_error, bad_dynamic_spec_msg);
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0.0, '0'),
format_error, "width/precision is not integer");
@@ -2408,6 +2412,7 @@ namespace adl_test {
template <typename... T> void make_format_args(const T&...) = delete;
struct string : std::string {};
auto format_as(const string& s) -> std::string { return s; }
} // namespace adl_test
// Test that formatting functions compile when make_format_args is found by ADL.
@@ -2568,3 +2573,11 @@ TEST(format_test, bitint) {
# endif
}
#endif
#ifdef __cpp_lib_byte
TEST(base_test, format_byte) {
auto s = std::string();
fmt::format_to(std::back_inserter(s), "{}", std::byte(42));
EXPECT_EQ(s, "42");
}
#endif

View File

@@ -429,7 +429,7 @@ TEST(file_test, read) {
}
TEST(file_test, read_error) {
auto test_file = uniq_file_name(__LINE__);
auto test_file = uniq_file_name(__LINE__);
file f(test_file, file::WRONLY | file::CREATE);
char buf;
// We intentionally read from a file opened in the write-only mode to

View File

@@ -111,9 +111,9 @@ TEST(scan_test, invalid_format) {
}
namespace std {
using fmt::scan;
using fmt::scan_error;
}
using fmt::scan;
using fmt::scan_error;
} // namespace std
TEST(scan_test, example) {
// Example from https://wg21.link/p1729r3.

View File

@@ -36,8 +36,10 @@ TEST(std_test, path) {
"Шчучыншчына");
EXPECT_EQ(fmt::format("{}", path(L"\xd800")), "<EFBFBD>");
EXPECT_EQ(fmt::format("{}", path(L"HEAD \xd800 TAIL")), "HEAD <20> TAIL");
EXPECT_EQ(fmt::format("{}", path(L"HEAD \xD83D\xDE00 TAIL")), "HEAD \xF0\x9F\x98\x80 TAIL");
EXPECT_EQ(fmt::format("{}", path(L"HEAD \xD83D\xD83D\xDE00 TAIL")), "HEAD <EFBFBD>\xF0\x9F\x98\x80 TAIL");
EXPECT_EQ(fmt::format("{}", path(L"HEAD \xD83D\xDE00 TAIL")),
"HEAD \xF0\x9F\x98\x80 TAIL");
EXPECT_EQ(fmt::format("{}", path(L"HEAD \xD83D\xD83D\xDE00 TAIL")),
"HEAD <20>\xF0\x9F\x98\x80 TAIL");
EXPECT_EQ(fmt::format("{:?}", path(L"\xd800")), "\"\\ud800\"");
# endif
}

View File

@@ -36,12 +36,11 @@ std::locale do_get_locale(const char* name) {
std::locale get_locale(const char* name, const char* alt_name) {
auto loc = do_get_locale(name);
if (loc == std::locale::classic() && alt_name)
loc = do_get_locale(alt_name);
if (loc == std::locale::classic() && alt_name) loc = do_get_locale(alt_name);
#ifdef __OpenBSD__
// Locales are not working in OpenBSD:
// https://github.com/fmtlib/fmt/issues/3670.
loc = std::locale::classic();
// Locales are not working in OpenBSD:
// https://github.com/fmtlib/fmt/issues/3670.
loc = std::locale::classic();
#endif
if (loc == std::locale::classic())
fmt::print(stderr, "{} locale is missing.\n", name);

View File

@@ -78,7 +78,6 @@ TEST(xchar_test, format) {
EXPECT_EQ(L"z", fmt::format(L"{}", L'z'));
EXPECT_THROW(fmt::format(fmt::runtime(L"{:*\x343E}"), 42), fmt::format_error);
EXPECT_EQ(L"true", fmt::format(L"{}", true));
EXPECT_EQ(L"a", fmt::format(L"{0}", 'a'));
EXPECT_EQ(L"a", fmt::format(L"{0}", L'a'));
EXPECT_EQ(L"Cyrillic letter \x42e",
fmt::format(L"Cyrillic letter {}", L'\x42e'));
@@ -585,7 +584,8 @@ TEST(locale_test, sign) {
TEST(std_test_xchar, complex) {
auto s = fmt::format(L"{}", std::complex<double>(1, 2));
EXPECT_EQ(s, L"(1+2i)");
EXPECT_EQ(fmt::format(L"{:.2f}", std::complex<double>(1, 2)), L"(1.00+2.00i)");
EXPECT_EQ(fmt::format(L"{:.2f}", std::complex<double>(1, 2)),
L"(1.00+2.00i)");
EXPECT_EQ(fmt::format(L"{:8}", std::complex<double>(1, 2)), L"(1+2i) ");
}