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