00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00042 std::vector<std::string> v = {"foo", "bar", "baz"};
00043 EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00044 }
00045
00046 {
00047
00048 std::vector<absl::string_view> v = {"foo", "bar", "baz"};
00049 EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00050 }
00051
00052 {
00053
00054 std::vector<const char*> v = {"foo", "bar", "baz"};
00055 EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
00056 }
00057
00058 {
00059
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
00067 std::vector<int> v = {1, 2, 3, -4};
00068 EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
00069 }
00070
00071 {
00072
00073 std::string s = absl::StrJoin({"a", "b", "c"}, "-");
00074 EXPECT_EQ("a-b-c", s);
00075 }
00076 {
00077
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
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
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
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
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
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
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
00127
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
00134
00135
00136 {
00137
00138 std::vector<std::string> v;
00139 EXPECT_EQ("", absl::StrJoin(v, "-"));
00140 }
00141
00142 {
00143
00144
00145 std::vector<std::string> v = {"foo"};
00146 EXPECT_EQ("foo", absl::StrJoin(v, "-"));
00147 }
00148
00149 {
00150
00151 std::vector<std::string> v = {""};
00152 EXPECT_EQ("", absl::StrJoin(v, "-"));
00153 }
00154
00155 {
00156
00157 std::vector<std::string> v = {"a", ""};
00158 EXPECT_EQ("a-", absl::StrJoin(v, "-"));
00159 }
00160
00161 {
00162
00163 std::vector<std::string> v = {"", ""};
00164 EXPECT_EQ("-", absl::StrJoin(v, "-"));
00165 }
00166
00167 {
00168
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
00212
00213
00214 TEST(AlphaNumFormatter, FormatterAPI) {
00215
00216
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
00232
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
00276
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
00287
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
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
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
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
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
00364
00365
00366 TEST(StrJoin, PublicAPIOverloads) {
00367 std::vector<std::string> v = {"a", "b", "c"};
00368
00369
00370 EXPECT_EQ("a-b-c",
00371 absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
00372
00373 EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
00374
00375 EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
00376
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
00410 auto a = {"a", "b", "c"};
00411 TestingParenFormatter f;
00412 EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
00413 }
00414
00415 {
00416
00417 EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
00418 }
00419
00420 {
00421
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
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 }