str_format_test.cc
Go to the documentation of this file.
00001 
00002 #include <cstdarg>
00003 #include <cstdint>
00004 #include <cstdio>
00005 #include <string>
00006 
00007 #include "gmock/gmock.h"
00008 #include "gtest/gtest.h"
00009 #include "absl/strings/str_format.h"
00010 #include "absl/strings/string_view.h"
00011 
00012 namespace absl {
00013 namespace {
00014 using str_format_internal::FormatArgImpl;
00015 
00016 using FormatEntryPointTest = ::testing::Test;
00017 
00018 TEST_F(FormatEntryPointTest, Format) {
00019   std::string sink;
00020   EXPECT_TRUE(Format(&sink, "A format %d", 123));
00021   EXPECT_EQ("A format 123", sink);
00022   sink.clear();
00023 
00024   ParsedFormat<'d'> pc("A format %d");
00025   EXPECT_TRUE(Format(&sink, pc, 123));
00026   EXPECT_EQ("A format 123", sink);
00027 }
00028 TEST_F(FormatEntryPointTest, UntypedFormat) {
00029   constexpr const char* formats[] = {
00030     "",
00031     "a",
00032     "%80d",
00033 #if !defined(_MSC_VER) && !defined(__ANDROID__)
00034     // MSVC and Android don't support positional syntax.
00035     "complicated multipart %% %1$d format %1$0999d",
00036 #endif  // _MSC_VER
00037   };
00038   for (const char* fmt : formats) {
00039     std::string actual;
00040     int i = 123;
00041     FormatArgImpl arg_123(i);
00042     absl::Span<const FormatArgImpl> args(&arg_123, 1);
00043     UntypedFormatSpec format(fmt);
00044 
00045     EXPECT_TRUE(FormatUntyped(&actual, format, args));
00046     char buf[4096]{};
00047     snprintf(buf, sizeof(buf), fmt, 123);
00048     EXPECT_EQ(
00049         str_format_internal::FormatPack(
00050             str_format_internal::UntypedFormatSpecImpl::Extract(format), args),
00051         buf);
00052     EXPECT_EQ(actual, buf);
00053   }
00054   // The internal version works with a preparsed format.
00055   ParsedFormat<'d'> pc("A format %d");
00056   int i = 345;
00057   FormatArg arg(i);
00058   std::string out;
00059   EXPECT_TRUE(str_format_internal::FormatUntyped(
00060       &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1}));
00061   EXPECT_EQ("A format 345", out);
00062 }
00063 
00064 TEST_F(FormatEntryPointTest, StringFormat) {
00065   EXPECT_EQ("123", StrFormat("%d", 123));
00066   constexpr absl::string_view view("=%d=", 4);
00067   EXPECT_EQ("=123=", StrFormat(view, 123));
00068 }
00069 
00070 TEST_F(FormatEntryPointTest, AppendFormat) {
00071   std::string s;
00072   std::string& r = StrAppendFormat(&s, "%d", 123);
00073   EXPECT_EQ(&s, &r);  // should be same object
00074   EXPECT_EQ("123", r);
00075 }
00076 
00077 TEST_F(FormatEntryPointTest, AppendFormatFail) {
00078   std::string s = "orig";
00079 
00080   UntypedFormatSpec format(" more %d");
00081   FormatArgImpl arg("not an int");
00082 
00083   EXPECT_EQ("orig",
00084             str_format_internal::AppendPack(
00085                 &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),
00086                 {&arg, 1}));
00087 }
00088 
00089 
00090 TEST_F(FormatEntryPointTest, ManyArgs) {
00091   EXPECT_EQ("24", StrFormat("%24$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
00092                             14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24));
00093   EXPECT_EQ("60", StrFormat("%60$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
00094                             14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
00095                             27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
00096                             40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
00097                             53, 54, 55, 56, 57, 58, 59, 60));
00098 }
00099 
00100 TEST_F(FormatEntryPointTest, Preparsed) {
00101   ParsedFormat<'d'> pc("%d");
00102   EXPECT_EQ("123", StrFormat(pc, 123));
00103   // rvalue ok?
00104   EXPECT_EQ("123", StrFormat(ParsedFormat<'d'>("%d"), 123));
00105   constexpr absl::string_view view("=%d=", 4);
00106   EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123));
00107 }
00108 
00109 TEST_F(FormatEntryPointTest, FormatCountCapture) {
00110   int n = 0;
00111   EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
00112   EXPECT_EQ(0, n);
00113   EXPECT_EQ("123", StrFormat("%d%n", 123, FormatCountCapture(&n)));
00114   EXPECT_EQ(3, n);
00115 }
00116 
00117 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {
00118   // Should reject int*.
00119   int n = 0;
00120   UntypedFormatSpec format("%d%n");
00121   int i = 123, *ip = &n;
00122   FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};
00123 
00124   EXPECT_EQ("", str_format_internal::FormatPack(
00125                     str_format_internal::UntypedFormatSpecImpl::Extract(format),
00126                     absl::MakeSpan(args)));
00127 }
00128 
00129 TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) {
00130   int n1 = 0;
00131   int n2 = 0;
00132   EXPECT_EQ("    1         2",
00133             StrFormat("%5d%n%10d%n", 1, FormatCountCapture(&n1), 2,
00134                       FormatCountCapture(&n2)));
00135   EXPECT_EQ(5, n1);
00136   EXPECT_EQ(15, n2);
00137 }
00138 
00139 TEST_F(FormatEntryPointTest, FormatCountCaptureExample) {
00140   int n;
00141   std::string s;
00142   StrAppendFormat(&s, "%s: %n%s\n", "(1,1)", FormatCountCapture(&n), "(1,2)");
00143   StrAppendFormat(&s, "%*s%s\n", n, "", "(2,2)");
00144   EXPECT_EQ(7, n);
00145   EXPECT_EQ(
00146       "(1,1): (1,2)\n"
00147       "       (2,2)\n",
00148       s);
00149 }
00150 
00151 TEST_F(FormatEntryPointTest, Stream) {
00152   const std::string formats[] = {
00153     "",
00154     "a",
00155     "%80d",
00156 #if !defined(_MSC_VER) && !defined(__ANDROID__)
00157     // MSVC doesn't support positional syntax.
00158     "complicated multipart %% %1$d format %1$080d",
00159 #endif  // _MSC_VER
00160   };
00161   std::string buf(4096, '\0');
00162   for (const auto& fmt : formats) {
00163     const auto parsed = ParsedFormat<'d'>::NewAllowIgnored(fmt);
00164     std::ostringstream oss;
00165     oss << StreamFormat(*parsed, 123);
00166     int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), 123);
00167     ASSERT_TRUE(oss) << fmt;
00168     ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
00169         << fmt_result;
00170     EXPECT_EQ(buf.c_str(), oss.str());
00171   }
00172 }
00173 
00174 TEST_F(FormatEntryPointTest, StreamOk) {
00175   std::ostringstream oss;
00176   oss << StreamFormat("hello %d", 123);
00177   EXPECT_EQ("hello 123", oss.str());
00178   EXPECT_TRUE(oss.good());
00179 }
00180 
00181 TEST_F(FormatEntryPointTest, StreamFail) {
00182   std::ostringstream oss;
00183   UntypedFormatSpec format("hello %d");
00184   FormatArgImpl arg("non-numeric");
00185   oss << str_format_internal::Streamable(
00186       str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});
00187   EXPECT_EQ("hello ", oss.str());  // partial write
00188   EXPECT_TRUE(oss.fail());
00189 }
00190 
00191 std::string WithSnprintf(const char* fmt, ...) {
00192   std::string buf;
00193   buf.resize(128);
00194   va_list va;
00195   va_start(va, fmt);
00196   int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va);
00197   va_end(va);
00198   EXPECT_GE(r, 0);
00199   EXPECT_LT(r, buf.size());
00200   buf.resize(r);
00201   return buf;
00202 }
00203 
00204 TEST_F(FormatEntryPointTest, FloatPrecisionArg) {
00205   // Test that positional parameters for width and precision
00206   // are indexed to precede the value.
00207   // Also sanity check the same formats against snprintf.
00208   EXPECT_EQ("0.1", StrFormat("%.1f", 0.1));
00209   EXPECT_EQ("0.1", WithSnprintf("%.1f", 0.1));
00210   EXPECT_EQ("  0.1", StrFormat("%*.1f", 5, 0.1));
00211   EXPECT_EQ("  0.1", WithSnprintf("%*.1f", 5, 0.1));
00212   EXPECT_EQ("0.1", StrFormat("%.*f", 1, 0.1));
00213   EXPECT_EQ("0.1", WithSnprintf("%.*f", 1, 0.1));
00214   EXPECT_EQ("  0.1", StrFormat("%*.*f", 5, 1, 0.1));
00215   EXPECT_EQ("  0.1", WithSnprintf("%*.*f", 5, 1, 0.1));
00216 }
00217 namespace streamed_test {
00218 struct X {};
00219 std::ostream& operator<<(std::ostream& os, const X&) {
00220   return os << "X";
00221 }
00222 }  // streamed_test
00223 
00224 TEST_F(FormatEntryPointTest, FormatStreamed) {
00225   EXPECT_EQ("123", StrFormat("%s", FormatStreamed(123)));
00226   EXPECT_EQ("  123", StrFormat("%5s", FormatStreamed(123)));
00227   EXPECT_EQ("123  ", StrFormat("%-5s", FormatStreamed(123)));
00228   EXPECT_EQ("X", StrFormat("%s", FormatStreamed(streamed_test::X())));
00229   EXPECT_EQ("123", StrFormat("%s", FormatStreamed(StreamFormat("%d", 123))));
00230 }
00231 
00232 // Helper class that creates a temporary file and exposes a FILE* to it.
00233 // It will close the file on destruction.
00234 class TempFile {
00235  public:
00236   TempFile() : file_(std::tmpfile()) {}
00237   ~TempFile() { std::fclose(file_); }
00238 
00239   std::FILE* file() const { return file_; }
00240 
00241   // Read the file into a std::string.
00242   std::string ReadFile() {
00243     std::fseek(file_, 0, SEEK_END);
00244     int size = std::ftell(file_);
00245     EXPECT_GT(size, 0);
00246     std::rewind(file_);
00247     std::string str(2 * size, ' ');
00248     int read_bytes = std::fread(&str[0], 1, str.size(), file_);
00249     EXPECT_EQ(read_bytes, size);
00250     str.resize(read_bytes);
00251     EXPECT_TRUE(std::feof(file_));
00252     return str;
00253   }
00254 
00255  private:
00256   std::FILE* file_;
00257 };
00258 
00259 TEST_F(FormatEntryPointTest, FPrintF) {
00260   TempFile tmp;
00261   int result =
00262       FPrintF(tmp.file(), "STRING: %s NUMBER: %010d", std::string("ABC"), -19);
00263   EXPECT_EQ(result, 30);
00264   EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
00265 }
00266 
00267 TEST_F(FormatEntryPointTest, FPrintFError) {
00268   errno = 0;
00269   int result = FPrintF(stdin, "ABC");
00270   EXPECT_LT(result, 0);
00271   EXPECT_EQ(errno, EBADF);
00272 }
00273 
00274 #if __GLIBC__
00275 TEST_F(FormatEntryPointTest, FprintfTooLarge) {
00276   std::FILE* f = std::fopen("/dev/null", "w");
00277   int width = 2000000000;
00278   errno = 0;
00279   int result = FPrintF(f, "%*d %*d", width, 0, width, 0);
00280   EXPECT_LT(result, 0);
00281   EXPECT_EQ(errno, EFBIG);
00282   std::fclose(f);
00283 }
00284 
00285 TEST_F(FormatEntryPointTest, PrintF) {
00286   int stdout_tmp = dup(STDOUT_FILENO);
00287 
00288   TempFile tmp;
00289   std::fflush(stdout);
00290   dup2(fileno(tmp.file()), STDOUT_FILENO);
00291 
00292   int result = PrintF("STRING: %s NUMBER: %010d", std::string("ABC"), -19);
00293 
00294   std::fflush(stdout);
00295   dup2(stdout_tmp, STDOUT_FILENO);
00296   close(stdout_tmp);
00297 
00298   EXPECT_EQ(result, 30);
00299   EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
00300 }
00301 #endif  // __GLIBC__
00302 
00303 TEST_F(FormatEntryPointTest, SNPrintF) {
00304   char buffer[16];
00305   int result =
00306       SNPrintF(buffer, sizeof(buffer), "STRING: %s", std::string("ABC"));
00307   EXPECT_EQ(result, 11);
00308   EXPECT_EQ(std::string(buffer), "STRING: ABC");
00309 
00310   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456);
00311   EXPECT_EQ(result, 14);
00312   EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
00313 
00314   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567);
00315   EXPECT_EQ(result, 15);
00316   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
00317 
00318   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678);
00319   EXPECT_EQ(result, 16);
00320   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
00321 
00322   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789);
00323   EXPECT_EQ(result, 17);
00324   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
00325 
00326   result = SNPrintF(nullptr, 0, "Just checking the %s of the output.", "size");
00327   EXPECT_EQ(result, 37);
00328 }
00329 
00330 TEST(StrFormat, BehavesAsDocumented) {
00331   std::string s = absl::StrFormat("%s, %d!", "Hello", 123);
00332   EXPECT_EQ("Hello, 123!", s);
00333   // The format of a replacement is
00334   // '%'[position][flags][width['.'precision]][length_modifier][format]
00335   EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10");
00336   // Text conversion:
00337   //     "c" - Character.              Eg: 'a' -> "A", 20 -> " "
00338   EXPECT_EQ(StrFormat("%c", 'a'), "a");
00339   EXPECT_EQ(StrFormat("%c", 0x20), " ");
00340   //           Formats char and integral types: int, long, uint64_t, etc.
00341   EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
00342   EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
00343   EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
00344   //     "s" - std::string       Eg: "C" -> "C", std::string("C++") -> "C++"
00345   //           Formats std::string, char*, string_view, and Cord.
00346   EXPECT_EQ(StrFormat("%s", "C"), "C");
00347   EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
00348   EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
00349   // Integral Conversion
00350   //     These format integral types: char, int, long, uint64_t, etc.
00351   EXPECT_EQ(StrFormat("%d", char{10}), "10");
00352   EXPECT_EQ(StrFormat("%d", int{10}), "10");
00353   EXPECT_EQ(StrFormat("%d", long{10}), "10");  // NOLINT
00354   EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10");
00355   //     d,i - signed decimal          Eg: -10 -> "-10"
00356   EXPECT_EQ(StrFormat("%d", -10), "-10");
00357   EXPECT_EQ(StrFormat("%i", -10), "-10");
00358   //      o  - octal                   Eg:  10 -> "12"
00359   EXPECT_EQ(StrFormat("%o", 10), "12");
00360   //      u  - unsigned decimal        Eg:  10 -> "10"
00361   EXPECT_EQ(StrFormat("%u", 10), "10");
00362   //     x/X - lower,upper case hex    Eg:  10 -> "a"/"A"
00363   EXPECT_EQ(StrFormat("%x", 10), "a");
00364   EXPECT_EQ(StrFormat("%X", 10), "A");
00365   // Floating-point, with upper/lower-case output.
00366   //     These format floating points types: float, double, long double, etc.
00367   EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0");
00368   EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0");
00369   const long double long_double = 1.0;
00370   EXPECT_EQ(StrFormat("%.1f", long_double), "1.0");
00371   //     These also format integral types: char, int, long, uint64_t, etc.:
00372   EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0");
00373   EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0");
00374   EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0");  // NOLINT
00375   EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0");
00376   //     f/F - decimal.                Eg: 123456789 -> "123456789.000000"
00377   EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000");
00378   EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000");
00379   //     e/E - exponentiated           Eg: .01 -> "1.00000e-2"/"1.00000E-2"
00380   EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02");
00381   EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02");
00382   //     g/G - exponentiate to fit     Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10"
00383   EXPECT_EQ(StrFormat("%g", .01), "0.01");
00384   EXPECT_EQ(StrFormat("%g", 1e10), "1e+10");
00385   EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
00386   //     a/A - lower,upper case hex    Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
00387 
00388 // On Android platform <=21, there is a regression in hexfloat formatting.
00389 #if !defined(__ANDROID_API__) || __ANDROID_API__ > 21
00390   EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1");  // .1 to fix MSVC output
00391   EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1");  // .1 to fix MSVC output
00392 #endif
00393 
00394   // Other conversion
00395   int64_t value = 0x7ffdeb4;
00396   auto ptr_value = static_cast<uintptr_t>(value);
00397   const int& something = *reinterpret_cast<const int*>(ptr_value);
00398   EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value));
00399 
00400   // Output widths are supported, with optional flags.
00401   EXPECT_EQ(StrFormat("%3d", 1), "  1");
00402   EXPECT_EQ(StrFormat("%3d", 123456), "123456");
00403   EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23");
00404   EXPECT_EQ(StrFormat("%+d", 1), "+1");
00405   EXPECT_EQ(StrFormat("% d", 1), " 1");
00406   EXPECT_EQ(StrFormat("%-4d", -1), "-1  ");
00407   EXPECT_EQ(StrFormat("%#o", 10), "012");
00408   EXPECT_EQ(StrFormat("%#x", 15), "0xf");
00409   EXPECT_EQ(StrFormat("%04d", 8), "0008");
00410   // Posix positional substitution.
00411   EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"),
00412             "veni, vidi, vici!");
00413   // Length modifiers are ignored.
00414   EXPECT_EQ(StrFormat("%hhd", int{1}), "1");
00415   EXPECT_EQ(StrFormat("%hd", int{1}), "1");
00416   EXPECT_EQ(StrFormat("%ld", int{1}), "1");
00417   EXPECT_EQ(StrFormat("%lld", int{1}), "1");
00418   EXPECT_EQ(StrFormat("%Ld", int{1}), "1");
00419   EXPECT_EQ(StrFormat("%jd", int{1}), "1");
00420   EXPECT_EQ(StrFormat("%zd", int{1}), "1");
00421   EXPECT_EQ(StrFormat("%td", int{1}), "1");
00422   EXPECT_EQ(StrFormat("%qd", int{1}), "1");
00423 }
00424 
00425 using str_format_internal::ExtendedParsedFormat;
00426 using str_format_internal::ParsedFormatBase;
00427 
00428 struct SummarizeConsumer {
00429   std::string* out;
00430   explicit SummarizeConsumer(std::string* out) : out(out) {}
00431 
00432   bool Append(string_view s) {
00433     *out += "[" + std::string(s) + "]";
00434     return true;
00435   }
00436 
00437   bool ConvertOne(const str_format_internal::UnboundConversion& conv,
00438                   string_view s) {
00439     *out += "{";
00440     *out += std::string(s);
00441     *out += ":";
00442     *out += std::to_string(conv.arg_position) + "$";
00443     if (conv.width.is_from_arg()) {
00444       *out += std::to_string(conv.width.get_from_arg()) + "$*";
00445     }
00446     if (conv.precision.is_from_arg()) {
00447       *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
00448     }
00449     *out += conv.conv.Char();
00450     *out += "}";
00451     return true;
00452   }
00453 };
00454 
00455 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
00456   std::string out;
00457   if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!";
00458   return out;
00459 }
00460 
00461 using ParsedFormatTest = ::testing::Test;
00462 
00463 TEST_F(ParsedFormatTest, SimpleChecked) {
00464   EXPECT_EQ("[ABC]{d:1$d}[DEF]",
00465             SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
00466   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}",
00467             SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f")));
00468   EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}",
00469             SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d")));
00470 }
00471 
00472 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
00473   auto f = ParsedFormat<'d'>::New("ABC%dDEF");
00474   ASSERT_TRUE(f);
00475   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
00476 
00477   std::string format = "%sFFF%dZZZ%f";
00478   auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);
00479 
00480   ASSERT_TRUE(f2);
00481   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
00482 
00483   f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f");
00484 
00485   ASSERT_TRUE(f2);
00486   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
00487 
00488   auto star = ParsedFormat<'*', 'd'>::New("%*d");
00489   ASSERT_TRUE(star);
00490   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
00491 
00492   auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d");
00493   ASSERT_TRUE(dollar);
00494   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
00495   // with reuse
00496   dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d");
00497   ASSERT_TRUE(dollar);
00498   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
00499             SummarizeParsedFormat(*dollar));
00500 }
00501 
00502 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
00503   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC")));
00504   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC")));
00505   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s")));
00506   auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC");
00507   ASSERT_TRUE(f);
00508   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
00509   f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC");
00510   ASSERT_TRUE(f);
00511   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
00512   f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s");
00513   ASSERT_TRUE(f);
00514   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
00515 }
00516 
00517 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
00518   EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
00519   EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
00520 }
00521 
00522 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
00523   EXPECT_FALSE(ParsedFormat<'d'>::New(""));
00524 
00525   EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
00526 
00527   std::string format = "%sFFF%dZZZ%f";
00528   EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
00529 }
00530 
00531 using str_format_internal::Conv;
00532 
00533 TEST_F(ParsedFormatTest, UncheckedCorrect) {
00534   auto f = ExtendedParsedFormat<Conv::d>::New("ABC%dDEF");
00535   ASSERT_TRUE(f);
00536   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
00537 
00538   std::string format = "%sFFF%dZZZ%f";
00539   auto f2 =
00540       ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
00541 
00542   ASSERT_TRUE(f2);
00543   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
00544 
00545   f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
00546       "%s %d %f");
00547 
00548   ASSERT_TRUE(f2);
00549   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
00550 
00551   auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
00552   ASSERT_TRUE(star);
00553   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
00554 
00555   auto dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d");
00556   ASSERT_TRUE(dollar);
00557   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
00558   // with reuse
00559   dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d %1$d");
00560   ASSERT_TRUE(dollar);
00561   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
00562             SummarizeParsedFormat(*dollar));
00563 }
00564 
00565 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
00566   EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC")));
00567   EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("%dABC")));
00568   EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC%2$s")));
00569   auto f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC");
00570   ASSERT_TRUE(f);
00571   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
00572   f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
00573   ASSERT_TRUE(f);
00574   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
00575   f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
00576   ASSERT_TRUE(f);
00577   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
00578 }
00579 
00580 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
00581   auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
00582   EXPECT_TRUE(dx);
00583   EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
00584 
00585   dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
00586   EXPECT_TRUE(dx);
00587   EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
00588 }
00589 
00590 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
00591   EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
00592 
00593   EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
00594 
00595   std::string format = "%sFFF%dZZZ%f";
00596   EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
00597 }
00598 
00599 TEST_F(ParsedFormatTest, RegressionMixPositional) {
00600   EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
00601 }
00602 
00603 using FormatWrapperTest = ::testing::Test;
00604 
00605 // Plain wrapper for StrFormat.
00606 template <typename... Args>
00607 std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
00608                           const Args&... args) {
00609   return StrFormat(format, args...);
00610 }
00611 
00612 TEST_F(FormatWrapperTest, ConstexprStringFormat) {
00613   EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
00614 }
00615 
00616 TEST_F(FormatWrapperTest, ParsedFormat) {
00617   ParsedFormat<'s'> format("%s there");
00618   EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
00619 }
00620 
00621 }  // namespace
00622 }  // namespace absl
00623 
00624 // Some codegen thunks that we can use to easily dump the generated assembly for
00625 // different StrFormat calls.
00626 
00627 std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
00628   return absl::StrFormat("%d", i);
00629 }
00630 
00631 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
00632                                                int64_t i64) {  // NOLINT
00633   return absl::StrFormat("%d %s %d", i, s, i64);
00634 }
00635 
00636 void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
00637   absl::StrAppendFormat(out, "%d", i);
00638 }
00639 
00640 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
00641                                               const std::string& s,
00642                                               int64_t i64) {  // NOLINT
00643   absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
00644 }


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15