• 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 <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 
TEST_F(FormatEntryPointTest,Format)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 
TEST_F(FormatEntryPointTest,FormatWithV)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 
TEST_F(FormatEntryPointTest,UntypedFormat)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 
TEST_F(FormatEntryPointTest,StringFormat)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 
TEST_F(FormatEntryPointTest,StringFormatV)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 
TEST_F(FormatEntryPointTest,AppendFormat)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 
TEST_F(FormatEntryPointTest,AppendFormatWithV)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 
TEST_F(FormatEntryPointTest,AppendFormatFail)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 
TEST_F(FormatEntryPointTest,AppendFormatFailWithV)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 
TEST_F(FormatEntryPointTest,ManyArgs)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 
TEST_F(FormatEntryPointTest,Preparsed)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 
TEST_F(FormatEntryPointTest,PreparsedWithV)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 
TEST_F(FormatEntryPointTest,FormatCountCapture)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureWithV)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureWrongType)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureWrongTypeWithV)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureMultiple)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureExample)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 
TEST_F(FormatEntryPointTest,FormatCountCaptureExampleWithV)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 
TEST_F(FormatEntryPointTest,Stream)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 
TEST_F(FormatEntryPointTest,StreamWithV)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 
TEST_F(FormatEntryPointTest,StreamOk)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 
TEST_F(FormatEntryPointTest,StreamOkWithV)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 
TEST_F(FormatEntryPointTest,StreamFail)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 
TEST_F(FormatEntryPointTest,StreamFailWithV)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 
WithSnprintf(const char * fmt,...)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 
TEST_F(FormatEntryPointTest,FloatPrecisionArg)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 {};
operator <<(std::ostream & os,const X &)381 std::ostream& operator<<(std::ostream& os, const X&) {
382   return os << "X";
383 }
384 }  // streamed_test
385 
TEST_F(FormatEntryPointTest,FormatStreamed)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 
TEST_F(FormatEntryPointTest,FormatStreamedWithV)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:
TempFile()404   TempFile() : file_(std::tmpfile()) {}
~TempFile()405   ~TempFile() { std::fclose(file_); }
406 
file() const407   std::FILE* file() const { return file_; }
408 
409   // Read the file into a string.
ReadFile()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 
TEST_F(FormatEntryPointTest,FPrintF)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 
TEST_F(FormatEntryPointTest,FPrintFWithV)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 
TEST_F(FormatEntryPointTest,FPrintFError)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__
TEST_F(FormatEntryPointTest,FprintfTooLarge)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 
TEST_F(FormatEntryPointTest,PrintF)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 
TEST_F(FormatEntryPointTest,PrintFWithV)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 
TEST_F(FormatEntryPointTest,SNPrintF)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   result = SNPrintF(nullptr, 0, "Just checking the %s of the output.", "size");
520   EXPECT_EQ(result, 37);
521 }
522 
TEST_F(FormatEntryPointTest,SNPrintFWithV)523 TEST_F(FormatEntryPointTest, SNPrintFWithV) {
524   char buffer[16];
525   int result =
526       SNPrintF(buffer, sizeof(buffer), "STRING: %v", std::string("ABC"));
527   EXPECT_EQ(result, 11);
528   EXPECT_EQ(std::string(buffer), "STRING: ABC");
529 
530   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456);
531   EXPECT_EQ(result, 14);
532   EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
533 
534   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 1234567);
535   EXPECT_EQ(result, 15);
536   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
537 
538   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 12345678);
539   EXPECT_EQ(result, 16);
540   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
541 
542   result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456789);
543   EXPECT_EQ(result, 17);
544   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
545 
546   std::string size = "size";
547 
548   result = SNPrintF(nullptr, 0, "Just checking the %v of the output.", size);
549   EXPECT_EQ(result, 37);
550 }
551 
TEST(StrFormat,BehavesAsDocumented)552 TEST(StrFormat, BehavesAsDocumented) {
553   std::string s = absl::StrFormat("%s, %d!", "Hello", 123);
554   EXPECT_EQ("Hello, 123!", s);
555   std::string hello = "Hello";
556   std::string s2 = absl::StrFormat("%v, %v!", hello, 123);
557   EXPECT_EQ("Hello, 123!", s2);
558   // The format of a replacement is
559   // '%'[position][flags][width['.'precision]][length_modifier][format]
560   EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10");
561   // Text conversion:
562   //     "c" - Character.              Eg: 'a' -> "A", 20 -> " "
563   EXPECT_EQ(StrFormat("%c", 'a'), "a");
564   EXPECT_EQ(StrFormat("%c", 0x20), " ");
565   //           Formats char and integral types: int, long, uint64_t, etc.
566   EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
567   EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
568   EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
569   //     "s" - string       Eg: "C" -> "C", std::string("C++") -> "C++"
570   //           Formats std::string, char*, string_view, and Cord.
571   EXPECT_EQ(StrFormat("%s", "C"), "C");
572   EXPECT_EQ(StrFormat("%v", std::string("C")), "C");
573   EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
574   EXPECT_EQ(StrFormat("%v", std::string("C++")), "C++");
575   EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
576   EXPECT_EQ(StrFormat("%v", string_view("view")), "view");
577   EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
578   EXPECT_EQ(StrFormat("%v", absl::Cord("cord")), "cord");
579   // Integral Conversion
580   //     These format integral types: char, int, long, uint64_t, etc.
581   EXPECT_EQ(StrFormat("%d", char{10}), "10");
582   EXPECT_EQ(StrFormat("%d", int{10}), "10");
583   EXPECT_EQ(StrFormat("%d", long{10}), "10");  // NOLINT
584   EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10");
585   EXPECT_EQ(StrFormat("%v", int{10}), "10");
586   EXPECT_EQ(StrFormat("%v", long{10}), "10");  // NOLINT
587   EXPECT_EQ(StrFormat("%v", uint64_t{10}), "10");
588   //     d,i - signed decimal          Eg: -10 -> "-10"
589   EXPECT_EQ(StrFormat("%d", -10), "-10");
590   EXPECT_EQ(StrFormat("%i", -10), "-10");
591   EXPECT_EQ(StrFormat("%v", -10), "-10");
592   //      o  - octal                   Eg:  10 -> "12"
593   EXPECT_EQ(StrFormat("%o", 10), "12");
594   //      u  - unsigned decimal        Eg:  10 -> "10"
595   EXPECT_EQ(StrFormat("%u", 10), "10");
596   EXPECT_EQ(StrFormat("%v", 10), "10");
597   //     x/X - lower,upper case hex    Eg:  10 -> "a"/"A"
598   EXPECT_EQ(StrFormat("%x", 10), "a");
599   EXPECT_EQ(StrFormat("%X", 10), "A");
600   // Floating-point, with upper/lower-case output.
601   //     These format floating points types: float, double, long double, etc.
602   EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0");
603   EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0");
604   const long double long_double = 1.0;
605   EXPECT_EQ(StrFormat("%.1f", long_double), "1.0");
606   //     These also format integral types: char, int, long, uint64_t, etc.:
607   EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0");
608   EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0");
609   EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0");  // NOLINT
610   EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0");
611   //     f/F - decimal.                Eg: 123456789 -> "123456789.000000"
612   EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000");
613   EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000");
614   //     e/E - exponentiated           Eg: .01 -> "1.00000e-2"/"1.00000E-2"
615   EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02");
616   EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02");
617   //     g/G - exponentiate to fit     Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10"
618   EXPECT_EQ(StrFormat("%g", .01), "0.01");
619   EXPECT_EQ(StrFormat("%g", 1e10), "1e+10");
620   EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
621   EXPECT_EQ(StrFormat("%v", .01), "0.01");
622   EXPECT_EQ(StrFormat("%v", 1e10), "1e+10");
623   //     a/A - lower,upper case hex    Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
624 
625 // On Android platform <=21, there is a regression in hexfloat formatting.
626 #if !defined(__ANDROID_API__) || __ANDROID_API__ > 21
627   EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1");  // .1 to fix MSVC output
628   EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1");  // .1 to fix MSVC output
629 #endif
630 
631   // Other conversion
632   int64_t value = 0x7ffdeb4;
633   auto ptr_value = static_cast<uintptr_t>(value);
634   const int& something = *reinterpret_cast<const int*>(ptr_value);
635   EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value));
636 
637   // Output widths are supported, with optional flags.
638   EXPECT_EQ(StrFormat("%3d", 1), "  1");
639   EXPECT_EQ(StrFormat("%3d", 123456), "123456");
640   EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23");
641   EXPECT_EQ(StrFormat("%+d", 1), "+1");
642   EXPECT_EQ(StrFormat("% d", 1), " 1");
643   EXPECT_EQ(StrFormat("%-4d", -1), "-1  ");
644   EXPECT_EQ(StrFormat("%#o", 10), "012");
645   EXPECT_EQ(StrFormat("%#x", 15), "0xf");
646   EXPECT_EQ(StrFormat("%04d", 8), "0008");
647   EXPECT_EQ(StrFormat("%#04x", 0), "0000");
648   EXPECT_EQ(StrFormat("%#04x", 1), "0x01");
649   // Posix positional substitution.
650   EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"),
651             "veni, vidi, vici!");
652   // Length modifiers are ignored.
653   EXPECT_EQ(StrFormat("%hhd", int{1}), "1");
654   EXPECT_EQ(StrFormat("%hd", int{1}), "1");
655   EXPECT_EQ(StrFormat("%ld", int{1}), "1");
656   EXPECT_EQ(StrFormat("%lld", int{1}), "1");
657   EXPECT_EQ(StrFormat("%Ld", int{1}), "1");
658   EXPECT_EQ(StrFormat("%jd", int{1}), "1");
659   EXPECT_EQ(StrFormat("%zd", int{1}), "1");
660   EXPECT_EQ(StrFormat("%td", int{1}), "1");
661   EXPECT_EQ(StrFormat("%qd", int{1}), "1");
662 
663   // Bool is handled correctly depending on whether %v is used
664   EXPECT_EQ(StrFormat("%v", true), "true");
665   EXPECT_EQ(StrFormat("%v", false), "false");
666   EXPECT_EQ(StrFormat("%d", true), "1");
667 }
668 
669 using str_format_internal::ExtendedParsedFormat;
670 using str_format_internal::ParsedFormatBase;
671 
672 struct SummarizeConsumer {
673   std::string* out;
SummarizeConsumerabsl::__anond3ed62050111::SummarizeConsumer674   explicit SummarizeConsumer(std::string* out) : out(out) {}
675 
Appendabsl::__anond3ed62050111::SummarizeConsumer676   bool Append(string_view s) {
677     *out += "[" + std::string(s) + "]";
678     return true;
679   }
680 
ConvertOneabsl::__anond3ed62050111::SummarizeConsumer681   bool ConvertOne(const str_format_internal::UnboundConversion& conv,
682                   string_view s) {
683     *out += "{";
684     *out += std::string(s);
685     *out += ":";
686     *out += std::to_string(conv.arg_position) + "$";
687     if (conv.width.is_from_arg()) {
688       *out += std::to_string(conv.width.get_from_arg()) + "$*";
689     }
690     if (conv.precision.is_from_arg()) {
691       *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
692     }
693     *out += str_format_internal::FormatConversionCharToChar(conv.conv);
694     *out += "}";
695     return true;
696   }
697 };
698 
SummarizeParsedFormat(const ParsedFormatBase & pc)699 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
700   std::string out;
701   if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!";
702   return out;
703 }
704 
705 using ParsedFormatTest = ::testing::Test;
706 
TEST_F(ParsedFormatTest,SimpleChecked)707 TEST_F(ParsedFormatTest, SimpleChecked) {
708   EXPECT_EQ("[ABC]{d:1$d}[DEF]",
709             SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
710   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}",
711             SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f")));
712   EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}",
713             SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d")));
714 }
715 
TEST_F(ParsedFormatTest,SimpleCheckedWithV)716 TEST_F(ParsedFormatTest, SimpleCheckedWithV) {
717   EXPECT_EQ("[ABC]{v:1$v}[DEF]",
718             SummarizeParsedFormat(ParsedFormat<'v'>("ABC%vDEF")));
719   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}",
720             SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>("%vFFF%vZZZ%f")));
721   EXPECT_EQ("{v:1$v}[ ]{.*d:3$.2$*d}",
722             SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>("%v %.*d")));
723 }
724 
TEST_F(ParsedFormatTest,SimpleUncheckedCorrect)725 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
726   auto f = ParsedFormat<'d'>::New("ABC%dDEF");
727   ASSERT_TRUE(f);
728   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
729 
730   std::string format = "%sFFF%dZZZ%f";
731   auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);
732 
733   ASSERT_TRUE(f2);
734   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
735 
736   f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f");
737 
738   ASSERT_TRUE(f2);
739   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
740 
741   auto star = ParsedFormat<'*', 'd'>::New("%*d");
742   ASSERT_TRUE(star);
743   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
744 
745   auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d");
746   ASSERT_TRUE(dollar);
747   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
748   // with reuse
749   dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d");
750   ASSERT_TRUE(dollar);
751   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
752             SummarizeParsedFormat(*dollar));
753 }
754 
TEST_F(ParsedFormatTest,SimpleUncheckedCorrectWithV)755 TEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) {
756   auto f = ParsedFormat<'v'>::New("ABC%vDEF");
757   ASSERT_TRUE(f);
758   EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
759 
760   std::string format = "%vFFF%vZZZ%f";
761   auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format);
762 
763   ASSERT_TRUE(f2);
764   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
765 
766   f2 = ParsedFormat<'v', 'v', 'f'>::New("%v %v %f");
767 
768   ASSERT_TRUE(f2);
769   EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
770 }
771 
TEST_F(ParsedFormatTest,SimpleUncheckedIgnoredArgs)772 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
773   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC")));
774   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC")));
775   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s")));
776   auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC");
777   ASSERT_TRUE(f);
778   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
779   f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC");
780   ASSERT_TRUE(f);
781   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
782   f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s");
783   ASSERT_TRUE(f);
784   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
785 }
786 
TEST_F(ParsedFormatTest,SimpleUncheckedIgnoredArgsWithV)787 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) {
788   EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("ABC")));
789   EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("%vABC")));
790   EXPECT_FALSE((ParsedFormat<'v', 's'>::New("ABC%2$s")));
791   auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored("ABC");
792   ASSERT_TRUE(f);
793   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
794   f = ParsedFormat<'v', 'v'>::NewAllowIgnored("%vABC");
795   ASSERT_TRUE(f);
796   EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
797 }
798 
TEST_F(ParsedFormatTest,SimpleUncheckedUnsupported)799 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
800   EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
801   EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
802 }
803 
TEST_F(ParsedFormatTest,SimpleUncheckedIncorrect)804 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
805   EXPECT_FALSE(ParsedFormat<'d'>::New(""));
806 
807   EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
808 
809   std::string format = "%sFFF%dZZZ%f";
810   EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
811 }
812 
TEST_F(ParsedFormatTest,SimpleUncheckedIncorrectWithV)813 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) {
814   EXPECT_FALSE(ParsedFormat<'v'>::New(""));
815 
816   EXPECT_FALSE(ParsedFormat<'v'>::New("ABC%vDEF%v"));
817 
818   std::string format = "%vFFF%vZZZ%f";
819   EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format)));
820 }
821 
822 #if defined(__cpp_nontype_template_parameter_auto)
823 
824 template <auto T>
825 std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
826 
827 template <auto T>
828 std::false_type IsValidParsedFormatArgTest(...);
829 
830 template <auto T>
831 using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
832 
TEST_F(ParsedFormatTest,OnlyValidTypesAllowed)833 TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
834   ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
835 
836   ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
837 
838   ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
839                                      absl::FormatConversionCharSet::x>::value);
840   ASSERT_TRUE(
841       IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
842 
843   // This is an easy mistake to make, however, this will reduce to an integer
844   // which has no meaning, so we need to ensure it doesn't compile.
845   ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
846 
847   // For now, we disallow construction based on ConversionChar (rather than
848   // CharSet)
849   ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
850 }
851 
TEST_F(ParsedFormatTest,ExtendedTyping)852 TEST_F(ParsedFormatTest, ExtendedTyping) {
853   EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
854   ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
855   auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
856   ASSERT_TRUE(v1);
857   auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
858   ASSERT_TRUE(v2);
859   auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
860                              absl::FormatConversionCharSet::s,
861                          's'>::New("%d%s");
862   ASSERT_TRUE(v3);
863   auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
864                              absl::FormatConversionCharSet::s,
865                          's'>::New("%s%s");
866   ASSERT_TRUE(v4);
867 }
868 
TEST_F(ParsedFormatTest,ExtendedTypingWithV)869 TEST_F(ParsedFormatTest, ExtendedTypingWithV) {
870   EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New(""));
871   ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New("%v"));
872   auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New("%v%v");
873   ASSERT_TRUE(v1);
874   auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New("%v%v");
875   ASSERT_TRUE(v2);
876   auto v3 = ParsedFormat<absl::FormatConversionCharSet::v |
877                              absl::FormatConversionCharSet::v,
878                          'v'>::New("%v%v");
879   ASSERT_TRUE(v3);
880   auto v4 = ParsedFormat<absl::FormatConversionCharSet::v |
881                              absl::FormatConversionCharSet::v,
882                          'v'>::New("%v%v");
883   ASSERT_TRUE(v4);
884 }
885 #endif
886 
TEST_F(ParsedFormatTest,UncheckedCorrect)887 TEST_F(ParsedFormatTest, UncheckedCorrect) {
888   auto f =
889       ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
890   ASSERT_TRUE(f);
891   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
892 
893   std::string format = "%sFFF%dZZZ%f";
894   auto f2 = ExtendedParsedFormat<
895       absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
896       absl::FormatConversionCharSet::kFloating>::New(format);
897 
898   ASSERT_TRUE(f2);
899   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
900 
901   f2 = ExtendedParsedFormat<
902       absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
903       absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
904 
905   ASSERT_TRUE(f2);
906   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
907 
908   auto star =
909       ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
910                            absl::FormatConversionCharSet::d>::New("%*d");
911   ASSERT_TRUE(star);
912   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
913 
914   auto dollar =
915       ExtendedParsedFormat<absl::FormatConversionCharSet::d,
916                            absl::FormatConversionCharSet::s>::New("%2$s %1$d");
917   ASSERT_TRUE(dollar);
918   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
919   // with reuse
920   dollar = ExtendedParsedFormat<
921       absl::FormatConversionCharSet::d,
922       absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
923   ASSERT_TRUE(dollar);
924   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
925             SummarizeParsedFormat(*dollar));
926 }
927 
TEST_F(ParsedFormatTest,UncheckedCorrectWithV)928 TEST_F(ParsedFormatTest, UncheckedCorrectWithV) {
929   auto f =
930       ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("ABC%vDEF");
931   ASSERT_TRUE(f);
932   EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
933 
934   std::string format = "%vFFF%vZZZ%f";
935   auto f2 = ExtendedParsedFormat<
936       absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
937       absl::FormatConversionCharSet::kFloating>::New(format);
938 
939   ASSERT_TRUE(f2);
940   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
941 
942   f2 = ExtendedParsedFormat<
943       absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
944       absl::FormatConversionCharSet::kFloating>::New("%v %v %f");
945 
946   ASSERT_TRUE(f2);
947   EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
948 }
949 
TEST_F(ParsedFormatTest,UncheckedIgnoredArgs)950 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
951   EXPECT_FALSE(
952       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
953                             absl::FormatConversionCharSet::s>::New("ABC")));
954   EXPECT_FALSE(
955       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
956                             absl::FormatConversionCharSet::s>::New("%dABC")));
957   EXPECT_FALSE(
958       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
959                             absl::FormatConversionCharSet::s>::New("ABC%2$s")));
960   auto f = ExtendedParsedFormat<
961       absl::FormatConversionCharSet::d,
962       absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
963   ASSERT_TRUE(f);
964   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
965   f = ExtendedParsedFormat<
966       absl::FormatConversionCharSet::d,
967       absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
968   ASSERT_TRUE(f);
969   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
970   f = ExtendedParsedFormat<
971       absl::FormatConversionCharSet::d,
972       absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
973   ASSERT_TRUE(f);
974   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
975 }
976 
TEST_F(ParsedFormatTest,UncheckedIgnoredArgsWithV)977 TEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) {
978   EXPECT_FALSE(
979       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
980                             absl::FormatConversionCharSet::v>::New("ABC")));
981   EXPECT_FALSE(
982       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
983                             absl::FormatConversionCharSet::v>::New("%vABC")));
984   EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v,
985                                      absl::FormatConversionCharSet::s>::
986                     New("ABC%2$s")));
987   auto f = ExtendedParsedFormat<
988       absl::FormatConversionCharSet::v,
989       absl::FormatConversionCharSet::v>::NewAllowIgnored("ABC");
990   ASSERT_TRUE(f);
991   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
992   f = ExtendedParsedFormat<
993       absl::FormatConversionCharSet::v,
994       absl::FormatConversionCharSet::v>::NewAllowIgnored("%vABC");
995   ASSERT_TRUE(f);
996   EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
997 }
998 
TEST_F(ParsedFormatTest,UncheckedMultipleTypes)999 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
1000   auto dx =
1001       ExtendedParsedFormat<absl::FormatConversionCharSet::d |
1002                            absl::FormatConversionCharSet::x>::New("%1$d %1$x");
1003   EXPECT_TRUE(dx);
1004   EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
1005 
1006   dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
1007                             absl::FormatConversionCharSet::x>::New("%1$d");
1008   EXPECT_TRUE(dx);
1009   EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
1010 }
1011 
TEST_F(ParsedFormatTest,UncheckedIncorrect)1012 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
1013   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
1014 
1015   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
1016       "ABC%dDEF%d"));
1017 
1018   std::string format = "%sFFF%dZZZ%f";
1019   EXPECT_FALSE(
1020       (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
1021                             absl::FormatConversionCharSet::d,
1022                             absl::FormatConversionCharSet::g>::New(format)));
1023 }
1024 
TEST_F(ParsedFormatTest,UncheckedIncorrectWithV)1025 TEST_F(ParsedFormatTest, UncheckedIncorrectWithV) {
1026   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(""));
1027 
1028   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(
1029       "ABC%vDEF%v"));
1030 
1031   std::string format = "%vFFF%vZZZ%f";
1032   EXPECT_FALSE(
1033       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
1034                             absl::FormatConversionCharSet::g>::New(format)));
1035 }
1036 
TEST_F(ParsedFormatTest,RegressionMixPositional)1037 TEST_F(ParsedFormatTest, RegressionMixPositional) {
1038   EXPECT_FALSE(
1039       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
1040                             absl::FormatConversionCharSet::o>::New("%1$d %o")));
1041 }
1042 
TEST_F(ParsedFormatTest,DisallowModifiersWithV)1043 TEST_F(ParsedFormatTest, DisallowModifiersWithV) {
1044   auto f = ParsedFormat<'v'>::New("ABC%80vDEF");
1045   EXPECT_EQ(f, nullptr);
1046 
1047   f = ParsedFormat<'v'>::New("ABC%0vDEF");
1048   EXPECT_EQ(f, nullptr);
1049 
1050   f = ParsedFormat<'v'>::New("ABC%.1vDEF");
1051   EXPECT_EQ(f, nullptr);
1052 }
1053 
1054 using FormatWrapperTest = ::testing::Test;
1055 
1056 // Plain wrapper for StrFormat.
1057 template <typename... Args>
WrappedFormat(const absl::FormatSpec<Args...> & format,const Args &...args)1058 std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
1059                           const Args&... args) {
1060   return StrFormat(format, args...);
1061 }
1062 
TEST_F(FormatWrapperTest,ConstexprStringFormat)1063 TEST_F(FormatWrapperTest, ConstexprStringFormat) {
1064   EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
1065 }
1066 
TEST_F(FormatWrapperTest,ConstexprStringFormatWithV)1067 TEST_F(FormatWrapperTest, ConstexprStringFormatWithV) {
1068   std::string hello = "hello";
1069   EXPECT_EQ(WrappedFormat("%v there", hello), "hello there");
1070 }
1071 
TEST_F(FormatWrapperTest,ParsedFormat)1072 TEST_F(FormatWrapperTest, ParsedFormat) {
1073   ParsedFormat<'s'> format("%s there");
1074   EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
1075 }
1076 
TEST_F(FormatWrapperTest,ParsedFormatWithV)1077 TEST_F(FormatWrapperTest, ParsedFormatWithV) {
1078   std::string hello = "hello";
1079   ParsedFormat<'v'> format("%v there");
1080   EXPECT_EQ(WrappedFormat(format, hello), "hello there");
1081 }
1082 
1083 }  // namespace
1084 ABSL_NAMESPACE_END
1085 }  // namespace absl
1086 
1087 namespace {
1088 using FormatExtensionTest = ::testing::Test;
1089 
1090 struct Point {
1091   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
1092                                    absl::FormatConversionCharSet::kIntegral |
1093                                    absl::FormatConversionCharSet::v>
AbslFormatConvert(const Point & p,const absl::FormatConversionSpec & spec,absl::FormatSink * s)1094   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
1095                     absl::FormatSink* s) {
1096     if (spec.conversion_char() == absl::FormatConversionChar::s) {
1097       s->Append(absl::StrCat("x=", p.x, " y=", p.y));
1098     } else {
1099       s->Append(absl::StrCat(p.x, ",", p.y));
1100     }
1101     return {true};
1102   }
1103 
1104   int x = 10;
1105   int y = 20;
1106 };
1107 
TEST_F(FormatExtensionTest,AbslFormatConvertExample)1108 TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
1109   Point p;
1110   EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
1111   EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
1112   EXPECT_EQ(absl::StrFormat("a %v z", p), "a 10,20 z");
1113 
1114   // Typed formatting will fail to compile an invalid format.
1115   // StrFormat("%f", p);  // Does not compile.
1116   std::string actual;
1117   absl::UntypedFormatSpec f1("%f");
1118   // FormatUntyped will return false for bad character.
1119   EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
1120 }
1121 
1122 struct PointStringify {
1123   template <typename FormatSink>
AbslStringify(FormatSink & sink,const PointStringify & p)1124   friend void AbslStringify(FormatSink& sink, const PointStringify& p) {
1125     sink.Append(absl::StrCat("(", p.x, ", ", p.y, ")"));
1126   }
1127 
1128   double x = 10.0;
1129   double y = 20.0;
1130 };
1131 
TEST_F(FormatExtensionTest,AbslStringifyExample)1132 TEST_F(FormatExtensionTest, AbslStringifyExample) {
1133   PointStringify p;
1134   EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
1135 }
1136 
1137 struct PointStringifyUsingFormat {
1138   template <typename FormatSink>
AbslStringify(FormatSink & sink,const PointStringifyUsingFormat & p)1139   friend void AbslStringify(FormatSink& sink,
1140                             const PointStringifyUsingFormat& p) {
1141     absl::Format(&sink, "(%g, %g)", p.x, p.y);
1142   }
1143 
1144   double x = 10.0;
1145   double y = 20.0;
1146 };
1147 
TEST_F(FormatExtensionTest,AbslStringifyExampleUsingFormat)1148 TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {
1149   PointStringifyUsingFormat p;
1150   EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
1151 }
1152 
1153 enum class EnumClassWithStringify { Many = 0, Choices = 1 };
1154 
1155 template <typename Sink>
AbslStringify(Sink & sink,EnumClassWithStringify e)1156 void AbslStringify(Sink& sink, EnumClassWithStringify e) {
1157   absl::Format(&sink, "%s",
1158                e == EnumClassWithStringify::Many ? "Many" : "Choices");
1159 }
1160 
1161 enum EnumWithStringify { Many, Choices };
1162 
1163 template <typename Sink>
AbslStringify(Sink & sink,EnumWithStringify e)1164 void AbslStringify(Sink& sink, EnumWithStringify e) {
1165   absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices");
1166 }
1167 
TEST_F(FormatExtensionTest,AbslStringifyWithEnumWithV)1168 TEST_F(FormatExtensionTest, AbslStringifyWithEnumWithV) {
1169   const auto e_class = EnumClassWithStringify::Choices;
1170   EXPECT_EQ(absl::StrFormat("My choice is %v", e_class),
1171             "My choice is Choices");
1172 
1173   const auto e = EnumWithStringify::Choices;
1174   EXPECT_EQ(absl::StrFormat("My choice is %v", e), "My choice is Choices");
1175 }
1176 
TEST_F(FormatExtensionTest,AbslStringifyEnumWithD)1177 TEST_F(FormatExtensionTest, AbslStringifyEnumWithD) {
1178   const auto e_class = EnumClassWithStringify::Many;
1179   EXPECT_EQ(absl::StrFormat("My choice is %d", e_class), "My choice is 0");
1180 
1181   const auto e = EnumWithStringify::Choices;
1182   EXPECT_EQ(absl::StrFormat("My choice is %d", e), "My choice is 1");
1183 }
1184 
1185 enum class EnumWithLargerValue { x = 32 };
1186 
1187 template <typename Sink>
AbslStringify(Sink & sink,EnumWithLargerValue e)1188 void AbslStringify(Sink& sink, EnumWithLargerValue e) {
1189   absl::Format(&sink, "%s", "Many");
1190 }
1191 
TEST_F(FormatExtensionTest,AbslStringifyEnumOtherSpecifiers)1192 TEST_F(FormatExtensionTest, AbslStringifyEnumOtherSpecifiers) {
1193   const auto e = EnumWithLargerValue::x;
1194   EXPECT_EQ(absl::StrFormat("My choice is %g", e), "My choice is 32");
1195   EXPECT_EQ(absl::StrFormat("My choice is %x", e), "My choice is 20");
1196 }
1197 
1198 }  // namespace
1199 
1200 // Some codegen thunks that we can use to easily dump the generated assembly for
1201 // different StrFormat calls.
1202 
CodegenAbslStrFormatInt(int i)1203 std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
1204   return absl::StrFormat("%d", i);
1205 }
1206 
CodegenAbslStrFormatIntStringInt64(int i,const std::string & s,int64_t i64)1207 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
1208                                                int64_t i64) {  // NOLINT
1209   return absl::StrFormat("%d %s %d", i, s, i64);
1210 }
1211 
CodegenAbslStrAppendFormatInt(std::string * out,int i)1212 void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
1213   absl::StrAppendFormat(out, "%d", i);
1214 }
1215 
CodegenAbslStrAppendFormatIntStringInt64(std::string * out,int i,const std::string & s,int64_t i64)1216 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
1217                                               const std::string& s,
1218                                               int64_t i64) {  // NOLINT
1219   absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
1220 }
1221