Add async-signal-safe flavor of demangle
[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 TEST(Escape, uriEscape) {
135   EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
136   EXPECT_EQ("hello%2c%20/world", uriEscape<std::string>("hello, /world",
137                                                         UriEscapeMode::PATH));
138   EXPECT_EQ("hello%2c+%2fworld", uriEscape<std::string>("hello, /world",
139                                                         UriEscapeMode::QUERY));
140 }
141
142 TEST(Escape, uriUnescape) {
143   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
144   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
145   EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
146   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c+%2fworld",
147                                                       UriEscapeMode::QUERY));
148   EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
149   EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
150   EXPECT_THROW({uriUnescape<std::string>("hello%");},
151                std::invalid_argument);
152   EXPECT_THROW({uriUnescape<std::string>("hello%2");},
153                std::invalid_argument);
154   EXPECT_THROW({uriUnescape<std::string>("hello%2g");},
155                std::invalid_argument);
156 }
157
158 namespace {
159 void expectPrintable(StringPiece s) {
160   for (char c : s) {
161     EXPECT_LE(32, c);
162     EXPECT_GE(127, c);
163   }
164 }
165 }  // namespace
166
167 TEST(Escape, uriEscapeAllCombinations) {
168   char c[3];
169   c[2] = '\0';
170   StringPiece in(c, 2);
171   fbstring tmp;
172   fbstring out;
173   for (int i = 0; i < 256; ++i) {
174     c[0] = i;
175     for (int j = 0; j < 256; ++j) {
176       c[1] = j;
177       tmp.clear();
178       out.clear();
179       uriEscape(in, tmp);
180       expectPrintable(tmp);
181       uriUnescape(tmp, out);
182       EXPECT_EQ(in, out);
183     }
184   }
185 }
186
187 namespace {
188 bool isHex(int v) {
189   return ((v >= '0' && v <= '9') ||
190           (v >= 'A' && v <= 'F') ||
191           (v >= 'a' && v <= 'f'));
192 }
193 }  // namespace
194
195 TEST(Escape, uriUnescapePercentDecoding) {
196   char c[4] = {'%', '\0', '\0', '\0'};
197   StringPiece in(c, 3);
198   fbstring out;
199   unsigned int expected = 0;
200   for (int i = 0; i < 256; ++i) {
201     c[1] = i;
202     for (int j = 0; j < 256; ++j) {
203       c[2] = j;
204       if (isHex(i) && isHex(j)) {
205         out.clear();
206         uriUnescape(in, out);
207         EXPECT_EQ(1, out.size());
208         EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
209         unsigned char v = out[0];
210         EXPECT_EQ(expected, v);
211       } else {
212         EXPECT_THROW({uriUnescape(in, out);}, std::invalid_argument);
213       }
214     }
215   }
216 }
217
218 namespace {
219 fbstring cbmString;
220 fbstring cbmEscapedString;
221 fbstring cEscapedString;
222 fbstring cUnescapedString;
223 const size_t kCBmStringLength = 64 << 10;
224 const uint32_t kCPrintablePercentage = 90;
225
226 fbstring uribmString;
227 fbstring uribmEscapedString;
228 fbstring uriEscapedString;
229 fbstring uriUnescapedString;
230 const size_t kURIBmStringLength = 256;
231 const uint32_t kURIPassThroughPercentage = 50;
232
233 void initBenchmark() {
234   std::mt19937 rnd;
235
236   // C escape
237   std::uniform_int_distribution<uint32_t> printable(32, 126);
238   std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
239   std::uniform_int_distribution<uint32_t> percentage(0, 99);
240
241   cbmString.reserve(kCBmStringLength);
242   for (size_t i = 0; i < kCBmStringLength; ++i) {
243     unsigned char c;
244     if (percentage(rnd) < kCPrintablePercentage) {
245       c = printable(rnd);
246     } else {
247       c = nonPrintable(rnd);
248       // Generate characters in both non-printable ranges:
249       // 0..31 and 127..255
250       if (c >= 32) {
251         c += (126 - 32) + 1;
252       }
253     }
254     cbmString.push_back(c);
255   }
256
257   cbmEscapedString = cEscape<fbstring>(cbmString);
258
259   // URI escape
260   std::uniform_int_distribution<uint32_t> passthrough('a', 'z');
261   std::string encodeChars = " ?!\"',+[]";
262   std::uniform_int_distribution<uint32_t> encode(0, encodeChars.size() - 1);
263
264   uribmString.reserve(kURIBmStringLength);
265   for (size_t i = 0; i < kURIBmStringLength; ++i) {
266     unsigned char c;
267     if (percentage(rnd) < kURIPassThroughPercentage) {
268       c = passthrough(rnd);
269     } else {
270       c = encodeChars[encode(rnd)];
271     }
272     uribmString.push_back(c);
273   }
274
275   uribmEscapedString = uriEscape<fbstring>(uribmString);
276 }
277
278 BENCHMARK(BM_cEscape, iters) {
279   while (iters--) {
280     cEscapedString = cEscape<fbstring>(cbmString);
281     doNotOptimizeAway(cEscapedString.size());
282   }
283 }
284
285 BENCHMARK(BM_cUnescape, iters) {
286   while (iters--) {
287     cUnescapedString = cUnescape<fbstring>(cbmEscapedString);
288     doNotOptimizeAway(cUnescapedString.size());
289   }
290 }
291
292 BENCHMARK(BM_uriEscape, iters) {
293   while (iters--) {
294     uriEscapedString = uriEscape<fbstring>(uribmString);
295     doNotOptimizeAway(uriEscapedString.size());
296   }
297 }
298
299 BENCHMARK(BM_uriUnescape, iters) {
300   while (iters--) {
301     uriUnescapedString = uriUnescape<fbstring>(uribmEscapedString);
302     doNotOptimizeAway(uriUnescapedString.size());
303   }
304 }
305
306 }  // namespace
307
308 namespace {
309
310 double pow2(int exponent) {
311   return double(int64_t(1) << exponent);
312 }
313
314 }  // namespace
315
316 TEST(PrettyPrint, Basic) {
317   // check time printing
318   EXPECT_EQ(string("8.53e+07 s "), prettyPrint(85.3e6, PRETTY_TIME));
319   EXPECT_EQ(string("85.3 s "), prettyPrint(85.3, PRETTY_TIME));
320   EXPECT_EQ(string("85.3 ms"), prettyPrint(85.3e-3, PRETTY_TIME));
321   EXPECT_EQ(string("85.3 us"), prettyPrint(85.3e-6, PRETTY_TIME));
322   EXPECT_EQ(string("85.3 ns"), prettyPrint(85.3e-9, PRETTY_TIME));
323   EXPECT_EQ(string("85.3 ps"), prettyPrint(85.3e-12, PRETTY_TIME));
324   EXPECT_EQ(string("8.53e-14 s "), prettyPrint(85.3e-15, PRETTY_TIME));
325
326   EXPECT_EQ(string("0 s "), prettyPrint(0, PRETTY_TIME));
327   EXPECT_EQ(string("1 s "), prettyPrint(1.0, PRETTY_TIME));
328   EXPECT_EQ(string("1 ms"), prettyPrint(1.0e-3, PRETTY_TIME));
329   EXPECT_EQ(string("1 us"), prettyPrint(1.0e-6, PRETTY_TIME));
330   EXPECT_EQ(string("1 ns"), prettyPrint(1.0e-9, PRETTY_TIME));
331   EXPECT_EQ(string("1 ps"), prettyPrint(1.0e-12, PRETTY_TIME));
332
333   // check bytes printing
334   EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES));
335   EXPECT_EQ(string("833 kB"), prettyPrint(853.e3, PRETTY_BYTES));
336   EXPECT_EQ(string("813.5 MB"), prettyPrint(853.e6, PRETTY_BYTES));
337   EXPECT_EQ(string("7.944 GB"), prettyPrint(8.53e9, PRETTY_BYTES));
338   EXPECT_EQ(string("794.4 GB"), prettyPrint(853.e9, PRETTY_BYTES));
339   EXPECT_EQ(string("775.8 TB"), prettyPrint(853.e12, PRETTY_BYTES));
340
341   EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES));
342   EXPECT_EQ(string("1 B "), prettyPrint(pow2(0), PRETTY_BYTES));
343   EXPECT_EQ(string("1 kB"), prettyPrint(pow2(10), PRETTY_BYTES));
344   EXPECT_EQ(string("1 MB"), prettyPrint(pow2(20), PRETTY_BYTES));
345   EXPECT_EQ(string("1 GB"), prettyPrint(pow2(30), PRETTY_BYTES));
346   EXPECT_EQ(string("1 TB"), prettyPrint(pow2(40), PRETTY_BYTES));
347
348   EXPECT_EQ(string("853 B  "), prettyPrint(853., PRETTY_BYTES_IEC));
349   EXPECT_EQ(string("833 KiB"), prettyPrint(853.e3, PRETTY_BYTES_IEC));
350   EXPECT_EQ(string("813.5 MiB"), prettyPrint(853.e6, PRETTY_BYTES_IEC));
351   EXPECT_EQ(string("7.944 GiB"), prettyPrint(8.53e9, PRETTY_BYTES_IEC));
352   EXPECT_EQ(string("794.4 GiB"), prettyPrint(853.e9, PRETTY_BYTES_IEC));
353   EXPECT_EQ(string("775.8 TiB"), prettyPrint(853.e12, PRETTY_BYTES_IEC));
354
355   EXPECT_EQ(string("0 B  "), prettyPrint(0, PRETTY_BYTES_IEC));
356   EXPECT_EQ(string("1 B  "), prettyPrint(pow2(0), PRETTY_BYTES_IEC));
357   EXPECT_EQ(string("1 KiB"), prettyPrint(pow2(10), PRETTY_BYTES_IEC));
358   EXPECT_EQ(string("1 MiB"), prettyPrint(pow2(20), PRETTY_BYTES_IEC));
359   EXPECT_EQ(string("1 GiB"), prettyPrint(pow2(30), PRETTY_BYTES_IEC));
360   EXPECT_EQ(string("1 TiB"), prettyPrint(pow2(40), PRETTY_BYTES_IEC));
361
362   // check bytes metric printing
363   EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES_METRIC));
364   EXPECT_EQ(string("853 kB"), prettyPrint(853.e3, PRETTY_BYTES_METRIC));
365   EXPECT_EQ(string("853 MB"), prettyPrint(853.e6, PRETTY_BYTES_METRIC));
366   EXPECT_EQ(string("8.53 GB"), prettyPrint(8.53e9, PRETTY_BYTES_METRIC));
367   EXPECT_EQ(string("853 GB"), prettyPrint(853.e9, PRETTY_BYTES_METRIC));
368   EXPECT_EQ(string("853 TB"), prettyPrint(853.e12, PRETTY_BYTES_METRIC));
369
370   EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES_METRIC));
371   EXPECT_EQ(string("1 B "), prettyPrint(1.0, PRETTY_BYTES_METRIC));
372   EXPECT_EQ(string("1 kB"), prettyPrint(1.0e+3, PRETTY_BYTES_METRIC));
373   EXPECT_EQ(string("1 MB"), prettyPrint(1.0e+6, PRETTY_BYTES_METRIC));
374
375   EXPECT_EQ(string("1 GB"), prettyPrint(1.0e+9, PRETTY_BYTES_METRIC));
376   EXPECT_EQ(string("1 TB"), prettyPrint(1.0e+12, PRETTY_BYTES_METRIC));
377
378   // check metric-units (powers of 1000) printing
379   EXPECT_EQ(string("853  "), prettyPrint(853., PRETTY_UNITS_METRIC));
380   EXPECT_EQ(string("853 k"), prettyPrint(853.e3, PRETTY_UNITS_METRIC));
381   EXPECT_EQ(string("853 M"), prettyPrint(853.e6, PRETTY_UNITS_METRIC));
382   EXPECT_EQ(string("8.53 bil"), prettyPrint(8.53e9, PRETTY_UNITS_METRIC));
383   EXPECT_EQ(string("853 bil"), prettyPrint(853.e9, PRETTY_UNITS_METRIC));
384   EXPECT_EQ(string("853 tril"), prettyPrint(853.e12, PRETTY_UNITS_METRIC));
385
386   // check binary-units (powers of 1024) printing
387   EXPECT_EQ(string("0  "), prettyPrint(0, PRETTY_UNITS_BINARY));
388   EXPECT_EQ(string("1  "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY));
389   EXPECT_EQ(string("1 k"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY));
390   EXPECT_EQ(string("1 M"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY));
391   EXPECT_EQ(string("1 G"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY));
392   EXPECT_EQ(string("1 T"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY));
393
394   EXPECT_EQ(string("1023  "),
395       prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY));
396   EXPECT_EQ(string("1024 k"),
397       prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY));
398   EXPECT_EQ(string("1024 M"),
399       prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY));
400   EXPECT_EQ(string("1024 G"),
401       prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY));
402
403   EXPECT_EQ(string("0   "), prettyPrint(0, PRETTY_UNITS_BINARY_IEC));
404   EXPECT_EQ(string("1   "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY_IEC));
405   EXPECT_EQ(string("1 Ki"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY_IEC));
406   EXPECT_EQ(string("1 Mi"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY_IEC));
407   EXPECT_EQ(string("1 Gi"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY_IEC));
408   EXPECT_EQ(string("1 Ti"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY_IEC));
409
410   EXPECT_EQ(string("1023   "),
411       prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY_IEC));
412   EXPECT_EQ(string("1024 Ki"),
413       prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY_IEC));
414   EXPECT_EQ(string("1024 Mi"),
415       prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY_IEC));
416   EXPECT_EQ(string("1024 Gi"),
417       prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY_IEC));
418
419   // check that negative values work
420   EXPECT_EQ(string("-85.3 s "), prettyPrint(-85.3, PRETTY_TIME));
421   EXPECT_EQ(string("-85.3 ms"), prettyPrint(-85.3e-3, PRETTY_TIME));
422   EXPECT_EQ(string("-85.3 us"), prettyPrint(-85.3e-6, PRETTY_TIME));
423   EXPECT_EQ(string("-85.3 ns"), prettyPrint(-85.3e-9, PRETTY_TIME));
424 }
425
426 TEST(PrettyPrint, HexDump) {
427   std::string a("abc\x00\x02\xa0", 6);  // embedded NUL
428   EXPECT_EQ(
429     "00000000  61 62 63 00 02 a0                                 "
430     "|abc...          |\n",
431     hexDump(a.data(), a.size()));
432
433   a = "abcdefghijklmnopqrstuvwxyz";
434   EXPECT_EQ(
435     "00000000  61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  "
436     "|abcdefghijklmnop|\n"
437     "00000010  71 72 73 74 75 76 77 78  79 7a                    "
438     "|qrstuvwxyz      |\n",
439     hexDump(a.data(), a.size()));
440 }
441
442 TEST(System, errnoStr) {
443   errno = EACCES;
444   EXPECT_EQ(EACCES, errno);
445   EXPECT_EQ(EACCES, errno);  // twice to make sure EXPECT_EQ doesn't change it
446
447   fbstring expected = strerror(ENOENT);
448
449   errno = EACCES;
450   EXPECT_EQ(expected, errnoStr(ENOENT));
451   // Ensure that errno isn't changed
452   EXPECT_EQ(EACCES, errno);
453
454   // Per POSIX, all errno values are positive, so -1 is invalid
455   errnoStr(-1);
456
457   // Ensure that errno isn't changed
458   EXPECT_EQ(EACCES, errno);
459 }
460
461 namespace folly_test {
462 struct ThisIsAVeryLongStructureName {
463 };
464 }  // namespace folly_test
465
466 TEST(System, demangle) {
467   char expected[] = "folly_test::ThisIsAVeryLongStructureName";
468   EXPECT_STREQ(
469       expected,
470       demangle(typeid(folly_test::ThisIsAVeryLongStructureName)).c_str());
471
472   {
473     char buf[sizeof(expected)];
474     EXPECT_EQ(sizeof(expected) - 1,
475               demangle(typeid(folly_test::ThisIsAVeryLongStructureName),
476                        buf, sizeof(buf)));
477     EXPECT_STREQ(expected, buf);
478
479     EXPECT_EQ(sizeof(expected) - 1,
480               demangle(typeid(folly_test::ThisIsAVeryLongStructureName),
481                        buf, 11));
482     EXPECT_STREQ("folly_test", buf);
483   }
484 }
485
486 namespace {
487
488 template<template<class,class> class VectorType>
489 void splitTest() {
490   VectorType<string,std::allocator<string> > parts;
491
492   folly::split(',', "a,b,c", parts);
493   EXPECT_EQ(parts.size(), 3);
494   EXPECT_EQ(parts[0], "a");
495   EXPECT_EQ(parts[1], "b");
496   EXPECT_EQ(parts[2], "c");
497   parts.clear();
498
499   folly::split(',', StringPiece("a,b,c"), parts);
500   EXPECT_EQ(parts.size(), 3);
501   EXPECT_EQ(parts[0], "a");
502   EXPECT_EQ(parts[1], "b");
503   EXPECT_EQ(parts[2], "c");
504   parts.clear();
505
506   folly::split(',', string("a,b,c"), parts);
507   EXPECT_EQ(parts.size(), 3);
508   EXPECT_EQ(parts[0], "a");
509   EXPECT_EQ(parts[1], "b");
510   EXPECT_EQ(parts[2], "c");
511   parts.clear();
512
513   folly::split(',', "a,,c", parts);
514   EXPECT_EQ(parts.size(), 3);
515   EXPECT_EQ(parts[0], "a");
516   EXPECT_EQ(parts[1], "");
517   EXPECT_EQ(parts[2], "c");
518   parts.clear();
519
520   folly::split(',', string("a,,c"), parts);
521   EXPECT_EQ(parts.size(), 3);
522   EXPECT_EQ(parts[0], "a");
523   EXPECT_EQ(parts[1], "");
524   EXPECT_EQ(parts[2], "c");
525   parts.clear();
526
527   folly::split(',', "a,,c", parts, true);
528   EXPECT_EQ(parts.size(), 2);
529   EXPECT_EQ(parts[0], "a");
530   EXPECT_EQ(parts[1], "c");
531   parts.clear();
532
533   folly::split(',', string("a,,c"), parts, true);
534   EXPECT_EQ(parts.size(), 2);
535   EXPECT_EQ(parts[0], "a");
536   EXPECT_EQ(parts[1], "c");
537   parts.clear();
538
539   folly::split(',', string(",,a,,c,,,"), parts, true);
540   EXPECT_EQ(parts.size(), 2);
541   EXPECT_EQ(parts[0], "a");
542   EXPECT_EQ(parts[1], "c");
543   parts.clear();
544
545   // test multiple split w/o clear
546   folly::split(',', ",,a,,c,,,", parts, true);
547   EXPECT_EQ(parts.size(), 2);
548   EXPECT_EQ(parts[0], "a");
549   EXPECT_EQ(parts[1], "c");
550   folly::split(',', ",,a,,c,,,", parts, true);
551   EXPECT_EQ(parts.size(), 4);
552   EXPECT_EQ(parts[2], "a");
553   EXPECT_EQ(parts[3], "c");
554   parts.clear();
555
556   // test splits that with multi-line delimiter
557   folly::split("ab", "dabcabkdbkab", parts, true);
558   EXPECT_EQ(parts.size(), 3);
559   EXPECT_EQ(parts[0], "d");
560   EXPECT_EQ(parts[1], "c");
561   EXPECT_EQ(parts[2], "kdbk");
562   parts.clear();
563
564   string orig = "ab2342asdfv~~!";
565   folly::split("", orig, parts, true);
566   EXPECT_EQ(parts.size(), 1);
567   EXPECT_EQ(parts[0], orig);
568   parts.clear();
569
570   folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
571   EXPECT_EQ(parts.size(), 1);
572   EXPECT_EQ(parts[0], "asfds");
573   parts.clear();
574
575   folly::split("a", "", parts, true);
576   EXPECT_EQ(parts.size(), 0);
577   parts.clear();
578
579   folly::split("a", "", parts);
580   EXPECT_EQ(parts.size(), 1);
581   EXPECT_EQ(parts[0], "");
582   parts.clear();
583
584   folly::split("a", StringPiece(), parts, true);
585   EXPECT_EQ(parts.size(), 0);
586   parts.clear();
587
588   folly::split("a", StringPiece(), parts);
589   EXPECT_EQ(parts.size(), 1);
590   EXPECT_EQ(parts[0], "");
591   parts.clear();
592
593   folly::split("a", "abcdefg", parts, true);
594   EXPECT_EQ(parts.size(), 1);
595   EXPECT_EQ(parts[0], "bcdefg");
596   parts.clear();
597
598   orig = "All, , your base, are , , belong to us";
599   folly::split(", ", orig, parts, true);
600   EXPECT_EQ(parts.size(), 4);
601   EXPECT_EQ(parts[0], "All");
602   EXPECT_EQ(parts[1], "your base");
603   EXPECT_EQ(parts[2], "are ");
604   EXPECT_EQ(parts[3], "belong to us");
605   parts.clear();
606   folly::split(", ", orig, parts);
607   EXPECT_EQ(parts.size(), 6);
608   EXPECT_EQ(parts[0], "All");
609   EXPECT_EQ(parts[1], "");
610   EXPECT_EQ(parts[2], "your base");
611   EXPECT_EQ(parts[3], "are ");
612   EXPECT_EQ(parts[4], "");
613   EXPECT_EQ(parts[5], "belong to us");
614   parts.clear();
615
616   orig = ", Facebook, rul,es!, ";
617   folly::split(", ", orig, parts, true);
618   EXPECT_EQ(parts.size(), 2);
619   EXPECT_EQ(parts[0], "Facebook");
620   EXPECT_EQ(parts[1], "rul,es!");
621   parts.clear();
622   folly::split(", ", orig, parts);
623   EXPECT_EQ(parts.size(), 4);
624   EXPECT_EQ(parts[0], "");
625   EXPECT_EQ(parts[1], "Facebook");
626   EXPECT_EQ(parts[2], "rul,es!");
627   EXPECT_EQ(parts[3], "");
628 }
629
630 template<template<class,class> class VectorType>
631 void piecesTest() {
632   VectorType<StringPiece,std::allocator<StringPiece> > pieces;
633   VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
634
635   folly::split(',', "a,b,c", pieces);
636   EXPECT_EQ(pieces.size(), 3);
637   EXPECT_EQ(pieces[0], "a");
638   EXPECT_EQ(pieces[1], "b");
639   EXPECT_EQ(pieces[2], "c");
640
641   pieces.clear();
642
643   folly::split(',', "a,,c", pieces);
644   EXPECT_EQ(pieces.size(), 3);
645   EXPECT_EQ(pieces[0], "a");
646   EXPECT_EQ(pieces[1], "");
647   EXPECT_EQ(pieces[2], "c");
648   pieces.clear();
649
650   folly::split(',', "a,,c", pieces, true);
651   EXPECT_EQ(pieces.size(), 2);
652   EXPECT_EQ(pieces[0], "a");
653   EXPECT_EQ(pieces[1], "c");
654   pieces.clear();
655
656   folly::split(',', ",,a,,c,,,", pieces, true);
657   EXPECT_EQ(pieces.size(), 2);
658   EXPECT_EQ(pieces[0], "a");
659   EXPECT_EQ(pieces[1], "c");
660   pieces.clear();
661
662   // test multiple split w/o clear
663   folly::split(',', ",,a,,c,,,", pieces, true);
664   EXPECT_EQ(pieces.size(), 2);
665   EXPECT_EQ(pieces[0], "a");
666   EXPECT_EQ(pieces[1], "c");
667   folly::split(',', ",,a,,c,,,", pieces, true);
668   EXPECT_EQ(pieces.size(), 4);
669   EXPECT_EQ(pieces[2], "a");
670   EXPECT_EQ(pieces[3], "c");
671   pieces.clear();
672
673   // test multiple split rounds
674   folly::split(",", "a_b,c_d", pieces);
675   EXPECT_EQ(pieces.size(), 2);
676   EXPECT_EQ(pieces[0], "a_b");
677   EXPECT_EQ(pieces[1], "c_d");
678   folly::split("_", pieces[0], pieces2);
679   EXPECT_EQ(pieces2.size(), 2);
680   EXPECT_EQ(pieces2[0], "a");
681   EXPECT_EQ(pieces2[1], "b");
682   pieces2.clear();
683   folly::split("_", pieces[1], pieces2);
684   EXPECT_EQ(pieces2.size(), 2);
685   EXPECT_EQ(pieces2[0], "c");
686   EXPECT_EQ(pieces2[1], "d");
687   pieces.clear();
688   pieces2.clear();
689
690   // test splits that with multi-line delimiter
691   folly::split("ab", "dabcabkdbkab", pieces, true);
692   EXPECT_EQ(pieces.size(), 3);
693   EXPECT_EQ(pieces[0], "d");
694   EXPECT_EQ(pieces[1], "c");
695   EXPECT_EQ(pieces[2], "kdbk");
696   pieces.clear();
697
698   string orig = "ab2342asdfv~~!";
699   folly::split("", orig.c_str(), pieces, true);
700   EXPECT_EQ(pieces.size(), 1);
701   EXPECT_EQ(pieces[0], orig);
702   pieces.clear();
703
704   folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
705   EXPECT_EQ(pieces.size(), 1);
706   EXPECT_EQ(pieces[0], "asfds");
707   pieces.clear();
708
709   folly::split("a", "", pieces, true);
710   EXPECT_EQ(pieces.size(), 0);
711   pieces.clear();
712
713   folly::split("a", "", pieces);
714   EXPECT_EQ(pieces.size(), 1);
715   EXPECT_EQ(pieces[0], "");
716   pieces.clear();
717
718   folly::split("a", "abcdefg", pieces, true);
719   EXPECT_EQ(pieces.size(), 1);
720   EXPECT_EQ(pieces[0], "bcdefg");
721   pieces.clear();
722
723   orig = "All, , your base, are , , belong to us";
724   folly::split(", ", orig, pieces, true);
725   EXPECT_EQ(pieces.size(), 4);
726   EXPECT_EQ(pieces[0], "All");
727   EXPECT_EQ(pieces[1], "your base");
728   EXPECT_EQ(pieces[2], "are ");
729   EXPECT_EQ(pieces[3], "belong to us");
730   pieces.clear();
731   folly::split(", ", orig, pieces);
732   EXPECT_EQ(pieces.size(), 6);
733   EXPECT_EQ(pieces[0], "All");
734   EXPECT_EQ(pieces[1], "");
735   EXPECT_EQ(pieces[2], "your base");
736   EXPECT_EQ(pieces[3], "are ");
737   EXPECT_EQ(pieces[4], "");
738   EXPECT_EQ(pieces[5], "belong to us");
739   pieces.clear();
740
741   orig = ", Facebook, rul,es!, ";
742   folly::split(", ", orig, pieces, true);
743   EXPECT_EQ(pieces.size(), 2);
744   EXPECT_EQ(pieces[0], "Facebook");
745   EXPECT_EQ(pieces[1], "rul,es!");
746   pieces.clear();
747   folly::split(", ", orig, pieces);
748   EXPECT_EQ(pieces.size(), 4);
749   EXPECT_EQ(pieces[0], "");
750   EXPECT_EQ(pieces[1], "Facebook");
751   EXPECT_EQ(pieces[2], "rul,es!");
752   EXPECT_EQ(pieces[3], "");
753   pieces.clear();
754
755   const char* str = "a,b";
756   folly::split(',', StringPiece(str), pieces);
757   EXPECT_EQ(pieces.size(), 2);
758   EXPECT_EQ(pieces[0], "a");
759   EXPECT_EQ(pieces[1], "b");
760   EXPECT_EQ(pieces[0].start(), str);
761   EXPECT_EQ(pieces[1].start(), str + 2);
762
763   std::set<StringPiece> unique;
764   folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
765     std::inserter(unique, unique.begin()), true);
766   EXPECT_EQ(unique.size(), 3);
767   if (unique.size() == 3) {
768     EXPECT_EQ(*unique.begin(), "asd");
769     EXPECT_EQ(*--unique.end(), "csd");
770   }
771
772   VectorType<fbstring,std::allocator<fbstring> > blah;
773   folly::split('-', "a-b-c-d-f-e", blah);
774   EXPECT_EQ(blah.size(), 6);
775 }
776
777 }
778
779 TEST(Split, split_vector) {
780   splitTest<std::vector>();
781 }
782 TEST(Split, split_fbvector) {
783   splitTest<folly::fbvector>();
784 }
785 TEST(Split, pieces_vector) {
786   piecesTest<std::vector>();
787 }
788 TEST(Split, pieces_fbvector) {
789   piecesTest<folly::fbvector>();
790 }
791
792 TEST(Split, fixed) {
793   StringPiece a, b, c, d;
794
795   EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
796   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
797   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
798   EXPECT_TRUE(folly::split<false>('.', "a", a));
799
800   EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
801   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
802   EXPECT_TRUE(folly::split('.', "a.b", a, b));
803   EXPECT_TRUE(folly::split('.', "a", a));
804
805   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
806   EXPECT_EQ("a", a);
807   EXPECT_EQ("b", b);
808   EXPECT_EQ("c", c);
809   EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
810   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
811   EXPECT_EQ("a", a);
812   EXPECT_EQ("b.c", b);
813
814   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
815   EXPECT_EQ("a", a);
816   EXPECT_EQ("b", b);
817   EXPECT_EQ("c", c);
818   EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
819   EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
820
821   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
822   EXPECT_EQ("a", a);
823   EXPECT_EQ("b", b);
824   EXPECT_FALSE(folly::split<false>('.', "a", a, b));
825   EXPECT_TRUE(folly::split<false>('.', "a.b", a));
826   EXPECT_EQ("a.b", a);
827
828   EXPECT_TRUE(folly::split('.', "a.b", a, b));
829   EXPECT_EQ("a", a);
830   EXPECT_EQ("b", b);
831   EXPECT_FALSE(folly::split('.', "a", a, b));
832   EXPECT_FALSE(folly::split('.', "a.b", a));
833 }
834
835 TEST(String, join) {
836   string output;
837
838   std::vector<int> empty = { };
839   join(":", empty, output);
840   EXPECT_TRUE(output.empty());
841
842   std::vector<std::string> input1 = { "1", "23", "456", "" };
843   join(':', input1, output);
844   EXPECT_EQ(output, "1:23:456:");
845   output = join(':', input1);
846   EXPECT_EQ(output, "1:23:456:");
847
848   auto input2 = { 1, 23, 456 };
849   join("-*-", input2, output);
850   EXPECT_EQ(output, "1-*-23-*-456");
851   output = join("-*-", input2);
852   EXPECT_EQ(output, "1-*-23-*-456");
853
854   auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
855   join("", input3, output);
856   EXPECT_EQ(output, "facebook");
857
858   join("_", { "", "f", "a", "c", "e", "b", "o", "o", "k", "" }, output);
859   EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
860 }
861
862 TEST(String, hexlify) {
863   string input1 = "0123";
864   string output1;
865   EXPECT_TRUE(hexlify(input1, output1));
866   EXPECT_EQ(output1, "30313233");
867
868   fbstring input2 = "abcdefg";
869   input2[1] = 0;
870   input2[3] = 0xff;
871   input2[5] = 0xb6;
872   fbstring output2;
873   EXPECT_TRUE(hexlify(input2, output2));
874   EXPECT_EQ(output2, "610063ff65b667");
875 }
876
877 TEST(String, unhexlify) {
878   string input1 = "30313233";
879   string output1;
880   EXPECT_TRUE(unhexlify(input1, output1));
881   EXPECT_EQ(output1, "0123");
882
883   fbstring input2 = "610063ff65b667";
884   fbstring output2;
885   EXPECT_TRUE(unhexlify(input2, output2));
886   EXPECT_EQ(output2.size(), 7);
887   EXPECT_EQ(output2[0], 'a');
888   EXPECT_EQ(output2[1], 0);
889   EXPECT_EQ(output2[2], 'c');
890   EXPECT_EQ(output2[3] & 0xff, 0xff);
891   EXPECT_EQ(output2[4], 'e');
892   EXPECT_EQ(output2[5] & 0xff, 0xb6);
893   EXPECT_EQ(output2[6], 'g');
894
895   string input3 = "x";
896   string output3;
897   EXPECT_FALSE(unhexlify(input3, output3));
898
899   string input4 = "xy";
900   string output4;
901   EXPECT_FALSE(unhexlify(input4, output4));
902 }
903
904 TEST(String, backslashify) {
905   EXPECT_EQ("abc", string("abc"));
906   EXPECT_EQ("abc", backslashify(string("abc")));
907   EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
908   EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
909   EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
910 }
911
912 TEST(String, humanify) {
913   // Simple cases; output is obvious.
914   EXPECT_EQ("abc", humanify(string("abc")));
915   EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
916   EXPECT_EQ("0xff", humanify(string("\xff")));
917   EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
918   EXPECT_EQ("abc\\b", humanify(string("abc\b")));
919   EXPECT_EQ("0x00", humanify(string(1, '\0')));
920   EXPECT_EQ("0x0000", humanify(string(2, '\0')));
921
922
923   // Mostly printable, so backslash!  80, 60, and 40% printable, respectively
924   EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
925   EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
926   EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
927
928   // 20% printable, and the printable portion isn't the prefix; hexify!
929   EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
930
931   // Same as previous, except swap first two chars; prefix is
932   // printable and within the threshold, so backslashify.
933   EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
934
935   // Just too much unprintable; hex, despite prefix.
936   EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
937 }
938
939 //////////////////////////////////////////////////////////////////////
940
941 BENCHMARK(splitOnSingleChar, iters) {
942   static const std::string line = "one:two:three:four";
943   for (int i = 0; i < iters << 4; ++i) {
944     std::vector<StringPiece> pieces;
945     folly::split(':', line, pieces);
946   }
947 }
948
949 BENCHMARK(splitOnSingleCharFixed, iters) {
950   static const std::string line = "one:two:three:four";
951   for (int i = 0; i < iters << 4; ++i) {
952     StringPiece a, b, c, d;
953     folly::split(':', line, a, b, c, d);
954   }
955 }
956
957 BENCHMARK(splitOnSingleCharFixedAllowExtra, iters) {
958   static const std::string line = "one:two:three:four";
959   for (int i = 0; i < iters << 4; ++i) {
960     StringPiece a, b, c, d;
961     folly::split<false>(':', line, a, b, c, d);
962   }
963 }
964
965 BENCHMARK(splitStr, iters) {
966   static const std::string line = "one-*-two-*-three-*-four";
967   for (int i = 0; i < iters << 4; ++i) {
968     std::vector<StringPiece> pieces;
969     folly::split("-*-", line, pieces);
970   }
971 }
972
973 BENCHMARK(splitStrFixed, iters) {
974   static const std::string line = "one-*-two-*-three-*-four";
975   for (int i = 0; i < iters << 4; ++i) {
976     StringPiece a, b, c, d;
977     folly::split("-*-", line, a, b, c, d);
978   }
979 }
980
981 BENCHMARK(boost_splitOnSingleChar, iters) {
982   static const std::string line = "one:two:three:four";
983   bool(*pred)(char) = [] (char c) -> bool { return c == ':'; };
984   for (int i = 0; i < iters << 4; ++i) {
985     std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
986     boost::split(pieces, line, pred);
987   }
988 }
989
990 BENCHMARK(joinCharStr, iters) {
991   static const std::vector<std::string> input = {
992     "one", "two", "three", "four", "five", "six", "seven" };
993   for (int i = 0; i < iters << 4; ++i) {
994     std::string output;
995     folly::join(':', input, output);
996   }
997 }
998
999 BENCHMARK(joinStrStr, iters) {
1000   static const std::vector<std::string> input = {
1001     "one", "two", "three", "four", "five", "six", "seven" };
1002   for (int i = 0; i < iters << 4; ++i) {
1003     std::string output;
1004     folly::join(":", input, output);
1005   }
1006 }
1007
1008 BENCHMARK(joinInt, iters) {
1009   static const auto input = {
1010     123, 456, 78910, 1112, 1314, 151, 61718 };
1011   for (int i = 0; i < iters << 4; ++i) {
1012     std::string output;
1013     folly::join(":", input, output);
1014   }
1015 }
1016
1017 int main(int argc, char *argv[]) {
1018   testing::InitGoogleTest(&argc, argv);
1019   google::ParseCommandLineFlags(&argc, &argv, true);
1020   auto ret = RUN_ALL_TESTS();
1021   if (!ret) {
1022     initBenchmark();
1023     if (FLAGS_benchmark) {
1024       folly::runBenchmarks();
1025     }
1026   }
1027   return ret;
1028 }
1029