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