args-test.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Formatting library for C++ - dynamic argument store tests
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #include "fmt/args.h"
  8. #include <memory>
  9. #include "gtest/gtest.h"
  10. TEST(args_test, basic) {
  11. fmt::dynamic_format_arg_store<fmt::format_context> store;
  12. store.push_back(42);
  13. store.push_back("abc1");
  14. store.push_back(1.5f);
  15. EXPECT_EQ("42 and abc1 and 1.5", fmt::vformat("{} and {} and {}", store));
  16. }
  17. TEST(args_test, strings_and_refs) {
  18. // Unfortunately the tests are compiled with old ABI so strings use COW.
  19. fmt::dynamic_format_arg_store<fmt::format_context> store;
  20. char str[] = "1234567890";
  21. store.push_back(str);
  22. store.push_back(std::cref(str));
  23. store.push_back(fmt::string_view{str});
  24. str[0] = 'X';
  25. auto result = fmt::vformat("{} and {} and {}", store);
  26. EXPECT_EQ("1234567890 and X234567890 and X234567890", result);
  27. }
  28. struct custom_type {
  29. int i = 0;
  30. };
  31. FMT_BEGIN_NAMESPACE
  32. template <> struct formatter<custom_type> {
  33. auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
  34. return ctx.begin();
  35. }
  36. template <typename FormatContext>
  37. auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) {
  38. return format_to(ctx.out(), "cust={}", p.i);
  39. }
  40. };
  41. FMT_END_NAMESPACE
  42. TEST(args_test, custom_format) {
  43. fmt::dynamic_format_arg_store<fmt::format_context> store;
  44. auto c = custom_type();
  45. store.push_back(c);
  46. ++c.i;
  47. store.push_back(c);
  48. ++c.i;
  49. store.push_back(std::cref(c));
  50. ++c.i;
  51. auto result = fmt::vformat("{} and {} and {}", store);
  52. EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
  53. }
  54. struct to_stringable {
  55. friend fmt::string_view to_string_view(to_stringable) { return {}; }
  56. };
  57. FMT_BEGIN_NAMESPACE
  58. template <> struct formatter<to_stringable> {
  59. auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
  60. return ctx.begin();
  61. }
  62. auto format(to_stringable, format_context& ctx) -> decltype(ctx.out()) {
  63. return ctx.out();
  64. }
  65. };
  66. FMT_END_NAMESPACE
  67. TEST(args_test, to_string_and_formatter) {
  68. fmt::dynamic_format_arg_store<fmt::format_context> store;
  69. auto s = to_stringable();
  70. store.push_back(s);
  71. store.push_back(std::cref(s));
  72. fmt::vformat("", store);
  73. }
  74. TEST(args_test, named_int) {
  75. fmt::dynamic_format_arg_store<fmt::format_context> store;
  76. store.push_back(fmt::arg("a1", 42));
  77. EXPECT_EQ("42", fmt::vformat("{a1}", store));
  78. }
  79. TEST(args_test, named_strings) {
  80. fmt::dynamic_format_arg_store<fmt::format_context> store;
  81. char str[] = "1234567890";
  82. store.push_back(fmt::arg("a1", str));
  83. store.push_back(fmt::arg("a2", std::cref(str)));
  84. str[0] = 'X';
  85. EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store));
  86. }
  87. TEST(args_test, named_arg_by_ref) {
  88. fmt::dynamic_format_arg_store<fmt::format_context> store;
  89. char band[] = "Rolling Stones";
  90. store.push_back(fmt::arg("band", std::cref(band)));
  91. band[9] = 'c'; // Changing band affects the output.
  92. EXPECT_EQ(fmt::vformat("{band}", store), "Rolling Scones");
  93. }
  94. TEST(args_test, named_custom_format) {
  95. fmt::dynamic_format_arg_store<fmt::format_context> store;
  96. auto c = custom_type();
  97. store.push_back(fmt::arg("c1", c));
  98. ++c.i;
  99. store.push_back(fmt::arg("c2", c));
  100. ++c.i;
  101. store.push_back(fmt::arg("c_ref", std::cref(c)));
  102. ++c.i;
  103. auto result = fmt::vformat("{c1} and {c2} and {c_ref}", store);
  104. EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
  105. }
  106. TEST(args_test, clear) {
  107. fmt::dynamic_format_arg_store<fmt::format_context> store;
  108. store.push_back(42);
  109. auto result = fmt::vformat("{}", store);
  110. EXPECT_EQ("42", result);
  111. store.push_back(43);
  112. result = fmt::vformat("{} and {}", store);
  113. EXPECT_EQ("42 and 43", result);
  114. store.clear();
  115. store.push_back(44);
  116. result = fmt::vformat("{}", store);
  117. EXPECT_EQ("44", result);
  118. }
  119. TEST(args_test, reserve) {
  120. fmt::dynamic_format_arg_store<fmt::format_context> store;
  121. store.reserve(2, 1);
  122. store.push_back(1.5f);
  123. store.push_back(fmt::arg("a1", 42));
  124. auto result = fmt::vformat("{a1} and {}", store);
  125. EXPECT_EQ("42 and 1.5", result);
  126. }
  127. struct copy_throwable {
  128. copy_throwable() {}
  129. copy_throwable(const copy_throwable&) { throw "deal with it"; }
  130. };
  131. FMT_BEGIN_NAMESPACE
  132. template <> struct formatter<copy_throwable> {
  133. auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
  134. return ctx.begin();
  135. }
  136. auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) {
  137. return ctx.out();
  138. }
  139. };
  140. FMT_END_NAMESPACE
  141. TEST(args_test, throw_on_copy) {
  142. fmt::dynamic_format_arg_store<fmt::format_context> store;
  143. store.push_back(std::string("foo"));
  144. try {
  145. store.push_back(copy_throwable());
  146. } catch (...) {
  147. }
  148. EXPECT_EQ(fmt::vformat("{}", store), "foo");
  149. }
  150. TEST(args_test, move_constructor) {
  151. using store_type = fmt::dynamic_format_arg_store<fmt::format_context>;
  152. auto store = std::unique_ptr<store_type>(new store_type());
  153. store->push_back(42);
  154. store->push_back(std::string("foo"));
  155. store->push_back(fmt::arg("a1", "foo"));
  156. auto moved_store = std::move(*store);
  157. store.reset();
  158. EXPECT_EQ(fmt::vformat("{} {} {a1}", moved_store), "42 foo foo");
  159. }