Copyright 2012 -> 2013
[folly.git] / folly / test / StringTest.cpp
1 /*
2  * Copyright 2013 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "folly/String.h"
18
19 #include <random>
20 #include <boost/algorithm/string.hpp>
21 #include <gtest/gtest.h>
22
23 #include "folly/Benchmark.h"
24
25 using namespace folly;
26 using namespace std;
27
28 TEST(StringPrintf, BasicTest) {
29   EXPECT_EQ("abc", stringPrintf("%s", "abc"));
30   EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
31   EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
32   EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
33
34   EXPECT_EQ("abc", stringPrintf("abc"));
35 }
36
37 TEST(StringPrintf, NumericFormats) {
38   EXPECT_EQ("12", stringPrintf("%d", 12));
39   EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000UL));
40   EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000L));
41   EXPECT_EQ("-5000000000", stringPrintf("%ld", -5000000000L));
42   EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
43   EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffff));
44   EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffffUL));
45
46   EXPECT_EQ("7.7", stringPrintf("%1.1f", 7.7));
47   EXPECT_EQ("7.7", stringPrintf("%1.1lf", 7.7));
48   EXPECT_EQ("7.70000000000000018",
49             stringPrintf("%.17f", 7.7));
50   EXPECT_EQ("7.70000000000000018",
51             stringPrintf("%.17lf", 7.7));
52 }
53
54 TEST(StringPrintf, Appending) {
55   string s;
56   stringAppendf(&s, "a%s", "b");
57   stringAppendf(&s, "%c", 'c');
58   EXPECT_EQ(s, "abc");
59   stringAppendf(&s, " %d", 123);
60   EXPECT_EQ(s, "abc 123");
61 }
62
63 TEST(StringPrintf, VariousSizes) {
64   // Test a wide variety of output sizes
65   for (int i = 0; i < 100; ++i) {
66     string expected(i + 1, 'a');
67     EXPECT_EQ("X" + expected + "X", stringPrintf("X%sX", expected.c_str()));
68   }
69
70   EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
71             stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
72                          "%d%d%d%d%d%d%d%d%d%d%dxyz",
73                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
74                          17, 18, 19, 20, 21, 22, 23, 24, 25));
75 }
76
77 TEST(StringPrintf, oldStringPrintfTests) {
78   EXPECT_EQ(string("a/b/c/d"),
79             stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
80
81   EXPECT_EQ(string("    5    10"),
82             stringPrintf("%5d %5d", 5, 10));
83
84   // check printing w/ a big buffer
85   for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
86     string a(size, 'z');
87     string b = stringPrintf("%s", a.c_str());
88     EXPECT_EQ(a.size(), b.size());
89   }
90 }
91
92 TEST(StringPrintf, oldStringAppendf) {
93   string s = "hello";
94   stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
95   EXPECT_EQ(string("helloa/b/c/d"), s);
96 }
97
98 BENCHMARK(new_stringPrintfSmall, iters) {
99   for (int64_t i = 0; i < iters; ++i) {
100     int32_t x = int32_t(i);
101     int32_t y = int32_t(i + 1);
102     string s =
103       stringPrintf("msg msg msg msg msg msg msg msg:  %d, %d, %s",
104                    x, y, "hello");
105   }
106 }
107
108 TEST(Escape, cEscape) {
109   EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
110   EXPECT_EQ("hello \\\\world\\\" goodbye",
111             cEscape<std::string>("hello \\world\" goodbye"));
112   EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
113   EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
114 }
115
116 TEST(Escape, cUnescape) {
117   EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
118   EXPECT_EQ("hello \\world\" goodbye",
119             cUnescape<std::string>("hello \\\\world\\\" goodbye"));
120   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
121   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
122   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
123   EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
124   EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
125
126   EXPECT_THROW({cUnescape<std::string>("hello\\");},
127                std::invalid_argument);
128   EXPECT_THROW({cUnescape<std::string>("hello\\x");},
129                std::invalid_argument);
130   EXPECT_THROW({cUnescape<std::string>("hello\\q");},
131                std::invalid_argument);
132 }
133
134 namespace {
135 fbstring bmString;
136 fbstring bmEscapedString;
137 fbstring escapedString;
138 fbstring unescapedString;
139 const size_t kBmStringLength = 64 << 10;
140 const uint32_t kPrintablePercentage = 90;
141
142 void initBenchmark() {
143   bmString.reserve(kBmStringLength);
144
145   std::mt19937 rnd;
146   std::uniform_int_distribution<uint32_t> printable(32, 126);
147   std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
148   std::uniform_int_distribution<uint32_t> percentage(0, 99);
149
150   for (size_t i = 0; i < kBmStringLength; ++i) {
151     unsigned char c;
152     if (percentage(rnd) < kPrintablePercentage) {
153       c = printable(rnd);
154     } else {
155       c = nonPrintable(rnd);
156       // Generate characters in both non-printable ranges:
157       // 0..31 and 127..255
158       if (c >= 32) {
159         c += (126 - 32) + 1;
160       }
161     }
162     bmString.push_back(c);
163   }
164
165   bmEscapedString = cEscape<fbstring>(bmString);
166 }
167
168 BENCHMARK(BM_cEscape, iters) {
169   while (iters--) {
170     escapedString = cEscape<fbstring>(bmString);
171     doNotOptimizeAway(escapedString.size());
172   }
173 }
174
175 BENCHMARK(BM_cUnescape, iters) {
176   while (iters--) {
177     unescapedString = cUnescape<fbstring>(bmEscapedString);
178     doNotOptimizeAway(unescapedString.size());
179   }
180 }
181
182 }  // namespace
183
184 namespace {
185
186 double pow2(int exponent) {
187   return double(int64_t(1) << exponent);
188 }
189
190 }  // namespace
191
192 TEST(PrettyPrint, Basic) {
193   // check time printing
194   EXPECT_EQ(string("8.53e+07 s "), prettyPrint(85.3e6, PRETTY_TIME));
195   EXPECT_EQ(string("85.3 s "), prettyPrint(85.3, PRETTY_TIME));
196   EXPECT_EQ(string("85.3 ms"), prettyPrint(85.3e-3, PRETTY_TIME));
197   EXPECT_EQ(string("85.3 us"), prettyPrint(85.3e-6, PRETTY_TIME));
198   EXPECT_EQ(string("85.3 ns"), prettyPrint(85.3e-9, PRETTY_TIME));
199   EXPECT_EQ(string("85.3 ps"), prettyPrint(85.3e-12, PRETTY_TIME));
200   EXPECT_EQ(string("8.53e-14 s "), prettyPrint(85.3e-15, PRETTY_TIME));
201
202   EXPECT_EQ(string("0 s "), prettyPrint(0, PRETTY_TIME));
203   EXPECT_EQ(string("1 s "), prettyPrint(1.0, PRETTY_TIME));
204   EXPECT_EQ(string("1 ms"), prettyPrint(1.0e-3, PRETTY_TIME));
205   EXPECT_EQ(string("1 us"), prettyPrint(1.0e-6, PRETTY_TIME));
206   EXPECT_EQ(string("1 ns"), prettyPrint(1.0e-9, PRETTY_TIME));
207   EXPECT_EQ(string("1 ps"), prettyPrint(1.0e-12, PRETTY_TIME));
208
209   // check bytes printing
210   EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES));
211   EXPECT_EQ(string("833 kB"), prettyPrint(853.e3, PRETTY_BYTES));
212   EXPECT_EQ(string("813.5 MB"), prettyPrint(853.e6, PRETTY_BYTES));
213   EXPECT_EQ(string("7.944 GB"), prettyPrint(8.53e9, PRETTY_BYTES));
214   EXPECT_EQ(string("794.4 GB"), prettyPrint(853.e9, PRETTY_BYTES));
215   EXPECT_EQ(string("775.8 TB"), prettyPrint(853.e12, PRETTY_BYTES));
216
217   EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES));
218   EXPECT_EQ(string("1 B "), prettyPrint(pow2(0), PRETTY_BYTES));
219   EXPECT_EQ(string("1 kB"), prettyPrint(pow2(10), PRETTY_BYTES));
220   EXPECT_EQ(string("1 MB"), prettyPrint(pow2(20), PRETTY_BYTES));
221   EXPECT_EQ(string("1 GB"), prettyPrint(pow2(30), PRETTY_BYTES));
222   EXPECT_EQ(string("1 TB"), prettyPrint(pow2(40), PRETTY_BYTES));
223
224   EXPECT_EQ(string("853 B  "), prettyPrint(853., PRETTY_BYTES_IEC));
225   EXPECT_EQ(string("833 KiB"), prettyPrint(853.e3, PRETTY_BYTES_IEC));
226   EXPECT_EQ(string("813.5 MiB"), prettyPrint(853.e6, PRETTY_BYTES_IEC));
227   EXPECT_EQ(string("7.944 GiB"), prettyPrint(8.53e9, PRETTY_BYTES_IEC));
228   EXPECT_EQ(string("794.4 GiB"), prettyPrint(853.e9, PRETTY_BYTES_IEC));
229   EXPECT_EQ(string("775.8 TiB"), prettyPrint(853.e12, PRETTY_BYTES_IEC));
230
231   EXPECT_EQ(string("0 B  "), prettyPrint(0, PRETTY_BYTES_IEC));
232   EXPECT_EQ(string("1 B  "), prettyPrint(pow2(0), PRETTY_BYTES_IEC));
233   EXPECT_EQ(string("1 KiB"), prettyPrint(pow2(10), PRETTY_BYTES_IEC));
234   EXPECT_EQ(string("1 MiB"), prettyPrint(pow2(20), PRETTY_BYTES_IEC));
235   EXPECT_EQ(string("1 GiB"), prettyPrint(pow2(30), PRETTY_BYTES_IEC));
236   EXPECT_EQ(string("1 TiB"), prettyPrint(pow2(40), PRETTY_BYTES_IEC));
237
238   // check bytes metric printing
239   EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES_METRIC));
240   EXPECT_EQ(string("853 kB"), prettyPrint(853.e3, PRETTY_BYTES_METRIC));
241   EXPECT_EQ(string("853 MB"), prettyPrint(853.e6, PRETTY_BYTES_METRIC));
242   EXPECT_EQ(string("8.53 GB"), prettyPrint(8.53e9, PRETTY_BYTES_METRIC));
243   EXPECT_EQ(string("853 GB"), prettyPrint(853.e9, PRETTY_BYTES_METRIC));
244   EXPECT_EQ(string("853 TB"), prettyPrint(853.e12, PRETTY_BYTES_METRIC));
245
246   EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES_METRIC));
247   EXPECT_EQ(string("1 B "), prettyPrint(1.0, PRETTY_BYTES_METRIC));
248   EXPECT_EQ(string("1 kB"), prettyPrint(1.0e+3, PRETTY_BYTES_METRIC));
249   EXPECT_EQ(string("1 MB"), prettyPrint(1.0e+6, PRETTY_BYTES_METRIC));
250
251   EXPECT_EQ(string("1 GB"), prettyPrint(1.0e+9, PRETTY_BYTES_METRIC));
252   EXPECT_EQ(string("1 TB"), prettyPrint(1.0e+12, PRETTY_BYTES_METRIC));
253
254   // check metric-units (powers of 1000) printing
255   EXPECT_EQ(string("853  "), prettyPrint(853., PRETTY_UNITS_METRIC));
256   EXPECT_EQ(string("853 k"), prettyPrint(853.e3, PRETTY_UNITS_METRIC));
257   EXPECT_EQ(string("853 M"), prettyPrint(853.e6, PRETTY_UNITS_METRIC));
258   EXPECT_EQ(string("8.53 bil"), prettyPrint(8.53e9, PRETTY_UNITS_METRIC));
259   EXPECT_EQ(string("853 bil"), prettyPrint(853.e9, PRETTY_UNITS_METRIC));
260   EXPECT_EQ(string("853 tril"), prettyPrint(853.e12, PRETTY_UNITS_METRIC));
261
262   // check binary-units (powers of 1024) printing
263   EXPECT_EQ(string("0  "), prettyPrint(0, PRETTY_UNITS_BINARY));
264   EXPECT_EQ(string("1  "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY));
265   EXPECT_EQ(string("1 k"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY));
266   EXPECT_EQ(string("1 M"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY));
267   EXPECT_EQ(string("1 G"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY));
268   EXPECT_EQ(string("1 T"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY));
269
270   EXPECT_EQ(string("1023  "),
271       prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY));
272   EXPECT_EQ(string("1024 k"),
273       prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY));
274   EXPECT_EQ(string("1024 M"),
275       prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY));
276   EXPECT_EQ(string("1024 G"),
277       prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY));
278
279   EXPECT_EQ(string("0   "), prettyPrint(0, PRETTY_UNITS_BINARY_IEC));
280   EXPECT_EQ(string("1   "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY_IEC));
281   EXPECT_EQ(string("1 Ki"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY_IEC));
282   EXPECT_EQ(string("1 Mi"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY_IEC));
283   EXPECT_EQ(string("1 Gi"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY_IEC));
284   EXPECT_EQ(string("1 Ti"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY_IEC));
285
286   EXPECT_EQ(string("1023   "),
287       prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY_IEC));
288   EXPECT_EQ(string("1024 Ki"),
289       prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY_IEC));
290   EXPECT_EQ(string("1024 Mi"),
291       prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY_IEC));
292   EXPECT_EQ(string("1024 Gi"),
293       prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY_IEC));
294
295   // check that negative values work
296   EXPECT_EQ(string("-85.3 s "), prettyPrint(-85.3, PRETTY_TIME));
297   EXPECT_EQ(string("-85.3 ms"), prettyPrint(-85.3e-3, PRETTY_TIME));
298   EXPECT_EQ(string("-85.3 us"), prettyPrint(-85.3e-6, PRETTY_TIME));
299   EXPECT_EQ(string("-85.3 ns"), prettyPrint(-85.3e-9, PRETTY_TIME));
300 }
301
302 TEST(PrettyPrint, HexDump) {
303   std::string a("abc\x00\x02\xa0", 6);  // embedded NUL
304   EXPECT_EQ(
305     "00000000  61 62 63 00 02 a0                                 "
306     "|abc...          |\n",
307     hexDump(a.data(), a.size()));
308
309   a = "abcdefghijklmnopqrstuvwxyz";
310   EXPECT_EQ(
311     "00000000  61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  "
312     "|abcdefghijklmnop|\n"
313     "00000010  71 72 73 74 75 76 77 78  79 7a                    "
314     "|qrstuvwxyz      |\n",
315     hexDump(a.data(), a.size()));
316 }
317
318 TEST(System, errnoStr) {
319   errno = EACCES;
320   EXPECT_EQ(EACCES, errno);
321   EXPECT_EQ(EACCES, errno);  // twice to make sure EXPECT_EQ doesn't change it
322
323   fbstring expected = strerror(ENOENT);
324
325   errno = EACCES;
326   EXPECT_EQ(expected, errnoStr(ENOENT));
327   // Ensure that errno isn't changed
328   EXPECT_EQ(EACCES, errno);
329
330   // Per POSIX, all errno values are positive, so -1 is invalid
331   errnoStr(-1);
332
333   // Ensure that errno isn't changed
334   EXPECT_EQ(EACCES, errno);
335 }
336
337 namespace folly_test {
338 struct ThisIsAVeryLongStructureName {
339 };
340 }  // namespace folly_test
341
342 TEST(System, demangle) {
343   EXPECT_EQ("folly_test::ThisIsAVeryLongStructureName",
344             demangle(typeid(folly_test::ThisIsAVeryLongStructureName)));
345 }
346
347 namespace {
348
349 template<template<class,class> class VectorType>
350 void splitTest() {
351   VectorType<string,std::allocator<string> > parts;
352
353   folly::split(',', "a,b,c", parts);
354   EXPECT_EQ(parts.size(), 3);
355   EXPECT_EQ(parts[0], "a");
356   EXPECT_EQ(parts[1], "b");
357   EXPECT_EQ(parts[2], "c");
358   parts.clear();
359
360   folly::split(',', string("a,b,c"), parts);
361   EXPECT_EQ(parts.size(), 3);
362   EXPECT_EQ(parts[0], "a");
363   EXPECT_EQ(parts[1], "b");
364   EXPECT_EQ(parts[2], "c");
365   parts.clear();
366
367   folly::split(',', "a,,c", parts);
368   EXPECT_EQ(parts.size(), 3);
369   EXPECT_EQ(parts[0], "a");
370   EXPECT_EQ(parts[1], "");
371   EXPECT_EQ(parts[2], "c");
372   parts.clear();
373
374   folly::split(',', string("a,,c"), parts);
375   EXPECT_EQ(parts.size(), 3);
376   EXPECT_EQ(parts[0], "a");
377   EXPECT_EQ(parts[1], "");
378   EXPECT_EQ(parts[2], "c");
379   parts.clear();
380
381   folly::split(',', "a,,c", parts, true);
382   EXPECT_EQ(parts.size(), 2);
383   EXPECT_EQ(parts[0], "a");
384   EXPECT_EQ(parts[1], "c");
385   parts.clear();
386
387   folly::split(',', string("a,,c"), parts, true);
388   EXPECT_EQ(parts.size(), 2);
389   EXPECT_EQ(parts[0], "a");
390   EXPECT_EQ(parts[1], "c");
391   parts.clear();
392
393   folly::split(',', string(",,a,,c,,,"), parts, true);
394   EXPECT_EQ(parts.size(), 2);
395   EXPECT_EQ(parts[0], "a");
396   EXPECT_EQ(parts[1], "c");
397   parts.clear();
398
399   // test multiple split w/o clear
400   folly::split(',', ",,a,,c,,,", parts, true);
401   EXPECT_EQ(parts.size(), 2);
402   EXPECT_EQ(parts[0], "a");
403   EXPECT_EQ(parts[1], "c");
404   folly::split(',', ",,a,,c,,,", parts, true);
405   EXPECT_EQ(parts.size(), 4);
406   EXPECT_EQ(parts[2], "a");
407   EXPECT_EQ(parts[3], "c");
408   parts.clear();
409
410   // test splits that with multi-line delimiter
411   folly::split("ab", "dabcabkdbkab", parts, true);
412   EXPECT_EQ(parts.size(), 3);
413   EXPECT_EQ(parts[0], "d");
414   EXPECT_EQ(parts[1], "c");
415   EXPECT_EQ(parts[2], "kdbk");
416   parts.clear();
417
418   string orig = "ab2342asdfv~~!";
419   folly::split("", orig, parts, true);
420   EXPECT_EQ(parts.size(), 1);
421   EXPECT_EQ(parts[0], orig);
422   parts.clear();
423
424   folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
425   EXPECT_EQ(parts.size(), 1);
426   EXPECT_EQ(parts[0], "asfds");
427   parts.clear();
428
429   folly::split("a", "", parts, true);
430   EXPECT_EQ(parts.size(), 0);
431   parts.clear();
432
433   folly::split("a", "", parts);
434   EXPECT_EQ(parts.size(), 1);
435   EXPECT_EQ(parts[0], "");
436   parts.clear();
437
438   folly::split("a", "abcdefg", parts, true);
439   EXPECT_EQ(parts.size(), 1);
440   EXPECT_EQ(parts[0], "bcdefg");
441   parts.clear();
442
443   orig = "All, , your bases, are , , belong to us";
444   folly::split(", ", orig, parts, true);
445   EXPECT_EQ(parts.size(), 4);
446   EXPECT_EQ(parts[0], "All");
447   EXPECT_EQ(parts[1], "your bases");
448   EXPECT_EQ(parts[2], "are ");
449   EXPECT_EQ(parts[3], "belong to us");
450   parts.clear();
451   folly::split(", ", orig, parts);
452   EXPECT_EQ(parts.size(), 6);
453   EXPECT_EQ(parts[0], "All");
454   EXPECT_EQ(parts[1], "");
455   EXPECT_EQ(parts[2], "your bases");
456   EXPECT_EQ(parts[3], "are ");
457   EXPECT_EQ(parts[4], "");
458   EXPECT_EQ(parts[5], "belong to us");
459   parts.clear();
460
461   orig = ", Facebook, rul,es!, ";
462   folly::split(", ", orig, parts, true);
463   EXPECT_EQ(parts.size(), 2);
464   EXPECT_EQ(parts[0], "Facebook");
465   EXPECT_EQ(parts[1], "rul,es!");
466   parts.clear();
467   folly::split(", ", orig, parts);
468   EXPECT_EQ(parts.size(), 4);
469   EXPECT_EQ(parts[0], "");
470   EXPECT_EQ(parts[1], "Facebook");
471   EXPECT_EQ(parts[2], "rul,es!");
472   EXPECT_EQ(parts[3], "");
473 }
474
475 template<template<class,class> class VectorType>
476 void piecesTest() {
477   VectorType<StringPiece,std::allocator<StringPiece> > pieces;
478   VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
479
480   folly::split(',', "a,b,c", pieces);
481   EXPECT_EQ(pieces.size(), 3);
482   EXPECT_EQ(pieces[0], "a");
483   EXPECT_EQ(pieces[1], "b");
484   EXPECT_EQ(pieces[2], "c");
485
486   pieces.clear();
487
488   folly::split(',', "a,,c", pieces);
489   EXPECT_EQ(pieces.size(), 3);
490   EXPECT_EQ(pieces[0], "a");
491   EXPECT_EQ(pieces[1], "");
492   EXPECT_EQ(pieces[2], "c");
493   pieces.clear();
494
495   folly::split(',', "a,,c", pieces, true);
496   EXPECT_EQ(pieces.size(), 2);
497   EXPECT_EQ(pieces[0], "a");
498   EXPECT_EQ(pieces[1], "c");
499   pieces.clear();
500
501   folly::split(',', ",,a,,c,,,", pieces, true);
502   EXPECT_EQ(pieces.size(), 2);
503   EXPECT_EQ(pieces[0], "a");
504   EXPECT_EQ(pieces[1], "c");
505   pieces.clear();
506
507   // test multiple split w/o clear
508   folly::split(',', ",,a,,c,,,", pieces, true);
509   EXPECT_EQ(pieces.size(), 2);
510   EXPECT_EQ(pieces[0], "a");
511   EXPECT_EQ(pieces[1], "c");
512   folly::split(',', ",,a,,c,,,", pieces, true);
513   EXPECT_EQ(pieces.size(), 4);
514   EXPECT_EQ(pieces[2], "a");
515   EXPECT_EQ(pieces[3], "c");
516   pieces.clear();
517
518   // test multiple split rounds
519   folly::split(",", "a_b,c_d", pieces);
520   EXPECT_EQ(pieces.size(), 2);
521   EXPECT_EQ(pieces[0], "a_b");
522   EXPECT_EQ(pieces[1], "c_d");
523   folly::split("_", pieces[0], pieces2);
524   EXPECT_EQ(pieces2.size(), 2);
525   EXPECT_EQ(pieces2[0], "a");
526   EXPECT_EQ(pieces2[1], "b");
527   pieces2.clear();
528   folly::split("_", pieces[1], pieces2);
529   EXPECT_EQ(pieces2.size(), 2);
530   EXPECT_EQ(pieces2[0], "c");
531   EXPECT_EQ(pieces2[1], "d");
532   pieces.clear();
533   pieces2.clear();
534
535   // test splits that with multi-line delimiter
536   folly::split("ab", "dabcabkdbkab", pieces, true);
537   EXPECT_EQ(pieces.size(), 3);
538   EXPECT_EQ(pieces[0], "d");
539   EXPECT_EQ(pieces[1], "c");
540   EXPECT_EQ(pieces[2], "kdbk");
541   pieces.clear();
542
543   string orig = "ab2342asdfv~~!";
544   folly::split("", orig.c_str(), pieces, true);
545   EXPECT_EQ(pieces.size(), 1);
546   EXPECT_EQ(pieces[0], orig);
547   pieces.clear();
548
549   folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
550   EXPECT_EQ(pieces.size(), 1);
551   EXPECT_EQ(pieces[0], "asfds");
552   pieces.clear();
553
554   folly::split("a", "", pieces, true);
555   EXPECT_EQ(pieces.size(), 0);
556   pieces.clear();
557
558   folly::split("a", "", pieces);
559   EXPECT_EQ(pieces.size(), 1);
560   EXPECT_EQ(pieces[0], "");
561   pieces.clear();
562
563   folly::split("a", "abcdefg", pieces, true);
564   EXPECT_EQ(pieces.size(), 1);
565   EXPECT_EQ(pieces[0], "bcdefg");
566   pieces.clear();
567
568   orig = "All, , your bases, are , , belong to us";
569   folly::split(", ", orig, pieces, true);
570   EXPECT_EQ(pieces.size(), 4);
571   EXPECT_EQ(pieces[0], "All");
572   EXPECT_EQ(pieces[1], "your bases");
573   EXPECT_EQ(pieces[2], "are ");
574   EXPECT_EQ(pieces[3], "belong to us");
575   pieces.clear();
576   folly::split(", ", orig, pieces);
577   EXPECT_EQ(pieces.size(), 6);
578   EXPECT_EQ(pieces[0], "All");
579   EXPECT_EQ(pieces[1], "");
580   EXPECT_EQ(pieces[2], "your bases");
581   EXPECT_EQ(pieces[3], "are ");
582   EXPECT_EQ(pieces[4], "");
583   EXPECT_EQ(pieces[5], "belong to us");
584   pieces.clear();
585
586   orig = ", Facebook, rul,es!, ";
587   folly::split(", ", orig, pieces, true);
588   EXPECT_EQ(pieces.size(), 2);
589   EXPECT_EQ(pieces[0], "Facebook");
590   EXPECT_EQ(pieces[1], "rul,es!");
591   pieces.clear();
592   folly::split(", ", orig, pieces);
593   EXPECT_EQ(pieces.size(), 4);
594   EXPECT_EQ(pieces[0], "");
595   EXPECT_EQ(pieces[1], "Facebook");
596   EXPECT_EQ(pieces[2], "rul,es!");
597   EXPECT_EQ(pieces[3], "");
598   pieces.clear();
599
600   const char* str = "a,b";
601   folly::split(',', StringPiece(str), pieces);
602   EXPECT_EQ(pieces.size(), 2);
603   EXPECT_EQ(pieces[0], "a");
604   EXPECT_EQ(pieces[1], "b");
605   EXPECT_EQ(pieces[0].start(), str);
606   EXPECT_EQ(pieces[1].start(), str + 2);
607
608   std::set<StringPiece> unique;
609   folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
610     std::inserter(unique, unique.begin()), true);
611   EXPECT_EQ(unique.size(), 3);
612   if (unique.size() == 3) {
613     EXPECT_EQ(*unique.begin(), "asd");
614     EXPECT_EQ(*--unique.end(), "csd");
615   }
616
617   VectorType<fbstring,std::allocator<fbstring> > blah;
618   folly::split('-', "a-b-c-d-f-e", blah);
619   EXPECT_EQ(blah.size(), 6);
620 }
621
622 }
623
624 TEST(Split, split_vector) {
625   splitTest<std::vector>();
626 }
627 TEST(Split, split_fbvector) {
628   splitTest<folly::fbvector>();
629 }
630 TEST(Split, pieces_vector) {
631   piecesTest<std::vector>();
632 }
633 TEST(Split, pieces_fbvector) {
634   piecesTest<folly::fbvector>();
635 }
636
637 TEST(String, join) {
638   string output;
639
640   std::vector<int> empty = { };
641   join(":", empty, output);
642   EXPECT_TRUE(output.empty());
643
644   std::vector<std::string> input1 = { "1", "23", "456", "" };
645   join(':', input1, output);
646   EXPECT_EQ(output, "1:23:456:");
647   output = join(':', input1);
648   EXPECT_EQ(output, "1:23:456:");
649
650   auto input2 = { 1, 23, 456 };
651   join("-*-", input2, output);
652   EXPECT_EQ(output, "1-*-23-*-456");
653   output = join("-*-", input2);
654   EXPECT_EQ(output, "1-*-23-*-456");
655
656   auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
657   join("", input3, output);
658   EXPECT_EQ(output, "facebook");
659 }
660
661 TEST(String, hexlify) {
662   string input1 = "0123";
663   string output1;
664   EXPECT_TRUE(hexlify(input1, output1));
665   EXPECT_EQ(output1, "30313233");
666
667   fbstring input2 = "abcdefg";
668   input2[1] = 0;
669   input2[3] = 0xff;
670   input2[5] = 0xb6;
671   fbstring output2;
672   EXPECT_TRUE(hexlify(input2, output2));
673   EXPECT_EQ(output2, "610063ff65b667");
674 }
675
676 TEST(String, unhexlify) {
677   string input1 = "30313233";
678   string output1;
679   EXPECT_TRUE(unhexlify(input1, output1));
680   EXPECT_EQ(output1, "0123");
681
682   fbstring input2 = "610063ff65b667";
683   fbstring output2;
684   EXPECT_TRUE(unhexlify(input2, output2));
685   EXPECT_EQ(output2.size(), 7);
686   EXPECT_EQ(output2[0], 'a');
687   EXPECT_EQ(output2[1], 0);
688   EXPECT_EQ(output2[2], 'c');
689   EXPECT_EQ(output2[3] & 0xff, 0xff);
690   EXPECT_EQ(output2[4], 'e');
691   EXPECT_EQ(output2[5] & 0xff, 0xb6);
692   EXPECT_EQ(output2[6], 'g');
693
694   string input3 = "x";
695   string output3;
696   EXPECT_FALSE(unhexlify(input3, output3));
697
698   string input4 = "xy";
699   string output4;
700   EXPECT_FALSE(unhexlify(input4, output4));
701 }
702
703 TEST(String, backslashify) {
704   EXPECT_EQ("abc", string("abc"));
705   EXPECT_EQ("abc", backslashify(string("abc")));
706   EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
707   EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
708   EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
709 }
710
711 TEST(String, humanify) {
712   // Simple cases; output is obvious.
713   EXPECT_EQ("abc", humanify(string("abc")));
714   EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
715   EXPECT_EQ("0xff", humanify(string("\xff")));
716   EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
717   EXPECT_EQ("abc\\b", humanify(string("abc\b")));
718   EXPECT_EQ("0x00", humanify(string(1, '\0')));
719   EXPECT_EQ("0x0000", humanify(string(2, '\0')));
720
721
722   // Mostly printable, so backslash!  80, 60, and 40% printable, respectively
723   EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
724   EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
725   EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
726
727   // 20% printable, and the printable portion isn't the prefix; hexify!
728   EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
729
730   // Same as previous, except swap first two chars; prefix is
731   // printable and within the threshold, so backslashify.
732   EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
733
734   // Just too much unprintable; hex, despite prefix.
735   EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
736 }
737
738 //////////////////////////////////////////////////////////////////////
739
740 BENCHMARK(splitOnSingleChar, iters) {
741   static const std::string line = "one:two:three:four";
742   for (int i = 0; i < iters << 4; ++i) {
743     std::vector<StringPiece> pieces;
744     folly::split(':', line, pieces);
745   }
746 }
747
748 BENCHMARK(splitStr, iters) {
749   static const std::string line = "one-*-two-*-three-*-four";
750   for (int i = 0; i < iters << 4; ++i) {
751     std::vector<StringPiece> pieces;
752     folly::split("-*-", line, pieces);
753   }
754 }
755
756 BENCHMARK(boost_splitOnSingleChar, iters) {
757   static const std::string line = "one:two:three:four";
758   for (int i = 0; i < iters << 4; ++i) {
759     std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
760     boost::split(pieces, line, [] (char c) { return c == ':'; });
761   }
762 }
763
764 BENCHMARK(joinCharStr, iters) {
765   static const std::vector<std::string> input = {
766     "one", "two", "three", "four", "five", "six", "seven" };
767   for (int i = 0; i < iters << 4; ++i) {
768     std::string output;
769     folly::join(':', input, output);
770   }
771 }
772
773 BENCHMARK(joinStrStr, iters) {
774   static const std::vector<std::string> input = {
775     "one", "two", "three", "four", "five", "six", "seven" };
776   for (int i = 0; i < iters << 4; ++i) {
777     std::string output;
778     folly::join(":", input, output);
779   }
780 }
781
782 BENCHMARK(joinInt, iters) {
783   static const auto input = {
784     123, 456, 78910, 1112, 1314, 151, 61718 };
785   for (int i = 0; i < iters << 4; ++i) {
786     std::string output;
787     folly::join(":", input, output);
788   }
789 }
790
791 int main(int argc, char *argv[]) {
792   testing::InitGoogleTest(&argc, argv);
793   google::ParseCommandLineFlags(&argc, &argv, true);
794   auto ret = RUN_ALL_TESTS();
795   if (!ret) {
796     initBenchmark();
797     if (FLAGS_benchmark) {
798       folly::runBenchmarks();
799     }
800   }
801   return ret;
802 }
803