diff options
Diffstat (limited to 'test/printf-test.cc')
-rw-r--r-- | test/printf-test.cc | 141 |
1 files changed, 78 insertions, 63 deletions
diff --git a/test/printf-test.cc b/test/printf-test.cc index 2d68fab4..ccd72dcd 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -5,18 +5,19 @@ // // For the license information refer to format.h. +#include "fmt/printf.h" + #include <cctype> #include <climits> #include <cstring> #include "fmt/core.h" -#include "fmt/printf.h" #include "gtest-extra.h" #include "util.h" using fmt::format; using fmt::format_error; -using fmt::internal::max_value; +using fmt::detail::max_value; const unsigned BIG_NUM = INT_MAX + 1u; @@ -112,14 +113,13 @@ TEST(PrintfTest, SwitchArgIndexing) { TEST(PrintfTest, InvalidArgIndex) { EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error, - "argument index out of range"); + "argument not found"); EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error, - "argument index out of range"); + "argument not found"); EXPECT_THROW_MSG(test_sprintf(format("%{}$d", INT_MAX), 42), format_error, - "argument index out of range"); + "argument not found"); - EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error, - "argument index out of range"); + EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error, "argument not found"); EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM), 42), format_error, "number is too big"); } @@ -139,8 +139,11 @@ TEST(PrintfTest, ZeroFlag) { EXPECT_PRINTF("+00042", "%00+6d", 42); + EXPECT_PRINTF(" 42", "%05.d", 42); + EXPECT_PRINTF(" 0042", "%05.4d", 42); + // '0' flag is ignored for non-numeric types. - EXPECT_PRINTF("0000x", "%05c", 'x'); + EXPECT_PRINTF(" x", "%05c", 'x'); } TEST(PrintfTest, PlusFlag) { @@ -151,11 +154,38 @@ TEST(PrintfTest, PlusFlag) { // '+' flag is ignored for non-numeric types. EXPECT_PRINTF("x", "%+c", 'x'); + + // '+' flag wins over space flag + EXPECT_PRINTF("+42", "%+ d", 42); + EXPECT_PRINTF("-42", "%+ d", -42); + EXPECT_PRINTF("+42", "% +d", 42); + EXPECT_PRINTF("-42", "% +d", -42); + EXPECT_PRINTF("+0042", "% +05d", 42); + EXPECT_PRINTF("+0042", "%0+ 5d", 42); + + // '+' flag and space flag are both ignored for non-numeric types. + EXPECT_PRINTF("x", "%+ c", 'x'); + EXPECT_PRINTF("x", "% +c", 'x'); } TEST(PrintfTest, MinusFlag) { EXPECT_PRINTF("abc ", "%-5s", "abc"); EXPECT_PRINTF("abc ", "%0--5s", "abc"); + + EXPECT_PRINTF("7 ", "%-5d", 7); + EXPECT_PRINTF("97 ", "%-5hhi", 'a'); + EXPECT_PRINTF("a ", "%-5c", 'a'); + + // '0' flag is ignored if '-' flag is given + EXPECT_PRINTF("7 ", "%-05d", 7); + EXPECT_PRINTF("7 ", "%0-5d", 7); + EXPECT_PRINTF("a ", "%-05c", 'a'); + EXPECT_PRINTF("a ", "%0-5c", 'a'); + EXPECT_PRINTF("97 ", "%-05hhi", 'a'); + EXPECT_PRINTF("97 ", "%0-5hhi", 'a'); + + // '-' and space flag don't interfere + EXPECT_PRINTF(" 42", "%- d", 42); } TEST(PrintfTest, SpaceFlag) { @@ -221,8 +251,7 @@ TEST(PrintfTest, DynamicWidth) { EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42)); EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error, "width is not integer"); - EXPECT_THROW_MSG(test_sprintf("%*d"), format_error, - "argument index out of range"); + EXPECT_THROW_MSG(test_sprintf("%*d"), format_error, "argument not found"); EXPECT_THROW_MSG(test_sprintf("%*d", BIG_NUM, 42), format_error, "number is too big"); } @@ -258,6 +287,11 @@ TEST(PrintfTest, FloatPrecision) { EXPECT_PRINTF(buffer, "%.3a", 1234.5678); } +TEST(PrintfTest, StringPrecision) { + char test[] = {'H', 'e', 'l', 'l', 'o'}; + EXPECT_EQ(fmt::sprintf("%.4s", test), "Hell"); +} + TEST(PrintfTest, IgnorePrecisionForNonNumericArg) { EXPECT_PRINTF("abc", "%.5s", "abc"); } @@ -267,8 +301,7 @@ TEST(PrintfTest, DynamicPrecision) { EXPECT_EQ("42", test_sprintf("%.*d", -5, 42)); EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error, "precision is not integer"); - EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error, - "argument index out of range"); + EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error, "argument not found"); EXPECT_THROW_MSG(test_sprintf("%.*d", BIG_NUM, 42), format_error, "number is too big"); if (sizeof(long long) != sizeof(int)) { @@ -297,18 +330,18 @@ void TestLength(const char* length_spec, U value) { unsigned long long unsigned_value = 0; // Apply integer promotion to the argument. unsigned long long max = max_value<U>(); - using fmt::internal::const_check; + using fmt::detail::const_check; if (const_check(max <= static_cast<unsigned>(max_value<int>()))) { signed_value = static_cast<int>(value); - unsigned_value = static_cast<unsigned>(value); + unsigned_value = static_cast<unsigned long long>(value); } else if (const_check(max <= max_value<unsigned>())) { signed_value = static_cast<unsigned>(value); - unsigned_value = static_cast<unsigned>(value); + unsigned_value = static_cast<unsigned long long>(value); } if (sizeof(U) <= sizeof(int) && sizeof(int) < sizeof(T)) { signed_value = static_cast<long long>(value); - unsigned_value = - static_cast<typename std::make_unsigned<unsigned>::type>(value); + unsigned_value = static_cast<unsigned long long>( + static_cast<typename std::make_unsigned<unsigned>::type>(value)); } else { signed_value = static_cast<typename make_signed<T>::type>(value); unsigned_value = static_cast<typename std::make_unsigned<T>::type>(value); @@ -366,7 +399,7 @@ TEST(PrintfTest, Length) { TestLength<long long>("ll"); TestLength<unsigned long long>("ll"); TestLength<intmax_t>("j"); - TestLength<std::size_t>("z"); + TestLength<size_t>("z"); TestLength<std::ptrdiff_t>("t"); long double max = max_value<long double>(); EXPECT_PRINTF(fmt::format("{:.6}", max), "%g", max); @@ -446,6 +479,12 @@ TEST(PrintfTest, String) { EXPECT_PRINTF(L" (null)", L"%10s", null_wstr); } +TEST(PrintfTest, UCharString) { + unsigned char str[] = "test"; + unsigned char* pstr = str; + EXPECT_EQ("test", fmt::sprintf("%s", pstr)); +} + TEST(PrintfTest, Pointer) { int n; void* p = &n; @@ -473,9 +512,13 @@ TEST(PrintfTest, Location) { // TODO: test %n } -enum E { A = 42 }; +enum test_enum { answer = 42 }; -TEST(PrintfTest, Enum) { EXPECT_PRINTF("42", "%d", A); } +TEST(PrintfTest, Enum) { + EXPECT_PRINTF("42", "%d", answer); + volatile test_enum volatile_enum = answer; + EXPECT_PRINTF("42", "%d", volatile_enum); +} #if FMT_USE_FCNTL TEST(PrintfTest, Examples) { @@ -564,50 +607,22 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) { #endif } -typedef fmt::printf_arg_formatter<fmt::buffer_range<char>> formatter_t; -typedef fmt::basic_printf_context<formatter_t::iterator, char> context_t; - -// A custom printf argument formatter that doesn't print `-` for floating-point -// values rounded to 0. -class custom_printf_arg_formatter : public formatter_t { - public: - using formatter_t::iterator; - - custom_printf_arg_formatter(formatter_t::iterator iter, - formatter_t::format_specs& specs, context_t& ctx) - : formatter_t(iter, specs, ctx) {} - - using formatter_t::operator(); - -#if FMT_MSC_VER > 0 && FMT_MSC_VER <= 1804 - template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> - iterator operator()(T value){ -#else - iterator operator()(double value) { -#endif - // Comparing a float to 0.0 is safe. - if (round(value * pow(10, specs()->precision)) == 0.0) value = 0; - return formatter_t::operator()(value); -} -}; - -typedef fmt::basic_format_args<context_t> format_args_t; +TEST(PrintfTest, PrintfDetermineOutputSize) { + using backit = std::back_insert_iterator<std::vector<char>>; + using truncated_printf_context = + fmt::basic_printf_context<fmt::detail::truncating_iterator<backit>, char>; -std::string custom_vformat(fmt::string_view format_str, format_args_t args) { - fmt::memory_buffer buffer; - fmt::vprintf<custom_printf_arg_formatter>(buffer, format_str, args); - return std::string(buffer.data(), buffer.size()); -} + auto v = std::vector<char>{}; + auto it = std::back_inserter(v); -template <typename... Args> -std::string custom_format(const char* format_str, const Args&... args) { - auto va = fmt::make_printf_args(args...); - return custom_vformat(format_str, {va}); -} + const auto format_string = "%s"; + const auto format_arg = "Hello"; + const auto expected_size = fmt::sprintf(format_string, format_arg).size(); -TEST(PrintfTest, CustomFormat) { - EXPECT_EQ("0.00", custom_format("%.2f", -.00001)); - EXPECT_EQ("0.00", custom_format("%.2f", .00001)); - EXPECT_EQ("1.00", custom_format("%.2f", 1.00001)); - EXPECT_EQ("-1.00", custom_format("%.2f", -1.00001)); + EXPECT_EQ((truncated_printf_context( + fmt::detail::truncating_iterator<backit>(it, 0), format_string, + fmt::make_format_args<truncated_printf_context>(format_arg)) + .format() + .count()), + expected_size); } |