#include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_format.h" namespace absl { namespace str_format_internal { namespace { std::string ConvToString(Conv conv) { std::string out; #define CONV_SET_CASE(c) \ if (Contains(conv, Conv::c)) out += #c; ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, ) #undef CONV_SET_CASE if (Contains(conv, Conv::star)) out += "*"; return out; } TEST(StrFormatChecker, ArgumentToConv) { Conv conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "s"); conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "sp"); conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "fFeEgGaA"); conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "cdiouxXfFeEgGaA*"); conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "p"); } #ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER struct Case { bool result; const char* format; }; template constexpr Case ValidFormat(const char* format) { return {ValidFormatImpl()...>(format), format}; } TEST(StrFormatChecker, ValidFormat) { // We want to make sure these expressions are constexpr and they have the // expected value. // If they are not constexpr the attribute will just ignore them and not give // a compile time error. enum e {}; enum class e2 {}; constexpr Case trues[] = { ValidFormat<>("abc"), // ValidFormat("%d"), // ValidFormat("%d"), // ValidFormat("%% %d"), // ValidFormat("%ld"), // ValidFormat("%lld"), // ValidFormat("%s"), // ValidFormat("%10s"), // ValidFormat("%.10x"), // ValidFormat("%*.3x"), // ValidFormat("%1.d"), // ValidFormat("%.d"), // ValidFormat("%d %g"), // ValidFormat("%*s"), // ValidFormat("%.*f"), // ValidFormat("%p %p"), // ValidFormat( "string_view=%s const char*=%s double=%f void*=%p)"), ValidFormat("%% %1$d"), // ValidFormat("%1$ld"), // ValidFormat("%1$lld"), // ValidFormat("%1$s"), // ValidFormat("%1$10s"), // ValidFormat("%1$.10x"), // ValidFormat("%1$*1$.*1$d"), // ValidFormat("%1$*2$.3x"), // ValidFormat("%1$1.d"), // ValidFormat("%1$.d"), // ValidFormat("%2$d %1$g"), // ValidFormat("%2$*1$s"), // ValidFormat("%2$.*1$f"), // ValidFormat( "string_view=%2$s const char*=%3$s double=%4$f void*=%1$p " "repeat=%3$s)")}; for (Case c : trues) { EXPECT_TRUE(c.result) << c.format; } constexpr Case falses[] = { ValidFormat(""), // ValidFormat("%s"), // ValidFormat("%s"), // ValidFormat<>("%s"), // ValidFormat<>("%r"), // ValidFormat("%s"), // ValidFormat("%.1.d"), // ValidFormat("%*1d"), // ValidFormat("%1-d"), // ValidFormat("%*s"), // ValidFormat("%*d"), // ValidFormat("%p"), // ValidFormat("%d"), // ValidFormat<>("%3$d"), // ValidFormat<>("%1$r"), // ValidFormat("%1$s"), // ValidFormat("%1$.1.d"), // ValidFormat("%1$*2$1d"), // ValidFormat("%1$1-d"), // ValidFormat("%2$*1$s"), // ValidFormat("%1$p"), ValidFormat("%d %2$d"), // }; for (Case c : falses) { EXPECT_FALSE(c.result) << c.format; } } TEST(StrFormatChecker, LongFormat) { #define CHARS_X_40 "1234567890123456789012345678901234567890" #define CHARS_X_400 \ CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 CHARS_X_40 \ CHARS_X_40 CHARS_X_40 CHARS_X_40 #define CHARS_X_4000 \ CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 \ CHARS_X_400 CHARS_X_400 CHARS_X_400 CHARS_X_400 constexpr char long_format[] = CHARS_X_4000 "%d" CHARS_X_4000 "%s" CHARS_X_4000; constexpr bool is_valid = ValidFormat(long_format).result; EXPECT_TRUE(is_valid); } #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER } // namespace } // namespace str_format_internal } // namespace absl