tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

str_format_test.cc (42708B)


      1 // Copyright 2020 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "absl/strings/str_format.h"
     16 
     17 #include <cerrno>
     18 #include <cstdarg>
     19 #include <cstdint>
     20 #include <cstdio>
     21 #include <ostream>
     22 #include <sstream>
     23 #include <string>
     24 #include <type_traits>
     25 
     26 #include "gtest/gtest.h"
     27 #include "absl/base/config.h"
     28 #include "absl/base/macros.h"
     29 #include "absl/strings/cord.h"
     30 #include "absl/strings/str_cat.h"
     31 #include "absl/strings/string_view.h"
     32 #include "absl/types/span.h"
     33 
     34 namespace absl {
     35 ABSL_NAMESPACE_BEGIN
     36 namespace {
     37 using str_format_internal::FormatArgImpl;
     38 
     39 using FormatEntryPointTest = ::testing::Test;
     40 
     41 TEST_F(FormatEntryPointTest, Format) {
     42  std::string sink;
     43  EXPECT_TRUE(Format(&sink, "A format %d", 123));
     44  EXPECT_EQ("A format 123", sink);
     45  sink.clear();
     46 
     47  ParsedFormat<'d'> pc("A format %d");
     48  EXPECT_TRUE(Format(&sink, pc, 123));
     49  EXPECT_EQ("A format 123", sink);
     50 }
     51 
     52 TEST_F(FormatEntryPointTest, FormatWithV) {
     53  std::string sink;
     54  EXPECT_TRUE(Format(&sink, "A format %v", 123));
     55  EXPECT_EQ("A format 123", sink);
     56  sink.clear();
     57 
     58  ParsedFormat<'v'> pc("A format %v");
     59  EXPECT_TRUE(Format(&sink, pc, 123));
     60  EXPECT_EQ("A format 123", sink);
     61 }
     62 
     63 TEST_F(FormatEntryPointTest, UntypedFormat) {
     64  constexpr const char* formats[] = {
     65    "",
     66    "a",
     67    "%80d",
     68 #if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
     69    // MSVC, NaCL and Android don't support positional syntax.
     70    "complicated multipart %% %1$d format %1$0999d",
     71 #endif  // _MSC_VER
     72  };
     73  for (const char* fmt : formats) {
     74    std::string actual;
     75    int i = 123;
     76    FormatArgImpl arg_123(i);
     77    absl::Span<const FormatArgImpl> args(&arg_123, 1);
     78    UntypedFormatSpec format(fmt);
     79 
     80    EXPECT_TRUE(FormatUntyped(&actual, format, args));
     81    char buf[4096]{};
     82    snprintf(buf, sizeof(buf), fmt, 123);
     83    EXPECT_EQ(
     84        str_format_internal::FormatPack(
     85            str_format_internal::UntypedFormatSpecImpl::Extract(format), args),
     86        buf);
     87    EXPECT_EQ(actual, buf);
     88  }
     89  // The internal version works with a preparsed format.
     90  ParsedFormat<'d'> pc("A format %d");
     91  int i = 345;
     92  FormatArg arg(i);
     93  std::string out;
     94  EXPECT_TRUE(str_format_internal::FormatUntyped(
     95      &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1}));
     96  EXPECT_EQ("A format 345", out);
     97 }
     98 
     99 TEST_F(FormatEntryPointTest, StringFormat) {
    100  EXPECT_EQ("123", StrFormat("%d", 123));
    101  constexpr absl::string_view view("=%d=", 4);
    102  EXPECT_EQ("=123=", StrFormat(view, 123));
    103 }
    104 
    105 TEST_F(FormatEntryPointTest, StringFormatV) {
    106  std::string hello = "hello";
    107  EXPECT_EQ("hello", StrFormat("%v", hello));
    108  EXPECT_EQ("123", StrFormat("%v", 123));
    109  constexpr absl::string_view view("=%v=", 4);
    110  EXPECT_EQ("=123=", StrFormat(view, 123));
    111 }
    112 
    113 TEST_F(FormatEntryPointTest, AppendFormat) {
    114  std::string s;
    115  std::string& r = StrAppendFormat(&s, "%d", 123);
    116  EXPECT_EQ(&s, &r);  // should be same object
    117  EXPECT_EQ("123", r);
    118 }
    119 
    120 TEST_F(FormatEntryPointTest, AppendFormatWithV) {
    121  std::string s;
    122  std::string& r = StrAppendFormat(&s, "%v", 123);
    123  EXPECT_EQ(&s, &r);  // should be same object
    124  EXPECT_EQ("123", r);
    125 }
    126 
    127 TEST_F(FormatEntryPointTest, AppendFormatFail) {
    128  std::string s = "orig";
    129 
    130  UntypedFormatSpec format(" more %d");
    131  FormatArgImpl arg("not an int");
    132 
    133  EXPECT_EQ("orig",
    134            str_format_internal::AppendPack(
    135                &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),
    136                {&arg, 1}));
    137 }
    138 
    139 TEST_F(FormatEntryPointTest, AppendFormatFailWithV) {
    140  std::string s = "orig";
    141 
    142  UntypedFormatSpec format(" more %v");
    143  FormatArgImpl arg("not an int");
    144 
    145  EXPECT_EQ("orig",
    146            str_format_internal::AppendPack(
    147                &s, str_format_internal::UntypedFormatSpecImpl::Extract(format),
    148                {&arg, 1}));
    149 }
    150 
    151 TEST_F(FormatEntryPointTest, ManyArgs) {
    152  EXPECT_EQ(
    153      "60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 "
    154      "36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 "
    155      "12 11 10 9 8 7 6 5 4 3 2 1",
    156      StrFormat("%60$d %59$d %58$d %57$d %56$d %55$d %54$d %53$d %52$d %51$d "
    157                "%50$d %49$d %48$d %47$d %46$d %45$d %44$d %43$d %42$d %41$d "
    158                "%40$d %39$d %38$d %37$d %36$d %35$d %34$d %33$d %32$d %31$d "
    159                "%30$d %29$d %28$d %27$d %26$d %25$d %24$d %23$d %22$d %21$d "
    160                "%20$d %19$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d "
    161                "%10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d",
    162                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
    163                19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
    164                35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
    165                51, 52, 53, 54, 55, 56, 57, 58, 59, 60));
    166 }
    167 
    168 TEST_F(FormatEntryPointTest, Preparsed) {
    169  ParsedFormat<'d'> pc("%d");
    170  EXPECT_EQ("123", StrFormat(pc, 123));
    171  // rvalue ok?
    172  EXPECT_EQ("123", StrFormat(ParsedFormat<'d'>("%d"), 123));
    173  constexpr absl::string_view view("=%d=", 4);
    174  EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123));
    175 }
    176 
    177 TEST_F(FormatEntryPointTest, PreparsedWithV) {
    178  ParsedFormat<'v'> pc("%v");
    179  EXPECT_EQ("123", StrFormat(pc, 123));
    180  // rvalue ok?
    181  EXPECT_EQ("123", StrFormat(ParsedFormat<'v'>("%v"), 123));
    182  constexpr absl::string_view view("=%v=", 4);
    183  EXPECT_EQ("=123=", StrFormat(ParsedFormat<'v'>(view), 123));
    184 }
    185 
    186 TEST_F(FormatEntryPointTest, FormatCountCapture) {
    187  int n = 0;
    188  EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
    189  EXPECT_EQ(0, n);
    190  EXPECT_EQ("123", StrFormat("%d%n", 123, FormatCountCapture(&n)));
    191  EXPECT_EQ(3, n);
    192 }
    193 
    194 TEST_F(FormatEntryPointTest, FormatCountCaptureWithV) {
    195  int n = 0;
    196  EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
    197  EXPECT_EQ(0, n);
    198  EXPECT_EQ("123", StrFormat("%v%n", 123, FormatCountCapture(&n)));
    199  EXPECT_EQ(3, n);
    200 }
    201 
    202 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {
    203  // Should reject int*.
    204  int n = 0;
    205  UntypedFormatSpec format("%d%n");
    206  int i = 123, *ip = &n;
    207  FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};
    208 
    209  EXPECT_EQ("", str_format_internal::FormatPack(
    210                    str_format_internal::UntypedFormatSpecImpl::Extract(format),
    211                    absl::MakeSpan(args)));
    212 }
    213 
    214 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongTypeWithV) {
    215  // Should reject int*.
    216  int n = 0;
    217  UntypedFormatSpec format("%v%n");
    218  int i = 123, *ip = &n;
    219  FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};
    220 
    221  EXPECT_EQ("", str_format_internal::FormatPack(
    222                    str_format_internal::UntypedFormatSpecImpl::Extract(format),
    223                    absl::MakeSpan(args)));
    224 }
    225 
    226 TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) {
    227  int n1 = 0;
    228  int n2 = 0;
    229  EXPECT_EQ("    1         2",
    230            StrFormat("%5d%n%10d%n", 1, FormatCountCapture(&n1), 2,
    231                      FormatCountCapture(&n2)));
    232  EXPECT_EQ(5, n1);
    233  EXPECT_EQ(15, n2);
    234 }
    235 
    236 TEST_F(FormatEntryPointTest, FormatCountCaptureExample) {
    237  int n;
    238  std::string s;
    239  StrAppendFormat(&s, "%s: %n%s\n", "(1,1)", FormatCountCapture(&n), "(1,2)");
    240  StrAppendFormat(&s, "%*s%s\n", n, "", "(2,2)");
    241  EXPECT_EQ(7, n);
    242  EXPECT_EQ(
    243      "(1,1): (1,2)\n"
    244      "       (2,2)\n",
    245      s);
    246 }
    247 
    248 TEST_F(FormatEntryPointTest, FormatCountCaptureExampleWithV) {
    249  int n;
    250  std::string s;
    251  std::string a1 = "(1,1)";
    252  std::string a2 = "(1,2)";
    253  std::string a3 = "(2,2)";
    254  StrAppendFormat(&s, "%v: %n%v\n", a1, FormatCountCapture(&n), a2);
    255  StrAppendFormat(&s, "%*s%v\n", n, "", a3);
    256  EXPECT_EQ(7, n);
    257  EXPECT_EQ(
    258      "(1,1): (1,2)\n"
    259      "       (2,2)\n",
    260      s);
    261 }
    262 
    263 TEST_F(FormatEntryPointTest, Stream) {
    264  const std::string formats[] = {
    265    "",
    266    "a",
    267    "%80d",
    268    "%d %u %c %s %f %g",
    269 #if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
    270    // MSVC, NaCL and Android don't support positional syntax.
    271    "complicated multipart %% %1$d format %1$080d",
    272 #endif  // _MSC_VER
    273  };
    274  std::string buf(4096, '\0');
    275  for (const auto& fmt : formats) {
    276    const auto parsed =
    277        ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt);
    278    std::ostringstream oss;
    279    oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
    280    int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(),  //
    281                              123, 3, 49, "multistreaming!!!", 1.01, 1.01);
    282    ASSERT_TRUE(oss) << fmt;
    283    ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
    284        << fmt_result;
    285    EXPECT_EQ(buf.c_str(), oss.str());
    286  }
    287 }
    288 
    289 TEST_F(FormatEntryPointTest, StreamWithV) {
    290  const std::string formats[] = {
    291      "",
    292      "a",
    293      "%v %u %c %v %f %v",
    294  };
    295 
    296  const std::string formats_for_buf[] = {
    297      "",
    298      "a",
    299      "%d %u %c %s %f %g",
    300  };
    301 
    302  std::string buf(4096, '\0');
    303  for (auto i = 0; i < ABSL_ARRAYSIZE(formats); ++i) {
    304    const auto parsed =
    305        ParsedFormat<'v', 'u', 'c', 'v', 'f', 'v'>::NewAllowIgnored(formats[i]);
    306    std::ostringstream oss;
    307    oss << StreamFormat(*parsed, 123, 3, 49,
    308                        absl::string_view("multistreaming!!!"), 1.01, 1.01);
    309    int fmt_result =
    310        snprintf(&*buf.begin(), buf.size(), formats_for_buf[i].c_str(),  //
    311                 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
    312    ASSERT_TRUE(oss) << formats[i];
    313    ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
    314        << fmt_result;
    315    EXPECT_EQ(buf.c_str(), oss.str());
    316  }
    317 }
    318 
    319 TEST_F(FormatEntryPointTest, StreamOk) {
    320  std::ostringstream oss;
    321  oss << StreamFormat("hello %d", 123);
    322  EXPECT_EQ("hello 123", oss.str());
    323  EXPECT_TRUE(oss.good());
    324 }
    325 
    326 TEST_F(FormatEntryPointTest, StreamOkWithV) {
    327  std::ostringstream oss;
    328  oss << StreamFormat("hello %v", 123);
    329  EXPECT_EQ("hello 123", oss.str());
    330  EXPECT_TRUE(oss.good());
    331 }
    332 
    333 TEST_F(FormatEntryPointTest, StreamFail) {
    334  std::ostringstream oss;
    335  UntypedFormatSpec format("hello %d");
    336  FormatArgImpl arg("non-numeric");
    337  oss << str_format_internal::Streamable(
    338      str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});
    339  EXPECT_EQ("hello ", oss.str());  // partial write
    340  EXPECT_TRUE(oss.fail());
    341 }
    342 
    343 TEST_F(FormatEntryPointTest, StreamFailWithV) {
    344  std::ostringstream oss;
    345  UntypedFormatSpec format("hello %v");
    346  FormatArgImpl arg("non-numeric");
    347  oss << str_format_internal::Streamable(
    348      str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1});
    349  EXPECT_EQ("hello ", oss.str());  // partial write
    350  EXPECT_TRUE(oss.fail());
    351 }
    352 
    353 std::string WithSnprintf(const char* fmt, ...) {
    354  std::string buf;
    355  buf.resize(128);
    356  va_list va;
    357  va_start(va, fmt);
    358  int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va);
    359  va_end(va);
    360  EXPECT_GE(r, 0);
    361  EXPECT_LT(r, buf.size());
    362  buf.resize(r);
    363  return buf;
    364 }
    365 
    366 TEST_F(FormatEntryPointTest, FloatPrecisionArg) {
    367  // Test that positional parameters for width and precision
    368  // are indexed to precede the value.
    369  // Also sanity check the same formats against snprintf.
    370  EXPECT_EQ("0.1", StrFormat("%.1f", 0.1));
    371  EXPECT_EQ("0.1", WithSnprintf("%.1f", 0.1));
    372  EXPECT_EQ("  0.1", StrFormat("%*.1f", 5, 0.1));
    373  EXPECT_EQ("  0.1", WithSnprintf("%*.1f", 5, 0.1));
    374  EXPECT_EQ("0.1", StrFormat("%.*f", 1, 0.1));
    375  EXPECT_EQ("0.1", WithSnprintf("%.*f", 1, 0.1));
    376  EXPECT_EQ("  0.1", StrFormat("%*.*f", 5, 1, 0.1));
    377  EXPECT_EQ("  0.1", WithSnprintf("%*.*f", 5, 1, 0.1));
    378 }
    379 namespace streamed_test {
    380 struct X {};
    381 std::ostream& operator<<(std::ostream& os, const X&) {
    382  return os << "X";
    383 }
    384 }  // streamed_test
    385 
    386 TEST_F(FormatEntryPointTest, FormatStreamed) {
    387  EXPECT_EQ("123", StrFormat("%s", FormatStreamed(123)));
    388  EXPECT_EQ("  123", StrFormat("%5s", FormatStreamed(123)));
    389  EXPECT_EQ("123  ", StrFormat("%-5s", FormatStreamed(123)));
    390  EXPECT_EQ("X", StrFormat("%s", FormatStreamed(streamed_test::X())));
    391  EXPECT_EQ("123", StrFormat("%s", FormatStreamed(StreamFormat("%d", 123))));
    392 }
    393 
    394 TEST_F(FormatEntryPointTest, FormatStreamedWithV) {
    395  EXPECT_EQ("123", StrFormat("%v", FormatStreamed(123)));
    396  EXPECT_EQ("X", StrFormat("%v", FormatStreamed(streamed_test::X())));
    397  EXPECT_EQ("123", StrFormat("%v", FormatStreamed(StreamFormat("%d", 123))));
    398 }
    399 
    400 // Helper class that creates a temporary file and exposes a FILE* to it.
    401 // It will close the file on destruction.
    402 class TempFile {
    403 public:
    404  TempFile() : file_(std::tmpfile()) {}
    405  ~TempFile() { std::fclose(file_); }
    406 
    407  std::FILE* file() const { return file_; }
    408 
    409  // Read the file into a string.
    410  std::string ReadFile() {
    411    std::fseek(file_, 0, SEEK_END);
    412    int size = std::ftell(file_);
    413    EXPECT_GT(size, 0);
    414    std::rewind(file_);
    415    std::string str(2 * size, ' ');
    416    int read_bytes = std::fread(&str[0], 1, str.size(), file_);
    417    EXPECT_EQ(read_bytes, size);
    418    str.resize(read_bytes);
    419    EXPECT_TRUE(std::feof(file_));
    420    return str;
    421  }
    422 
    423 private:
    424  std::FILE* file_;
    425 };
    426 
    427 TEST_F(FormatEntryPointTest, FPrintF) {
    428  TempFile tmp;
    429  int result =
    430      FPrintF(tmp.file(), "STRING: %s NUMBER: %010d", std::string("ABC"), -19);
    431  EXPECT_EQ(result, 30);
    432  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
    433 }
    434 
    435 TEST_F(FormatEntryPointTest, FPrintFWithV) {
    436  TempFile tmp;
    437  int result =
    438      FPrintF(tmp.file(), "STRING: %v NUMBER: %010d", std::string("ABC"), -19);
    439  EXPECT_EQ(result, 30);
    440  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
    441 }
    442 
    443 TEST_F(FormatEntryPointTest, FPrintFError) {
    444  errno = 0;
    445  int result = FPrintF(stdin, "ABC");
    446  EXPECT_LT(result, 0);
    447  EXPECT_EQ(errno, EBADF);
    448 }
    449 
    450 #ifdef __GLIBC__
    451 TEST_F(FormatEntryPointTest, FprintfTooLarge) {
    452  std::FILE* f = std::fopen("/dev/null", "w");
    453  int width = 2000000000;
    454  errno = 0;
    455  int result = FPrintF(f, "%*d %*d", width, 0, width, 0);
    456  EXPECT_LT(result, 0);
    457  EXPECT_EQ(errno, EFBIG);
    458  std::fclose(f);
    459 }
    460 
    461 TEST_F(FormatEntryPointTest, PrintF) {
    462  int stdout_tmp = dup(STDOUT_FILENO);
    463 
    464  TempFile tmp;
    465  std::fflush(stdout);
    466  dup2(fileno(tmp.file()), STDOUT_FILENO);
    467 
    468  int result = PrintF("STRING: %s NUMBER: %010d", std::string("ABC"), -19);
    469 
    470  std::fflush(stdout);
    471  dup2(stdout_tmp, STDOUT_FILENO);
    472  close(stdout_tmp);
    473 
    474  EXPECT_EQ(result, 30);
    475  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
    476 }
    477 
    478 TEST_F(FormatEntryPointTest, PrintFWithV) {
    479  int stdout_tmp = dup(STDOUT_FILENO);
    480 
    481  TempFile tmp;
    482  std::fflush(stdout);
    483  dup2(fileno(tmp.file()), STDOUT_FILENO);
    484 
    485  int result = PrintF("STRING: %v NUMBER: %010d", std::string("ABC"), -19);
    486 
    487  std::fflush(stdout);
    488  dup2(stdout_tmp, STDOUT_FILENO);
    489  close(stdout_tmp);
    490 
    491  EXPECT_EQ(result, 30);
    492  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
    493 }
    494 #endif  // __GLIBC__
    495 
    496 TEST_F(FormatEntryPointTest, SNPrintF) {
    497  char buffer[16];
    498  int result =
    499      SNPrintF(buffer, sizeof(buffer), "STRING: %s", std::string("ABC"));
    500  EXPECT_EQ(result, 11);
    501  EXPECT_EQ(std::string(buffer), "STRING: ABC");
    502 
    503  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456);
    504  EXPECT_EQ(result, 14);
    505  EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
    506 
    507  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567);
    508  EXPECT_EQ(result, 15);
    509  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    510 
    511  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678);
    512  EXPECT_EQ(result, 16);
    513  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    514 
    515  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789);
    516  EXPECT_EQ(result, 17);
    517  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    518 
    519  // The `output` parameter is annotated nonnull, but we want to test that
    520  // it is never written to if the size is zero.
    521  // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull`
    522  // warning.
    523  char* null_output = nullptr;
    524  result =
    525      SNPrintF(null_output, 0, "Just checking the %s of the output.", "size");
    526  EXPECT_EQ(result, 37);
    527 }
    528 
    529 TEST_F(FormatEntryPointTest, SNPrintFWithV) {
    530  char buffer[16];
    531  int result =
    532      SNPrintF(buffer, sizeof(buffer), "STRING: %v", std::string("ABC"));
    533  EXPECT_EQ(result, 11);
    534  EXPECT_EQ(std::string(buffer), "STRING: ABC");
    535 
    536  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456);
    537  EXPECT_EQ(result, 14);
    538  EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
    539 
    540  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 1234567);
    541  EXPECT_EQ(result, 15);
    542  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    543 
    544  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 12345678);
    545  EXPECT_EQ(result, 16);
    546  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    547 
    548  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456789);
    549  EXPECT_EQ(result, 17);
    550  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
    551 
    552  std::string size = "size";
    553 
    554  // The `output` parameter is annotated nonnull, but we want to test that
    555  // it is never written to if the size is zero.
    556  // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull`
    557  // warning.
    558  char* null_output = nullptr;
    559  result =
    560      SNPrintF(null_output, 0, "Just checking the %v of the output.", size);
    561  EXPECT_EQ(result, 37);
    562 }
    563 
    564 TEST(StrFormat, BehavesAsDocumented) {
    565  std::string s = absl::StrFormat("%s, %d!", "Hello", 123);
    566  EXPECT_EQ("Hello, 123!", s);
    567  std::string hello = "Hello";
    568  std::string s2 = absl::StrFormat("%v, %v!", hello, 123);
    569  EXPECT_EQ("Hello, 123!", s2);
    570  // The format of a replacement is
    571  // '%'[position][flags][width['.'precision]][length_modifier][format]
    572  EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10");
    573  // Text conversion:
    574  //     "c" - Character.              Eg: 'a' -> "A", 20 -> " "
    575  EXPECT_EQ(StrFormat("%c", 'a'), "a");
    576  EXPECT_EQ(StrFormat("%c", 0x20), " ");
    577  //           Formats char and integral types: int, long, uint64_t, etc.
    578  EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
    579  EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
    580  EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
    581  //     "s" - string       Eg: "C" -> "C", std::string("C++") -> "C++"
    582  //           Formats std::string, char*, string_view, and Cord.
    583  EXPECT_EQ(StrFormat("%s", "C"), "C");
    584  EXPECT_EQ(StrFormat("%v", std::string("C")), "C");
    585  EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
    586  EXPECT_EQ(StrFormat("%v", std::string("C++")), "C++");
    587  EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
    588  EXPECT_EQ(StrFormat("%v", string_view("view")), "view");
    589  EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
    590  EXPECT_EQ(StrFormat("%v", absl::Cord("cord")), "cord");
    591  // Integral Conversion
    592  //     These format integral types: char, int, long, uint64_t, etc.
    593  EXPECT_EQ(StrFormat("%d", char{10}), "10");
    594  EXPECT_EQ(StrFormat("%d", int{10}), "10");
    595  EXPECT_EQ(StrFormat("%d", long{10}), "10");  // NOLINT
    596  EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10");
    597  EXPECT_EQ(StrFormat("%v", int{10}), "10");
    598  EXPECT_EQ(StrFormat("%v", long{10}), "10");  // NOLINT
    599  EXPECT_EQ(StrFormat("%v", uint64_t{10}), "10");
    600  //     d,i - signed decimal          Eg: -10 -> "-10"
    601  EXPECT_EQ(StrFormat("%d", -10), "-10");
    602  EXPECT_EQ(StrFormat("%i", -10), "-10");
    603  EXPECT_EQ(StrFormat("%v", -10), "-10");
    604  //      o  - octal                   Eg:  10 -> "12"
    605  EXPECT_EQ(StrFormat("%o", 10), "12");
    606  //      u  - unsigned decimal        Eg:  10 -> "10"
    607  EXPECT_EQ(StrFormat("%u", 10), "10");
    608  EXPECT_EQ(StrFormat("%v", 10), "10");
    609  //     x/X - lower,upper case hex    Eg:  10 -> "a"/"A"
    610  EXPECT_EQ(StrFormat("%x", 10), "a");
    611  EXPECT_EQ(StrFormat("%X", 10), "A");
    612  // Floating-point, with upper/lower-case output.
    613  //     These format floating points types: float, double, long double, etc.
    614  EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0");
    615  EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0");
    616  const long double long_double = 1.0;
    617  EXPECT_EQ(StrFormat("%.1f", long_double), "1.0");
    618  //     These also format integral types: char, int, long, uint64_t, etc.:
    619  EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0");
    620  EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0");
    621  EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0");  // NOLINT
    622  EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0");
    623  //     f/F - decimal.                Eg: 123456789 -> "123456789.000000"
    624  EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000");
    625  EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000");
    626  //     e/E - exponentiated           Eg: .01 -> "1.00000e-2"/"1.00000E-2"
    627  EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02");
    628  EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02");
    629  //     g/G - exponentiate to fit     Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10"
    630  EXPECT_EQ(StrFormat("%g", .01), "0.01");
    631  EXPECT_EQ(StrFormat("%g", 1e10), "1e+10");
    632  EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
    633  EXPECT_EQ(StrFormat("%v", .01), "0.01");
    634  EXPECT_EQ(StrFormat("%v", 1e10), "1e+10");
    635  //     a/A - lower,upper case hex    Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
    636 
    637 // On Android platform <=21, there is a regression in hexfloat formatting.
    638 #if !defined(__ANDROID_API__) || __ANDROID_API__ > 21
    639  EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1");  // .1 to fix MSVC output
    640  EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1");  // .1 to fix MSVC output
    641 #endif
    642 
    643  // Other conversion
    644  int64_t value = 0x7ffdeb4;
    645  auto ptr_value = static_cast<uintptr_t>(value);
    646  const int& something = *reinterpret_cast<const int*>(ptr_value);
    647  EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value));
    648 
    649  // The output of formatting a null pointer is not documented as being a
    650  // specific thing, but the attempt should at least compile.
    651  (void)StrFormat("%p", nullptr);
    652 
    653  // Output widths are supported, with optional flags.
    654  EXPECT_EQ(StrFormat("%3d", 1), "  1");
    655  EXPECT_EQ(StrFormat("%3d", 123456), "123456");
    656  EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23");
    657  EXPECT_EQ(StrFormat("%+d", 1), "+1");
    658  EXPECT_EQ(StrFormat("% d", 1), " 1");
    659  EXPECT_EQ(StrFormat("%-4d", -1), "-1  ");
    660  EXPECT_EQ(StrFormat("%#o", 10), "012");
    661  EXPECT_EQ(StrFormat("%#x", 15), "0xf");
    662  EXPECT_EQ(StrFormat("%04d", 8), "0008");
    663  EXPECT_EQ(StrFormat("%#04x", 0), "0000");
    664  EXPECT_EQ(StrFormat("%#04x", 1), "0x01");
    665  // Posix positional substitution.
    666  EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"),
    667            "veni, vidi, vici!");
    668  // Length modifiers are ignored.
    669  EXPECT_EQ(StrFormat("%hhd", int{1}), "1");
    670  EXPECT_EQ(StrFormat("%hd", int{1}), "1");
    671  EXPECT_EQ(StrFormat("%ld", int{1}), "1");
    672  EXPECT_EQ(StrFormat("%lld", int{1}), "1");
    673  EXPECT_EQ(StrFormat("%Ld", int{1}), "1");
    674  EXPECT_EQ(StrFormat("%jd", int{1}), "1");
    675  EXPECT_EQ(StrFormat("%zd", int{1}), "1");
    676  EXPECT_EQ(StrFormat("%td", int{1}), "1");
    677  EXPECT_EQ(StrFormat("%qd", int{1}), "1");
    678 
    679  // Bool is handled correctly depending on whether %v is used
    680  EXPECT_EQ(StrFormat("%v", true), "true");
    681  EXPECT_EQ(StrFormat("%v", false), "false");
    682  EXPECT_EQ(StrFormat("%d", true), "1");
    683 }
    684 
    685 using str_format_internal::ExtendedParsedFormat;
    686 using str_format_internal::ParsedFormatBase;
    687 
    688 struct SummarizeConsumer {
    689  std::string* out;
    690  explicit SummarizeConsumer(std::string* out) : out(out) {}
    691 
    692  bool Append(string_view s) {
    693    *out += "[" + std::string(s) + "]";
    694    return true;
    695  }
    696 
    697  bool ConvertOne(const str_format_internal::UnboundConversion& conv,
    698                  string_view s) {
    699    *out += "{";
    700    *out += std::string(s);
    701    *out += ":";
    702    *out += std::to_string(conv.arg_position) + "$";
    703    if (conv.width.is_from_arg()) {
    704      *out += std::to_string(conv.width.get_from_arg()) + "$*";
    705    }
    706    if (conv.precision.is_from_arg()) {
    707      *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
    708    }
    709    *out += str_format_internal::FormatConversionCharToChar(conv.conv);
    710    *out += "}";
    711    return true;
    712  }
    713 };
    714 
    715 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
    716  std::string out;
    717  if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!";
    718  return out;
    719 }
    720 
    721 using ParsedFormatTest = ::testing::Test;
    722 
    723 TEST_F(ParsedFormatTest, SimpleChecked) {
    724  EXPECT_EQ("[ABC]{d:1$d}[DEF]",
    725            SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
    726  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}",
    727            SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f")));
    728  EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}",
    729            SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d")));
    730 }
    731 
    732 TEST_F(ParsedFormatTest, SimpleCheckedWithV) {
    733  EXPECT_EQ("[ABC]{v:1$v}[DEF]",
    734            SummarizeParsedFormat(ParsedFormat<'v'>("ABC%vDEF")));
    735  EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}",
    736            SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>("%vFFF%vZZZ%f")));
    737  EXPECT_EQ("{v:1$v}[ ]{.*d:3$.2$*d}",
    738            SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>("%v %.*d")));
    739 }
    740 
    741 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
    742  auto f = ParsedFormat<'d'>::New("ABC%dDEF");
    743  ASSERT_TRUE(f);
    744  EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
    745 
    746  std::string format = "%sFFF%dZZZ%f";
    747  auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);
    748 
    749  ASSERT_TRUE(f2);
    750  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
    751 
    752  f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f");
    753 
    754  ASSERT_TRUE(f2);
    755  EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
    756 
    757  auto star = ParsedFormat<'*', 'd'>::New("%*d");
    758  ASSERT_TRUE(star);
    759  EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
    760 
    761  auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d");
    762  ASSERT_TRUE(dollar);
    763  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
    764  // with reuse
    765  dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d");
    766  ASSERT_TRUE(dollar);
    767  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
    768            SummarizeParsedFormat(*dollar));
    769 }
    770 
    771 TEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) {
    772  auto f = ParsedFormat<'v'>::New("ABC%vDEF");
    773  ASSERT_TRUE(f);
    774  EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
    775 
    776  std::string format = "%vFFF%vZZZ%f";
    777  auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format);
    778 
    779  ASSERT_TRUE(f2);
    780  EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
    781 
    782  f2 = ParsedFormat<'v', 'v', 'f'>::New("%v %v %f");
    783 
    784  ASSERT_TRUE(f2);
    785  EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
    786 }
    787 
    788 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
    789  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC")));
    790  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC")));
    791  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s")));
    792  auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC");
    793  ASSERT_TRUE(f);
    794  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
    795  f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC");
    796  ASSERT_TRUE(f);
    797  EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
    798  f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s");
    799  ASSERT_TRUE(f);
    800  EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
    801 }
    802 
    803 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) {
    804  EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("ABC")));
    805  EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("%vABC")));
    806  EXPECT_FALSE((ParsedFormat<'v', 's'>::New("ABC%2$s")));
    807  auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored("ABC");
    808  ASSERT_TRUE(f);
    809  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
    810  f = ParsedFormat<'v', 'v'>::NewAllowIgnored("%vABC");
    811  ASSERT_TRUE(f);
    812  EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
    813 }
    814 
    815 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
    816  EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
    817  EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
    818 }
    819 
    820 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
    821  EXPECT_FALSE(ParsedFormat<'d'>::New(""));
    822 
    823  EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
    824 
    825  std::string format = "%sFFF%dZZZ%f";
    826  EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
    827 }
    828 
    829 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) {
    830  EXPECT_FALSE(ParsedFormat<'v'>::New(""));
    831 
    832  EXPECT_FALSE(ParsedFormat<'v'>::New("ABC%vDEF%v"));
    833 
    834  std::string format = "%vFFF%vZZZ%f";
    835  EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format)));
    836 }
    837 
    838 #if defined(__cpp_nontype_template_parameter_auto)
    839 
    840 template <auto T>
    841 std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
    842 
    843 template <auto T>
    844 std::false_type IsValidParsedFormatArgTest(...);
    845 
    846 template <auto T>
    847 using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
    848 
    849 TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
    850  ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
    851 
    852  ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
    853 
    854  ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
    855                                     absl::FormatConversionCharSet::x>::value);
    856  ASSERT_TRUE(
    857      IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
    858 
    859  // This is an easy mistake to make, however, this will reduce to an integer
    860  // which has no meaning, so we need to ensure it doesn't compile.
    861  ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
    862 
    863  // For now, we disallow construction based on ConversionChar (rather than
    864  // CharSet)
    865  ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
    866 }
    867 
    868 TEST_F(ParsedFormatTest, ExtendedTyping) {
    869  EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
    870  ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
    871  auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
    872  ASSERT_TRUE(v1);
    873  auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
    874  ASSERT_TRUE(v2);
    875  auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
    876                             absl::FormatConversionCharSet::s,
    877                         's'>::New("%d%s");
    878  ASSERT_TRUE(v3);
    879  auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
    880                             absl::FormatConversionCharSet::s,
    881                         's'>::New("%s%s");
    882  ASSERT_TRUE(v4);
    883 }
    884 
    885 TEST_F(ParsedFormatTest, ExtendedTypingWithV) {
    886  EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New(""));
    887  ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New("%v"));
    888  auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New("%v%v");
    889  ASSERT_TRUE(v1);
    890  auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New("%v%v");
    891  ASSERT_TRUE(v2);
    892  auto v3 = ParsedFormat<absl::FormatConversionCharSet::v |
    893                             absl::FormatConversionCharSet::v,
    894                         'v'>::New("%v%v");
    895  ASSERT_TRUE(v3);
    896  auto v4 = ParsedFormat<absl::FormatConversionCharSet::v |
    897                             absl::FormatConversionCharSet::v,
    898                         'v'>::New("%v%v");
    899  ASSERT_TRUE(v4);
    900 }
    901 #endif
    902 
    903 TEST_F(ParsedFormatTest, UncheckedCorrect) {
    904  auto f =
    905      ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
    906  ASSERT_TRUE(f);
    907  EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
    908 
    909  std::string format = "%sFFF%dZZZ%f";
    910  auto f2 = ExtendedParsedFormat<
    911      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
    912      absl::FormatConversionCharSet::kFloating>::New(format);
    913 
    914  ASSERT_TRUE(f2);
    915  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
    916 
    917  f2 = ExtendedParsedFormat<
    918      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
    919      absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
    920 
    921  ASSERT_TRUE(f2);
    922  EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
    923 
    924  auto star =
    925      ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
    926                           absl::FormatConversionCharSet::d>::New("%*d");
    927  ASSERT_TRUE(star);
    928  EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
    929 
    930  auto dollar =
    931      ExtendedParsedFormat<absl::FormatConversionCharSet::d,
    932                           absl::FormatConversionCharSet::s>::New("%2$s %1$d");
    933  ASSERT_TRUE(dollar);
    934  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
    935  // with reuse
    936  dollar = ExtendedParsedFormat<
    937      absl::FormatConversionCharSet::d,
    938      absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
    939  ASSERT_TRUE(dollar);
    940  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
    941            SummarizeParsedFormat(*dollar));
    942 }
    943 
    944 TEST_F(ParsedFormatTest, UncheckedCorrectWithV) {
    945  auto f =
    946      ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("ABC%vDEF");
    947  ASSERT_TRUE(f);
    948  EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
    949 
    950  std::string format = "%vFFF%vZZZ%f";
    951  auto f2 = ExtendedParsedFormat<
    952      absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
    953      absl::FormatConversionCharSet::kFloating>::New(format);
    954 
    955  ASSERT_TRUE(f2);
    956  EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
    957 
    958  f2 = ExtendedParsedFormat<
    959      absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
    960      absl::FormatConversionCharSet::kFloating>::New("%v %v %f");
    961 
    962  ASSERT_TRUE(f2);
    963  EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
    964 }
    965 
    966 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
    967  EXPECT_FALSE(
    968      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
    969                            absl::FormatConversionCharSet::s>::New("ABC")));
    970  EXPECT_FALSE(
    971      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
    972                            absl::FormatConversionCharSet::s>::New("%dABC")));
    973  EXPECT_FALSE(
    974      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
    975                            absl::FormatConversionCharSet::s>::New("ABC%2$s")));
    976  auto f = ExtendedParsedFormat<
    977      absl::FormatConversionCharSet::d,
    978      absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
    979  ASSERT_TRUE(f);
    980  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
    981  f = ExtendedParsedFormat<
    982      absl::FormatConversionCharSet::d,
    983      absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
    984  ASSERT_TRUE(f);
    985  EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
    986  f = ExtendedParsedFormat<
    987      absl::FormatConversionCharSet::d,
    988      absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
    989  ASSERT_TRUE(f);
    990  EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
    991 }
    992 
    993 TEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) {
    994  EXPECT_FALSE(
    995      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
    996                            absl::FormatConversionCharSet::v>::New("ABC")));
    997  EXPECT_FALSE(
    998      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
    999                            absl::FormatConversionCharSet::v>::New("%vABC")));
   1000  EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v,
   1001                                     absl::FormatConversionCharSet::s>::
   1002                    New("ABC%2$s")));
   1003  auto f = ExtendedParsedFormat<
   1004      absl::FormatConversionCharSet::v,
   1005      absl::FormatConversionCharSet::v>::NewAllowIgnored("ABC");
   1006  ASSERT_TRUE(f);
   1007  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
   1008  f = ExtendedParsedFormat<
   1009      absl::FormatConversionCharSet::v,
   1010      absl::FormatConversionCharSet::v>::NewAllowIgnored("%vABC");
   1011  ASSERT_TRUE(f);
   1012  EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
   1013 }
   1014 
   1015 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
   1016  auto dx =
   1017      ExtendedParsedFormat<absl::FormatConversionCharSet::d |
   1018                           absl::FormatConversionCharSet::x>::New("%1$d %1$x");
   1019  EXPECT_TRUE(dx);
   1020  EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
   1021 
   1022  dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
   1023                            absl::FormatConversionCharSet::x>::New("%1$d");
   1024  EXPECT_TRUE(dx);
   1025  EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
   1026 }
   1027 
   1028 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
   1029  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
   1030 
   1031  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
   1032      "ABC%dDEF%d"));
   1033 
   1034  std::string format = "%sFFF%dZZZ%f";
   1035  EXPECT_FALSE(
   1036      (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
   1037                            absl::FormatConversionCharSet::d,
   1038                            absl::FormatConversionCharSet::g>::New(format)));
   1039 }
   1040 
   1041 TEST_F(ParsedFormatTest, UncheckedIncorrectWithV) {
   1042  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(""));
   1043 
   1044  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(
   1045      "ABC%vDEF%v"));
   1046 
   1047  std::string format = "%vFFF%vZZZ%f";
   1048  EXPECT_FALSE(
   1049      (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
   1050                            absl::FormatConversionCharSet::g>::New(format)));
   1051 }
   1052 
   1053 TEST_F(ParsedFormatTest, RegressionMixPositional) {
   1054  EXPECT_FALSE(
   1055      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
   1056                            absl::FormatConversionCharSet::o>::New("%1$d %o")));
   1057 }
   1058 
   1059 TEST_F(ParsedFormatTest, DisallowModifiersWithV) {
   1060  auto f = ParsedFormat<'v'>::New("ABC%80vDEF");
   1061  EXPECT_EQ(f, nullptr);
   1062 
   1063  f = ParsedFormat<'v'>::New("ABC%0vDEF");
   1064  EXPECT_EQ(f, nullptr);
   1065 
   1066  f = ParsedFormat<'v'>::New("ABC%.1vDEF");
   1067  EXPECT_EQ(f, nullptr);
   1068 }
   1069 
   1070 using FormatWrapperTest = ::testing::Test;
   1071 
   1072 // Plain wrapper for StrFormat.
   1073 template <typename... Args>
   1074 std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
   1075                          const Args&... args) {
   1076  return StrFormat(format, args...);
   1077 }
   1078 
   1079 TEST_F(FormatWrapperTest, ConstexprStringFormat) {
   1080  EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
   1081 }
   1082 
   1083 TEST_F(FormatWrapperTest, ConstexprStringFormatWithV) {
   1084  std::string hello = "hello";
   1085  EXPECT_EQ(WrappedFormat("%v there", hello), "hello there");
   1086 }
   1087 
   1088 TEST_F(FormatWrapperTest, ParsedFormat) {
   1089  ParsedFormat<'s'> format("%s there");
   1090  EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
   1091 }
   1092 
   1093 TEST_F(FormatWrapperTest, ParsedFormatWithV) {
   1094  std::string hello = "hello";
   1095  ParsedFormat<'v'> format("%v there");
   1096  EXPECT_EQ(WrappedFormat(format, hello), "hello there");
   1097 }
   1098 
   1099 }  // namespace
   1100 ABSL_NAMESPACE_END
   1101 }  // namespace absl
   1102 
   1103 namespace {
   1104 using FormatExtensionTest = ::testing::Test;
   1105 
   1106 struct Point {
   1107  friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
   1108                                   absl::FormatConversionCharSet::kIntegral |
   1109                                   absl::FormatConversionCharSet::v>
   1110  AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
   1111                    absl::FormatSink* s) {
   1112    if (spec.conversion_char() == absl::FormatConversionChar::s) {
   1113      s->Append(absl::StrCat("x=", p.x, " y=", p.y));
   1114    } else {
   1115      s->Append(absl::StrCat(p.x, ",", p.y));
   1116    }
   1117    return {true};
   1118  }
   1119 
   1120  int x = 10;
   1121  int y = 20;
   1122 };
   1123 
   1124 TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
   1125  Point p;
   1126  EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
   1127  EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
   1128  EXPECT_EQ(absl::StrFormat("a %v z", p), "a 10,20 z");
   1129 
   1130  // Typed formatting will fail to compile an invalid format.
   1131  // StrFormat("%f", p);  // Does not compile.
   1132  std::string actual;
   1133  absl::UntypedFormatSpec f1("%f");
   1134  // FormatUntyped will return false for bad character.
   1135  EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
   1136 }
   1137 
   1138 struct PointStringify {
   1139  template <typename FormatSink>
   1140  friend void AbslStringify(FormatSink& sink, const PointStringify& p) {
   1141    sink.Append(absl::StrCat("(", p.x, ", ", p.y, ")"));
   1142  }
   1143 
   1144  double x = 10.0;
   1145  double y = 20.0;
   1146 };
   1147 
   1148 TEST_F(FormatExtensionTest, AbslStringifyExample) {
   1149  PointStringify p;
   1150  EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
   1151 }
   1152 
   1153 struct PointStringifyUsingFormat {
   1154  template <typename FormatSink>
   1155  friend void AbslStringify(FormatSink& sink,
   1156                            const PointStringifyUsingFormat& p) {
   1157    absl::Format(&sink, "(%g, %g)", p.x, p.y);
   1158  }
   1159 
   1160  double x = 10.0;
   1161  double y = 20.0;
   1162 };
   1163 
   1164 TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {
   1165  PointStringifyUsingFormat p;
   1166  EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
   1167 }
   1168 
   1169 enum class EnumClassWithStringify { Many = 0, Choices = 1 };
   1170 
   1171 template <typename Sink>
   1172 void AbslStringify(Sink& sink, EnumClassWithStringify e) {
   1173  absl::Format(&sink, "%s",
   1174               e == EnumClassWithStringify::Many ? "Many" : "Choices");
   1175 }
   1176 
   1177 enum EnumWithStringify { Many, Choices };
   1178 
   1179 template <typename Sink>
   1180 void AbslStringify(Sink& sink, EnumWithStringify e) {
   1181  absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices");
   1182 }
   1183 
   1184 TEST_F(FormatExtensionTest, AbslStringifyWithEnumWithV) {
   1185  const auto e_class = EnumClassWithStringify::Choices;
   1186  EXPECT_EQ(absl::StrFormat("My choice is %v", e_class),
   1187            "My choice is Choices");
   1188 
   1189  const auto e = EnumWithStringify::Choices;
   1190  EXPECT_EQ(absl::StrFormat("My choice is %v", e), "My choice is Choices");
   1191 }
   1192 
   1193 TEST_F(FormatExtensionTest, AbslStringifyEnumWithD) {
   1194  const auto e_class = EnumClassWithStringify::Many;
   1195  EXPECT_EQ(absl::StrFormat("My choice is %d", e_class), "My choice is 0");
   1196 
   1197  const auto e = EnumWithStringify::Choices;
   1198  EXPECT_EQ(absl::StrFormat("My choice is %d", e), "My choice is 1");
   1199 }
   1200 
   1201 enum class EnumWithLargerValue { x = 32 };
   1202 
   1203 template <typename Sink>
   1204 void AbslStringify(Sink& sink, EnumWithLargerValue e) {
   1205  absl::Format(&sink, "%s", "Many");
   1206 }
   1207 
   1208 TEST_F(FormatExtensionTest, AbslStringifyEnumOtherSpecifiers) {
   1209  const auto e = EnumWithLargerValue::x;
   1210  EXPECT_EQ(absl::StrFormat("My choice is %g", e), "My choice is 32");
   1211  EXPECT_EQ(absl::StrFormat("My choice is %x", e), "My choice is 20");
   1212 }
   1213 
   1214 }  // namespace
   1215 
   1216 // Some codegen thunks that we can use to easily dump the generated assembly for
   1217 // different StrFormat calls.
   1218 
   1219 std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
   1220  return absl::StrFormat("%d", i);
   1221 }
   1222 
   1223 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
   1224                                               int64_t i64) {  // NOLINT
   1225  return absl::StrFormat("%d %s %d", i, s, i64);
   1226 }
   1227 
   1228 void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
   1229  absl::StrAppendFormat(out, "%d", i);
   1230 }
   1231 
   1232 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
   1233                                              const std::string& s,
   1234                                              int64_t i64) {  // NOLINT
   1235  absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
   1236 }