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