str_join_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 // Unit tests for all join.h functions
00016 
00017 #include "absl/strings/str_join.h"
00018 
00019 #include <cstddef>
00020 #include <cstdint>
00021 #include <cstdio>
00022 #include <functional>
00023 #include <initializer_list>
00024 #include <map>
00025 #include <memory>
00026 #include <ostream>
00027 #include <tuple>
00028 #include <type_traits>
00029 #include <vector>
00030 
00031 #include "gtest/gtest.h"
00032 #include "absl/base/macros.h"
00033 #include "absl/memory/memory.h"
00034 #include "absl/strings/str_cat.h"
00035 #include "absl/strings/str_split.h"
00036 
00037 namespace {
00038 
00039 TEST(StrJoin, APIExamples) {
00040   {
00041     // Collection of strings
00042     std::vector<std::string> v = {"foo", "bar", "baz"};
00043     EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00044   }
00045 
00046   {
00047     // Collection of absl::string_view
00048     std::vector<absl::string_view> v = {"foo", "bar", "baz"};
00049     EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00050   }
00051 
00052   {
00053     // Collection of const char*
00054     std::vector<const char*> v = {"foo", "bar", "baz"};
00055     EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00056   }
00057 
00058   {
00059     // Collection of non-const char*
00060     std::string a = "foo", b = "bar", c = "baz";
00061     std::vector<char*> v = {&a[0], &b[0], &c[0]};
00062     EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00063   }
00064 
00065   {
00066     // Collection of ints
00067     std::vector<int> v = {1, 2, 3, -4};
00068     EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
00069   }
00070 
00071   {
00072     // Literals passed as a std::initializer_list
00073     std::string s = absl::StrJoin({"a", "b", "c"}, "-");
00074     EXPECT_EQ("a-b-c", s);
00075   }
00076   {
00077     // Join a std::tuple<T...>.
00078     std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
00079     EXPECT_EQ("123-abc-0.456", s);
00080   }
00081 
00082   {
00083     // Collection of unique_ptrs
00084     std::vector<std::unique_ptr<int>> v;
00085     v.emplace_back(new int(1));
00086     v.emplace_back(new int(2));
00087     v.emplace_back(new int(3));
00088     EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
00089   }
00090 
00091   {
00092     // Array of ints
00093     const int a[] = {1, 2, 3, -4};
00094     EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
00095   }
00096 
00097   {
00098     // Collection of pointers
00099     int x = 1, y = 2, z = 3;
00100     std::vector<int*> v = {&x, &y, &z};
00101     EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
00102   }
00103 
00104   {
00105     // Collection of pointers to pointers
00106     int x = 1, y = 2, z = 3;
00107     int *px = &x, *py = &y, *pz = &z;
00108     std::vector<int**> v = {&px, &py, &pz};
00109     EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
00110   }
00111 
00112   {
00113     // Collection of pointers to std::string
00114     std::string a("a"), b("b");
00115     std::vector<std::string*> v = {&a, &b};
00116     EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
00117   }
00118 
00119   {
00120     // A std::map, which is a collection of std::pair<>s.
00121     std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
00122     EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
00123   }
00124 
00125   {
00126     // Shows absl::StrSplit and absl::StrJoin working together. This example is
00127     // equivalent to s/=/-/g.
00128     const std::string s = "a=b=c=d";
00129     EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
00130   }
00131 
00132   //
00133   // A few examples of edge cases
00134   //
00135 
00136   {
00137     // Empty range yields an empty std::string.
00138     std::vector<std::string> v;
00139     EXPECT_EQ("", absl::StrJoin(v, "-"));
00140   }
00141 
00142   {
00143     // A range of 1 element gives a std::string with that element but no
00144     // separator.
00145     std::vector<std::string> v = {"foo"};
00146     EXPECT_EQ("foo", absl::StrJoin(v, "-"));
00147   }
00148 
00149   {
00150     // A range with a single empty std::string element
00151     std::vector<std::string> v = {""};
00152     EXPECT_EQ("", absl::StrJoin(v, "-"));
00153   }
00154 
00155   {
00156     // A range with 2 elements, one of which is an empty std::string
00157     std::vector<std::string> v = {"a", ""};
00158     EXPECT_EQ("a-", absl::StrJoin(v, "-"));
00159   }
00160 
00161   {
00162     // A range with 2 empty elements.
00163     std::vector<std::string> v = {"", ""};
00164     EXPECT_EQ("-", absl::StrJoin(v, "-"));
00165   }
00166 
00167   {
00168     // A std::vector of bool.
00169     std::vector<bool> v = {true, false, true};
00170     EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
00171   }
00172 }
00173 
00174 TEST(StrJoin, CustomFormatter) {
00175   std::vector<std::string> v{"One", "Two", "Three"};
00176   {
00177     std::string joined =
00178         absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
00179           absl::StrAppend(out, "(", in, ")");
00180         });
00181     EXPECT_EQ("(One)(Two)(Three)", joined);
00182   }
00183   {
00184     class ImmovableFormatter {
00185      public:
00186       void operator()(std::string* out, const std::string& in) {
00187         absl::StrAppend(out, "(", in, ")");
00188       }
00189       ImmovableFormatter() {}
00190       ImmovableFormatter(const ImmovableFormatter&) = delete;
00191     };
00192     EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter()));
00193   }
00194   {
00195     class OverloadedFormatter {
00196      public:
00197       void operator()(std::string* out, const std::string& in) {
00198         absl::StrAppend(out, "(", in, ")");
00199       }
00200       void operator()(std::string* out, const std::string& in) const {
00201         absl::StrAppend(out, "[", in, "]");
00202       }
00203     };
00204     EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter()));
00205     const OverloadedFormatter fmt = {};
00206     EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt));
00207   }
00208 }
00209 
00210 //
00211 // Tests the Formatters
00212 //
00213 
00214 TEST(AlphaNumFormatter, FormatterAPI) {
00215   // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test
00216   // of what AlphaNum can convert.
00217   auto f = absl::AlphaNumFormatter();
00218   std::string s;
00219   f(&s, "Testing: ");
00220   f(&s, static_cast<int>(1));
00221   f(&s, static_cast<int16_t>(2));
00222   f(&s, static_cast<int64_t>(3));
00223   f(&s, static_cast<float>(4));
00224   f(&s, static_cast<double>(5));
00225   f(&s, static_cast<unsigned>(6));
00226   f(&s, static_cast<size_t>(7));
00227   f(&s, absl::string_view(" OK"));
00228   EXPECT_EQ("Testing: 1234567 OK", s);
00229 }
00230 
00231 // Make sure people who are mistakenly using std::vector<bool> even though
00232 // they're not memory-constrained can use absl::AlphaNumFormatter().
00233 TEST(AlphaNumFormatter, VectorOfBool) {
00234   auto f = absl::AlphaNumFormatter();
00235   std::string s;
00236   std::vector<bool> v = {true, false, true};
00237   f(&s, *v.cbegin());
00238   f(&s, *v.begin());
00239   f(&s, v[1]);
00240   EXPECT_EQ("110", s);
00241 }
00242 
00243 TEST(AlphaNumFormatter, AlphaNum) {
00244   auto f = absl::AlphaNumFormatter();
00245   std::string s;
00246   f(&s, absl::AlphaNum("hello"));
00247   EXPECT_EQ("hello", s);
00248 }
00249 
00250 struct StreamableType {
00251   std::string contents;
00252 };
00253 inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {
00254   os << "Streamable:" << t.contents;
00255   return os;
00256 }
00257 
00258 TEST(StreamFormatter, FormatterAPI) {
00259   auto f = absl::StreamFormatter();
00260   std::string s;
00261   f(&s, "Testing: ");
00262   f(&s, static_cast<int>(1));
00263   f(&s, static_cast<int16_t>(2));
00264   f(&s, static_cast<int64_t>(3));
00265   f(&s, static_cast<float>(4));
00266   f(&s, static_cast<double>(5));
00267   f(&s, static_cast<unsigned>(6));
00268   f(&s, static_cast<size_t>(7));
00269   f(&s, absl::string_view(" OK "));
00270   StreamableType streamable = {"object"};
00271   f(&s, streamable);
00272   EXPECT_EQ("Testing: 1234567 OK Streamable:object", s);
00273 }
00274 
00275 // A dummy formatter that wraps each element in parens. Used in some tests
00276 // below.
00277 struct TestingParenFormatter {
00278   template <typename T>
00279   void operator()(std::string* s, const T& t) {
00280     absl::StrAppend(s, "(", t, ")");
00281   }
00282 };
00283 
00284 TEST(PairFormatter, FormatterAPI) {
00285   {
00286     // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the
00287     // 'first' and 'second' members.
00288     const auto f = absl::PairFormatter("=");
00289     std::string s;
00290     f(&s, std::make_pair("a", "b"));
00291     f(&s, std::make_pair(1, 2));
00292     EXPECT_EQ("a=b1=2", s);
00293   }
00294 
00295   {
00296     // Tests using a custom formatter for the 'first' and 'second' members.
00297     auto f = absl::PairFormatter(TestingParenFormatter(), "=",
00298                                  TestingParenFormatter());
00299     std::string s;
00300     f(&s, std::make_pair("a", "b"));
00301     f(&s, std::make_pair(1, 2));
00302     EXPECT_EQ("(a)=(b)(1)=(2)", s);
00303   }
00304 }
00305 
00306 TEST(DereferenceFormatter, FormatterAPI) {
00307   {
00308     // Tests wrapping the default AlphaNumFormatter.
00309     const absl::strings_internal::DereferenceFormatterImpl<
00310         absl::strings_internal::AlphaNumFormatterImpl>
00311         f;
00312     int x = 1, y = 2, z = 3;
00313     std::string s;
00314     f(&s, &x);
00315     f(&s, &y);
00316     f(&s, &z);
00317     EXPECT_EQ("123", s);
00318   }
00319 
00320   {
00321     // Tests wrapping std::string's default formatter.
00322     absl::strings_internal::DereferenceFormatterImpl<
00323         absl::strings_internal::DefaultFormatter<std::string>::Type>
00324         f;
00325 
00326     std::string x = "x";
00327     std::string y = "y";
00328     std::string z = "z";
00329     std::string s;
00330     f(&s, &x);
00331     f(&s, &y);
00332     f(&s, &z);
00333     EXPECT_EQ(s, "xyz");
00334   }
00335 
00336   {
00337     // Tests wrapping a custom formatter.
00338     auto f = absl::DereferenceFormatter(TestingParenFormatter());
00339     int x = 1, y = 2, z = 3;
00340     std::string s;
00341     f(&s, &x);
00342     f(&s, &y);
00343     f(&s, &z);
00344     EXPECT_EQ("(1)(2)(3)", s);
00345   }
00346 
00347   {
00348     absl::strings_internal::DereferenceFormatterImpl<
00349         absl::strings_internal::AlphaNumFormatterImpl>
00350         f;
00351     auto x = std::unique_ptr<int>(new int(1));
00352     auto y = std::unique_ptr<int>(new int(2));
00353     auto z = std::unique_ptr<int>(new int(3));
00354     std::string s;
00355     f(&s, x);
00356     f(&s, y);
00357     f(&s, z);
00358     EXPECT_EQ("123", s);
00359   }
00360 }
00361 
00362 //
00363 // Tests the interfaces for the 4 public Join function overloads. The semantics
00364 // of the algorithm is covered in the above APIExamples test.
00365 //
00366 TEST(StrJoin, PublicAPIOverloads) {
00367   std::vector<std::string> v = {"a", "b", "c"};
00368 
00369   // Iterators + formatter
00370   EXPECT_EQ("a-b-c",
00371             absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
00372   // Range + formatter
00373   EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
00374   // Iterators, no formatter
00375   EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
00376   // Range, no formatter
00377   EXPECT_EQ("a-b-c", absl::StrJoin(v, "-"));
00378 }
00379 
00380 TEST(StrJoin, Array) {
00381   const absl::string_view a[] = {"a", "b", "c"};
00382   EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
00383 }
00384 
00385 TEST(StrJoin, InitializerList) {
00386   { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); }
00387 
00388   {
00389     auto a = {"a", "b", "c"};
00390     EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
00391   }
00392 
00393   {
00394     std::initializer_list<const char*> a = {"a", "b", "c"};
00395     EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
00396   }
00397 
00398   {
00399     std::initializer_list<std::string> a = {"a", "b", "c"};
00400     EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
00401   }
00402 
00403   {
00404     std::initializer_list<absl::string_view> a = {"a", "b", "c"};
00405     EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
00406   }
00407 
00408   {
00409     // Tests initializer_list with a non-default formatter
00410     auto a = {"a", "b", "c"};
00411     TestingParenFormatter f;
00412     EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
00413   }
00414 
00415   {
00416     // initializer_list of ints
00417     EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
00418   }
00419 
00420   {
00421     // Tests initializer_list of ints with a non-default formatter
00422     auto a = {1, 2, 3};
00423     TestingParenFormatter f;
00424     EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
00425   }
00426 }
00427 
00428 TEST(StrJoin, Tuple) {
00429   EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-"));
00430   EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-"));
00431 
00432   int x(10);
00433   std::string y("hello");
00434   double z(3.14);
00435   EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-"));
00436 
00437   // Faster! Faster!!
00438   EXPECT_EQ("10-hello-3.14",
00439             absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-"));
00440 
00441   struct TestFormatter {
00442     char buffer[128];
00443     void operator()(std::string* out, int v) {
00444       snprintf(buffer, sizeof(buffer), "%#.8x", v);
00445       out->append(buffer);
00446     }
00447     void operator()(std::string* out, double v) {
00448       snprintf(buffer, sizeof(buffer), "%#.0f", v);
00449       out->append(buffer);
00450     }
00451     void operator()(std::string* out, const std::string& v) {
00452       snprintf(buffer, sizeof(buffer), "%.4s", v.c_str());
00453       out->append(buffer);
00454     }
00455   };
00456   EXPECT_EQ("0x0000000a-hell-3.",
00457             absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter()));
00458   EXPECT_EQ(
00459       "0x0000000a-hell-3.",
00460       absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter()));
00461   EXPECT_EQ("0x0000000a-hell-3.",
00462             absl::StrJoin(std::make_tuple(&x, &y, &z), "-",
00463                           absl::DereferenceFormatter(TestFormatter())));
00464   EXPECT_EQ("0x0000000a-hell-3.",
00465             absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),
00466                                           absl::make_unique<std::string>(y),
00467                                           absl::make_unique<double>(z)),
00468                           "-", absl::DereferenceFormatter(TestFormatter())));
00469   EXPECT_EQ("0x0000000a-hell-3.",
00470             absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),
00471                           "-", absl::DereferenceFormatter(TestFormatter())));
00472 }
00473 
00474 }  // namespace


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