str_format_test.cc
Go to the documentation of this file.
1 
2 #include <cstdarg>
3 #include <cstdint>
4 #include <cstdio>
5 #include <string>
6 
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
11 
12 namespace absl {
13 namespace {
14 using str_format_internal::FormatArgImpl;
15 
16 using FormatEntryPointTest = ::testing::Test;
17 
18 TEST_F(FormatEntryPointTest, Format) {
19  std::string sink;
20  EXPECT_TRUE(Format(&sink, "A format %d", 123));
21  EXPECT_EQ("A format 123", sink);
22  sink.clear();
23 
24  ParsedFormat<'d'> pc("A format %d");
25  EXPECT_TRUE(Format(&sink, pc, 123));
26  EXPECT_EQ("A format 123", sink);
27 }
28 TEST_F(FormatEntryPointTest, UntypedFormat) {
29  constexpr const char* formats[] = {
30  "",
31  "a",
32  "%80d",
33 #if !defined(_MSC_VER) && !defined(__ANDROID__)
34  // MSVC and Android don't support positional syntax.
35  "complicated multipart %% %1$d format %1$0999d",
36 #endif // _MSC_VER
37  };
38  for (const char* fmt : formats) {
39  std::string actual;
40  int i = 123;
41  FormatArgImpl arg_123(i);
42  absl::Span<const FormatArgImpl> args(&arg_123, 1);
43  UntypedFormatSpec format(fmt);
44 
45  EXPECT_TRUE(FormatUntyped(&actual, format, args));
46  char buf[4096]{};
47  snprintf(buf, sizeof(buf), fmt, 123);
48  EXPECT_EQ(
51  buf);
52  EXPECT_EQ(actual, buf);
53  }
54  // The internal version works with a preparsed format.
55  ParsedFormat<'d'> pc("A format %d");
56  int i = 345;
57  FormatArg arg(i);
58  std::string out;
60  &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1}));
61  EXPECT_EQ("A format 345", out);
62 }
63 
64 TEST_F(FormatEntryPointTest, StringFormat) {
65  EXPECT_EQ("123", StrFormat("%d", 123));
66  constexpr absl::string_view view("=%d=", 4);
67  EXPECT_EQ("=123=", StrFormat(view, 123));
68 }
69 
70 TEST_F(FormatEntryPointTest, AppendFormat) {
71  std::string s;
72  std::string& r = StrAppendFormat(&s, "%d", 123);
73  EXPECT_EQ(&s, &r); // should be same object
74  EXPECT_EQ("123", r);
75 }
76 
77 TEST_F(FormatEntryPointTest, AppendFormatFail) {
78  std::string s = "orig";
79 
80  UntypedFormatSpec format(" more %d");
81  FormatArgImpl arg("not an int");
82 
83  EXPECT_EQ("orig",
86  {&arg, 1}));
87 }
88 
89 
90 TEST_F(FormatEntryPointTest, ManyArgs) {
91  EXPECT_EQ("24", StrFormat("%24$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
92  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24));
93  EXPECT_EQ("60", StrFormat("%60$d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
94  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
95  27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
96  40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
97  53, 54, 55, 56, 57, 58, 59, 60));
98 }
99 
100 TEST_F(FormatEntryPointTest, Preparsed) {
101  ParsedFormat<'d'> pc("%d");
102  EXPECT_EQ("123", StrFormat(pc, 123));
103  // rvalue ok?
104  EXPECT_EQ("123", StrFormat(ParsedFormat<'d'>("%d"), 123));
105  constexpr absl::string_view view("=%d=", 4);
106  EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123));
107 }
108 
109 TEST_F(FormatEntryPointTest, FormatCountCapture) {
110  int n = 0;
111  EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n)));
112  EXPECT_EQ(0, n);
113  EXPECT_EQ("123", StrFormat("%d%n", 123, FormatCountCapture(&n)));
114  EXPECT_EQ(3, n);
115 }
116 
117 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) {
118  // Should reject int*.
119  int n = 0;
120  UntypedFormatSpec format("%d%n");
121  int i = 123, *ip = &n;
122  FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)};
123 
124  EXPECT_EQ("", str_format_internal::FormatPack(
126  absl::MakeSpan(args)));
127 }
128 
129 TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) {
130  int n1 = 0;
131  int n2 = 0;
132  EXPECT_EQ(" 1 2",
133  StrFormat("%5d%n%10d%n", 1, FormatCountCapture(&n1), 2,
134  FormatCountCapture(&n2)));
135  EXPECT_EQ(5, n1);
136  EXPECT_EQ(15, n2);
137 }
138 
139 TEST_F(FormatEntryPointTest, FormatCountCaptureExample) {
140  int n;
141  std::string s;
142  StrAppendFormat(&s, "%s: %n%s\n", "(1,1)", FormatCountCapture(&n), "(1,2)");
143  StrAppendFormat(&s, "%*s%s\n", n, "", "(2,2)");
144  EXPECT_EQ(7, n);
145  EXPECT_EQ(
146  "(1,1): (1,2)\n"
147  " (2,2)\n",
148  s);
149 }
150 
151 TEST_F(FormatEntryPointTest, Stream) {
152  const std::string formats[] = {
153  "",
154  "a",
155  "%80d",
156 #if !defined(_MSC_VER) && !defined(__ANDROID__)
157  // MSVC doesn't support positional syntax.
158  "complicated multipart %% %1$d format %1$080d",
159 #endif // _MSC_VER
160  };
161  std::string buf(4096, '\0');
162  for (const auto& fmt : formats) {
163  const auto parsed = ParsedFormat<'d'>::NewAllowIgnored(fmt);
164  std::ostringstream oss;
165  oss << StreamFormat(*parsed, 123);
166  int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), 123);
167  ASSERT_TRUE(oss) << fmt;
168  ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
169  << fmt_result;
170  EXPECT_EQ(buf.c_str(), oss.str());
171  }
172 }
173 
174 TEST_F(FormatEntryPointTest, StreamOk) {
175  std::ostringstream oss;
176  oss << StreamFormat("hello %d", 123);
177  EXPECT_EQ("hello 123", oss.str());
178  EXPECT_TRUE(oss.good());
179 }
180 
181 TEST_F(FormatEntryPointTest, StreamFail) {
182  std::ostringstream oss;
183  UntypedFormatSpec format("hello %d");
184  FormatArgImpl arg("non-numeric");
185  oss << str_format_internal::Streamable(
187  EXPECT_EQ("hello ", oss.str()); // partial write
188  EXPECT_TRUE(oss.fail());
189 }
190 
191 std::string WithSnprintf(const char* fmt, ...) {
192  std::string buf;
193  buf.resize(128);
194  va_list va;
195  va_start(va, fmt);
196  int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va);
197  va_end(va);
198  EXPECT_GE(r, 0);
199  EXPECT_LT(r, buf.size());
200  buf.resize(r);
201  return buf;
202 }
203 
204 TEST_F(FormatEntryPointTest, FloatPrecisionArg) {
205  // Test that positional parameters for width and precision
206  // are indexed to precede the value.
207  // Also sanity check the same formats against snprintf.
208  EXPECT_EQ("0.1", StrFormat("%.1f", 0.1));
209  EXPECT_EQ("0.1", WithSnprintf("%.1f", 0.1));
210  EXPECT_EQ(" 0.1", StrFormat("%*.1f", 5, 0.1));
211  EXPECT_EQ(" 0.1", WithSnprintf("%*.1f", 5, 0.1));
212  EXPECT_EQ("0.1", StrFormat("%.*f", 1, 0.1));
213  EXPECT_EQ("0.1", WithSnprintf("%.*f", 1, 0.1));
214  EXPECT_EQ(" 0.1", StrFormat("%*.*f", 5, 1, 0.1));
215  EXPECT_EQ(" 0.1", WithSnprintf("%*.*f", 5, 1, 0.1));
216 }
217 namespace streamed_test {
218 struct X {};
219 std::ostream& operator<<(std::ostream& os, const X&) {
220  return os << "X";
221 }
222 } // streamed_test
223 
224 TEST_F(FormatEntryPointTest, FormatStreamed) {
225  EXPECT_EQ("123", StrFormat("%s", FormatStreamed(123)));
226  EXPECT_EQ(" 123", StrFormat("%5s", FormatStreamed(123)));
227  EXPECT_EQ("123 ", StrFormat("%-5s", FormatStreamed(123)));
228  EXPECT_EQ("X", StrFormat("%s", FormatStreamed(streamed_test::X())));
229  EXPECT_EQ("123", StrFormat("%s", FormatStreamed(StreamFormat("%d", 123))));
230 }
231 
232 // Helper class that creates a temporary file and exposes a FILE* to it.
233 // It will close the file on destruction.
234 class TempFile {
235  public:
236  TempFile() : file_(std::tmpfile()) {}
237  ~TempFile() { std::fclose(file_); }
238 
239  std::FILE* file() const { return file_; }
240 
241  // Read the file into a std::string.
242  std::string ReadFile() {
243  std::fseek(file_, 0, SEEK_END);
244  int size = std::ftell(file_);
245  EXPECT_GT(size, 0);
246  std::rewind(file_);
247  std::string str(2 * size, ' ');
248  int read_bytes = std::fread(&str[0], 1, str.size(), file_);
249  EXPECT_EQ(read_bytes, size);
250  str.resize(read_bytes);
251  EXPECT_TRUE(std::feof(file_));
252  return str;
253  }
254 
255  private:
256  std::FILE* file_;
257 };
258 
259 TEST_F(FormatEntryPointTest, FPrintF) {
260  TempFile tmp;
261  int result =
262  FPrintF(tmp.file(), "STRING: %s NUMBER: %010d", std::string("ABC"), -19);
263  EXPECT_EQ(result, 30);
264  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
265 }
266 
267 TEST_F(FormatEntryPointTest, FPrintFError) {
268  errno = 0;
269  int result = FPrintF(stdin, "ABC");
270  EXPECT_LT(result, 0);
271  EXPECT_EQ(errno, EBADF);
272 }
273 
274 #if __GLIBC__
275 TEST_F(FormatEntryPointTest, FprintfTooLarge) {
276  std::FILE* f = std::fopen("/dev/null", "w");
277  int width = 2000000000;
278  errno = 0;
279  int result = FPrintF(f, "%*d %*d", width, 0, width, 0);
280  EXPECT_LT(result, 0);
281  EXPECT_EQ(errno, EFBIG);
282  std::fclose(f);
283 }
284 
285 TEST_F(FormatEntryPointTest, PrintF) {
286  int stdout_tmp = dup(STDOUT_FILENO);
287 
288  TempFile tmp;
289  std::fflush(stdout);
290  dup2(fileno(tmp.file()), STDOUT_FILENO);
291 
292  int result = PrintF("STRING: %s NUMBER: %010d", std::string("ABC"), -19);
293 
294  std::fflush(stdout);
295  dup2(stdout_tmp, STDOUT_FILENO);
296  close(stdout_tmp);
297 
298  EXPECT_EQ(result, 30);
299  EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
300 }
301 #endif // __GLIBC__
302 
303 TEST_F(FormatEntryPointTest, SNPrintF) {
304  char buffer[16];
305  int result =
306  SNPrintF(buffer, sizeof(buffer), "STRING: %s", std::string("ABC"));
307  EXPECT_EQ(result, 11);
308  EXPECT_EQ(std::string(buffer), "STRING: ABC");
309 
310  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456);
311  EXPECT_EQ(result, 14);
312  EXPECT_EQ(std::string(buffer), "NUMBER: 123456");
313 
314  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567);
315  EXPECT_EQ(result, 15);
316  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
317 
318  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678);
319  EXPECT_EQ(result, 16);
320  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
321 
322  result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789);
323  EXPECT_EQ(result, 17);
324  EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
325 
326  result = SNPrintF(nullptr, 0, "Just checking the %s of the output.", "size");
327  EXPECT_EQ(result, 37);
328 }
329 
330 TEST(StrFormat, BehavesAsDocumented) {
331  std::string s = absl::StrFormat("%s, %d!", "Hello", 123);
332  EXPECT_EQ("Hello, 123!", s);
333  // The format of a replacement is
334  // '%'[position][flags][width['.'precision]][length_modifier][format]
335  EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10");
336  // Text conversion:
337  // "c" - Character. Eg: 'a' -> "A", 20 -> " "
338  EXPECT_EQ(StrFormat("%c", 'a'), "a");
339  EXPECT_EQ(StrFormat("%c", 0x20), " ");
340  // Formats char and integral types: int, long, uint64_t, etc.
341  EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
342  EXPECT_EQ(StrFormat("%c", long{'a'}), "a"); // NOLINT
343  EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
344  // "s" - std::string Eg: "C" -> "C", std::string("C++") -> "C++"
345  // Formats std::string, char*, string_view, and Cord.
346  EXPECT_EQ(StrFormat("%s", "C"), "C");
347  EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
348  EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
349  // Integral Conversion
350  // These format integral types: char, int, long, uint64_t, etc.
351  EXPECT_EQ(StrFormat("%d", char{10}), "10");
352  EXPECT_EQ(StrFormat("%d", int{10}), "10");
353  EXPECT_EQ(StrFormat("%d", long{10}), "10"); // NOLINT
354  EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10");
355  // d,i - signed decimal Eg: -10 -> "-10"
356  EXPECT_EQ(StrFormat("%d", -10), "-10");
357  EXPECT_EQ(StrFormat("%i", -10), "-10");
358  // o - octal Eg: 10 -> "12"
359  EXPECT_EQ(StrFormat("%o", 10), "12");
360  // u - unsigned decimal Eg: 10 -> "10"
361  EXPECT_EQ(StrFormat("%u", 10), "10");
362  // x/X - lower,upper case hex Eg: 10 -> "a"/"A"
363  EXPECT_EQ(StrFormat("%x", 10), "a");
364  EXPECT_EQ(StrFormat("%X", 10), "A");
365  // Floating-point, with upper/lower-case output.
366  // These format floating points types: float, double, long double, etc.
367  EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0");
368  EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0");
369  const long double long_double = 1.0;
370  EXPECT_EQ(StrFormat("%.1f", long_double), "1.0");
371  // These also format integral types: char, int, long, uint64_t, etc.:
372  EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0");
373  EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0");
374  EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0"); // NOLINT
375  EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0");
376  // f/F - decimal. Eg: 123456789 -> "123456789.000000"
377  EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000");
378  EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000");
379  // e/E - exponentiated Eg: .01 -> "1.00000e-2"/"1.00000E-2"
380  EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02");
381  EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02");
382  // g/G - exponentiate to fit Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10"
383  EXPECT_EQ(StrFormat("%g", .01), "0.01");
384  EXPECT_EQ(StrFormat("%g", 1e10), "1e+10");
385  EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
386  // a/A - lower,upper case hex Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
387 
388 // On Android platform <=21, there is a regression in hexfloat formatting.
389 #if !defined(__ANDROID_API__) || __ANDROID_API__ > 21
390  EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1"); // .1 to fix MSVC output
391  EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1"); // .1 to fix MSVC output
392 #endif
393 
394  // Other conversion
395  int64_t value = 0x7ffdeb4;
396  auto ptr_value = static_cast<uintptr_t>(value);
397  const int& something = *reinterpret_cast<const int*>(ptr_value);
398  EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value));
399 
400  // Output widths are supported, with optional flags.
401  EXPECT_EQ(StrFormat("%3d", 1), " 1");
402  EXPECT_EQ(StrFormat("%3d", 123456), "123456");
403  EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23");
404  EXPECT_EQ(StrFormat("%+d", 1), "+1");
405  EXPECT_EQ(StrFormat("% d", 1), " 1");
406  EXPECT_EQ(StrFormat("%-4d", -1), "-1 ");
407  EXPECT_EQ(StrFormat("%#o", 10), "012");
408  EXPECT_EQ(StrFormat("%#x", 15), "0xf");
409  EXPECT_EQ(StrFormat("%04d", 8), "0008");
410  // Posix positional substitution.
411  EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"),
412  "veni, vidi, vici!");
413  // Length modifiers are ignored.
414  EXPECT_EQ(StrFormat("%hhd", int{1}), "1");
415  EXPECT_EQ(StrFormat("%hd", int{1}), "1");
416  EXPECT_EQ(StrFormat("%ld", int{1}), "1");
417  EXPECT_EQ(StrFormat("%lld", int{1}), "1");
418  EXPECT_EQ(StrFormat("%Ld", int{1}), "1");
419  EXPECT_EQ(StrFormat("%jd", int{1}), "1");
420  EXPECT_EQ(StrFormat("%zd", int{1}), "1");
421  EXPECT_EQ(StrFormat("%td", int{1}), "1");
422  EXPECT_EQ(StrFormat("%qd", int{1}), "1");
423 }
424 
425 using str_format_internal::ExtendedParsedFormat;
427 
428 struct SummarizeConsumer {
429  std::string* out;
430  explicit SummarizeConsumer(std::string* out) : out(out) {}
431 
432  bool Append(string_view s) {
433  *out += "[" + std::string(s) + "]";
434  return true;
435  }
436 
437  bool ConvertOne(const str_format_internal::UnboundConversion& conv,
438  string_view s) {
439  *out += "{";
440  *out += std::string(s);
441  *out += ":";
442  *out += std::to_string(conv.arg_position) + "$";
443  if (conv.width.is_from_arg()) {
444  *out += std::to_string(conv.width.get_from_arg()) + "$*";
445  }
446  if (conv.precision.is_from_arg()) {
447  *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
448  }
449  *out += conv.conv.Char();
450  *out += "}";
451  return true;
452  }
453 };
454 
455 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
456  std::string out;
457  if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!";
458  return out;
459 }
460 
461 using ParsedFormatTest = ::testing::Test;
462 
463 TEST_F(ParsedFormatTest, SimpleChecked) {
464  EXPECT_EQ("[ABC]{d:1$d}[DEF]",
465  SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF")));
466  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}",
467  SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f")));
468  EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}",
469  SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d")));
470 }
471 
472 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) {
473  auto f = ParsedFormat<'d'>::New("ABC%dDEF");
474  ASSERT_TRUE(f);
475  EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
476 
477  std::string format = "%sFFF%dZZZ%f";
478  auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format);
479 
480  ASSERT_TRUE(f2);
481  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
482 
483  f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f");
484 
485  ASSERT_TRUE(f2);
486  EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
487 
488  auto star = ParsedFormat<'*', 'd'>::New("%*d");
489  ASSERT_TRUE(star);
490  EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
491 
492  auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d");
493  ASSERT_TRUE(dollar);
494  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
495  // with reuse
496  dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d");
497  ASSERT_TRUE(dollar);
498  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
499  SummarizeParsedFormat(*dollar));
500 }
501 
502 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) {
503  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC")));
504  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC")));
505  EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s")));
507  ASSERT_TRUE(f);
508  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
510  ASSERT_TRUE(f);
511  EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
513  ASSERT_TRUE(f);
514  EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
515 }
516 
517 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) {
518  EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x"));
519  EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x"));
520 }
521 
522 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
523  EXPECT_FALSE(ParsedFormat<'d'>::New(""));
524 
525  EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d"));
526 
527  std::string format = "%sFFF%dZZZ%f";
528  EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
529 }
530 
532 
533 TEST_F(ParsedFormatTest, UncheckedCorrect) {
534  auto f = ExtendedParsedFormat<Conv::d>::New("ABC%dDEF");
535  ASSERT_TRUE(f);
536  EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
537 
538  std::string format = "%sFFF%dZZZ%f";
539  auto f2 =
540  ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
541 
542  ASSERT_TRUE(f2);
543  EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
544 
545  f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
546  "%s %d %f");
547 
548  ASSERT_TRUE(f2);
549  EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
550 
551  auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
552  ASSERT_TRUE(star);
553  EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
554 
555  auto dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d");
556  ASSERT_TRUE(dollar);
557  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
558  // with reuse
559  dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d %1$d");
560  ASSERT_TRUE(dollar);
561  EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
562  SummarizeParsedFormat(*dollar));
563 }
564 
565 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
566  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC")));
567  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("%dABC")));
568  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC%2$s")));
569  auto f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC");
570  ASSERT_TRUE(f);
571  EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
572  f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
573  ASSERT_TRUE(f);
574  EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
575  f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
576  ASSERT_TRUE(f);
577  EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
578 }
579 
580 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
581  auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
582  EXPECT_TRUE(dx);
583  EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
584 
585  dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
586  EXPECT_TRUE(dx);
587  EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
588 }
589 
590 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
591  EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
592 
593  EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
594 
595  std::string format = "%sFFF%dZZZ%f";
596  EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
597 }
598 
599 TEST_F(ParsedFormatTest, RegressionMixPositional) {
600  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
601 }
602 
603 using FormatWrapperTest = ::testing::Test;
604 
605 // Plain wrapper for StrFormat.
606 template <typename... Args>
607 std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
608  const Args&... args) {
609  return StrFormat(format, args...);
610 }
611 
612 TEST_F(FormatWrapperTest, ConstexprStringFormat) {
613  EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
614 }
615 
616 TEST_F(FormatWrapperTest, ParsedFormat) {
617  ParsedFormat<'s'> format("%s there");
618  EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
619 }
620 
621 } // namespace
622 } // namespace absl
623 
624 // Some codegen thunks that we can use to easily dump the generated assembly for
625 // different StrFormat calls.
626 
627 std::string CodegenAbslStrFormatInt(int i) { // NOLINT
628  return absl::StrFormat("%d", i);
629 }
630 
631 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
632  int64_t i64) { // NOLINT
633  return absl::StrFormat("%d %s %d", i, s, i64);
634 }
635 
636 void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
637  absl::StrAppendFormat(out, "%d", i);
638 }
639 
640 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
641  const std::string& s,
642  int64_t i64) { // NOLINT
643  absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
644 }
str_format_internal::StreamedWrapper< T > FormatStreamed(const T &v)
Definition: str_format.h:122
ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:342
std::string CodegenAbslStrFormatInt(int i)
static std::unique_ptr< ExtendedParsedFormat > New(string_view format)
Definition: parser.h:299
TEST(NotificationTest, SanityTest)
std::string & StrAppendFormat(std::string *dst, const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:323
std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: log_severity.cc:21
std::FILE * file_
ABSL_MUST_USE_RESULT bool FormatUntyped(FormatRawSink raw_sink, const UntypedFormatSpec &format, absl::Span< const FormatArg > args)
Definition: str_format.h:512
#define X(c)
char buf[N]
Definition: algorithm.h:29
void CodegenAbslStrAppendFormatInt(std::string *out, int i)
std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string &s, int64_t i64)
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:305
str_format_internal::FormatArgImpl FormatArg
Definition: str_format.h:470
void CodegenAbslStrAppendFormatIntStringInt64(std::string *out, int i, const std::string &s, int64_t i64)
size_t value
str_format_internal::ExtendedParsedFormat< str_format_internal::ConversionCharToConv(Conv)... > ParsedFormat
Definition: str_format.h:280
TEST_F(GraphCyclesTest, NoCycle)
std::string format(const std::string &, const time_point< seconds > &, const femtoseconds &, const time_zone &)
int FPrintF(std::FILE *output, const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:383
static const UntypedFormatSpecImpl & Extract(const T &s)
Definition: bind.h:54
uintptr_t size
static std::unique_ptr< ExtendedParsedFormat > NewAllowIgnored(string_view format)
Definition: parser.h:302
bool FormatUntyped(FormatRawSinkImpl raw_sink, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: bind.cc:177
int PrintF(const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:363
void * arg
Definition: mutex.cc:292
std::string & AppendPack(std::string *out, const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: bind.cc:190
std::string FormatPack(const UntypedFormatSpecImpl format, absl::Span< const FormatArgImpl > args)
Definition: bind.h:167
static char * Append(char *out, const AlphaNum &x)
Definition: str_cat.cc:88
typename str_format_internal::FormatSpecDeductionBarrier< Args... >::type FormatSpec
Definition: str_format.h:251
bool Format(FormatRawSink raw_sink, const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:454
constexpr Span< T > MakeSpan(T *ptr, size_t size) noexcept
Definition: span.h:647
char * out
Definition: mutex.h:1013
int SNPrintF(char *output, std::size_t size, const FormatSpec< Args... > &format, const Args &...args)
Definition: str_format.h:406


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:19:58