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