1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker // Unit tests for all join.h functions
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_join.h"
18*9356374aSAndroid Build Coastguard Worker
19*9356374aSAndroid Build Coastguard Worker #include <cstddef>
20*9356374aSAndroid Build Coastguard Worker #include <cstdint>
21*9356374aSAndroid Build Coastguard Worker #include <cstdio>
22*9356374aSAndroid Build Coastguard Worker #include <functional>
23*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
24*9356374aSAndroid Build Coastguard Worker #include <iterator>
25*9356374aSAndroid Build Coastguard Worker #include <map>
26*9356374aSAndroid Build Coastguard Worker #include <memory>
27*9356374aSAndroid Build Coastguard Worker #include <ostream>
28*9356374aSAndroid Build Coastguard Worker #include <string>
29*9356374aSAndroid Build Coastguard Worker #include <tuple>
30*9356374aSAndroid Build Coastguard Worker #include <utility>
31*9356374aSAndroid Build Coastguard Worker #include <vector>
32*9356374aSAndroid Build Coastguard Worker
33*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_split.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
39*9356374aSAndroid Build Coastguard Worker
40*9356374aSAndroid Build Coastguard Worker namespace {
41*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,APIExamples)42*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, APIExamples) {
43*9356374aSAndroid Build Coastguard Worker {
44*9356374aSAndroid Build Coastguard Worker // Collection of strings
45*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {"foo", "bar", "baz"};
46*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
47*9356374aSAndroid Build Coastguard Worker }
48*9356374aSAndroid Build Coastguard Worker
49*9356374aSAndroid Build Coastguard Worker {
50*9356374aSAndroid Build Coastguard Worker // Collection of absl::string_view
51*9356374aSAndroid Build Coastguard Worker std::vector<absl::string_view> v = {"foo", "bar", "baz"};
52*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
53*9356374aSAndroid Build Coastguard Worker }
54*9356374aSAndroid Build Coastguard Worker
55*9356374aSAndroid Build Coastguard Worker {
56*9356374aSAndroid Build Coastguard Worker // Collection of const char*
57*9356374aSAndroid Build Coastguard Worker std::vector<const char*> v = {"foo", "bar", "baz"};
58*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
59*9356374aSAndroid Build Coastguard Worker }
60*9356374aSAndroid Build Coastguard Worker
61*9356374aSAndroid Build Coastguard Worker {
62*9356374aSAndroid Build Coastguard Worker // Collection of non-const char*
63*9356374aSAndroid Build Coastguard Worker std::string a = "foo", b = "bar", c = "baz";
64*9356374aSAndroid Build Coastguard Worker std::vector<char*> v = {&a[0], &b[0], &c[0]};
65*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
66*9356374aSAndroid Build Coastguard Worker }
67*9356374aSAndroid Build Coastguard Worker
68*9356374aSAndroid Build Coastguard Worker {
69*9356374aSAndroid Build Coastguard Worker // Collection of ints
70*9356374aSAndroid Build Coastguard Worker std::vector<int> v = {1, 2, 3, -4};
71*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
72*9356374aSAndroid Build Coastguard Worker }
73*9356374aSAndroid Build Coastguard Worker
74*9356374aSAndroid Build Coastguard Worker {
75*9356374aSAndroid Build Coastguard Worker // Literals passed as a std::initializer_list
76*9356374aSAndroid Build Coastguard Worker std::string s = absl::StrJoin({"a", "b", "c"}, "-");
77*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", s);
78*9356374aSAndroid Build Coastguard Worker }
79*9356374aSAndroid Build Coastguard Worker {
80*9356374aSAndroid Build Coastguard Worker // Join a std::tuple<T...>.
81*9356374aSAndroid Build Coastguard Worker std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
82*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("123-abc-0.456", s);
83*9356374aSAndroid Build Coastguard Worker }
84*9356374aSAndroid Build Coastguard Worker
85*9356374aSAndroid Build Coastguard Worker {
86*9356374aSAndroid Build Coastguard Worker // Collection of unique_ptrs
87*9356374aSAndroid Build Coastguard Worker std::vector<std::unique_ptr<int>> v;
88*9356374aSAndroid Build Coastguard Worker v.emplace_back(new int(1));
89*9356374aSAndroid Build Coastguard Worker v.emplace_back(new int(2));
90*9356374aSAndroid Build Coastguard Worker v.emplace_back(new int(3));
91*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
92*9356374aSAndroid Build Coastguard Worker }
93*9356374aSAndroid Build Coastguard Worker
94*9356374aSAndroid Build Coastguard Worker {
95*9356374aSAndroid Build Coastguard Worker // Array of ints
96*9356374aSAndroid Build Coastguard Worker const int a[] = {1, 2, 3, -4};
97*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
98*9356374aSAndroid Build Coastguard Worker }
99*9356374aSAndroid Build Coastguard Worker
100*9356374aSAndroid Build Coastguard Worker {
101*9356374aSAndroid Build Coastguard Worker // Collection of pointers
102*9356374aSAndroid Build Coastguard Worker int x = 1, y = 2, z = 3;
103*9356374aSAndroid Build Coastguard Worker std::vector<int*> v = {&x, &y, &z};
104*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
105*9356374aSAndroid Build Coastguard Worker }
106*9356374aSAndroid Build Coastguard Worker
107*9356374aSAndroid Build Coastguard Worker {
108*9356374aSAndroid Build Coastguard Worker // Collection of pointers to pointers
109*9356374aSAndroid Build Coastguard Worker int x = 1, y = 2, z = 3;
110*9356374aSAndroid Build Coastguard Worker int *px = &x, *py = &y, *pz = &z;
111*9356374aSAndroid Build Coastguard Worker std::vector<int**> v = {&px, &py, &pz};
112*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
113*9356374aSAndroid Build Coastguard Worker }
114*9356374aSAndroid Build Coastguard Worker
115*9356374aSAndroid Build Coastguard Worker {
116*9356374aSAndroid Build Coastguard Worker // Collection of pointers to std::string
117*9356374aSAndroid Build Coastguard Worker std::string a("a"), b("b");
118*9356374aSAndroid Build Coastguard Worker std::vector<std::string*> v = {&a, &b};
119*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
120*9356374aSAndroid Build Coastguard Worker }
121*9356374aSAndroid Build Coastguard Worker
122*9356374aSAndroid Build Coastguard Worker {
123*9356374aSAndroid Build Coastguard Worker // A std::map, which is a collection of std::pair<>s.
124*9356374aSAndroid Build Coastguard Worker std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
125*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
126*9356374aSAndroid Build Coastguard Worker }
127*9356374aSAndroid Build Coastguard Worker
128*9356374aSAndroid Build Coastguard Worker {
129*9356374aSAndroid Build Coastguard Worker // Shows absl::StrSplit and absl::StrJoin working together. This example is
130*9356374aSAndroid Build Coastguard Worker // equivalent to s/=/-/g.
131*9356374aSAndroid Build Coastguard Worker const std::string s = "a=b=c=d";
132*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
133*9356374aSAndroid Build Coastguard Worker }
134*9356374aSAndroid Build Coastguard Worker
135*9356374aSAndroid Build Coastguard Worker //
136*9356374aSAndroid Build Coastguard Worker // A few examples of edge cases
137*9356374aSAndroid Build Coastguard Worker //
138*9356374aSAndroid Build Coastguard Worker
139*9356374aSAndroid Build Coastguard Worker {
140*9356374aSAndroid Build Coastguard Worker // Empty range yields an empty string.
141*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v;
142*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("", absl::StrJoin(v, "-"));
143*9356374aSAndroid Build Coastguard Worker }
144*9356374aSAndroid Build Coastguard Worker
145*9356374aSAndroid Build Coastguard Worker {
146*9356374aSAndroid Build Coastguard Worker // A range of 1 element gives a string with that element but no
147*9356374aSAndroid Build Coastguard Worker // separator.
148*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {"foo"};
149*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("foo", absl::StrJoin(v, "-"));
150*9356374aSAndroid Build Coastguard Worker }
151*9356374aSAndroid Build Coastguard Worker
152*9356374aSAndroid Build Coastguard Worker {
153*9356374aSAndroid Build Coastguard Worker // A range with a single empty string element
154*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {""};
155*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("", absl::StrJoin(v, "-"));
156*9356374aSAndroid Build Coastguard Worker }
157*9356374aSAndroid Build Coastguard Worker
158*9356374aSAndroid Build Coastguard Worker {
159*9356374aSAndroid Build Coastguard Worker // A range with 2 elements, one of which is an empty string
160*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {"a", ""};
161*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-", absl::StrJoin(v, "-"));
162*9356374aSAndroid Build Coastguard Worker }
163*9356374aSAndroid Build Coastguard Worker
164*9356374aSAndroid Build Coastguard Worker {
165*9356374aSAndroid Build Coastguard Worker // A range with 2 empty elements.
166*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {"", ""};
167*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("-", absl::StrJoin(v, "-"));
168*9356374aSAndroid Build Coastguard Worker }
169*9356374aSAndroid Build Coastguard Worker
170*9356374aSAndroid Build Coastguard Worker {
171*9356374aSAndroid Build Coastguard Worker // A std::vector of bool.
172*9356374aSAndroid Build Coastguard Worker std::vector<bool> v = {true, false, true};
173*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
174*9356374aSAndroid Build Coastguard Worker }
175*9356374aSAndroid Build Coastguard Worker }
176*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,CustomFormatter)177*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, CustomFormatter) {
178*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v{"One", "Two", "Three"};
179*9356374aSAndroid Build Coastguard Worker {
180*9356374aSAndroid Build Coastguard Worker std::string joined =
181*9356374aSAndroid Build Coastguard Worker absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
182*9356374aSAndroid Build Coastguard Worker absl::StrAppend(out, "(", in, ")");
183*9356374aSAndroid Build Coastguard Worker });
184*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(One)(Two)(Three)", joined);
185*9356374aSAndroid Build Coastguard Worker }
186*9356374aSAndroid Build Coastguard Worker {
187*9356374aSAndroid Build Coastguard Worker class ImmovableFormatter {
188*9356374aSAndroid Build Coastguard Worker public:
189*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, const std::string& in) {
190*9356374aSAndroid Build Coastguard Worker absl::StrAppend(out, "(", in, ")");
191*9356374aSAndroid Build Coastguard Worker }
192*9356374aSAndroid Build Coastguard Worker ImmovableFormatter() {}
193*9356374aSAndroid Build Coastguard Worker ImmovableFormatter(const ImmovableFormatter&) = delete;
194*9356374aSAndroid Build Coastguard Worker };
195*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter()));
196*9356374aSAndroid Build Coastguard Worker }
197*9356374aSAndroid Build Coastguard Worker {
198*9356374aSAndroid Build Coastguard Worker class OverloadedFormatter {
199*9356374aSAndroid Build Coastguard Worker public:
200*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, const std::string& in) {
201*9356374aSAndroid Build Coastguard Worker absl::StrAppend(out, "(", in, ")");
202*9356374aSAndroid Build Coastguard Worker }
203*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, const std::string& in) const {
204*9356374aSAndroid Build Coastguard Worker absl::StrAppend(out, "[", in, "]");
205*9356374aSAndroid Build Coastguard Worker }
206*9356374aSAndroid Build Coastguard Worker };
207*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter()));
208*9356374aSAndroid Build Coastguard Worker const OverloadedFormatter fmt = {};
209*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt));
210*9356374aSAndroid Build Coastguard Worker }
211*9356374aSAndroid Build Coastguard Worker }
212*9356374aSAndroid Build Coastguard Worker
213*9356374aSAndroid Build Coastguard Worker //
214*9356374aSAndroid Build Coastguard Worker // Tests the Formatters
215*9356374aSAndroid Build Coastguard Worker //
216*9356374aSAndroid Build Coastguard Worker
TEST(AlphaNumFormatter,FormatterAPI)217*9356374aSAndroid Build Coastguard Worker TEST(AlphaNumFormatter, FormatterAPI) {
218*9356374aSAndroid Build Coastguard Worker // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test
219*9356374aSAndroid Build Coastguard Worker // of what AlphaNum can convert.
220*9356374aSAndroid Build Coastguard Worker auto f = absl::AlphaNumFormatter();
221*9356374aSAndroid Build Coastguard Worker std::string s;
222*9356374aSAndroid Build Coastguard Worker f(&s, "Testing: ");
223*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int>(1));
224*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int16_t>(2));
225*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int64_t>(3));
226*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<float>(4));
227*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<double>(5));
228*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<unsigned>(6));
229*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<size_t>(7));
230*9356374aSAndroid Build Coastguard Worker f(&s, absl::string_view(" OK"));
231*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("Testing: 1234567 OK", s);
232*9356374aSAndroid Build Coastguard Worker }
233*9356374aSAndroid Build Coastguard Worker
234*9356374aSAndroid Build Coastguard Worker // Make sure people who are mistakenly using std::vector<bool> even though
235*9356374aSAndroid Build Coastguard Worker // they're not memory-constrained can use absl::AlphaNumFormatter().
TEST(AlphaNumFormatter,VectorOfBool)236*9356374aSAndroid Build Coastguard Worker TEST(AlphaNumFormatter, VectorOfBool) {
237*9356374aSAndroid Build Coastguard Worker auto f = absl::AlphaNumFormatter();
238*9356374aSAndroid Build Coastguard Worker std::string s;
239*9356374aSAndroid Build Coastguard Worker std::vector<bool> v = {true, false, true};
240*9356374aSAndroid Build Coastguard Worker f(&s, *v.cbegin());
241*9356374aSAndroid Build Coastguard Worker f(&s, *v.begin());
242*9356374aSAndroid Build Coastguard Worker f(&s, v[1]);
243*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("110", s);
244*9356374aSAndroid Build Coastguard Worker }
245*9356374aSAndroid Build Coastguard Worker
TEST(AlphaNumFormatter,AlphaNum)246*9356374aSAndroid Build Coastguard Worker TEST(AlphaNumFormatter, AlphaNum) {
247*9356374aSAndroid Build Coastguard Worker auto f = absl::AlphaNumFormatter();
248*9356374aSAndroid Build Coastguard Worker std::string s;
249*9356374aSAndroid Build Coastguard Worker f(&s, absl::AlphaNum("hello"));
250*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("hello", s);
251*9356374aSAndroid Build Coastguard Worker }
252*9356374aSAndroid Build Coastguard Worker
253*9356374aSAndroid Build Coastguard Worker struct StreamableType {
254*9356374aSAndroid Build Coastguard Worker std::string contents;
255*9356374aSAndroid Build Coastguard Worker };
operator <<(std::ostream & os,const StreamableType & t)256*9356374aSAndroid Build Coastguard Worker inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {
257*9356374aSAndroid Build Coastguard Worker os << "Streamable:" << t.contents;
258*9356374aSAndroid Build Coastguard Worker return os;
259*9356374aSAndroid Build Coastguard Worker }
260*9356374aSAndroid Build Coastguard Worker
TEST(StreamFormatter,FormatterAPI)261*9356374aSAndroid Build Coastguard Worker TEST(StreamFormatter, FormatterAPI) {
262*9356374aSAndroid Build Coastguard Worker auto f = absl::StreamFormatter();
263*9356374aSAndroid Build Coastguard Worker std::string s;
264*9356374aSAndroid Build Coastguard Worker f(&s, "Testing: ");
265*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int>(1));
266*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int16_t>(2));
267*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<int64_t>(3));
268*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<float>(4));
269*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<double>(5));
270*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<unsigned>(6));
271*9356374aSAndroid Build Coastguard Worker f(&s, static_cast<size_t>(7));
272*9356374aSAndroid Build Coastguard Worker f(&s, absl::string_view(" OK "));
273*9356374aSAndroid Build Coastguard Worker StreamableType streamable = {"object"};
274*9356374aSAndroid Build Coastguard Worker f(&s, streamable);
275*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("Testing: 1234567 OK Streamable:object", s);
276*9356374aSAndroid Build Coastguard Worker }
277*9356374aSAndroid Build Coastguard Worker
278*9356374aSAndroid Build Coastguard Worker // A dummy formatter that wraps each element in parens. Used in some tests
279*9356374aSAndroid Build Coastguard Worker // below.
280*9356374aSAndroid Build Coastguard Worker struct TestingParenFormatter {
281*9356374aSAndroid Build Coastguard Worker template <typename T>
operator ()__anonf0c5f2db0111::TestingParenFormatter282*9356374aSAndroid Build Coastguard Worker void operator()(std::string* s, const T& t) {
283*9356374aSAndroid Build Coastguard Worker absl::StrAppend(s, "(", t, ")");
284*9356374aSAndroid Build Coastguard Worker }
285*9356374aSAndroid Build Coastguard Worker };
286*9356374aSAndroid Build Coastguard Worker
TEST(PairFormatter,FormatterAPI)287*9356374aSAndroid Build Coastguard Worker TEST(PairFormatter, FormatterAPI) {
288*9356374aSAndroid Build Coastguard Worker {
289*9356374aSAndroid Build Coastguard Worker // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the
290*9356374aSAndroid Build Coastguard Worker // 'first' and 'second' members.
291*9356374aSAndroid Build Coastguard Worker const auto f = absl::PairFormatter("=");
292*9356374aSAndroid Build Coastguard Worker std::string s;
293*9356374aSAndroid Build Coastguard Worker f(&s, std::make_pair("a", "b"));
294*9356374aSAndroid Build Coastguard Worker f(&s, std::make_pair(1, 2));
295*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a=b1=2", s);
296*9356374aSAndroid Build Coastguard Worker }
297*9356374aSAndroid Build Coastguard Worker
298*9356374aSAndroid Build Coastguard Worker {
299*9356374aSAndroid Build Coastguard Worker // Tests using a custom formatter for the 'first' and 'second' members.
300*9356374aSAndroid Build Coastguard Worker auto f = absl::PairFormatter(TestingParenFormatter(), "=",
301*9356374aSAndroid Build Coastguard Worker TestingParenFormatter());
302*9356374aSAndroid Build Coastguard Worker std::string s;
303*9356374aSAndroid Build Coastguard Worker f(&s, std::make_pair("a", "b"));
304*9356374aSAndroid Build Coastguard Worker f(&s, std::make_pair(1, 2));
305*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(a)=(b)(1)=(2)", s);
306*9356374aSAndroid Build Coastguard Worker }
307*9356374aSAndroid Build Coastguard Worker }
308*9356374aSAndroid Build Coastguard Worker
TEST(DereferenceFormatter,FormatterAPI)309*9356374aSAndroid Build Coastguard Worker TEST(DereferenceFormatter, FormatterAPI) {
310*9356374aSAndroid Build Coastguard Worker {
311*9356374aSAndroid Build Coastguard Worker // Tests wrapping the default AlphaNumFormatter.
312*9356374aSAndroid Build Coastguard Worker const absl::strings_internal::DereferenceFormatterImpl<
313*9356374aSAndroid Build Coastguard Worker absl::strings_internal::AlphaNumFormatterImpl>
314*9356374aSAndroid Build Coastguard Worker f;
315*9356374aSAndroid Build Coastguard Worker int x = 1, y = 2, z = 3;
316*9356374aSAndroid Build Coastguard Worker std::string s;
317*9356374aSAndroid Build Coastguard Worker f(&s, &x);
318*9356374aSAndroid Build Coastguard Worker f(&s, &y);
319*9356374aSAndroid Build Coastguard Worker f(&s, &z);
320*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("123", s);
321*9356374aSAndroid Build Coastguard Worker }
322*9356374aSAndroid Build Coastguard Worker
323*9356374aSAndroid Build Coastguard Worker {
324*9356374aSAndroid Build Coastguard Worker // Tests wrapping std::string's default formatter.
325*9356374aSAndroid Build Coastguard Worker absl::strings_internal::DereferenceFormatterImpl<
326*9356374aSAndroid Build Coastguard Worker absl::strings_internal::DefaultFormatter<std::string>::Type>
327*9356374aSAndroid Build Coastguard Worker f;
328*9356374aSAndroid Build Coastguard Worker
329*9356374aSAndroid Build Coastguard Worker std::string x = "x";
330*9356374aSAndroid Build Coastguard Worker std::string y = "y";
331*9356374aSAndroid Build Coastguard Worker std::string z = "z";
332*9356374aSAndroid Build Coastguard Worker std::string s;
333*9356374aSAndroid Build Coastguard Worker f(&s, &x);
334*9356374aSAndroid Build Coastguard Worker f(&s, &y);
335*9356374aSAndroid Build Coastguard Worker f(&s, &z);
336*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(s, "xyz");
337*9356374aSAndroid Build Coastguard Worker }
338*9356374aSAndroid Build Coastguard Worker
339*9356374aSAndroid Build Coastguard Worker {
340*9356374aSAndroid Build Coastguard Worker // Tests wrapping a custom formatter.
341*9356374aSAndroid Build Coastguard Worker auto f = absl::DereferenceFormatter(TestingParenFormatter());
342*9356374aSAndroid Build Coastguard Worker int x = 1, y = 2, z = 3;
343*9356374aSAndroid Build Coastguard Worker std::string s;
344*9356374aSAndroid Build Coastguard Worker f(&s, &x);
345*9356374aSAndroid Build Coastguard Worker f(&s, &y);
346*9356374aSAndroid Build Coastguard Worker f(&s, &z);
347*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(1)(2)(3)", s);
348*9356374aSAndroid Build Coastguard Worker }
349*9356374aSAndroid Build Coastguard Worker
350*9356374aSAndroid Build Coastguard Worker {
351*9356374aSAndroid Build Coastguard Worker absl::strings_internal::DereferenceFormatterImpl<
352*9356374aSAndroid Build Coastguard Worker absl::strings_internal::AlphaNumFormatterImpl>
353*9356374aSAndroid Build Coastguard Worker f;
354*9356374aSAndroid Build Coastguard Worker auto x = std::unique_ptr<int>(new int(1));
355*9356374aSAndroid Build Coastguard Worker auto y = std::unique_ptr<int>(new int(2));
356*9356374aSAndroid Build Coastguard Worker auto z = std::unique_ptr<int>(new int(3));
357*9356374aSAndroid Build Coastguard Worker std::string s;
358*9356374aSAndroid Build Coastguard Worker f(&s, x);
359*9356374aSAndroid Build Coastguard Worker f(&s, y);
360*9356374aSAndroid Build Coastguard Worker f(&s, z);
361*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("123", s);
362*9356374aSAndroid Build Coastguard Worker }
363*9356374aSAndroid Build Coastguard Worker }
364*9356374aSAndroid Build Coastguard Worker
365*9356374aSAndroid Build Coastguard Worker //
366*9356374aSAndroid Build Coastguard Worker // Tests the interfaces for the 4 public Join function overloads. The semantics
367*9356374aSAndroid Build Coastguard Worker // of the algorithm is covered in the above APIExamples test.
368*9356374aSAndroid Build Coastguard Worker //
TEST(StrJoin,PublicAPIOverloads)369*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, PublicAPIOverloads) {
370*9356374aSAndroid Build Coastguard Worker std::vector<std::string> v = {"a", "b", "c"};
371*9356374aSAndroid Build Coastguard Worker
372*9356374aSAndroid Build Coastguard Worker // Iterators + formatter
373*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c",
374*9356374aSAndroid Build Coastguard Worker absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
375*9356374aSAndroid Build Coastguard Worker // Range + formatter
376*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
377*9356374aSAndroid Build Coastguard Worker // Iterators, no formatter
378*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
379*9356374aSAndroid Build Coastguard Worker // Range, no formatter
380*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(v, "-"));
381*9356374aSAndroid Build Coastguard Worker }
382*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,Array)383*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, Array) {
384*9356374aSAndroid Build Coastguard Worker const absl::string_view a[] = {"a", "b", "c"};
385*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
386*9356374aSAndroid Build Coastguard Worker }
387*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,InitializerList)388*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, InitializerList) {
389*9356374aSAndroid Build Coastguard Worker { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); }
390*9356374aSAndroid Build Coastguard Worker
391*9356374aSAndroid Build Coastguard Worker {
392*9356374aSAndroid Build Coastguard Worker auto a = {"a", "b", "c"};
393*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
394*9356374aSAndroid Build Coastguard Worker }
395*9356374aSAndroid Build Coastguard Worker
396*9356374aSAndroid Build Coastguard Worker {
397*9356374aSAndroid Build Coastguard Worker std::initializer_list<const char*> a = {"a", "b", "c"};
398*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
399*9356374aSAndroid Build Coastguard Worker }
400*9356374aSAndroid Build Coastguard Worker
401*9356374aSAndroid Build Coastguard Worker {
402*9356374aSAndroid Build Coastguard Worker std::initializer_list<std::string> a = {"a", "b", "c"};
403*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
404*9356374aSAndroid Build Coastguard Worker }
405*9356374aSAndroid Build Coastguard Worker
406*9356374aSAndroid Build Coastguard Worker {
407*9356374aSAndroid Build Coastguard Worker std::initializer_list<absl::string_view> a = {"a", "b", "c"};
408*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
409*9356374aSAndroid Build Coastguard Worker }
410*9356374aSAndroid Build Coastguard Worker
411*9356374aSAndroid Build Coastguard Worker {
412*9356374aSAndroid Build Coastguard Worker // Tests initializer_list with a non-default formatter
413*9356374aSAndroid Build Coastguard Worker auto a = {"a", "b", "c"};
414*9356374aSAndroid Build Coastguard Worker TestingParenFormatter f;
415*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
416*9356374aSAndroid Build Coastguard Worker }
417*9356374aSAndroid Build Coastguard Worker
418*9356374aSAndroid Build Coastguard Worker {
419*9356374aSAndroid Build Coastguard Worker // initializer_list of ints
420*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
421*9356374aSAndroid Build Coastguard Worker }
422*9356374aSAndroid Build Coastguard Worker
423*9356374aSAndroid Build Coastguard Worker {
424*9356374aSAndroid Build Coastguard Worker // Tests initializer_list of ints with a non-default formatter
425*9356374aSAndroid Build Coastguard Worker auto a = {1, 2, 3};
426*9356374aSAndroid Build Coastguard Worker TestingParenFormatter f;
427*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
428*9356374aSAndroid Build Coastguard Worker }
429*9356374aSAndroid Build Coastguard Worker }
430*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,StringViewInitializerList)431*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, StringViewInitializerList) {
432*9356374aSAndroid Build Coastguard Worker {
433*9356374aSAndroid Build Coastguard Worker // Tests initializer_list of string_views
434*9356374aSAndroid Build Coastguard Worker std::string b = "b";
435*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c", absl::StrJoin({"a", b, "c"}, "-"));
436*9356374aSAndroid Build Coastguard Worker }
437*9356374aSAndroid Build Coastguard Worker {
438*9356374aSAndroid Build Coastguard Worker // Tests initializer_list of string_views with a non-default formatter
439*9356374aSAndroid Build Coastguard Worker TestingParenFormatter f;
440*9356374aSAndroid Build Coastguard Worker std::string b = "b";
441*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin({"a", b, "c"}, "-", f));
442*9356374aSAndroid Build Coastguard Worker }
443*9356374aSAndroid Build Coastguard Worker
444*9356374aSAndroid Build Coastguard Worker class NoCopy {
445*9356374aSAndroid Build Coastguard Worker public:
446*9356374aSAndroid Build Coastguard Worker explicit NoCopy(absl::string_view view) : view_(view) {}
447*9356374aSAndroid Build Coastguard Worker NoCopy(const NoCopy&) = delete;
448*9356374aSAndroid Build Coastguard Worker operator absl::string_view() { return view_; } // NOLINT
449*9356374aSAndroid Build Coastguard Worker private:
450*9356374aSAndroid Build Coastguard Worker absl::string_view view_;
451*9356374aSAndroid Build Coastguard Worker };
452*9356374aSAndroid Build Coastguard Worker {
453*9356374aSAndroid Build Coastguard Worker // Tests initializer_list of string_views preferred over initializer_list<T>
454*9356374aSAndroid Build Coastguard Worker // for T that is implicitly convertible to string_view
455*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c",
456*9356374aSAndroid Build Coastguard Worker absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-"));
457*9356374aSAndroid Build Coastguard Worker }
458*9356374aSAndroid Build Coastguard Worker {
459*9356374aSAndroid Build Coastguard Worker // Tests initializer_list of string_views preferred over initializer_list<T>
460*9356374aSAndroid Build Coastguard Worker // for T that is implicitly convertible to string_view
461*9356374aSAndroid Build Coastguard Worker TestingParenFormatter f;
462*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("(a)-(b)-(c)",
463*9356374aSAndroid Build Coastguard Worker absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-", f));
464*9356374aSAndroid Build Coastguard Worker }
465*9356374aSAndroid Build Coastguard Worker }
466*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,Tuple)467*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, Tuple) {
468*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-"));
469*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-"));
470*9356374aSAndroid Build Coastguard Worker
471*9356374aSAndroid Build Coastguard Worker int x(10);
472*9356374aSAndroid Build Coastguard Worker std::string y("hello");
473*9356374aSAndroid Build Coastguard Worker double z(3.14);
474*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-"));
475*9356374aSAndroid Build Coastguard Worker
476*9356374aSAndroid Build Coastguard Worker // Faster! Faster!!
477*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("10-hello-3.14",
478*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-"));
479*9356374aSAndroid Build Coastguard Worker
480*9356374aSAndroid Build Coastguard Worker struct TestFormatter {
481*9356374aSAndroid Build Coastguard Worker char buffer[128];
482*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, int v) {
483*9356374aSAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%#.8x", v);
484*9356374aSAndroid Build Coastguard Worker out->append(buffer);
485*9356374aSAndroid Build Coastguard Worker }
486*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, double v) {
487*9356374aSAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%#.0f", v);
488*9356374aSAndroid Build Coastguard Worker out->append(buffer);
489*9356374aSAndroid Build Coastguard Worker }
490*9356374aSAndroid Build Coastguard Worker void operator()(std::string* out, const std::string& v) {
491*9356374aSAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%.4s", v.c_str());
492*9356374aSAndroid Build Coastguard Worker out->append(buffer);
493*9356374aSAndroid Build Coastguard Worker }
494*9356374aSAndroid Build Coastguard Worker };
495*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("0x0000000a-hell-3.",
496*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter()));
497*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(
498*9356374aSAndroid Build Coastguard Worker "0x0000000a-hell-3.",
499*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter()));
500*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("0x0000000a-hell-3.",
501*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(&x, &y, &z), "-",
502*9356374aSAndroid Build Coastguard Worker absl::DereferenceFormatter(TestFormatter())));
503*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("0x0000000a-hell-3.",
504*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),
505*9356374aSAndroid Build Coastguard Worker absl::make_unique<std::string>(y),
506*9356374aSAndroid Build Coastguard Worker absl::make_unique<double>(z)),
507*9356374aSAndroid Build Coastguard Worker "-", absl::DereferenceFormatter(TestFormatter())));
508*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("0x0000000a-hell-3.",
509*9356374aSAndroid Build Coastguard Worker absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),
510*9356374aSAndroid Build Coastguard Worker "-", absl::DereferenceFormatter(TestFormatter())));
511*9356374aSAndroid Build Coastguard Worker }
512*9356374aSAndroid Build Coastguard Worker
513*9356374aSAndroid Build Coastguard Worker // A minimal value type for `StrJoin` inputs.
514*9356374aSAndroid Build Coastguard Worker // Used to ensure we do not excessively require more a specific type, such as a
515*9356374aSAndroid Build Coastguard Worker // `string_view`.
516*9356374aSAndroid Build Coastguard Worker //
517*9356374aSAndroid Build Coastguard Worker // Anything that can be `data()` and `size()` is OK.
518*9356374aSAndroid Build Coastguard Worker class TestValue {
519*9356374aSAndroid Build Coastguard Worker public:
TestValue(const char * data,size_t size)520*9356374aSAndroid Build Coastguard Worker TestValue(const char* data, size_t size) : data_(data), size_(size) {}
data() const521*9356374aSAndroid Build Coastguard Worker const char* data() const { return data_; }
size() const522*9356374aSAndroid Build Coastguard Worker size_t size() const { return size_; }
523*9356374aSAndroid Build Coastguard Worker
524*9356374aSAndroid Build Coastguard Worker private:
525*9356374aSAndroid Build Coastguard Worker const char* data_;
526*9356374aSAndroid Build Coastguard Worker size_t size_;
527*9356374aSAndroid Build Coastguard Worker };
528*9356374aSAndroid Build Coastguard Worker
529*9356374aSAndroid Build Coastguard Worker // A minimal C++20 forward iterator, used to test that we do not impose
530*9356374aSAndroid Build Coastguard Worker // excessive requirements on StrJoin inputs.
531*9356374aSAndroid Build Coastguard Worker //
532*9356374aSAndroid Build Coastguard Worker // The 2 main differences between pre-C++20 LegacyForwardIterator and the
533*9356374aSAndroid Build Coastguard Worker // C++20 ForwardIterator are:
534*9356374aSAndroid Build Coastguard Worker // 1. `operator->` is not required in C++20.
535*9356374aSAndroid Build Coastguard Worker // 2. `operator*` result does not need to be an lvalue (a reference).
536*9356374aSAndroid Build Coastguard Worker //
537*9356374aSAndroid Build Coastguard Worker // The `operator->` requirement was removed on page 17 in:
538*9356374aSAndroid Build Coastguard Worker // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1037r0.pdf
539*9356374aSAndroid Build Coastguard Worker //
540*9356374aSAndroid Build Coastguard Worker // See the `[iterator.requirements]` section of the C++ standard.
541*9356374aSAndroid Build Coastguard Worker //
542*9356374aSAndroid Build Coastguard Worker // The value type is a template parameter so that we can test the behaviour
543*9356374aSAndroid Build Coastguard Worker // of `StrJoin` specializations, e.g. the NoFormatter specialization for
544*9356374aSAndroid Build Coastguard Worker // `string_view`.
545*9356374aSAndroid Build Coastguard Worker template <typename ValueT>
546*9356374aSAndroid Build Coastguard Worker class TestIterator {
547*9356374aSAndroid Build Coastguard Worker public:
548*9356374aSAndroid Build Coastguard Worker using iterator_category = std::forward_iterator_tag;
549*9356374aSAndroid Build Coastguard Worker using value_type = ValueT;
550*9356374aSAndroid Build Coastguard Worker using pointer = void;
551*9356374aSAndroid Build Coastguard Worker using reference = const value_type&;
552*9356374aSAndroid Build Coastguard Worker using difference_type = int;
553*9356374aSAndroid Build Coastguard Worker
554*9356374aSAndroid Build Coastguard Worker // `data` must outlive the result.
begin(const std::vector<absl::string_view> & data)555*9356374aSAndroid Build Coastguard Worker static TestIterator begin(const std::vector<absl::string_view>& data) {
556*9356374aSAndroid Build Coastguard Worker return TestIterator(&data, 0);
557*9356374aSAndroid Build Coastguard Worker }
558*9356374aSAndroid Build Coastguard Worker
end(const std::vector<absl::string_view> & data)559*9356374aSAndroid Build Coastguard Worker static TestIterator end(const std::vector<absl::string_view>& data) {
560*9356374aSAndroid Build Coastguard Worker return TestIterator(nullptr, data.size());
561*9356374aSAndroid Build Coastguard Worker }
562*9356374aSAndroid Build Coastguard Worker
operator ==(const TestIterator & other) const563*9356374aSAndroid Build Coastguard Worker bool operator==(const TestIterator& other) const {
564*9356374aSAndroid Build Coastguard Worker return pos_ == other.pos_;
565*9356374aSAndroid Build Coastguard Worker }
operator !=(const TestIterator & other) const566*9356374aSAndroid Build Coastguard Worker bool operator!=(const TestIterator& other) const {
567*9356374aSAndroid Build Coastguard Worker return pos_ != other.pos_;
568*9356374aSAndroid Build Coastguard Worker }
569*9356374aSAndroid Build Coastguard Worker
570*9356374aSAndroid Build Coastguard Worker // This deliberately returns a `prvalue`.
571*9356374aSAndroid Build Coastguard Worker // The requirement to return a reference was removed in C++20.
operator *() const572*9356374aSAndroid Build Coastguard Worker value_type operator*() const {
573*9356374aSAndroid Build Coastguard Worker return ValueT((*data_)[pos_].data(), (*data_)[pos_].size());
574*9356374aSAndroid Build Coastguard Worker }
575*9356374aSAndroid Build Coastguard Worker
576*9356374aSAndroid Build Coastguard Worker // `operator->()` is deliberately omitted.
577*9356374aSAndroid Build Coastguard Worker // The requirement to provide it was removed in C++20.
578*9356374aSAndroid Build Coastguard Worker
operator ++()579*9356374aSAndroid Build Coastguard Worker TestIterator& operator++() {
580*9356374aSAndroid Build Coastguard Worker ++pos_;
581*9356374aSAndroid Build Coastguard Worker return *this;
582*9356374aSAndroid Build Coastguard Worker }
583*9356374aSAndroid Build Coastguard Worker
operator ++(int)584*9356374aSAndroid Build Coastguard Worker TestIterator operator++(int) {
585*9356374aSAndroid Build Coastguard Worker TestIterator result = *this;
586*9356374aSAndroid Build Coastguard Worker ++(*this);
587*9356374aSAndroid Build Coastguard Worker return result;
588*9356374aSAndroid Build Coastguard Worker }
589*9356374aSAndroid Build Coastguard Worker
operator --()590*9356374aSAndroid Build Coastguard Worker TestIterator& operator--() {
591*9356374aSAndroid Build Coastguard Worker --pos_;
592*9356374aSAndroid Build Coastguard Worker return *this;
593*9356374aSAndroid Build Coastguard Worker }
594*9356374aSAndroid Build Coastguard Worker
operator --(int)595*9356374aSAndroid Build Coastguard Worker TestIterator operator--(int) {
596*9356374aSAndroid Build Coastguard Worker TestIterator result = *this;
597*9356374aSAndroid Build Coastguard Worker --(*this);
598*9356374aSAndroid Build Coastguard Worker return result;
599*9356374aSAndroid Build Coastguard Worker }
600*9356374aSAndroid Build Coastguard Worker
601*9356374aSAndroid Build Coastguard Worker private:
TestIterator(const std::vector<absl::string_view> * data,size_t pos)602*9356374aSAndroid Build Coastguard Worker TestIterator(const std::vector<absl::string_view>* data, size_t pos)
603*9356374aSAndroid Build Coastguard Worker : data_(data), pos_(pos) {}
604*9356374aSAndroid Build Coastguard Worker
605*9356374aSAndroid Build Coastguard Worker const std::vector<absl::string_view>* data_;
606*9356374aSAndroid Build Coastguard Worker size_t pos_;
607*9356374aSAndroid Build Coastguard Worker };
608*9356374aSAndroid Build Coastguard Worker
609*9356374aSAndroid Build Coastguard Worker template <typename ValueT>
610*9356374aSAndroid Build Coastguard Worker class TestIteratorRange {
611*9356374aSAndroid Build Coastguard Worker public:
612*9356374aSAndroid Build Coastguard Worker // `data` must be non-null and must outlive the result.
TestIteratorRange(const std::vector<absl::string_view> & data)613*9356374aSAndroid Build Coastguard Worker explicit TestIteratorRange(const std::vector<absl::string_view>& data)
614*9356374aSAndroid Build Coastguard Worker : begin_(TestIterator<ValueT>::begin(data)),
615*9356374aSAndroid Build Coastguard Worker end_(TestIterator<ValueT>::end(data)) {}
616*9356374aSAndroid Build Coastguard Worker
begin() const617*9356374aSAndroid Build Coastguard Worker const TestIterator<ValueT>& begin() const { return begin_; }
end() const618*9356374aSAndroid Build Coastguard Worker const TestIterator<ValueT>& end() const { return end_; }
619*9356374aSAndroid Build Coastguard Worker
620*9356374aSAndroid Build Coastguard Worker private:
621*9356374aSAndroid Build Coastguard Worker TestIterator<ValueT> begin_;
622*9356374aSAndroid Build Coastguard Worker TestIterator<ValueT> end_;
623*9356374aSAndroid Build Coastguard Worker };
624*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,TestIteratorRequirementsNoFormatter)625*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, TestIteratorRequirementsNoFormatter) {
626*9356374aSAndroid Build Coastguard Worker const std::vector<absl::string_view> a = {"a", "b", "c"};
627*9356374aSAndroid Build Coastguard Worker
628*9356374aSAndroid Build Coastguard Worker // When the value type is string-like (`std::string` or `string_view`),
629*9356374aSAndroid Build Coastguard Worker // the NoFormatter template specialization is used internally.
630*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c",
631*9356374aSAndroid Build Coastguard Worker absl::StrJoin(TestIteratorRange<absl::string_view>(a), "-"));
632*9356374aSAndroid Build Coastguard Worker }
633*9356374aSAndroid Build Coastguard Worker
TEST(StrJoin,TestIteratorRequirementsCustomFormatter)634*9356374aSAndroid Build Coastguard Worker TEST(StrJoin, TestIteratorRequirementsCustomFormatter) {
635*9356374aSAndroid Build Coastguard Worker const std::vector<absl::string_view> a = {"a", "b", "c"};
636*9356374aSAndroid Build Coastguard Worker EXPECT_EQ("a-b-c",
637*9356374aSAndroid Build Coastguard Worker absl::StrJoin(TestIteratorRange<TestValue>(a), "-",
638*9356374aSAndroid Build Coastguard Worker [](std::string* out, const TestValue& value) {
639*9356374aSAndroid Build Coastguard Worker absl::StrAppend(
640*9356374aSAndroid Build Coastguard Worker out,
641*9356374aSAndroid Build Coastguard Worker absl::string_view(value.data(), value.size()));
642*9356374aSAndroid Build Coastguard Worker }));
643*9356374aSAndroid Build Coastguard Worker }
644*9356374aSAndroid Build Coastguard Worker
645*9356374aSAndroid Build Coastguard Worker } // namespace
646