• 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   EXPECT_EQ(StrFormat("%#04x", 0), "0000");
642   EXPECT_EQ(StrFormat("%#04x", 1), "0x01");
643   // Posix positional substitution.
644   EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"),
645             "veni, vidi, vici!");
646   // Length modifiers are ignored.
647   EXPECT_EQ(StrFormat("%hhd", int{1}), "1");
648   EXPECT_EQ(StrFormat("%hd", int{1}), "1");
649   EXPECT_EQ(StrFormat("%ld", int{1}), "1");
650   EXPECT_EQ(StrFormat("%lld", int{1}), "1");
651   EXPECT_EQ(StrFormat("%Ld", int{1}), "1");
652   EXPECT_EQ(StrFormat("%jd", int{1}), "1");
653   EXPECT_EQ(StrFormat("%zd", int{1}), "1");
654   EXPECT_EQ(StrFormat("%td", int{1}), "1");
655   EXPECT_EQ(StrFormat("%qd", int{1}), "1");
656 
657   // Bool is handled correctly depending on whether %v is used
658   EXPECT_EQ(StrFormat("%v", true), "true");
659   EXPECT_EQ(StrFormat("%v", false), "false");
660   EXPECT_EQ(StrFormat("%d", true), "1");
661 }
662 
663 using str_format_internal::ExtendedParsedFormat;
664 using str_format_internal::ParsedFormatBase;
665 
666 struct SummarizeConsumer {
667   std::string* out;
SummarizeConsumerabsl::__anon2f0891220111::SummarizeConsumer668   explicit SummarizeConsumer(std::string* out) : out(out) {}
669 
Appendabsl::__anon2f0891220111::SummarizeConsumer670   bool Append(string_view s) {
671     *out += "[" + std::string(s) + "]";
672     return true;
673   }
674 
ConvertOneabsl::__anon2f0891220111::SummarizeConsumer675   bool ConvertOne(const str_format_internal::UnboundConversion& conv,
676                   string_view s) {
677     *out += "{";
678     *out += std::string(s);
679     *out += ":";
680     *out += std::to_string(conv.arg_position) + "$";
681     if (conv.width.is_from_arg()) {
682       *out += std::to_string(conv.width.get_from_arg()) + "$*";
683     }
684     if (conv.precision.is_from_arg()) {
685       *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
686     }
687     *out += str_format_internal::FormatConversionCharToChar(conv.conv);
688     *out += "}";
689     return true;
690   }
691 };
692 
SummarizeParsedFormat(const ParsedFormatBase & pc)693 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
694   std::string out;
695   if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!";
696   return out;
697 }
698 
699 using ParsedFormatTest = ::testing::Test;
700 
TEST_F(ParsedFormatTest,SimpleChecked)701 TEST_F(ParsedFormatTest, SimpleChecked) {
702   EXPECT_EQ("[ABC]{d:1$d}[DEF]",
703             SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
704   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}",
705             SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f")));
706   EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}",
707             SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d")));
708 }
709 
TEST_F(ParsedFormatTest,SimpleCheckedWithV)710 TEST_F(ParsedFormatTest, SimpleCheckedWithV) {
711   EXPECT_EQ("[ABC]{v:1$v}[DEF]",
712             SummarizeParsedFormat(ParsedFormat<'v'>("ABC%vDEF")));
713   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}",
714             SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>("%vFFF%vZZZ%f")));
715   EXPECT_EQ("{v:1$v}[ ]{.*d:3$.2$*d}",
716             SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>("%v %.*d")));
717 }
718 
TEST_F(ParsedFormatTest,SimpleUncheckedCorrect)719 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
720   auto f = ParsedFormat<'d'>::New("ABC%dDEF");
721   ASSERT_TRUE(f);
722   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
723 
724   std::string format = "%sFFF%dZZZ%f";
725   auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);
726 
727   ASSERT_TRUE(f2);
728   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
729 
730   f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f");
731 
732   ASSERT_TRUE(f2);
733   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
734 
735   auto star = ParsedFormat<'*', 'd'>::New("%*d");
736   ASSERT_TRUE(star);
737   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
738 
739   auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d");
740   ASSERT_TRUE(dollar);
741   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
742   // with reuse
743   dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d");
744   ASSERT_TRUE(dollar);
745   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
746             SummarizeParsedFormat(*dollar));
747 }
748 
TEST_F(ParsedFormatTest,SimpleUncheckedCorrectWithV)749 TEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) {
750   auto f = ParsedFormat<'v'>::New("ABC%vDEF");
751   ASSERT_TRUE(f);
752   EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
753 
754   std::string format = "%vFFF%vZZZ%f";
755   auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format);
756 
757   ASSERT_TRUE(f2);
758   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
759 
760   f2 = ParsedFormat<'v', 'v', 'f'>::New("%v %v %f");
761 
762   ASSERT_TRUE(f2);
763   EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
764 }
765 
TEST_F(ParsedFormatTest,SimpleUncheckedIgnoredArgs)766 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
767   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC")));
768   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC")));
769   EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s")));
770   auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC");
771   ASSERT_TRUE(f);
772   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
773   f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC");
774   ASSERT_TRUE(f);
775   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
776   f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s");
777   ASSERT_TRUE(f);
778   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
779 }
780 
TEST_F(ParsedFormatTest,SimpleUncheckedIgnoredArgsWithV)781 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) {
782   EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("ABC")));
783   EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("%vABC")));
784   EXPECT_FALSE((ParsedFormat<'v', 's'>::New("ABC%2$s")));
785   auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored("ABC");
786   ASSERT_TRUE(f);
787   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
788   f = ParsedFormat<'v', 'v'>::NewAllowIgnored("%vABC");
789   ASSERT_TRUE(f);
790   EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
791 }
792 
TEST_F(ParsedFormatTest,SimpleUncheckedUnsupported)793 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
794   EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
795   EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
796 }
797 
TEST_F(ParsedFormatTest,SimpleUncheckedIncorrect)798 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
799   EXPECT_FALSE(ParsedFormat<'d'>::New(""));
800 
801   EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
802 
803   std::string format = "%sFFF%dZZZ%f";
804   EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
805 }
806 
TEST_F(ParsedFormatTest,SimpleUncheckedIncorrectWithV)807 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) {
808   EXPECT_FALSE(ParsedFormat<'v'>::New(""));
809 
810   EXPECT_FALSE(ParsedFormat<'v'>::New("ABC%vDEF%v"));
811 
812   std::string format = "%vFFF%vZZZ%f";
813   EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format)));
814 }
815 
816 #if defined(__cpp_nontype_template_parameter_auto)
817 
818 template <auto T>
819 std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
820 
821 template <auto T>
822 std::false_type IsValidParsedFormatArgTest(...);
823 
824 template <auto T>
825 using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
826 
TEST_F(ParsedFormatTest,OnlyValidTypesAllowed)827 TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
828   ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
829 
830   ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
831 
832   ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
833                                      absl::FormatConversionCharSet::x>::value);
834   ASSERT_TRUE(
835       IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
836 
837   // This is an easy mistake to make, however, this will reduce to an integer
838   // which has no meaning, so we need to ensure it doesn't compile.
839   ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
840 
841   // For now, we disallow construction based on ConversionChar (rather than
842   // CharSet)
843   ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
844 }
845 
TEST_F(ParsedFormatTest,ExtendedTyping)846 TEST_F(ParsedFormatTest, ExtendedTyping) {
847   EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
848   ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
849   auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
850   ASSERT_TRUE(v1);
851   auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
852   ASSERT_TRUE(v2);
853   auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
854                              absl::FormatConversionCharSet::s,
855                          's'>::New("%d%s");
856   ASSERT_TRUE(v3);
857   auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
858                              absl::FormatConversionCharSet::s,
859                          's'>::New("%s%s");
860   ASSERT_TRUE(v4);
861 }
862 
TEST_F(ParsedFormatTest,ExtendedTypingWithV)863 TEST_F(ParsedFormatTest, ExtendedTypingWithV) {
864   EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New(""));
865   ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New("%v"));
866   auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New("%v%v");
867   ASSERT_TRUE(v1);
868   auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New("%v%v");
869   ASSERT_TRUE(v2);
870   auto v3 = ParsedFormat<absl::FormatConversionCharSet::v |
871                              absl::FormatConversionCharSet::v,
872                          'v'>::New("%v%v");
873   ASSERT_TRUE(v3);
874   auto v4 = ParsedFormat<absl::FormatConversionCharSet::v |
875                              absl::FormatConversionCharSet::v,
876                          'v'>::New("%v%v");
877   ASSERT_TRUE(v4);
878 }
879 #endif
880 
TEST_F(ParsedFormatTest,UncheckedCorrect)881 TEST_F(ParsedFormatTest, UncheckedCorrect) {
882   auto f =
883       ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
884   ASSERT_TRUE(f);
885   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
886 
887   std::string format = "%sFFF%dZZZ%f";
888   auto f2 = ExtendedParsedFormat<
889       absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
890       absl::FormatConversionCharSet::kFloating>::New(format);
891 
892   ASSERT_TRUE(f2);
893   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
894 
895   f2 = ExtendedParsedFormat<
896       absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
897       absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
898 
899   ASSERT_TRUE(f2);
900   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
901 
902   auto star =
903       ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
904                            absl::FormatConversionCharSet::d>::New("%*d");
905   ASSERT_TRUE(star);
906   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
907 
908   auto dollar =
909       ExtendedParsedFormat<absl::FormatConversionCharSet::d,
910                            absl::FormatConversionCharSet::s>::New("%2$s %1$d");
911   ASSERT_TRUE(dollar);
912   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
913   // with reuse
914   dollar = ExtendedParsedFormat<
915       absl::FormatConversionCharSet::d,
916       absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
917   ASSERT_TRUE(dollar);
918   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
919             SummarizeParsedFormat(*dollar));
920 }
921 
TEST_F(ParsedFormatTest,UncheckedCorrectWithV)922 TEST_F(ParsedFormatTest, UncheckedCorrectWithV) {
923   auto f =
924       ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("ABC%vDEF");
925   ASSERT_TRUE(f);
926   EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f));
927 
928   std::string format = "%vFFF%vZZZ%f";
929   auto f2 = ExtendedParsedFormat<
930       absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
931       absl::FormatConversionCharSet::kFloating>::New(format);
932 
933   ASSERT_TRUE(f2);
934   EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
935 
936   f2 = ExtendedParsedFormat<
937       absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v,
938       absl::FormatConversionCharSet::kFloating>::New("%v %v %f");
939 
940   ASSERT_TRUE(f2);
941   EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
942 }
943 
TEST_F(ParsedFormatTest,UncheckedIgnoredArgs)944 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
945   EXPECT_FALSE(
946       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
947                             absl::FormatConversionCharSet::s>::New("ABC")));
948   EXPECT_FALSE(
949       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
950                             absl::FormatConversionCharSet::s>::New("%dABC")));
951   EXPECT_FALSE(
952       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
953                             absl::FormatConversionCharSet::s>::New("ABC%2$s")));
954   auto f = ExtendedParsedFormat<
955       absl::FormatConversionCharSet::d,
956       absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
957   ASSERT_TRUE(f);
958   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
959   f = ExtendedParsedFormat<
960       absl::FormatConversionCharSet::d,
961       absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
962   ASSERT_TRUE(f);
963   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
964   f = ExtendedParsedFormat<
965       absl::FormatConversionCharSet::d,
966       absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
967   ASSERT_TRUE(f);
968   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
969 }
970 
TEST_F(ParsedFormatTest,UncheckedIgnoredArgsWithV)971 TEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) {
972   EXPECT_FALSE(
973       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
974                             absl::FormatConversionCharSet::v>::New("ABC")));
975   EXPECT_FALSE(
976       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
977                             absl::FormatConversionCharSet::v>::New("%vABC")));
978   EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v,
979                                      absl::FormatConversionCharSet::s>::
980                     New("ABC%2$s")));
981   auto f = ExtendedParsedFormat<
982       absl::FormatConversionCharSet::v,
983       absl::FormatConversionCharSet::v>::NewAllowIgnored("ABC");
984   ASSERT_TRUE(f);
985   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
986   f = ExtendedParsedFormat<
987       absl::FormatConversionCharSet::v,
988       absl::FormatConversionCharSet::v>::NewAllowIgnored("%vABC");
989   ASSERT_TRUE(f);
990   EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f));
991 }
992 
TEST_F(ParsedFormatTest,UncheckedMultipleTypes)993 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
994   auto dx =
995       ExtendedParsedFormat<absl::FormatConversionCharSet::d |
996                            absl::FormatConversionCharSet::x>::New("%1$d %1$x");
997   EXPECT_TRUE(dx);
998   EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
999 
1000   dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
1001                             absl::FormatConversionCharSet::x>::New("%1$d");
1002   EXPECT_TRUE(dx);
1003   EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
1004 }
1005 
TEST_F(ParsedFormatTest,UncheckedIncorrect)1006 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
1007   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
1008 
1009   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
1010       "ABC%dDEF%d"));
1011 
1012   std::string format = "%sFFF%dZZZ%f";
1013   EXPECT_FALSE(
1014       (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
1015                             absl::FormatConversionCharSet::d,
1016                             absl::FormatConversionCharSet::g>::New(format)));
1017 }
1018 
TEST_F(ParsedFormatTest,UncheckedIncorrectWithV)1019 TEST_F(ParsedFormatTest, UncheckedIncorrectWithV) {
1020   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(""));
1021 
1022   EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New(
1023       "ABC%vDEF%v"));
1024 
1025   std::string format = "%vFFF%vZZZ%f";
1026   EXPECT_FALSE(
1027       (ExtendedParsedFormat<absl::FormatConversionCharSet::v,
1028                             absl::FormatConversionCharSet::g>::New(format)));
1029 }
1030 
TEST_F(ParsedFormatTest,RegressionMixPositional)1031 TEST_F(ParsedFormatTest, RegressionMixPositional) {
1032   EXPECT_FALSE(
1033       (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
1034                             absl::FormatConversionCharSet::o>::New("%1$d %o")));
1035 }
1036 
TEST_F(ParsedFormatTest,DisallowModifiersWithV)1037 TEST_F(ParsedFormatTest, DisallowModifiersWithV) {
1038   auto f = ParsedFormat<'v'>::New("ABC%80vDEF");
1039   EXPECT_EQ(f, nullptr);
1040 
1041   f = ParsedFormat<'v'>::New("ABC%0vDEF");
1042   EXPECT_EQ(f, nullptr);
1043 
1044   f = ParsedFormat<'v'>::New("ABC%.1vDEF");
1045   EXPECT_EQ(f, nullptr);
1046 }
1047 
1048 using FormatWrapperTest = ::testing::Test;
1049 
1050 // Plain wrapper for StrFormat.
1051 template <typename... Args>
WrappedFormat(const absl::FormatSpec<Args...> & format,const Args &...args)1052 std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
1053                           const Args&... args) {
1054   return StrFormat(format, args...);
1055 }
1056 
TEST_F(FormatWrapperTest,ConstexprStringFormat)1057 TEST_F(FormatWrapperTest, ConstexprStringFormat) {
1058   EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
1059 }
1060 
TEST_F(FormatWrapperTest,ConstexprStringFormatWithV)1061 TEST_F(FormatWrapperTest, ConstexprStringFormatWithV) {
1062   std::string hello = "hello";
1063   EXPECT_EQ(WrappedFormat("%v there", hello), "hello there");
1064 }
1065 
TEST_F(FormatWrapperTest,ParsedFormat)1066 TEST_F(FormatWrapperTest, ParsedFormat) {
1067   ParsedFormat<'s'> format("%s there");
1068   EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
1069 }
1070 
TEST_F(FormatWrapperTest,ParsedFormatWithV)1071 TEST_F(FormatWrapperTest, ParsedFormatWithV) {
1072   std::string hello = "hello";
1073   ParsedFormat<'v'> format("%v there");
1074   EXPECT_EQ(WrappedFormat(format, hello), "hello there");
1075 }
1076 
1077 }  // namespace
1078 ABSL_NAMESPACE_END
1079 }  // namespace absl
1080 
1081 namespace {
1082 using FormatExtensionTest = ::testing::Test;
1083 
1084 struct Point {
1085   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
1086                                    absl::FormatConversionCharSet::kIntegral |
1087                                    absl::FormatConversionCharSet::v>
AbslFormatConvert(const Point & p,const absl::FormatConversionSpec & spec,absl::FormatSink * s)1088   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
1089                     absl::FormatSink* s) {
1090     if (spec.conversion_char() == absl::FormatConversionChar::s) {
1091       s->Append(absl::StrCat("x=", p.x, " y=", p.y));
1092     } else {
1093       s->Append(absl::StrCat(p.x, ",", p.y));
1094     }
1095     return {true};
1096   }
1097 
1098   int x = 10;
1099   int y = 20;
1100 };
1101 
TEST_F(FormatExtensionTest,AbslFormatConvertExample)1102 TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
1103   Point p;
1104   EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
1105   EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
1106   EXPECT_EQ(absl::StrFormat("a %v z", p), "a 10,20 z");
1107 
1108   // Typed formatting will fail to compile an invalid format.
1109   // StrFormat("%f", p);  // Does not compile.
1110   std::string actual;
1111   absl::UntypedFormatSpec f1("%f");
1112   // FormatUntyped will return false for bad character.
1113   EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
1114 }
1115 
1116 struct PointStringify {
1117   template <typename FormatSink>
AbslStringify(FormatSink & sink,const PointStringify & p)1118   friend void AbslStringify(FormatSink& sink, const PointStringify& p) {
1119     sink.Append(absl::StrCat("(", p.x, ", ", p.y, ")"));
1120   }
1121 
1122   double x = 10.0;
1123   double y = 20.0;
1124 };
1125 
TEST_F(FormatExtensionTest,AbslStringifyExample)1126 TEST_F(FormatExtensionTest, AbslStringifyExample) {
1127   PointStringify p;
1128   EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
1129 }
1130 
1131 struct PointStringifyUsingFormat {
1132   template <typename FormatSink>
AbslStringify(FormatSink & sink,const PointStringifyUsingFormat & p)1133   friend void AbslStringify(FormatSink& sink,
1134                             const PointStringifyUsingFormat& p) {
1135     absl::Format(&sink, "(%g, %g)", p.x, p.y);
1136   }
1137 
1138   double x = 10.0;
1139   double y = 20.0;
1140 };
1141 
TEST_F(FormatExtensionTest,AbslStringifyExampleUsingFormat)1142 TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {
1143   PointStringifyUsingFormat p;
1144   EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
1145 }
1146 
1147 enum class EnumClassWithStringify { Many = 0, Choices = 1 };
1148 
1149 template <typename Sink>
AbslStringify(Sink & sink,EnumClassWithStringify e)1150 void AbslStringify(Sink& sink, EnumClassWithStringify e) {
1151   absl::Format(&sink, "%s",
1152                e == EnumClassWithStringify::Many ? "Many" : "Choices");
1153 }
1154 
1155 enum EnumWithStringify { Many, Choices };
1156 
1157 template <typename Sink>
AbslStringify(Sink & sink,EnumWithStringify e)1158 void AbslStringify(Sink& sink, EnumWithStringify e) {
1159   absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices");
1160 }
1161 
TEST_F(FormatExtensionTest,AbslStringifyWithEnumWithV)1162 TEST_F(FormatExtensionTest, AbslStringifyWithEnumWithV) {
1163   const auto e_class = EnumClassWithStringify::Choices;
1164   EXPECT_EQ(absl::StrFormat("My choice is %v", e_class),
1165             "My choice is Choices");
1166 
1167   const auto e = EnumWithStringify::Choices;
1168   EXPECT_EQ(absl::StrFormat("My choice is %v", e), "My choice is Choices");
1169 }
1170 
TEST_F(FormatExtensionTest,AbslStringifyEnumWithD)1171 TEST_F(FormatExtensionTest, AbslStringifyEnumWithD) {
1172   const auto e_class = EnumClassWithStringify::Many;
1173   EXPECT_EQ(absl::StrFormat("My choice is %d", e_class), "My choice is 0");
1174 
1175   const auto e = EnumWithStringify::Choices;
1176   EXPECT_EQ(absl::StrFormat("My choice is %d", e), "My choice is 1");
1177 }
1178 
1179 enum class EnumWithLargerValue { x = 32 };
1180 
1181 template <typename Sink>
AbslStringify(Sink & sink,EnumWithLargerValue e)1182 void AbslStringify(Sink& sink, EnumWithLargerValue e) {
1183   absl::Format(&sink, "%s", "Many");
1184 }
1185 
TEST_F(FormatExtensionTest,AbslStringifyEnumOtherSpecifiers)1186 TEST_F(FormatExtensionTest, AbslStringifyEnumOtherSpecifiers) {
1187   const auto e = EnumWithLargerValue::x;
1188   EXPECT_EQ(absl::StrFormat("My choice is %g", e), "My choice is 32");
1189   EXPECT_EQ(absl::StrFormat("My choice is %x", e), "My choice is 20");
1190 }
1191 
1192 }  // namespace
1193 
1194 // Some codegen thunks that we can use to easily dump the generated assembly for
1195 // different StrFormat calls.
1196 
CodegenAbslStrFormatInt(int i)1197 std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
1198   return absl::StrFormat("%d", i);
1199 }
1200 
CodegenAbslStrFormatIntStringInt64(int i,const std::string & s,int64_t i64)1201 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
1202                                                int64_t i64) {  // NOLINT
1203   return absl::StrFormat("%d %s %d", i, s, i64);
1204 }
1205 
CodegenAbslStrAppendFormatInt(std::string * out,int i)1206 void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
1207   absl::StrAppendFormat(out, "%d", i);
1208 }
1209 
CodegenAbslStrAppendFormatIntStringInt64(std::string * out,int i,const std::string & s,int64_t i64)1210 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
1211                                               const std::string& s,
1212                                               int64_t i64) {  // NOLINT
1213   absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
1214 }
1215