str_join_test.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Unit tests for all join.h functions
16 
17 #include "absl/strings/str_join.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstdio>
22 #include <functional>
23 #include <initializer_list>
24 #include <map>
25 #include <memory>
26 #include <ostream>
27 #include <tuple>
28 #include <type_traits>
29 #include <vector>
30 
31 #include "gtest/gtest.h"
32 #include "absl/base/macros.h"
33 #include "absl/memory/memory.h"
34 #include "absl/strings/str_cat.h"
35 #include "absl/strings/str_split.h"
36 
37 namespace {
38 
39 TEST(StrJoin, APIExamples) {
40  {
41  // Collection of strings
42  std::vector<std::string> v = {"foo", "bar", "baz"};
43  EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
44  }
45 
46  {
47  // Collection of absl::string_view
48  std::vector<absl::string_view> v = {"foo", "bar", "baz"};
49  EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
50  }
51 
52  {
53  // Collection of const char*
54  std::vector<const char*> v = {"foo", "bar", "baz"};
55  EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
56  }
57 
58  {
59  // Collection of non-const char*
60  std::string a = "foo", b = "bar", c = "baz";
61  std::vector<char*> v = {&a[0], &b[0], &c[0]};
62  EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
63  }
64 
65  {
66  // Collection of ints
67  std::vector<int> v = {1, 2, 3, -4};
68  EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
69  }
70 
71  {
72  // Literals passed as a std::initializer_list
73  std::string s = absl::StrJoin({"a", "b", "c"}, "-");
74  EXPECT_EQ("a-b-c", s);
75  }
76  {
77  // Join a std::tuple<T...>.
78  std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
79  EXPECT_EQ("123-abc-0.456", s);
80  }
81 
82  {
83  // Collection of unique_ptrs
84  std::vector<std::unique_ptr<int>> v;
85  v.emplace_back(new int(1));
86  v.emplace_back(new int(2));
87  v.emplace_back(new int(3));
88  EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
89  }
90 
91  {
92  // Array of ints
93  const int a[] = {1, 2, 3, -4};
94  EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
95  }
96 
97  {
98  // Collection of pointers
99  int x = 1, y = 2, z = 3;
100  std::vector<int*> v = {&x, &y, &z};
101  EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
102  }
103 
104  {
105  // Collection of pointers to pointers
106  int x = 1, y = 2, z = 3;
107  int *px = &x, *py = &y, *pz = &z;
108  std::vector<int**> v = {&px, &py, &pz};
109  EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
110  }
111 
112  {
113  // Collection of pointers to std::string
114  std::string a("a"), b("b");
115  std::vector<std::string*> v = {&a, &b};
116  EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
117  }
118 
119  {
120  // A std::map, which is a collection of std::pair<>s.
121  std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
122  EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
123  }
124 
125  {
126  // Shows absl::StrSplit and absl::StrJoin working together. This example is
127  // equivalent to s/=/-/g.
128  const std::string s = "a=b=c=d";
129  EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
130  }
131 
132  //
133  // A few examples of edge cases
134  //
135 
136  {
137  // Empty range yields an empty std::string.
138  std::vector<std::string> v;
139  EXPECT_EQ("", absl::StrJoin(v, "-"));
140  }
141 
142  {
143  // A range of 1 element gives a std::string with that element but no
144  // separator.
145  std::vector<std::string> v = {"foo"};
146  EXPECT_EQ("foo", absl::StrJoin(v, "-"));
147  }
148 
149  {
150  // A range with a single empty std::string element
151  std::vector<std::string> v = {""};
152  EXPECT_EQ("", absl::StrJoin(v, "-"));
153  }
154 
155  {
156  // A range with 2 elements, one of which is an empty std::string
157  std::vector<std::string> v = {"a", ""};
158  EXPECT_EQ("a-", absl::StrJoin(v, "-"));
159  }
160 
161  {
162  // A range with 2 empty elements.
163  std::vector<std::string> v = {"", ""};
164  EXPECT_EQ("-", absl::StrJoin(v, "-"));
165  }
166 
167  {
168  // A std::vector of bool.
169  std::vector<bool> v = {true, false, true};
170  EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
171  }
172 }
173 
174 TEST(StrJoin, CustomFormatter) {
175  std::vector<std::string> v{"One", "Two", "Three"};
176  {
177  std::string joined =
178  absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
179  absl::StrAppend(out, "(", in, ")");
180  });
181  EXPECT_EQ("(One)(Two)(Three)", joined);
182  }
183  {
184  class ImmovableFormatter {
185  public:
186  void operator()(std::string* out, const std::string& in) {
187  absl::StrAppend(out, "(", in, ")");
188  }
189  ImmovableFormatter() {}
190  ImmovableFormatter(const ImmovableFormatter&) = delete;
191  };
192  EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter()));
193  }
194  {
195  class OverloadedFormatter {
196  public:
197  void operator()(std::string* out, const std::string& in) {
198  absl::StrAppend(out, "(", in, ")");
199  }
200  void operator()(std::string* out, const std::string& in) const {
201  absl::StrAppend(out, "[", in, "]");
202  }
203  };
204  EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter()));
205  const OverloadedFormatter fmt = {};
206  EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt));
207  }
208 }
209 
210 //
211 // Tests the Formatters
212 //
213 
214 TEST(AlphaNumFormatter, FormatterAPI) {
215  // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test
216  // of what AlphaNum can convert.
217  auto f = absl::AlphaNumFormatter();
218  std::string s;
219  f(&s, "Testing: ");
220  f(&s, static_cast<int>(1));
221  f(&s, static_cast<int16_t>(2));
222  f(&s, static_cast<int64_t>(3));
223  f(&s, static_cast<float>(4));
224  f(&s, static_cast<double>(5));
225  f(&s, static_cast<unsigned>(6));
226  f(&s, static_cast<size_t>(7));
227  f(&s, absl::string_view(" OK"));
228  EXPECT_EQ("Testing: 1234567 OK", s);
229 }
230 
231 // Make sure people who are mistakenly using std::vector<bool> even though
232 // they're not memory-constrained can use absl::AlphaNumFormatter().
233 TEST(AlphaNumFormatter, VectorOfBool) {
234  auto f = absl::AlphaNumFormatter();
235  std::string s;
236  std::vector<bool> v = {true, false, true};
237  f(&s, *v.cbegin());
238  f(&s, *v.begin());
239  f(&s, v[1]);
240  EXPECT_EQ("110", s);
241 }
242 
243 TEST(AlphaNumFormatter, AlphaNum) {
244  auto f = absl::AlphaNumFormatter();
245  std::string s;
246  f(&s, absl::AlphaNum("hello"));
247  EXPECT_EQ("hello", s);
248 }
249 
250 struct StreamableType {
251  std::string contents;
252 };
253 inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {
254  os << "Streamable:" << t.contents;
255  return os;
256 }
257 
258 TEST(StreamFormatter, FormatterAPI) {
259  auto f = absl::StreamFormatter();
260  std::string s;
261  f(&s, "Testing: ");
262  f(&s, static_cast<int>(1));
263  f(&s, static_cast<int16_t>(2));
264  f(&s, static_cast<int64_t>(3));
265  f(&s, static_cast<float>(4));
266  f(&s, static_cast<double>(5));
267  f(&s, static_cast<unsigned>(6));
268  f(&s, static_cast<size_t>(7));
269  f(&s, absl::string_view(" OK "));
270  StreamableType streamable = {"object"};
271  f(&s, streamable);
272  EXPECT_EQ("Testing: 1234567 OK Streamable:object", s);
273 }
274 
275 // A dummy formatter that wraps each element in parens. Used in some tests
276 // below.
277 struct TestingParenFormatter {
278  template <typename T>
279  void operator()(std::string* s, const T& t) {
280  absl::StrAppend(s, "(", t, ")");
281  }
282 };
283 
284 TEST(PairFormatter, FormatterAPI) {
285  {
286  // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the
287  // 'first' and 'second' members.
288  const auto f = absl::PairFormatter("=");
289  std::string s;
290  f(&s, std::make_pair("a", "b"));
291  f(&s, std::make_pair(1, 2));
292  EXPECT_EQ("a=b1=2", s);
293  }
294 
295  {
296  // Tests using a custom formatter for the 'first' and 'second' members.
297  auto f = absl::PairFormatter(TestingParenFormatter(), "=",
298  TestingParenFormatter());
299  std::string s;
300  f(&s, std::make_pair("a", "b"));
301  f(&s, std::make_pair(1, 2));
302  EXPECT_EQ("(a)=(b)(1)=(2)", s);
303  }
304 }
305 
306 TEST(DereferenceFormatter, FormatterAPI) {
307  {
308  // Tests wrapping the default AlphaNumFormatter.
311  f;
312  int x = 1, y = 2, z = 3;
313  std::string s;
314  f(&s, &x);
315  f(&s, &y);
316  f(&s, &z);
317  EXPECT_EQ("123", s);
318  }
319 
320  {
321  // Tests wrapping std::string's default formatter.
324  f;
325 
326  std::string x = "x";
327  std::string y = "y";
328  std::string z = "z";
329  std::string s;
330  f(&s, &x);
331  f(&s, &y);
332  f(&s, &z);
333  EXPECT_EQ(s, "xyz");
334  }
335 
336  {
337  // Tests wrapping a custom formatter.
338  auto f = absl::DereferenceFormatter(TestingParenFormatter());
339  int x = 1, y = 2, z = 3;
340  std::string s;
341  f(&s, &x);
342  f(&s, &y);
343  f(&s, &z);
344  EXPECT_EQ("(1)(2)(3)", s);
345  }
346 
347  {
350  f;
351  auto x = std::unique_ptr<int>(new int(1));
352  auto y = std::unique_ptr<int>(new int(2));
353  auto z = std::unique_ptr<int>(new int(3));
354  std::string s;
355  f(&s, x);
356  f(&s, y);
357  f(&s, z);
358  EXPECT_EQ("123", s);
359  }
360 }
361 
362 //
363 // Tests the interfaces for the 4 public Join function overloads. The semantics
364 // of the algorithm is covered in the above APIExamples test.
365 //
366 TEST(StrJoin, PublicAPIOverloads) {
367  std::vector<std::string> v = {"a", "b", "c"};
368 
369  // Iterators + formatter
370  EXPECT_EQ("a-b-c",
371  absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
372  // Range + formatter
373  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
374  // Iterators, no formatter
375  EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
376  // Range, no formatter
377  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-"));
378 }
379 
380 TEST(StrJoin, Array) {
381  const absl::string_view a[] = {"a", "b", "c"};
382  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
383 }
384 
385 TEST(StrJoin, InitializerList) {
386  { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); }
387 
388  {
389  auto a = {"a", "b", "c"};
390  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
391  }
392 
393  {
394  std::initializer_list<const char*> a = {"a", "b", "c"};
395  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
396  }
397 
398  {
399  std::initializer_list<std::string> a = {"a", "b", "c"};
400  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
401  }
402 
403  {
404  std::initializer_list<absl::string_view> a = {"a", "b", "c"};
405  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
406  }
407 
408  {
409  // Tests initializer_list with a non-default formatter
410  auto a = {"a", "b", "c"};
411  TestingParenFormatter f;
412  EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
413  }
414 
415  {
416  // initializer_list of ints
417  EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
418  }
419 
420  {
421  // Tests initializer_list of ints with a non-default formatter
422  auto a = {1, 2, 3};
423  TestingParenFormatter f;
424  EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
425  }
426 }
427 
428 TEST(StrJoin, Tuple) {
429  EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-"));
430  EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-"));
431 
432  int x(10);
433  std::string y("hello");
434  double z(3.14);
435  EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-"));
436 
437  // Faster! Faster!!
438  EXPECT_EQ("10-hello-3.14",
439  absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-"));
440 
441  struct TestFormatter {
442  char buffer[128];
443  void operator()(std::string* out, int v) {
444  snprintf(buffer, sizeof(buffer), "%#.8x", v);
445  out->append(buffer);
446  }
447  void operator()(std::string* out, double v) {
448  snprintf(buffer, sizeof(buffer), "%#.0f", v);
449  out->append(buffer);
450  }
451  void operator()(std::string* out, const std::string& v) {
452  snprintf(buffer, sizeof(buffer), "%.4s", v.c_str());
453  out->append(buffer);
454  }
455  };
456  EXPECT_EQ("0x0000000a-hell-3.",
457  absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter()));
458  EXPECT_EQ(
459  "0x0000000a-hell-3.",
460  absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter()));
461  EXPECT_EQ("0x0000000a-hell-3.",
462  absl::StrJoin(std::make_tuple(&x, &y, &z), "-",
463  absl::DereferenceFormatter(TestFormatter())));
464  EXPECT_EQ("0x0000000a-hell-3.",
465  absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),
466  absl::make_unique<std::string>(y),
467  absl::make_unique<double>(z)),
468  "-", absl::DereferenceFormatter(TestFormatter())));
469  EXPECT_EQ("0x0000000a-hell-3.",
470  absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),
471  "-", absl::DereferenceFormatter(TestFormatter())));
472 }
473 
474 } // namespace
int v
Definition: variant_test.cc:81
std::string * out
Definition: parser_test.cc:293
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: str_cat.cc:193
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, Formatter &&fmt)
Definition: str_join.h:244
std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: log_severity.cc:21
strings_internal::PairFormatterImpl< FirstFormatter, SecondFormatter > PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2)
Definition: str_join.h:119
strings_internal::Splitter< typename strings_internal::SelectDelimiter< Delimiter >::type, AllowEmpty > StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d)
Definition: str_split.h:491
strings_internal::AlphaNumFormatterImpl AlphaNumFormatter()
Definition: str_join.h:101
strings_internal::DereferenceFormatterImpl< Formatter > DereferenceFormatter(Formatter &&f)
Definition: str_join.h:140
#define ABSL_ARRAYSIZE(array)
Definition: macros.h:42
TEST(Symbolize, Unimplemented)
uint64_t b
Definition: layout_test.cc:50
strings_internal::StreamFormatterImpl StreamFormatter()
Definition: str_join.h:108
const char * in
Definition: parser_test.cc:350


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:19:58