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