str_join_test.cc 13 KB

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