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