Home | History | Annotate | Download | only in test
      1 /*
      2  printf tests.
      3 
      4  Copyright (c) 2012-2014, Victor Zverovich
      5  All rights reserved.
      6 
      7  Redistribution and use in source and binary forms, with or without
      8  modification, are permitted provided that the following conditions are met:
      9 
     10  1. Redistributions of source code must retain the above copyright notice, this
     11     list of conditions and the following disclaimer.
     12  2. Redistributions in binary form must reproduce the above copyright notice,
     13     this list of conditions and the following disclaimer in the documentation
     14     and/or other materials provided with the distribution.
     15 
     16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     17  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     20  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     23  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <cctype>
     29 #include <climits>
     30 #include <cstring>
     31 
     32 #include "fmt/printf.h"
     33 #include "fmt/format.h"
     34 #include "gtest-extra.h"
     35 #include "util.h"
     36 
     37 using fmt::format;
     38 using fmt::FormatError;
     39 
     40 const unsigned BIG_NUM = INT_MAX + 1u;
     41 
     42 // Makes format string argument positional.
     43 std::string make_positional(fmt::StringRef format) {
     44   std::string s(format.to_string());
     45   s.replace(s.find('%'), 1, "%1$");
     46   return s;
     47 }
     48 
     49 #define EXPECT_PRINTF(expected_output, format, arg) \
     50   EXPECT_EQ(expected_output, fmt::sprintf(format, arg)) \
     51     << "format: " << format; \
     52   EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
     53 
     54 TEST(PrintfTest, NoArgs) {
     55   EXPECT_EQ("test", fmt::sprintf("test"));
     56 }
     57 
     58 TEST(PrintfTest, Escape) {
     59   EXPECT_EQ("%", fmt::sprintf("%%"));
     60   EXPECT_EQ("before %", fmt::sprintf("before %%"));
     61   EXPECT_EQ("% after", fmt::sprintf("%% after"));
     62   EXPECT_EQ("before % after", fmt::sprintf("before %% after"));
     63   EXPECT_EQ("%s", fmt::sprintf("%%s"));
     64 }
     65 
     66 TEST(PrintfTest, PositionalArgs) {
     67   EXPECT_EQ("42", fmt::sprintf("%1$d", 42));
     68   EXPECT_EQ("before 42", fmt::sprintf("before %1$d", 42));
     69   EXPECT_EQ("42 after", fmt::sprintf("%1$d after",42));
     70   EXPECT_EQ("before 42 after", fmt::sprintf("before %1$d after", 42));
     71   EXPECT_EQ("answer = 42", fmt::sprintf("%1$s = %2$d", "answer", 42));
     72   EXPECT_EQ("42 is the answer",
     73       fmt::sprintf("%2$d is the %1$s", "answer", 42));
     74   EXPECT_EQ("abracadabra", fmt::sprintf("%1$s%2$s%1$s", "abra", "cad"));
     75 }
     76 
     77 TEST(PrintfTest, AutomaticArgIndexing) {
     78   EXPECT_EQ("abc", fmt::sprintf("%c%c%c", 'a', 'b', 'c'));
     79 }
     80 
     81 TEST(PrintfTest, NumberIsTooBigInArgIndex) {
     82   EXPECT_THROW_MSG(fmt::sprintf(format("%{}$", BIG_NUM)),
     83       FormatError, "number is too big");
     84   EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", BIG_NUM)),
     85       FormatError, "number is too big");
     86 }
     87 
     88 TEST(PrintfTest, SwitchArgIndexing) {
     89   EXPECT_THROW_MSG(fmt::sprintf("%1$d%", 1, 2),
     90       FormatError, "invalid format string");
     91   EXPECT_THROW_MSG(fmt::sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
     92       FormatError, "number is too big");
     93   EXPECT_THROW_MSG(fmt::sprintf("%1$d%d", 1, 2),
     94       FormatError, "cannot switch from manual to automatic argument indexing");
     95 
     96   EXPECT_THROW_MSG(fmt::sprintf("%d%1$", 1, 2),
     97       FormatError, "invalid format string");
     98   EXPECT_THROW_MSG(fmt::sprintf(format("%d%{}$d", BIG_NUM), 1, 2),
     99       FormatError, "number is too big");
    100   EXPECT_THROW_MSG(fmt::sprintf("%d%1$d", 1, 2),
    101       FormatError, "cannot switch from automatic to manual argument indexing");
    102 
    103   // Indexing errors override width errors.
    104   EXPECT_THROW_MSG(fmt::sprintf(format("%d%1${}d", BIG_NUM), 1, 2),
    105       FormatError, "number is too big");
    106   EXPECT_THROW_MSG(fmt::sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
    107       FormatError, "number is too big");
    108 }
    109 
    110 TEST(PrintfTest, InvalidArgIndex) {
    111   EXPECT_THROW_MSG(fmt::sprintf("%0$d", 42), FormatError,
    112       "argument index out of range");
    113   EXPECT_THROW_MSG(fmt::sprintf("%2$d", 42), FormatError,
    114       "argument index out of range");
    115   EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", INT_MAX), 42),
    116       FormatError, "argument index out of range");
    117 
    118   EXPECT_THROW_MSG(fmt::sprintf("%2$", 42),
    119       FormatError, "invalid format string");
    120   EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", BIG_NUM), 42),
    121       FormatError, "number is too big");
    122 }
    123 
    124 TEST(PrintfTest, DefaultAlignRight) {
    125   EXPECT_PRINTF("   42", "%5d", 42);
    126   EXPECT_PRINTF("  abc", "%5s", "abc");
    127 }
    128 
    129 TEST(PrintfTest, ZeroFlag) {
    130   EXPECT_PRINTF("00042", "%05d", 42);
    131   EXPECT_PRINTF("-0042", "%05d", -42);
    132 
    133   EXPECT_PRINTF("00042", "%05d", 42);
    134   EXPECT_PRINTF("-0042", "%05d", -42);
    135   EXPECT_PRINTF("-004.2", "%06g", -4.2);
    136 
    137   EXPECT_PRINTF("+00042", "%00+6d", 42);
    138 
    139   // '0' flag is ignored for non-numeric types.
    140   EXPECT_PRINTF("    x", "%05c", 'x');
    141 }
    142 
    143 TEST(PrintfTest, PlusFlag) {
    144   EXPECT_PRINTF("+42", "%+d", 42);
    145   EXPECT_PRINTF("-42", "%+d", -42);
    146   EXPECT_PRINTF("+0042", "%+05d", 42);
    147   EXPECT_PRINTF("+0042", "%0++5d", 42);
    148 
    149   // '+' flag is ignored for non-numeric types.
    150   EXPECT_PRINTF("x", "%+c", 'x');
    151 }
    152 
    153 TEST(PrintfTest, MinusFlag) {
    154   EXPECT_PRINTF("abc  ", "%-5s", "abc");
    155   EXPECT_PRINTF("abc  ", "%0--5s", "abc");
    156 }
    157 
    158 TEST(PrintfTest, SpaceFlag) {
    159   EXPECT_PRINTF(" 42", "% d", 42);
    160   EXPECT_PRINTF("-42", "% d", -42);
    161   EXPECT_PRINTF(" 0042", "% 05d", 42);
    162   EXPECT_PRINTF(" 0042", "%0  5d", 42);
    163 
    164   // ' ' flag is ignored for non-numeric types.
    165   EXPECT_PRINTF("x", "% c", 'x');
    166 }
    167 
    168 TEST(PrintfTest, HashFlag) {
    169   EXPECT_PRINTF("042", "%#o", 042);
    170   EXPECT_PRINTF(fmt::format("0{:o}", static_cast<unsigned>(-042)), "%#o", -042);
    171   EXPECT_PRINTF("0", "%#o", 0);
    172 
    173   EXPECT_PRINTF("0x42", "%#x", 0x42);
    174   EXPECT_PRINTF("0X42", "%#X", 0x42);
    175   EXPECT_PRINTF(
    176         fmt::format("0x{:x}", static_cast<unsigned>(-0x42)), "%#x", -0x42);
    177   EXPECT_PRINTF("0", "%#x", 0);
    178 
    179   EXPECT_PRINTF("0x0042", "%#06x", 0x42);
    180   EXPECT_PRINTF("0x0042", "%0##6x", 0x42);
    181 
    182   EXPECT_PRINTF("-42.000000", "%#f", -42.0);
    183   EXPECT_PRINTF("-42.000000", "%#F", -42.0);
    184 
    185   char buffer[BUFFER_SIZE];
    186   safe_sprintf(buffer, "%#e", -42.0);
    187   EXPECT_PRINTF(buffer, "%#e", -42.0);
    188   safe_sprintf(buffer, "%#E", -42.0);
    189   EXPECT_PRINTF(buffer, "%#E", -42.0);
    190 
    191   EXPECT_PRINTF("-42.0000", "%#g", -42.0);
    192   EXPECT_PRINTF("-42.0000", "%#G", -42.0);
    193 
    194   safe_sprintf(buffer, "%#a", 16.0);
    195   EXPECT_PRINTF(buffer, "%#a", 16.0);
    196   safe_sprintf(buffer, "%#A", 16.0);
    197   EXPECT_PRINTF(buffer, "%#A", 16.0);
    198 
    199   // '#' flag is ignored for non-numeric types.
    200   EXPECT_PRINTF("x", "%#c", 'x');
    201 }
    202 
    203 TEST(PrintfTest, Width) {
    204   EXPECT_PRINTF("  abc", "%5s", "abc");
    205 
    206   // Width cannot be specified twice.
    207   EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
    208       "unknown format code '-' for integer");
    209 
    210   EXPECT_THROW_MSG(fmt::sprintf(format("%{}d", BIG_NUM), 42),
    211       FormatError, "number is too big");
    212   EXPECT_THROW_MSG(fmt::sprintf(format("%1${}d", BIG_NUM), 42),
    213       FormatError, "number is too big");
    214 }
    215 
    216 TEST(PrintfTest, DynamicWidth) {
    217   EXPECT_EQ("   42", fmt::sprintf("%*d", 5, 42));
    218   EXPECT_EQ("42   ", fmt::sprintf("%*d", -5, 42));
    219   EXPECT_THROW_MSG(fmt::sprintf("%*d", 5.0, 42), FormatError,
    220       "width is not integer");
    221   EXPECT_THROW_MSG(fmt::sprintf("%*d"), FormatError,
    222       "argument index out of range");
    223   EXPECT_THROW_MSG(fmt::sprintf("%*d", BIG_NUM, 42), FormatError,
    224       "number is too big");
    225 }
    226 
    227 TEST(PrintfTest, IntPrecision) {
    228   EXPECT_PRINTF("00042", "%.5d", 42);
    229   EXPECT_PRINTF("-00042", "%.5d", -42);
    230   EXPECT_PRINTF("00042", "%.5x", 0x42);
    231   EXPECT_PRINTF("0x00042", "%#.5x", 0x42);
    232   EXPECT_PRINTF("00042", "%.5o", 042);
    233   EXPECT_PRINTF("00042", "%#.5o", 042);
    234 
    235   EXPECT_PRINTF("  00042", "%7.5d", 42);
    236   EXPECT_PRINTF("  00042", "%7.5x", 0x42);
    237   EXPECT_PRINTF("   0x00042", "%#10.5x", 0x42);
    238   EXPECT_PRINTF("  00042", "%7.5o", 042);
    239   EXPECT_PRINTF("     00042", "%#10.5o", 042);
    240 
    241   EXPECT_PRINTF("00042  ", "%-7.5d", 42);
    242   EXPECT_PRINTF("00042  ", "%-7.5x", 0x42);
    243   EXPECT_PRINTF("0x00042   ", "%-#10.5x", 0x42);
    244   EXPECT_PRINTF("00042  ", "%-7.5o", 042);
    245   EXPECT_PRINTF("00042     ", "%-#10.5o", 042);
    246 }
    247 
    248 TEST(PrintfTest, FloatPrecision) {
    249   char buffer[BUFFER_SIZE];
    250   safe_sprintf(buffer, "%.3e", 1234.5678);
    251   EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
    252   EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
    253   safe_sprintf(buffer, "%.3g", 1234.5678);
    254   EXPECT_PRINTF(buffer, "%.3g", 1234.5678);
    255   safe_sprintf(buffer, "%.3a", 1234.5678);
    256   EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
    257 }
    258 
    259 TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
    260   EXPECT_PRINTF("abc", "%.5s", "abc");
    261 }
    262 
    263 TEST(PrintfTest, DynamicPrecision) {
    264   EXPECT_EQ("00042", fmt::sprintf("%.*d", 5, 42));
    265   EXPECT_EQ("42", fmt::sprintf("%.*d", -5, 42));
    266   EXPECT_THROW_MSG(fmt::sprintf("%.*d", 5.0, 42), FormatError,
    267       "precision is not integer");
    268   EXPECT_THROW_MSG(fmt::sprintf("%.*d"), FormatError,
    269       "argument index out of range");
    270   EXPECT_THROW_MSG(fmt::sprintf("%.*d", BIG_NUM, 42), FormatError,
    271       "number is too big");
    272   if (sizeof(fmt::LongLong) != sizeof(int)) {
    273     fmt::LongLong prec = static_cast<fmt::LongLong>(INT_MIN) - 1;
    274     EXPECT_THROW_MSG(fmt::sprintf("%.*d", prec, 42), FormatError,
    275         "number is too big");
    276  }
    277 }
    278 
    279 template <typename T>
    280 struct MakeSigned { typedef T Type; };
    281 
    282 #define SPECIALIZE_MAKE_SIGNED(T, S) \
    283   template <> \
    284   struct MakeSigned<T> { typedef S Type; }
    285 
    286 SPECIALIZE_MAKE_SIGNED(char, signed char);
    287 SPECIALIZE_MAKE_SIGNED(unsigned char, signed char);
    288 SPECIALIZE_MAKE_SIGNED(unsigned short, short);
    289 SPECIALIZE_MAKE_SIGNED(unsigned, int);
    290 SPECIALIZE_MAKE_SIGNED(unsigned long, long);
    291 SPECIALIZE_MAKE_SIGNED(fmt::ULongLong, fmt::LongLong);
    292 
    293 // Test length format specifier ``length_spec``.
    294 template <typename T, typename U>
    295 void TestLength(const char *length_spec, U value) {
    296   fmt::LongLong signed_value = 0;
    297   fmt::ULongLong unsigned_value = 0;
    298   // Apply integer promotion to the argument.
    299   using std::numeric_limits;
    300   fmt::ULongLong max = numeric_limits<U>::max();
    301   using fmt::internal::const_check;
    302   if (const_check(max <= static_cast<unsigned>(numeric_limits<int>::max()))) {
    303     signed_value = static_cast<int>(value);
    304     unsigned_value = static_cast<unsigned>(value);
    305   } else if (const_check(max <= numeric_limits<unsigned>::max())) {
    306     signed_value = static_cast<unsigned>(value);
    307     unsigned_value = static_cast<unsigned>(value);
    308   }
    309   using fmt::internal::MakeUnsigned;
    310   if (sizeof(U) <= sizeof(int) && sizeof(int) < sizeof(T)) {
    311     signed_value = static_cast<fmt::LongLong>(value);
    312     unsigned_value = static_cast<typename MakeUnsigned<unsigned>::Type>(value);
    313   } else {
    314     signed_value = static_cast<typename MakeSigned<T>::Type>(value);
    315     unsigned_value = static_cast<typename MakeUnsigned<T>::Type>(value);
    316   }
    317   std::ostringstream os;
    318   os << signed_value;
    319   EXPECT_PRINTF(os.str(), fmt::format("%{}d", length_spec), value);
    320   EXPECT_PRINTF(os.str(), fmt::format("%{}i", length_spec), value);
    321   os.str("");
    322   os << unsigned_value;
    323   EXPECT_PRINTF(os.str(), fmt::format("%{}u", length_spec), value);
    324   os.str("");
    325   os << std::oct << unsigned_value;
    326   EXPECT_PRINTF(os.str(), fmt::format("%{}o", length_spec), value);
    327   os.str("");
    328   os << std::hex << unsigned_value;
    329   EXPECT_PRINTF(os.str(), fmt::format("%{}x", length_spec), value);
    330   os.str("");
    331   os << std::hex << std::uppercase << unsigned_value;
    332   EXPECT_PRINTF(os.str(), fmt::format("%{}X", length_spec), value);
    333 }
    334 
    335 template <typename T>
    336 void TestLength(const char *length_spec) {
    337   T min = std::numeric_limits<T>::min(), max = std::numeric_limits<T>::max();
    338   TestLength<T>(length_spec, 42);
    339   TestLength<T>(length_spec, -42);
    340   TestLength<T>(length_spec, min);
    341   TestLength<T>(length_spec, max);
    342   TestLength<T>(length_spec, fmt::LongLong(min) - 1);
    343   fmt::ULongLong long_long_max = std::numeric_limits<fmt::LongLong>::max();
    344   if (static_cast<fmt::ULongLong>(max) < long_long_max)
    345     TestLength<T>(length_spec, fmt::LongLong(max) + 1);
    346   TestLength<T>(length_spec, std::numeric_limits<short>::min());
    347   TestLength<T>(length_spec, std::numeric_limits<unsigned short>::max());
    348   TestLength<T>(length_spec, std::numeric_limits<int>::min());
    349   TestLength<T>(length_spec, std::numeric_limits<int>::max());
    350   TestLength<T>(length_spec, std::numeric_limits<unsigned>::min());
    351   TestLength<T>(length_spec, std::numeric_limits<unsigned>::max());
    352   TestLength<T>(length_spec, std::numeric_limits<fmt::LongLong>::min());
    353   TestLength<T>(length_spec, std::numeric_limits<fmt::LongLong>::max());
    354   TestLength<T>(length_spec, std::numeric_limits<fmt::ULongLong>::min());
    355   TestLength<T>(length_spec, std::numeric_limits<fmt::ULongLong>::max());
    356 }
    357 
    358 TEST(PrintfTest, Length) {
    359   TestLength<char>("hh");
    360   TestLength<signed char>("hh");
    361   TestLength<unsigned char>("hh");
    362   TestLength<short>("h");
    363   TestLength<unsigned short>("h");
    364   TestLength<long>("l");
    365   TestLength<unsigned long>("l");
    366   TestLength<fmt::LongLong>("ll");
    367   TestLength<fmt::ULongLong>("ll");
    368   TestLength<intmax_t>("j");
    369   TestLength<std::size_t>("z");
    370   TestLength<std::ptrdiff_t>("t");
    371   long double max = std::numeric_limits<long double>::max();
    372   EXPECT_PRINTF(fmt::format("{}", max), "%g", max);
    373   EXPECT_PRINTF(fmt::format("{}", max), "%Lg", max);
    374 }
    375 
    376 TEST(PrintfTest, Bool) {
    377   EXPECT_PRINTF("1", "%d", true);
    378   EXPECT_PRINTF("true", "%s", true);
    379 }
    380 
    381 TEST(PrintfTest, Int) {
    382   EXPECT_PRINTF("-42", "%d", -42);
    383   EXPECT_PRINTF("-42", "%i", -42);
    384   unsigned u = 0 - 42u;
    385   EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
    386   EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -42);
    387   EXPECT_PRINTF(fmt::format("{:x}", u), "%x", -42);
    388   EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
    389 }
    390 
    391 TEST(PrintfTest, LongLong) {
    392   // fmt::printf allows passing long long arguments to %d without length
    393   // specifiers.
    394   fmt::LongLong max = std::numeric_limits<fmt::LongLong>::max();
    395   EXPECT_PRINTF(fmt::format("{}", max), "%d", max);
    396 }
    397 
    398 TEST(PrintfTest, Float) {
    399   EXPECT_PRINTF("392.650000", "%f", 392.65);
    400   EXPECT_PRINTF("392.650000", "%F", 392.65);
    401   char buffer[BUFFER_SIZE];
    402   safe_sprintf(buffer, "%e", 392.65);
    403   EXPECT_PRINTF(buffer, "%e", 392.65);
    404   safe_sprintf(buffer, "%E", 392.65);
    405   EXPECT_PRINTF(buffer, "%E", 392.65);
    406   EXPECT_PRINTF("392.65", "%g", 392.65);
    407   EXPECT_PRINTF("392.65", "%G", 392.65);
    408   safe_sprintf(buffer, "%a", -392.65);
    409   EXPECT_EQ(buffer, format("{:a}", -392.65));
    410   safe_sprintf(buffer, "%A", -392.65);
    411   EXPECT_EQ(buffer, format("{:A}", -392.65));
    412 }
    413 
    414 TEST(PrintfTest, Inf) {
    415   double inf = std::numeric_limits<double>::infinity();
    416   for (const char* type = "fega"; *type; ++type) {
    417     EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
    418     char upper = std::toupper(*type);
    419     EXPECT_PRINTF("INF", fmt::format("%{}", upper), inf);
    420   }
    421 }
    422 
    423 TEST(PrintfTest, Char) {
    424   EXPECT_PRINTF("x", "%c", 'x');
    425   int max = std::numeric_limits<int>::max();
    426   EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
    427   //EXPECT_PRINTF("x", "%lc", L'x');
    428   // TODO: test wchar_t
    429 }
    430 
    431 TEST(PrintfTest, String) {
    432   EXPECT_PRINTF("abc", "%s", "abc");
    433   const char *null_str = 0;
    434   EXPECT_PRINTF("(null)", "%s", null_str);
    435   EXPECT_PRINTF("    (null)", "%10s", null_str);
    436   // TODO: wide string
    437 }
    438 
    439 TEST(PrintfTest, Pointer) {
    440   int n;
    441   void *p = &n;
    442   EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
    443   p = 0;
    444   EXPECT_PRINTF("(nil)", "%p", p);
    445   EXPECT_PRINTF("     (nil)", "%10p", p);
    446   const char *s = "test";
    447   EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
    448   const char *null_str = 0;
    449   EXPECT_PRINTF("(nil)", "%p", null_str);
    450 }
    451 
    452 TEST(PrintfTest, Location) {
    453   // TODO: test %n
    454 }
    455 
    456 enum E { A = 42 };
    457 
    458 TEST(PrintfTest, Enum) {
    459   EXPECT_PRINTF("42", "%d", A);
    460 }
    461 
    462 #if FMT_USE_FILE_DESCRIPTORS
    463 TEST(PrintfTest, Examples) {
    464   const char *weekday = "Thursday";
    465   const char *month = "August";
    466   int day = 21;
    467   EXPECT_WRITE(stdout, fmt::printf("%1$s, %3$d %2$s", weekday, month, day),
    468                "Thursday, 21 August");
    469 }
    470 
    471 TEST(PrintfTest, PrintfError) {
    472   fmt::File read_end, write_end;
    473   fmt::File::pipe(read_end, write_end);
    474   int result = fmt::fprintf(read_end.fdopen("r").get(), "test");
    475   EXPECT_LT(result, 0);
    476 }
    477 #endif
    478 
    479 TEST(PrintfTest, WideString) {
    480   EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
    481 }
    482 
    483 TEST(PrintfTest, PrintfCustom) {
    484   EXPECT_EQ("abc", fmt::sprintf("%s", TestString("abc")));
    485 }
    486 
    487 TEST(PrintfTest, OStream) {
    488   std::ostringstream os;
    489   int ret = fmt::fprintf(os, "Don't %s!", "panic");
    490   EXPECT_EQ("Don't panic!", os.str());
    491   EXPECT_EQ(12, ret);
    492 }
    493