proxygen
FormatTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2012-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/Format.h>
18 #include <folly/Utility.h>
20 
21 #include <string>
22 
23 using namespace folly;
24 
25 template <class Uint>
26 void compareOctal(Uint u) {
27  char buf1[detail::kMaxOctalLength + 1];
28  buf1[detail::kMaxOctalLength] = '\0';
29  char* p = buf1 + detail::uintToOctal(buf1, detail::kMaxOctalLength, u);
30 
31  char buf2[detail::kMaxOctalLength + 1];
32  EXPECT_LT(
33  snprintf(buf2, sizeof(buf2), "%jo", static_cast<uintmax_t>(u)),
34  sizeof(buf2));
35 
37 }
38 
39 template <class Uint>
40 void compareHex(Uint u) {
41  char buf1[detail::kMaxHexLength + 1];
42  buf1[detail::kMaxHexLength] = '\0';
43  char* p = buf1 + detail::uintToHexLower(buf1, detail::kMaxHexLength, u);
44 
45  char buf2[detail::kMaxHexLength + 1];
46  EXPECT_LT(
47  snprintf(buf2, sizeof(buf2), "%jx", static_cast<uintmax_t>(u)),
48  sizeof(buf2));
49 
51 }
52 
53 template <class Uint>
54 void compareBinary(Uint u) {
55  char buf[detail::kMaxBinaryLength + 1];
56  buf[detail::kMaxBinaryLength] = '\0';
57  char* p = buf + detail::uintToBinary(buf, detail::kMaxBinaryLength, u);
58 
59  std::string repr;
60  if (u == 0) {
61  repr = '0';
62  } else {
63  std::string tmp;
64  for (; u; u >>= 1) {
65  tmp.push_back(u & 1 ? '1' : '0');
66  }
67  repr.assign(tmp.rbegin(), tmp.rend());
68  }
69 
70  EXPECT_EQ(repr, std::string(p));
71 }
72 
73 TEST(Format, uintToOctal) {
74  for (unsigned i = 0; i < (1u << 16) + 2; i++) {
75  compareOctal(i);
76  }
77 }
78 
79 TEST(Format, uintToHex) {
80  for (unsigned i = 0; i < (1u << 16) + 2; i++) {
81  compareHex(i);
82  }
83 }
84 
85 TEST(Format, uintToBinary) {
86  for (unsigned i = 0; i < (1u << 16) + 2; i++) {
88  }
89 }
90 
91 TEST(Format, Simple) {
92  EXPECT_EQ("hello", sformat("hello"));
93  EXPECT_EQ("42", sformat("{}", 42));
94  EXPECT_EQ("42 42", sformat("{0} {0}", 42));
95  EXPECT_EQ("00042 23 42", sformat("{0:05} {1:3} {0:4}", 42, 23));
96  EXPECT_EQ(
97  "hello world hello 42", sformat("{0} {1} {0} {2}", "hello", "world", 42));
98  EXPECT_EQ("XXhelloXX", sformat("{:X^9}", "hello"));
99  EXPECT_EQ("XXX42XXXX", sformat("{:X^9}", 42));
100  EXPECT_EQ("-0xYYYY2a", sformat("{:Y=#9x}", -42));
101  EXPECT_EQ("*", sformat("{}", '*'));
102  EXPECT_EQ("42", sformat("{}", 42));
103  EXPECT_EQ("0042", sformat("{:04}", 42));
104 
105  EXPECT_EQ("hello ", sformat("{:7}", "hello"));
106  EXPECT_EQ("hello ", sformat("{:<7}", "hello"));
107  EXPECT_EQ(" hello", sformat("{:>7}", "hello"));
108 
109  EXPECT_EQ(" hi", sformat("{:>*}", 4, "hi"));
110  EXPECT_EQ(" hi!", sformat("{:*}{}", 3, "", "hi!"));
111  EXPECT_EQ(" 123", sformat("{:*}", 7, 123));
112  EXPECT_EQ("123 ", sformat("{:<*}", 7, 123));
113  EXPECT_EQ("----<=>----", sformat("{:-^*}", 11, "<=>"));
114  EXPECT_EQ("+++456+++", sformat("{2:+^*0}", 9, "unused", 456));
115 
116  std::vector<int> v1{10, 20, 30};
117  EXPECT_EQ("0020", sformat("{0[1]:04}", v1));
118  EXPECT_EQ("0020", svformat("{1:04}", v1));
119  EXPECT_EQ("10 20", svformat("{} {}", v1));
120 
121  const std::vector<int> v2 = v1;
122  EXPECT_EQ("0020", sformat("{0[1]:04}", v2));
123  EXPECT_EQ("0020", svformat("{1:04}", v2));
124  EXPECT_THROW(sformat("{0[3]:04}", v2), std::out_of_range);
125  EXPECT_THROW(svformat("{3:04}", v2), std::out_of_range);
126  EXPECT_EQ("0020", sformat("{0[1]:04}", defaulted(v2, 42)));
127  EXPECT_EQ("0020", svformat("{1:04}", defaulted(v2, 42)));
128  EXPECT_EQ("0042", sformat("{0[3]:04}", defaulted(v2, 42)));
129  EXPECT_EQ("0042", svformat("{3:04}", defaulted(v2, 42)));
130 
131  {
132  const int p[] = {10, 20, 30};
133  const int* q = p;
134  EXPECT_EQ("0020", sformat("{0[1]:04}", p));
135  EXPECT_EQ("0020", svformat("{1:04}", p));
136  EXPECT_EQ("0020", sformat("{0[1]:04}", q));
137  EXPECT_EQ("0020", svformat("{1:04}", q));
138  EXPECT_NE("", sformat("{}", q));
139 
140  EXPECT_EQ("0x", sformat("{}", p).substr(0, 2));
141  EXPECT_EQ("10", svformat("{}", p));
142  EXPECT_EQ("0x", sformat("{}", q).substr(0, 2));
143  EXPECT_EQ("10", svformat("{}", q));
144  q = nullptr;
145  EXPECT_EQ("(null)", sformat("{}", q));
146  }
147 
148  std::map<int, std::string> m{{10, "hello"}, {20, "world"}};
149  EXPECT_EQ("worldXX", sformat("{[20]:X<7}", m));
150  EXPECT_EQ("worldXX", svformat("{20:X<7}", m));
151  EXPECT_THROW(sformat("{[42]:X<7}", m), std::out_of_range);
152  EXPECT_THROW(svformat("{42:X<7}", m), std::out_of_range);
153  EXPECT_EQ("worldXX", sformat("{[20]:X<7}", defaulted(m, "meow")));
154  EXPECT_EQ("worldXX", svformat("{20:X<7}", defaulted(m, "meow")));
155  EXPECT_EQ("meowXXX", sformat("{[42]:X<7}", defaulted(m, "meow")));
156  EXPECT_EQ("meowXXX", svformat("{42:X<7}", defaulted(m, "meow")));
157 
158  std::map<std::string, std::string> m2{{"hello", "world"}};
159  EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", m2));
160  EXPECT_EQ("worldXX", svformat("{hello:X<7}", m2));
161  EXPECT_THROW(sformat("{[none]:X<7}", m2), std::out_of_range);
162  EXPECT_THROW(svformat("{none:X<7}", m2), std::out_of_range);
163  EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", defaulted(m2, "meow")));
164  EXPECT_EQ("worldXX", svformat("{hello:X<7}", defaulted(m2, "meow")));
165  EXPECT_EQ("meowXXX", sformat("{[none]:X<7}", defaulted(m2, "meow")));
166  EXPECT_EQ("meowXXX", svformat("{none:X<7}", defaulted(m2, "meow")));
167  try {
168  svformat("{none:X<7}", m2);
169  EXPECT_FALSE(true) << "svformat should throw on missing key";
170  } catch (const FormatKeyNotFoundException& e) {
171  EXPECT_STREQ("none", e.key());
172  }
173 
174  // Test indexing in strings
175  EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", "abcde"));
176  EXPECT_EQ("61 62", svformat("{0:x} {1:x}", "abcde"));
177  EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", std::string("abcde")));
178  EXPECT_EQ("61 62", svformat("{0:x} {1:x}", std::string("abcde")));
179 
180  // Test booleans
181  EXPECT_EQ("true", sformat("{}", true));
182  EXPECT_EQ("1", sformat("{:d}", true));
183  EXPECT_EQ("false", sformat("{}", false));
184  EXPECT_EQ("0", sformat("{:d}", false));
185 
186  // Test pairs
187  {
188  std::pair<int, std::string> p{42, "hello"};
189  EXPECT_EQ(" 42 hello ", sformat("{0[0]:6} {0[1]:6}", p));
190  EXPECT_EQ(" 42 hello ", svformat("{:6} {:6}", p));
191  }
192 
193  // Test tuples
194  {
195  std::tuple<int, std::string, int> t{42, "hello", 23};
196  EXPECT_EQ(" 42 hello 23", sformat("{0[0]:6} {0[1]:6} {0[2]:6}", t));
197  EXPECT_EQ(" 42 hello 23", svformat("{:6} {:6} {:6}", t));
198  }
199 
200  // Test writing to stream
201  std::ostringstream os;
202  os << format("{} {}", 42, 23);
203  EXPECT_EQ("42 23", os.str());
204 
205  // Test appending to string
206  std::string s;
207  format(&s, "{} {}", 42, 23);
208  format(&s, " hello {:X<7}", "world");
209  EXPECT_EQ("42 23 hello worldXX", s);
210 }
211 
212 TEST(Format, Float) {
213  EXPECT_EQ("1", sformat("{}", 1.0));
214  EXPECT_EQ("0.1", sformat("{}", 0.1));
215  EXPECT_EQ("0.01", sformat("{}", 0.01));
216  EXPECT_EQ("0.001", sformat("{}", 0.001));
217  EXPECT_EQ("0.0001", sformat("{}", 0.0001));
218  EXPECT_EQ("1e-5", sformat("{}", 0.00001));
219  EXPECT_EQ("1e-6", sformat("{}", 0.000001));
220 
221  EXPECT_EQ("10", sformat("{}", 10.0));
222  EXPECT_EQ("100", sformat("{}", 100.0));
223  EXPECT_EQ("1000", sformat("{}", 1000.0));
224  EXPECT_EQ("10000", sformat("{}", 10000.0));
225  EXPECT_EQ("100000", sformat("{}", 100000.0));
226  EXPECT_EQ("1e+6", sformat("{}", 1000000.0));
227  EXPECT_EQ("1e+7", sformat("{}", 10000000.0));
228 
229  EXPECT_EQ("1.00", sformat("{:.2f}", 1.0));
230  EXPECT_EQ("0.10", sformat("{:.2f}", 0.1));
231  EXPECT_EQ("0.01", sformat("{:.2f}", 0.01));
232  EXPECT_EQ("0.00", sformat("{:.2f}", 0.001));
233 
234  EXPECT_EQ("100000. !== 100000", sformat("{:.} !== {:.}", 100000.0, 100000));
235  EXPECT_EQ("100000.", sformat("{:.}", 100000.0));
236  EXPECT_EQ("1e+6", sformat("{:.}", 1000000.0));
237  EXPECT_EQ(" 100000.", sformat("{:8.}", 100000.0));
238  EXPECT_EQ("100000.", sformat("{:4.}", 100000.0));
239  EXPECT_EQ(" 100000", sformat("{:8.8}", 100000.0));
240  EXPECT_EQ(" 100000.", sformat("{:8.8.}", 100000.0));
241 }
242 
243 TEST(Format, MultiLevel) {
244  std::vector<std::map<std::string, std::string>> v = {
245  {
246  {"hello", "world"},
247  },
248  };
249 
250  EXPECT_EQ("world", sformat("{[0.hello]}", v));
251 }
252 
253 TEST(Format, separatorDecimalInteger) {
254  EXPECT_EQ("0", sformat("{:,d}", 0));
255  EXPECT_EQ("1", sformat("{:d}", 1));
256  EXPECT_EQ("1", sformat("{:,d}", 1));
257  EXPECT_EQ("1", sformat("{:,}", 1));
258  EXPECT_EQ("123", sformat("{:d}", 123));
259  EXPECT_EQ("123", sformat("{:,d}", 123));
260  EXPECT_EQ("123", sformat("{:,}", 123));
261  EXPECT_EQ("1234", sformat("{:d}", 1234));
262  EXPECT_EQ("1,234", sformat("{:,d}", 1234));
263  EXPECT_EQ("1,234", sformat("{:,}", 1234));
264  EXPECT_EQ("12345678", sformat("{:d}", 12345678));
265  EXPECT_EQ("12,345,678", sformat("{:,d}", 12345678));
266  EXPECT_EQ("12,345,678", sformat("{:,}", 12345678));
267  EXPECT_EQ("-1234", sformat("{:d}", -1234));
268  EXPECT_EQ("-1,234", sformat("{:,d}", -1234));
269  EXPECT_EQ("-1,234", sformat("{:,}", -1234));
270 
274  EXPECT_EQ("9223372036854775807", sformat("{:d}", max_int64_t));
275  EXPECT_EQ("9,223,372,036,854,775,807", sformat("{:,d}", max_int64_t));
276  EXPECT_EQ("9,223,372,036,854,775,807", sformat("{:,}", max_int64_t));
277  EXPECT_EQ("-9223372036854775808", sformat("{:d}", min_int64_t));
278  EXPECT_EQ("-9,223,372,036,854,775,808", sformat("{:,d}", min_int64_t));
279  EXPECT_EQ("-9,223,372,036,854,775,808", sformat("{:,}", min_int64_t));
280  EXPECT_EQ("18446744073709551615", sformat("{:d}", max_uint64_t));
281  EXPECT_EQ("18,446,744,073,709,551,615", sformat("{:,d}", max_uint64_t));
282  EXPECT_EQ("18,446,744,073,709,551,615", sformat("{:,}", max_uint64_t));
283 
284  EXPECT_EQ(" -1,234", sformat("{: 8,}", -1234));
285  EXPECT_EQ("-001,234", sformat("{:08,d}", -1234));
286  EXPECT_EQ("-00001,234", sformat("{:010,d}", -1234));
287  EXPECT_EQ(" -1,234 ", sformat("{:^ 8,d}", -1234));
288 }
289 
290 // Note that sformat("{:n}", ...) uses the current locale setting to insert the
291 // appropriate number separator characters.
292 TEST(Format, separatorNumber) {
293  EXPECT_EQ("0", sformat("{:n}", 0));
294  EXPECT_EQ("1", sformat("{:n}", 1));
295  EXPECT_EQ("123", sformat("{:n}", 123));
296  EXPECT_EQ("1234", sformat("{:n}", 1234));
297  EXPECT_EQ("12345678", sformat("{:n}", 12345678));
298  EXPECT_EQ("-1234", sformat("{:n}", -1234));
299 
303  EXPECT_EQ("9223372036854775807", sformat("{:n}", max_int64_t));
304  EXPECT_EQ("-9223372036854775808", sformat("{:n}", min_int64_t));
305  EXPECT_EQ("18446744073709551615", sformat("{:n}", max_uint64_t));
306 
307  EXPECT_EQ(" -1234", sformat("{: 8n}", -1234));
308  EXPECT_EQ("-0001234", sformat("{:08n}", -1234));
309  EXPECT_EQ("-000001234", sformat("{:010n}", -1234));
310  EXPECT_EQ(" -1234 ", sformat("{:^ 8n}", -1234));
311 }
312 
313 // insertThousandsGroupingUnsafe requires non-const params
314 static void testGrouping(const char* a_str, const char* expected) {
315  char str[256];
316  char* end_ptr = str + snprintf(str, sizeof(str), "%s", a_str);
317  ASSERT_LT(end_ptr, str + sizeof(str));
319  ASSERT_STREQ(expected, str);
320 }
321 
322 TEST(Format, separatorUnit) {
323  testGrouping("0", "0");
324  testGrouping("1", "1");
325  testGrouping("12", "12");
326  testGrouping("123", "123");
327  testGrouping("1234", "1,234");
328  testGrouping("12345", "12,345");
329  testGrouping("123456", "123,456");
330  testGrouping("1234567", "1,234,567");
331  testGrouping("1234567890", "1,234,567,890");
332  testGrouping("9223372036854775807", "9,223,372,036,854,775,807");
333  testGrouping("18446744073709551615", "18,446,744,073,709,551,615");
334 }
335 
336 namespace {
337 
338 struct KeyValue {
339  std::string key;
340  int value;
341 };
342 
343 } // namespace
344 
345 namespace folly {
346 
347 template <>
348 class FormatValue<KeyValue> {
349  public:
350  explicit FormatValue(const KeyValue& kv) : kv_(kv) {}
351 
352  template <class FormatCallback>
353  void format(FormatArg& arg, FormatCallback& cb) const {
355  folly::format("<key={}, value={}>", kv_.key, kv_.value), arg, cb);
356  }
357 
358  private:
359  const KeyValue& kv_;
360 };
361 
362 } // namespace folly
363 
364 TEST(Format, Custom) {
365  KeyValue kv{"hello", 42};
366 
367  EXPECT_EQ("<key=hello, value=42>", sformat("{}", kv));
368  EXPECT_EQ("<key=hello, value=42>", sformat("{:10}", kv));
369  EXPECT_EQ("<key=hello", sformat("{:.10}", kv));
370  EXPECT_EQ("<key=hello, value=42>XX", sformat("{:X<23}", kv));
371  EXPECT_EQ("XX<key=hello, value=42>", sformat("{:X>23}", kv));
372  EXPECT_EQ("<key=hello, value=42>", sformat("{0[0]}", &kv));
373  EXPECT_NE("", sformat("{}", &kv));
374 }
375 
376 namespace {
377 
378 struct Opaque {
379  int k;
380 };
381 
382 } // namespace
383 
384 #define EXPECT_THROW_STR(code, type, str) \
385  do { \
386  bool caught = false; \
387  try { \
388  code; \
389  } catch (const type& e) { \
390  caught = true; \
391  EXPECT_TRUE(strstr(e.what(), (str)) != nullptr) \
392  << "Expected message [" << (str) << "], actual message [" \
393  << e.what(); \
394  } catch (const std::exception& e) { \
395  caught = true; \
396  ADD_FAILURE() << "Caught different exception type; expected " #type \
397  ", caught " \
398  << folly::demangle(typeid(e)); \
399  } catch (...) { \
400  caught = true; \
401  ADD_FAILURE() << "Caught unknown exception type; expected " #type; \
402  } \
403  if (!caught) { \
404  ADD_FAILURE() << "Expected exception " #type ", caught nothing"; \
405  } \
406  } while (false)
407 
408 #define EXPECT_FORMAT_ERROR(code, str) \
409  EXPECT_THROW_STR(code, folly::BadFormatArg, (str))
410 
411 TEST(Format, Unformatted) {
412  Opaque o;
413  EXPECT_NE("", sformat("{}", &o));
415  sformat("{0[0]}", &o), "No formatter available for this type");
416 }
417 
418 TEST(Format, Nested) {
419  EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, format("{} {}", 3, 4)));
420  //
421  // not copyable, must hold temporary in scope instead.
422  auto&& saved = format("{} {}", 3, 4);
423  EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, saved));
424 }
425 
426 TEST(Format, OutOfBounds) {
427  std::vector<int> ints{1, 2, 3, 4, 5};
428  EXPECT_EQ("1 3 5", sformat("{0[0]} {0[2]} {0[4]}", ints));
429  EXPECT_THROW(sformat("{[5]}", ints), std::out_of_range);
430 
431  std::map<std::string, int> map{{"hello", 0}, {"world", 1}};
432  EXPECT_EQ("hello = 0", sformat("hello = {[hello]}", map));
433  EXPECT_THROW(sformat("{[nope]}", map), std::out_of_range);
434  EXPECT_THROW(svformat("{nope}", map), std::out_of_range);
435 }
436 
437 TEST(Format, BogusFormatString) {
438  EXPECT_FORMAT_ERROR(sformat("}"), "single '}' in format string");
439  EXPECT_FORMAT_ERROR(sformat("foo}bar"), "single '}' in format string");
440  EXPECT_FORMAT_ERROR(sformat("foo{bar"), "missing ending '}'");
441  EXPECT_FORMAT_ERROR(sformat("{[test]"), "missing ending '}'");
442  EXPECT_FORMAT_ERROR(sformat("{-1.3}"), "argument index must be non-negative");
443  EXPECT_FORMAT_ERROR(sformat("{1.3}", 0, 1, 2), "index not allowed");
445  sformat("{0} {} {1}", 0, 1, 2),
446  "may not have both default and explicit arg indexes");
448  sformat("{:*}", 1.2), "dynamic field width argument must be integral");
450  sformat("{} {:*}", "hi"), "argument index out of range, max=1");
452  sformat("{:*0}", 12, "ok"),
453  "cannot provide width arg index without value arg index");
455  sformat("{0:*}", 12, "ok"),
456  "cannot provide value arg index without width arg index");
457 
458  std::vector<int> v{1, 2, 3};
460  svformat("{:*}", v), "dynamic field width not supported in vformat()");
461 
462  // This one fails in detail::enforceWhitespace(), which throws
463  // std::range_error
464  EXPECT_THROW_STR(sformat("{0[test}"), std::range_error, "Non-whitespace");
465 }
466 
467 template <bool containerMode, class... Args>
469 
470 template <bool containerMode, class... Args>
472  : public BaseFormatter<
473  TestExtendingFormatter<containerMode, Args...>,
474  containerMode,
475  Args...> {
476  private:
477  explicit TestExtendingFormatter(StringPiece& str, Args&&... args)
478  : BaseFormatter<
479  TestExtendingFormatter<containerMode, Args...>,
480  containerMode,
481  Args...>(str, std::forward<Args>(args)...) {}
482 
483  template <size_t K, class Callback>
484  void doFormatArg(FormatArg& arg, Callback& cb) const {
485  std::string result;
486  auto appender = [&result](StringPiece s) {
487  result.append(s.data(), s.size());
488  };
489  this->template getFormatValue<K>().format(arg, appender);
490  result = sformat("{{{}}}", result);
491  cb(StringPiece(result));
492  }
493 
494  friend class BaseFormatter<
495  TestExtendingFormatter<containerMode, Args...>,
496  containerMode,
497  Args...>;
498 
499  template <class... A>
500  friend std::string texsformat(StringPiece fmt, A&&... arg);
501 };
502 
503 template <class... Args>
505  return TestExtendingFormatter<false, Args...>(
506  fmt, std::forward<Args>(args)...)
507  .str();
508 }
509 
510 TEST(Format, Extending) {
511  EXPECT_EQ(texsformat("I {} brackets", "love"), "I {love} brackets");
512  EXPECT_EQ(
513  texsformat("I {} nesting", sformat("really {}", "love")),
514  "I {really love} nesting");
515  EXPECT_EQ(
516  sformat("I also {} nesting", texsformat("have an {} for", "affinity")),
517  "I also have an {affinity} for nesting");
518  EXPECT_EQ(
519  texsformat(
520  "Extending {} in {}",
521  texsformat("a {}", "formatter"),
522  "another formatter"),
523  "Extending {a {formatter}} in {another formatter}");
524 }
525 
526 TEST(Format, Temporary) {
527  constexpr StringPiece kStr = "A long string that should go on the heap";
528  auto fmt = format("{}", kStr.str()); // Pass a temporary std::string.
529  EXPECT_EQ(fmt.str(), kStr);
530  // The formatter can be reused.
531  EXPECT_EQ(fmt.str(), kStr);
532 }
533 
534 namespace {
535 
536 struct NoncopyableInt : MoveOnly {
537  explicit NoncopyableInt(int v) : value(v) {}
538  int value;
539 };
540 
541 } // namespace
542 
543 namespace folly {
544 
545 template <>
546 class FormatValue<NoncopyableInt> {
547  public:
548  explicit FormatValue(const NoncopyableInt& v) : v_(v) {}
549 
550  template <class FormatCallback>
551  void format(FormatArg& arg, FormatCallback& cb) const {
552  FormatValue<int>(v_.value).format(arg, cb);
553  }
554 
555  private:
556  const NoncopyableInt& v_;
557 };
558 
559 } // namespace folly
560 
561 TEST(Format, NoncopyableArg) {
562  {
563  // Test that lvalues are held by reference.
564  NoncopyableInt v(1);
565  auto fmt = format("{}", v);
566  EXPECT_EQ(fmt.str(), "1");
567  // The formatter can be reused.
568  EXPECT_EQ(fmt.str(), "1");
569  }
570 
571  {
572  // Test that rvalues are moved.
573  auto fmt = format("{}", NoncopyableInt(1));
574  EXPECT_EQ(fmt.str(), "1");
575  }
576 }
TestExtendingFormatter(StringPiece &str, Args &&...args)
Definition: FormatTest.cpp:477
static void testGrouping(const char *a_str, const char *expected)
Definition: FormatTest.cpp:314
#define ASSERT_STREQ(s1, s2)
Definition: gtest.h:2004
void compareOctal(Uint u)
Definition: FormatTest.cpp:26
auto v
std::unique_ptr< int > A
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
LogLevel max
Definition: LogLevel.cpp:31
#define ASSERT_LT(val1, val2)
Definition: gtest.h:1968
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
size_t uintToBinary(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:142
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void compareBinary(Uint u)
Definition: FormatTest.cpp:54
size_t uintToHexLower(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:90
#define EXPECT_THROW_STR(code, type, str)
Definition: FormatTest.cpp:384
STL namespace.
size_t uintToOctal(char *buffer, size_t bufLen, Uint v)
Definition: Format-inl.h:112
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::string texsformat(StringPiece fmt, Args &&...args)
Definition: FormatTest.cpp:504
detail::DefaultValueWrapper< Container, Value > defaulted(const Container &c, const Value &v)
Definition: Format.h:353
#define EXPECT_FORMAT_ERROR(code, str)
Definition: FormatTest.cpp:408
const size_t kMaxHexLength
Definition: Format-inl.h:51
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:1995
LogLevel min
Definition: LogLevel.cpp:30
FloatingPoint< float > Float
void formatFormatter(const BaseFormatter< Derived, containerMode, Args... > &formatter, FormatArg &arg, FormatCallback &cb)
Definition: Format-inl.h:380
static map< string, int > m
FormatValue(const KeyValue &kv)
Definition: FormatTest.cpp:350
Definition: Traits.h:594
size_t uintToHex(char *buffer, size_t bufLen, Uint v, std::array< std::array< char, 2 >, 256 > const &repr)
Definition: Format-inl.h:65
void insertThousandsGroupingUnsafe(char *start_buffer, char **end_buffer)
Definition: Format.cpp:387
void compareHex(Uint u)
Definition: FormatTest.cpp:40
std::string svformat(StringPiece fmt, Container &&container)
Definition: Format.h:307
const char * string
Definition: Conv.cpp:212
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
Formatter< false, Args... > format(StringPiece fmt, Args &&...args)
Definition: Format.h:271
void format(FormatArg &arg, FormatCallback &cb) const
Definition: FormatTest.cpp:353
FormatValue(const NoncopyableInt &v)
Definition: FormatTest.cpp:548
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
void format(FormatArg &arg, FormatCallback &cb) const
Definition: FormatTest.cpp:551
char const * key() const noexcept
Definition: Format.h:326
const size_t kMaxBinaryLength
Definition: Format-inl.h:53
Range< const char * > StringPiece
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
KeyT k
TEST(SequencedExecutor, CPUThreadPoolExecutor)
void doFormatArg(FormatArg &arg, Callback &cb) const
Definition: FormatTest.cpp:484
const size_t kMaxOctalLength
Definition: Format-inl.h:52