args-test.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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) -> decltype(ctx.begin()) {
  34. return ctx.begin();
  35. }
  36. template <typename FormatContext>
  37. auto format(const custom_type& p, FormatContext& ctx) const
  38. -> decltype(ctx.out()) {
  39. return fmt::format_to(ctx.out(), "cust={}", p.i);
  40. }
  41. };
  42. FMT_END_NAMESPACE
  43. TEST(args_test, custom_format) {
  44. fmt::dynamic_format_arg_store<fmt::format_context> store;
  45. auto c = custom_type();
  46. store.push_back(c);
  47. ++c.i;
  48. store.push_back(c);
  49. ++c.i;
  50. store.push_back(std::cref(c));
  51. ++c.i;
  52. auto result = fmt::vformat("{} and {} and {}", store);
  53. EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
  54. }
  55. struct to_stringable {
  56. friend fmt::string_view to_string_view(to_stringable) { return {}; }
  57. };
  58. FMT_BEGIN_NAMESPACE
  59. template <> struct formatter<to_stringable> {
  60. auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
  61. return ctx.begin();
  62. }
  63. auto format(to_stringable, format_context& ctx) const -> decltype(ctx.out()) {
  64. return ctx.out();
  65. }
  66. };
  67. FMT_END_NAMESPACE
  68. TEST(args_test, to_string_and_formatter) {
  69. fmt::dynamic_format_arg_store<fmt::format_context> store;
  70. auto s = to_stringable();
  71. store.push_back(s);
  72. store.push_back(std::cref(s));
  73. fmt::vformat("", store);
  74. }
  75. TEST(args_test, named_int) {
  76. fmt::dynamic_format_arg_store<fmt::format_context> store;
  77. store.push_back(fmt::arg("a1", 42));
  78. EXPECT_EQ("42", fmt::vformat("{a1}", store));
  79. }
  80. TEST(args_test, named_strings) {
  81. fmt::dynamic_format_arg_store<fmt::format_context> store;
  82. char str[] = "1234567890";
  83. store.push_back(fmt::arg("a1", str));
  84. store.push_back(fmt::arg("a2", std::cref(str)));
  85. str[0] = 'X';
  86. EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store));
  87. }
  88. TEST(args_test, named_arg_by_ref) {
  89. fmt::dynamic_format_arg_store<fmt::format_context> store;
  90. char band[] = "Rolling Stones";
  91. store.push_back(fmt::arg("band", std::cref(band)));
  92. band[9] = 'c'; // Changing band affects the output.
  93. EXPECT_EQ(fmt::vformat("{band}", store), "Rolling Scones");
  94. }
  95. TEST(args_test, named_custom_format) {
  96. fmt::dynamic_format_arg_store<fmt::format_context> store;
  97. auto c = custom_type();
  98. store.push_back(fmt::arg("c1", c));
  99. ++c.i;
  100. store.push_back(fmt::arg("c2", c));
  101. ++c.i;
  102. store.push_back(fmt::arg("c_ref", std::cref(c)));
  103. ++c.i;
  104. auto result = fmt::vformat("{c1} and {c2} and {c_ref}", store);
  105. EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
  106. }
  107. TEST(args_test, clear) {
  108. fmt::dynamic_format_arg_store<fmt::format_context> store;
  109. store.push_back(42);
  110. auto result = fmt::vformat("{}", store);
  111. EXPECT_EQ("42", result);
  112. store.push_back(43);
  113. result = fmt::vformat("{} and {}", store);
  114. EXPECT_EQ("42 and 43", result);
  115. store.clear();
  116. store.push_back(44);
  117. result = fmt::vformat("{}", store);
  118. EXPECT_EQ("44", result);
  119. }
  120. TEST(args_test, reserve) {
  121. fmt::dynamic_format_arg_store<fmt::format_context> store;
  122. store.reserve(2, 1);
  123. store.push_back(1.5f);
  124. store.push_back(fmt::arg("a", 42));
  125. auto result = fmt::vformat("{} and {a}", store);
  126. EXPECT_EQ("1.5 and 42", result);
  127. }
  128. struct copy_throwable {
  129. copy_throwable() {}
  130. copy_throwable(const copy_throwable&) { throw "deal with it"; }
  131. };
  132. FMT_BEGIN_NAMESPACE
  133. template <> struct formatter<copy_throwable> {
  134. auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
  135. return ctx.begin();
  136. }
  137. auto format(copy_throwable, format_context& ctx) const
  138. -> decltype(ctx.out()) {
  139. return ctx.out();
  140. }
  141. };
  142. FMT_END_NAMESPACE
  143. TEST(args_test, throw_on_copy) {
  144. fmt::dynamic_format_arg_store<fmt::format_context> store;
  145. store.push_back(std::string("foo"));
  146. try {
  147. store.push_back(copy_throwable());
  148. } catch (...) {
  149. }
  150. EXPECT_EQ(fmt::vformat("{}", store), "foo");
  151. }
  152. TEST(args_test, move_constructor) {
  153. using store_type = fmt::dynamic_format_arg_store<fmt::format_context>;
  154. auto store = std::unique_ptr<store_type>(new store_type());
  155. store->push_back(42);
  156. store->push_back(std::string("foo"));
  157. store->push_back(fmt::arg("a1", "foo"));
  158. auto moved_store = std::move(*store);
  159. store.reset();
  160. EXPECT_EQ(fmt::vformat("{} {} {a1}", moved_store), "42 foo foo");
  161. }
  162. TEST(args_test, size) {
  163. fmt::dynamic_format_arg_store<fmt::format_context> store;
  164. EXPECT_EQ(store.size(), 0);
  165. store.push_back(42);
  166. EXPECT_EQ(store.size(), 1);
  167. store.push_back("Molybdenum");
  168. EXPECT_EQ(store.size(), 2);
  169. store.clear();
  170. EXPECT_EQ(store.size(), 0);
  171. }