FormatTest.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  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. #include <folly/Format.h>
  17. #include <folly/Utility.h>
  18. #include <folly/portability/GTest.h>
  19. #include <string>
  20. using namespace folly;
  21. template <class Uint>
  22. void compareOctal(Uint u) {
  23. char buf1[detail::kMaxOctalLength + 1];
  24. buf1[detail::kMaxOctalLength] = '\0';
  25. char* p = buf1 + detail::uintToOctal(buf1, detail::kMaxOctalLength, u);
  26. char buf2[detail::kMaxOctalLength + 1];
  27. EXPECT_LT(
  28. snprintf(buf2, sizeof(buf2), "%jo", static_cast<uintmax_t>(u)),
  29. sizeof(buf2));
  30. EXPECT_EQ(std::string(buf2), std::string(p));
  31. }
  32. template <class Uint>
  33. void compareHex(Uint u) {
  34. char buf1[detail::kMaxHexLength + 1];
  35. buf1[detail::kMaxHexLength] = '\0';
  36. char* p = buf1 + detail::uintToHexLower(buf1, detail::kMaxHexLength, u);
  37. char buf2[detail::kMaxHexLength + 1];
  38. EXPECT_LT(
  39. snprintf(buf2, sizeof(buf2), "%jx", static_cast<uintmax_t>(u)),
  40. sizeof(buf2));
  41. EXPECT_EQ(std::string(buf2), std::string(p));
  42. }
  43. template <class Uint>
  44. void compareBinary(Uint u) {
  45. char buf[detail::kMaxBinaryLength + 1];
  46. buf[detail::kMaxBinaryLength] = '\0';
  47. char* p = buf + detail::uintToBinary(buf, detail::kMaxBinaryLength, u);
  48. std::string repr;
  49. if (u == 0) {
  50. repr = '0';
  51. } else {
  52. std::string tmp;
  53. for (; u; u >>= 1) {
  54. tmp.push_back(u & 1 ? '1' : '0');
  55. }
  56. repr.assign(tmp.rbegin(), tmp.rend());
  57. }
  58. EXPECT_EQ(repr, std::string(p));
  59. }
  60. TEST(Format, uintToOctal) {
  61. for (unsigned i = 0; i < (1u << 16) + 2; i++) {
  62. compareOctal(i);
  63. }
  64. }
  65. TEST(Format, uintToHex) {
  66. for (unsigned i = 0; i < (1u << 16) + 2; i++) {
  67. compareHex(i);
  68. }
  69. }
  70. TEST(Format, uintToBinary) {
  71. for (unsigned i = 0; i < (1u << 16) + 2; i++) {
  72. compareBinary(i);
  73. }
  74. }
  75. TEST(Format, Simple) {
  76. EXPECT_EQ("hello", sformat("hello"));
  77. EXPECT_EQ("42", sformat("{}", 42));
  78. EXPECT_EQ("42 42", sformat("{0} {0}", 42));
  79. EXPECT_EQ("00042 23 42", sformat("{0:05} {1:3} {0:4}", 42, 23));
  80. EXPECT_EQ(
  81. "hello world hello 42", sformat("{0} {1} {0} {2}", "hello", "world", 42));
  82. EXPECT_EQ("XXhelloXX", sformat("{:X^9}", "hello"));
  83. EXPECT_EQ("XXX42XXXX", sformat("{:X^9}", 42));
  84. EXPECT_EQ("-0xYYYY2a", sformat("{:Y=#9x}", -42));
  85. EXPECT_EQ("*", sformat("{}", '*'));
  86. EXPECT_EQ("42", sformat("{}", 42));
  87. EXPECT_EQ("0042", sformat("{:04}", 42));
  88. EXPECT_EQ("hello ", sformat("{:7}", "hello"));
  89. EXPECT_EQ("hello ", sformat("{:<7}", "hello"));
  90. EXPECT_EQ(" hello", sformat("{:>7}", "hello"));
  91. EXPECT_EQ(" hi", sformat("{:>*}", 4, "hi"));
  92. EXPECT_EQ(" hi!", sformat("{:*}{}", 3, "", "hi!"));
  93. EXPECT_EQ(" 123", sformat("{:*}", 7, 123));
  94. EXPECT_EQ("123 ", sformat("{:<*}", 7, 123));
  95. EXPECT_EQ("----<=>----", sformat("{:-^*}", 11, "<=>"));
  96. EXPECT_EQ("+++456+++", sformat("{2:+^*0}", 9, "unused", 456));
  97. std::vector<int> v1{10, 20, 30};
  98. EXPECT_EQ("0020", sformat("{0[1]:04}", v1));
  99. EXPECT_EQ("0020", svformat("{1:04}", v1));
  100. EXPECT_EQ("10 20", svformat("{} {}", v1));
  101. const std::vector<int> v2 = v1;
  102. EXPECT_EQ("0020", sformat("{0[1]:04}", v2));
  103. EXPECT_EQ("0020", svformat("{1:04}", v2));
  104. EXPECT_THROW(sformat("{0[3]:04}", v2), std::out_of_range);
  105. EXPECT_THROW(svformat("{3:04}", v2), std::out_of_range);
  106. EXPECT_EQ("0020", sformat("{0[1]:04}", defaulted(v2, 42)));
  107. EXPECT_EQ("0020", svformat("{1:04}", defaulted(v2, 42)));
  108. EXPECT_EQ("0042", sformat("{0[3]:04}", defaulted(v2, 42)));
  109. EXPECT_EQ("0042", svformat("{3:04}", defaulted(v2, 42)));
  110. {
  111. const int p[] = {10, 20, 30};
  112. const int* q = p;
  113. EXPECT_EQ("0020", sformat("{0[1]:04}", p));
  114. EXPECT_EQ("0020", svformat("{1:04}", p));
  115. EXPECT_EQ("0020", sformat("{0[1]:04}", q));
  116. EXPECT_EQ("0020", svformat("{1:04}", q));
  117. EXPECT_NE("", sformat("{}", q));
  118. EXPECT_EQ("0x", sformat("{}", p).substr(0, 2));
  119. EXPECT_EQ("10", svformat("{}", p));
  120. EXPECT_EQ("0x", sformat("{}", q).substr(0, 2));
  121. EXPECT_EQ("10", svformat("{}", q));
  122. q = nullptr;
  123. EXPECT_EQ("(null)", sformat("{}", q));
  124. }
  125. std::map<int, std::string> m{{10, "hello"}, {20, "world"}};
  126. EXPECT_EQ("worldXX", sformat("{[20]:X<7}", m));
  127. EXPECT_EQ("worldXX", svformat("{20:X<7}", m));
  128. EXPECT_THROW(sformat("{[42]:X<7}", m), std::out_of_range);
  129. EXPECT_THROW(svformat("{42:X<7}", m), std::out_of_range);
  130. EXPECT_EQ("worldXX", sformat("{[20]:X<7}", defaulted(m, "meow")));
  131. EXPECT_EQ("worldXX", svformat("{20:X<7}", defaulted(m, "meow")));
  132. EXPECT_EQ("meowXXX", sformat("{[42]:X<7}", defaulted(m, "meow")));
  133. EXPECT_EQ("meowXXX", svformat("{42:X<7}", defaulted(m, "meow")));
  134. std::map<std::string, std::string> m2{{"hello", "world"}};
  135. EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", m2));
  136. EXPECT_EQ("worldXX", svformat("{hello:X<7}", m2));
  137. EXPECT_THROW(sformat("{[none]:X<7}", m2), std::out_of_range);
  138. EXPECT_THROW(svformat("{none:X<7}", m2), std::out_of_range);
  139. EXPECT_EQ("worldXX", sformat("{[hello]:X<7}", defaulted(m2, "meow")));
  140. EXPECT_EQ("worldXX", svformat("{hello:X<7}", defaulted(m2, "meow")));
  141. EXPECT_EQ("meowXXX", sformat("{[none]:X<7}", defaulted(m2, "meow")));
  142. EXPECT_EQ("meowXXX", svformat("{none:X<7}", defaulted(m2, "meow")));
  143. try {
  144. svformat("{none:X<7}", m2);
  145. EXPECT_FALSE(true) << "svformat should throw on missing key";
  146. } catch (const FormatKeyNotFoundException& e) {
  147. EXPECT_STREQ("none", e.key());
  148. }
  149. // Test indexing in strings
  150. EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", "abcde"));
  151. EXPECT_EQ("61 62", svformat("{0:x} {1:x}", "abcde"));
  152. EXPECT_EQ("61 62", sformat("{0[0]:x} {0[1]:x}", std::string("abcde")));
  153. EXPECT_EQ("61 62", svformat("{0:x} {1:x}", std::string("abcde")));
  154. // Test booleans
  155. EXPECT_EQ("true", sformat("{}", true));
  156. EXPECT_EQ("1", sformat("{:d}", true));
  157. EXPECT_EQ("false", sformat("{}", false));
  158. EXPECT_EQ("0", sformat("{:d}", false));
  159. // Test pairs
  160. {
  161. std::pair<int, std::string> p{42, "hello"};
  162. EXPECT_EQ(" 42 hello ", sformat("{0[0]:6} {0[1]:6}", p));
  163. EXPECT_EQ(" 42 hello ", svformat("{:6} {:6}", p));
  164. }
  165. // Test tuples
  166. {
  167. std::tuple<int, std::string, int> t{42, "hello", 23};
  168. EXPECT_EQ(" 42 hello 23", sformat("{0[0]:6} {0[1]:6} {0[2]:6}", t));
  169. EXPECT_EQ(" 42 hello 23", svformat("{:6} {:6} {:6}", t));
  170. }
  171. // Test writing to stream
  172. std::ostringstream os;
  173. os << format("{} {}", 42, 23);
  174. EXPECT_EQ("42 23", os.str());
  175. // Test appending to string
  176. std::string s;
  177. format(&s, "{} {}", 42, 23);
  178. format(&s, " hello {:X<7}", "world");
  179. EXPECT_EQ("42 23 hello worldXX", s);
  180. }
  181. TEST(Format, Float) {
  182. EXPECT_EQ("1", sformat("{}", 1.0));
  183. EXPECT_EQ("0.1", sformat("{}", 0.1));
  184. EXPECT_EQ("0.01", sformat("{}", 0.01));
  185. EXPECT_EQ("0.001", sformat("{}", 0.001));
  186. EXPECT_EQ("0.0001", sformat("{}", 0.0001));
  187. EXPECT_EQ("1e-5", sformat("{}", 0.00001));
  188. EXPECT_EQ("1e-6", sformat("{}", 0.000001));
  189. EXPECT_EQ("10", sformat("{}", 10.0));
  190. EXPECT_EQ("100", sformat("{}", 100.0));
  191. EXPECT_EQ("1000", sformat("{}", 1000.0));
  192. EXPECT_EQ("10000", sformat("{}", 10000.0));
  193. EXPECT_EQ("100000", sformat("{}", 100000.0));
  194. EXPECT_EQ("1e+6", sformat("{}", 1000000.0));
  195. EXPECT_EQ("1e+7", sformat("{}", 10000000.0));
  196. EXPECT_EQ("1.00", sformat("{:.2f}", 1.0));
  197. EXPECT_EQ("0.10", sformat("{:.2f}", 0.1));
  198. EXPECT_EQ("0.01", sformat("{:.2f}", 0.01));
  199. EXPECT_EQ("0.00", sformat("{:.2f}", 0.001));
  200. EXPECT_EQ("100000. !== 100000", sformat("{:.} !== {:.}", 100000.0, 100000));
  201. EXPECT_EQ("100000.", sformat("{:.}", 100000.0));
  202. EXPECT_EQ("1e+6", sformat("{:.}", 1000000.0));
  203. EXPECT_EQ(" 100000.", sformat("{:8.}", 100000.0));
  204. EXPECT_EQ("100000.", sformat("{:4.}", 100000.0));
  205. EXPECT_EQ(" 100000", sformat("{:8.8}", 100000.0));
  206. EXPECT_EQ(" 100000.", sformat("{:8.8.}", 100000.0));
  207. }
  208. TEST(Format, MultiLevel) {
  209. std::vector<std::map<std::string, std::string>> v = {
  210. {
  211. {"hello", "world"},
  212. },
  213. };
  214. EXPECT_EQ("world", sformat("{[0.hello]}", v));
  215. }
  216. TEST(Format, separatorDecimalInteger) {
  217. EXPECT_EQ("0", sformat("{:,d}", 0));
  218. EXPECT_EQ("1", sformat("{:d}", 1));
  219. EXPECT_EQ("1", sformat("{:,d}", 1));
  220. EXPECT_EQ("1", sformat("{:,}", 1));
  221. EXPECT_EQ("123", sformat("{:d}", 123));
  222. EXPECT_EQ("123", sformat("{:,d}", 123));
  223. EXPECT_EQ("123", sformat("{:,}", 123));
  224. EXPECT_EQ("1234", sformat("{:d}", 1234));
  225. EXPECT_EQ("1,234", sformat("{:,d}", 1234));
  226. EXPECT_EQ("1,234", sformat("{:,}", 1234));
  227. EXPECT_EQ("12345678", sformat("{:d}", 12345678));
  228. EXPECT_EQ("12,345,678", sformat("{:,d}", 12345678));
  229. EXPECT_EQ("12,345,678", sformat("{:,}", 12345678));
  230. EXPECT_EQ("-1234", sformat("{:d}", -1234));
  231. EXPECT_EQ("-1,234", sformat("{:,d}", -1234));
  232. EXPECT_EQ("-1,234", sformat("{:,}", -1234));
  233. int64_t max_int64_t = std::numeric_limits<int64_t>::max();
  234. int64_t min_int64_t = std::numeric_limits<int64_t>::min();
  235. uint64_t max_uint64_t = std::numeric_limits<uint64_t>::max();
  236. EXPECT_EQ("9223372036854775807", sformat("{:d}", max_int64_t));
  237. EXPECT_EQ("9,223,372,036,854,775,807", sformat("{:,d}", max_int64_t));
  238. EXPECT_EQ("9,223,372,036,854,775,807", sformat("{:,}", max_int64_t));
  239. EXPECT_EQ("-9223372036854775808", sformat("{:d}", min_int64_t));
  240. EXPECT_EQ("-9,223,372,036,854,775,808", sformat("{:,d}", min_int64_t));
  241. EXPECT_EQ("-9,223,372,036,854,775,808", sformat("{:,}", min_int64_t));
  242. EXPECT_EQ("18446744073709551615", sformat("{:d}", max_uint64_t));
  243. EXPECT_EQ("18,446,744,073,709,551,615", sformat("{:,d}", max_uint64_t));
  244. EXPECT_EQ("18,446,744,073,709,551,615", sformat("{:,}", max_uint64_t));
  245. EXPECT_EQ(" -1,234", sformat("{: 8,}", -1234));
  246. EXPECT_EQ("-001,234", sformat("{:08,d}", -1234));
  247. EXPECT_EQ("-00001,234", sformat("{:010,d}", -1234));
  248. EXPECT_EQ(" -1,234 ", sformat("{:^ 8,d}", -1234));
  249. }
  250. // Note that sformat("{:n}", ...) uses the current locale setting to insert the
  251. // appropriate number separator characters.
  252. TEST(Format, separatorNumber) {
  253. EXPECT_EQ("0", sformat("{:n}", 0));
  254. EXPECT_EQ("1", sformat("{:n}", 1));
  255. EXPECT_EQ("123", sformat("{:n}", 123));
  256. EXPECT_EQ("1234", sformat("{:n}", 1234));
  257. EXPECT_EQ("12345678", sformat("{:n}", 12345678));
  258. EXPECT_EQ("-1234", sformat("{:n}", -1234));
  259. int64_t max_int64_t = std::numeric_limits<int64_t>::max();
  260. int64_t min_int64_t = std::numeric_limits<int64_t>::min();
  261. uint64_t max_uint64_t = std::numeric_limits<uint64_t>::max();
  262. EXPECT_EQ("9223372036854775807", sformat("{:n}", max_int64_t));
  263. EXPECT_EQ("-9223372036854775808", sformat("{:n}", min_int64_t));
  264. EXPECT_EQ("18446744073709551615", sformat("{:n}", max_uint64_t));
  265. EXPECT_EQ(" -1234", sformat("{: 8n}", -1234));
  266. EXPECT_EQ("-0001234", sformat("{:08n}", -1234));
  267. EXPECT_EQ("-000001234", sformat("{:010n}", -1234));
  268. EXPECT_EQ(" -1234 ", sformat("{:^ 8n}", -1234));
  269. }
  270. // insertThousandsGroupingUnsafe requires non-const params
  271. static void testGrouping(const char* a_str, const char* expected) {
  272. char str[256];
  273. char* end_ptr = str + snprintf(str, sizeof(str), "%s", a_str);
  274. ASSERT_LT(end_ptr, str + sizeof(str));
  275. folly::detail::insertThousandsGroupingUnsafe(str, &end_ptr);
  276. ASSERT_STREQ(expected, str);
  277. }
  278. TEST(Format, separatorUnit) {
  279. testGrouping("0", "0");
  280. testGrouping("1", "1");
  281. testGrouping("12", "12");
  282. testGrouping("123", "123");
  283. testGrouping("1234", "1,234");
  284. testGrouping("12345", "12,345");
  285. testGrouping("123456", "123,456");
  286. testGrouping("1234567", "1,234,567");
  287. testGrouping("1234567890", "1,234,567,890");
  288. testGrouping("9223372036854775807", "9,223,372,036,854,775,807");
  289. testGrouping("18446744073709551615", "18,446,744,073,709,551,615");
  290. }
  291. namespace {
  292. struct KeyValue {
  293. std::string key;
  294. int value;
  295. };
  296. } // namespace
  297. namespace folly {
  298. template <>
  299. class FormatValue<KeyValue> {
  300. public:
  301. explicit FormatValue(const KeyValue& kv) : kv_(kv) {}
  302. template <class FormatCallback>
  303. void format(FormatArg& arg, FormatCallback& cb) const {
  304. format_value::formatFormatter(
  305. folly::format("<key={}, value={}>", kv_.key, kv_.value), arg, cb);
  306. }
  307. private:
  308. const KeyValue& kv_;
  309. };
  310. } // namespace folly
  311. TEST(Format, Custom) {
  312. KeyValue kv{"hello", 42};
  313. EXPECT_EQ("<key=hello, value=42>", sformat("{}", kv));
  314. EXPECT_EQ("<key=hello, value=42>", sformat("{:10}", kv));
  315. EXPECT_EQ("<key=hello", sformat("{:.10}", kv));
  316. EXPECT_EQ("<key=hello, value=42>XX", sformat("{:X<23}", kv));
  317. EXPECT_EQ("XX<key=hello, value=42>", sformat("{:X>23}", kv));
  318. EXPECT_EQ("<key=hello, value=42>", sformat("{0[0]}", &kv));
  319. EXPECT_NE("", sformat("{}", &kv));
  320. }
  321. namespace {
  322. struct Opaque {
  323. int k;
  324. };
  325. } // namespace
  326. #define EXPECT_THROW_STR(code, type, str) \
  327. do { \
  328. bool caught = false; \
  329. try { \
  330. code; \
  331. } catch (const type& e) { \
  332. caught = true; \
  333. EXPECT_TRUE(strstr(e.what(), (str)) != nullptr) \
  334. << "Expected message [" << (str) << "], actual message [" \
  335. << e.what(); \
  336. } catch (const std::exception& e) { \
  337. caught = true; \
  338. ADD_FAILURE() << "Caught different exception type; expected " #type \
  339. ", caught " \
  340. << folly::demangle(typeid(e)); \
  341. } catch (...) { \
  342. caught = true; \
  343. ADD_FAILURE() << "Caught unknown exception type; expected " #type; \
  344. } \
  345. if (!caught) { \
  346. ADD_FAILURE() << "Expected exception " #type ", caught nothing"; \
  347. } \
  348. } while (false)
  349. #define EXPECT_FORMAT_ERROR(code, str) \
  350. EXPECT_THROW_STR(code, folly::BadFormatArg, (str))
  351. TEST(Format, Unformatted) {
  352. Opaque o;
  353. EXPECT_NE("", sformat("{}", &o));
  354. EXPECT_FORMAT_ERROR(
  355. sformat("{0[0]}", &o), "No formatter available for this type");
  356. }
  357. TEST(Format, Nested) {
  358. EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, format("{} {}", 3, 4)));
  359. //
  360. // not copyable, must hold temporary in scope instead.
  361. auto&& saved = format("{} {}", 3, 4);
  362. EXPECT_EQ("1 2 3 4", sformat("{} {} {}", 1, 2, saved));
  363. }
  364. TEST(Format, OutOfBounds) {
  365. std::vector<int> ints{1, 2, 3, 4, 5};
  366. EXPECT_EQ("1 3 5", sformat("{0[0]} {0[2]} {0[4]}", ints));
  367. EXPECT_THROW(sformat("{[5]}", ints), std::out_of_range);
  368. std::map<std::string, int> map{{"hello", 0}, {"world", 1}};
  369. EXPECT_EQ("hello = 0", sformat("hello = {[hello]}", map));
  370. EXPECT_THROW(sformat("{[nope]}", map), std::out_of_range);
  371. EXPECT_THROW(svformat("{nope}", map), std::out_of_range);
  372. }
  373. TEST(Format, BogusFormatString) {
  374. EXPECT_FORMAT_ERROR(sformat("}"), "single '}' in format string");
  375. EXPECT_FORMAT_ERROR(sformat("foo}bar"), "single '}' in format string");
  376. EXPECT_FORMAT_ERROR(sformat("foo{bar"), "missing ending '}'");
  377. EXPECT_FORMAT_ERROR(sformat("{[test]"), "missing ending '}'");
  378. EXPECT_FORMAT_ERROR(sformat("{-1.3}"), "argument index must be non-negative");
  379. EXPECT_FORMAT_ERROR(sformat("{1.3}", 0, 1, 2), "index not allowed");
  380. EXPECT_FORMAT_ERROR(
  381. sformat("{0} {} {1}", 0, 1, 2),
  382. "may not have both default and explicit arg indexes");
  383. EXPECT_FORMAT_ERROR(
  384. sformat("{:*}", 1.2), "dynamic field width argument must be integral");
  385. EXPECT_FORMAT_ERROR(
  386. sformat("{} {:*}", "hi"), "argument index out of range, max=1");
  387. EXPECT_FORMAT_ERROR(
  388. sformat("{:*0}", 12, "ok"),
  389. "cannot provide width arg index without value arg index");
  390. EXPECT_FORMAT_ERROR(
  391. sformat("{0:*}", 12, "ok"),
  392. "cannot provide value arg index without width arg index");
  393. std::vector<int> v{1, 2, 3};
  394. EXPECT_FORMAT_ERROR(
  395. svformat("{:*}", v), "dynamic field width not supported in vformat()");
  396. // This one fails in detail::enforceWhitespace(), which throws
  397. // std::range_error
  398. EXPECT_THROW_STR(sformat("{0[test}"), std::range_error, "Non-whitespace");
  399. }
  400. template <bool containerMode, class... Args>
  401. class TestExtendingFormatter;
  402. template <bool containerMode, class... Args>
  403. class TestExtendingFormatter
  404. : public BaseFormatter<
  405. TestExtendingFormatter<containerMode, Args...>,
  406. containerMode,
  407. Args...> {
  408. private:
  409. explicit TestExtendingFormatter(StringPiece& str, Args&&... args)
  410. : BaseFormatter<
  411. TestExtendingFormatter<containerMode, Args...>,
  412. containerMode,
  413. Args...>(str, std::forward<Args>(args)...) {}
  414. template <size_t K, class Callback>
  415. void doFormatArg(FormatArg& arg, Callback& cb) const {
  416. std::string result;
  417. auto appender = [&result](StringPiece s) {
  418. result.append(s.data(), s.size());
  419. };
  420. this->template getFormatValue<K>().format(arg, appender);
  421. result = sformat("{{{}}}", result);
  422. cb(StringPiece(result));
  423. }
  424. friend class BaseFormatter<
  425. TestExtendingFormatter<containerMode, Args...>,
  426. containerMode,
  427. Args...>;
  428. template <class... A>
  429. friend std::string texsformat(StringPiece fmt, A&&... arg);
  430. };
  431. template <class... Args>
  432. std::string texsformat(StringPiece fmt, Args&&... args) {
  433. return TestExtendingFormatter<false, Args...>(
  434. fmt, std::forward<Args>(args)...)
  435. .str();
  436. }
  437. TEST(Format, Extending) {
  438. EXPECT_EQ(texsformat("I {} brackets", "love"), "I {love} brackets");
  439. EXPECT_EQ(
  440. texsformat("I {} nesting", sformat("really {}", "love")),
  441. "I {really love} nesting");
  442. EXPECT_EQ(
  443. sformat("I also {} nesting", texsformat("have an {} for", "affinity")),
  444. "I also have an {affinity} for nesting");
  445. EXPECT_EQ(
  446. texsformat(
  447. "Extending {} in {}",
  448. texsformat("a {}", "formatter"),
  449. "another formatter"),
  450. "Extending {a {formatter}} in {another formatter}");
  451. }
  452. TEST(Format, Temporary) {
  453. constexpr StringPiece kStr = "A long string that should go on the heap";
  454. auto fmt = format("{}", kStr.str()); // Pass a temporary std::string.
  455. EXPECT_EQ(fmt.str(), kStr);
  456. // The formatter can be reused.
  457. EXPECT_EQ(fmt.str(), kStr);
  458. }
  459. namespace {
  460. struct NoncopyableInt : MoveOnly {
  461. explicit NoncopyableInt(int v) : value(v) {}
  462. int value;
  463. };
  464. } // namespace
  465. namespace folly {
  466. template <>
  467. class FormatValue<NoncopyableInt> {
  468. public:
  469. explicit FormatValue(const NoncopyableInt& v) : v_(v) {}
  470. template <class FormatCallback>
  471. void format(FormatArg& arg, FormatCallback& cb) const {
  472. FormatValue<int>(v_.value).format(arg, cb);
  473. }
  474. private:
  475. const NoncopyableInt& v_;
  476. };
  477. } // namespace folly
  478. TEST(Format, NoncopyableArg) {
  479. {
  480. // Test that lvalues are held by reference.
  481. NoncopyableInt v(1);
  482. auto fmt = format("{}", v);
  483. EXPECT_EQ(fmt.str(), "1");
  484. // The formatter can be reused.
  485. EXPECT_EQ(fmt.str(), "1");
  486. }
  487. {
  488. // Test that rvalues are moved.
  489. auto fmt = format("{}", NoncopyableInt(1));
  490. EXPECT_EQ(fmt.str(), "1");
  491. }
  492. }