f2162567dd8830b2e8d91d7545653e95dbfc0f3c
[folly.git] / folly / test / StringTest.cpp
1 /*
2  * Copyright 2014 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 struct PrettyTestCase{
316   std::string prettyString;
317   double realValue;
318   PrettyType prettyType;
319 };
320
321 PrettyTestCase prettyTestCases[] =
322 {
323   {string("8.53e+07 s "), 85.3e6,  PRETTY_TIME},
324   {string("8.53e+07 s "), 85.3e6,  PRETTY_TIME},
325   {string("85.3 ms"), 85.3e-3,  PRETTY_TIME},
326   {string("85.3 us"), 85.3e-6,  PRETTY_TIME},
327   {string("85.3 ns"), 85.3e-9,  PRETTY_TIME},
328   {string("85.3 ps"), 85.3e-12,  PRETTY_TIME},
329   {string("8.53e-14 s "), 85.3e-15,  PRETTY_TIME},
330
331   {string("0 s "), 0,  PRETTY_TIME},
332   {string("1 s "), 1.0,  PRETTY_TIME},
333   {string("1 ms"), 1.0e-3,  PRETTY_TIME},
334   {string("1 us"), 1.0e-6,  PRETTY_TIME},
335   {string("1 ns"), 1.0e-9,  PRETTY_TIME},
336   {string("1 ps"), 1.0e-12,  PRETTY_TIME},
337
338   // check bytes printing
339   {string("853 B "), 853.,  PRETTY_BYTES},
340   {string("833 kB"), 853.e3,  PRETTY_BYTES},
341   {string("813.5 MB"), 853.e6,  PRETTY_BYTES},
342   {string("7.944 GB"), 8.53e9,  PRETTY_BYTES},
343   {string("794.4 GB"), 853.e9,  PRETTY_BYTES},
344   {string("775.8 TB"), 853.e12,  PRETTY_BYTES},
345
346   {string("0 B "), 0,  PRETTY_BYTES},
347   {string("1 B "), pow2(0),  PRETTY_BYTES},
348   {string("1 kB"), pow2(10),  PRETTY_BYTES},
349   {string("1 MB"), pow2(20),  PRETTY_BYTES},
350   {string("1 GB"), pow2(30),  PRETTY_BYTES},
351   {string("1 TB"), pow2(40),  PRETTY_BYTES},
352
353   {string("853 B  "), 853.,  PRETTY_BYTES_IEC},
354   {string("833 KiB"), 853.e3,  PRETTY_BYTES_IEC},
355   {string("813.5 MiB"), 853.e6,  PRETTY_BYTES_IEC},
356   {string("7.944 GiB"), 8.53e9,  PRETTY_BYTES_IEC},
357   {string("794.4 GiB"), 853.e9,  PRETTY_BYTES_IEC},
358   {string("775.8 TiB"), 853.e12,  PRETTY_BYTES_IEC},
359
360   {string("0 B  "), 0,  PRETTY_BYTES_IEC},
361   {string("1 B  "), pow2(0),  PRETTY_BYTES_IEC},
362   {string("1 KiB"), pow2(10),  PRETTY_BYTES_IEC},
363   {string("1 MiB"), pow2(20),  PRETTY_BYTES_IEC},
364   {string("1 GiB"), pow2(30),  PRETTY_BYTES_IEC},
365   {string("1 TiB"), pow2(40),  PRETTY_BYTES_IEC},
366
367   // check bytes metric printing
368   {string("853 B "), 853.,  PRETTY_BYTES_METRIC},
369   {string("853 kB"), 853.e3,  PRETTY_BYTES_METRIC},
370   {string("853 MB"), 853.e6,  PRETTY_BYTES_METRIC},
371   {string("8.53 GB"), 8.53e9,  PRETTY_BYTES_METRIC},
372   {string("853 GB"), 853.e9,  PRETTY_BYTES_METRIC},
373   {string("853 TB"), 853.e12,  PRETTY_BYTES_METRIC},
374
375   {string("0 B "), 0,  PRETTY_BYTES_METRIC},
376   {string("1 B "), 1.0,  PRETTY_BYTES_METRIC},
377   {string("1 kB"), 1.0e+3,  PRETTY_BYTES_METRIC},
378   {string("1 MB"), 1.0e+6,  PRETTY_BYTES_METRIC},
379
380   {string("1 GB"), 1.0e+9,  PRETTY_BYTES_METRIC},
381   {string("1 TB"), 1.0e+12,  PRETTY_BYTES_METRIC},
382
383   // check metric-units (powers of 1000) printing
384   {string("853  "), 853.,  PRETTY_UNITS_METRIC},
385   {string("853 k"), 853.e3,  PRETTY_UNITS_METRIC},
386   {string("853 M"), 853.e6,  PRETTY_UNITS_METRIC},
387   {string("8.53 bil"), 8.53e9,  PRETTY_UNITS_METRIC},
388   {string("853 bil"), 853.e9,  PRETTY_UNITS_METRIC},
389   {string("853 tril"), 853.e12,  PRETTY_UNITS_METRIC},
390
391   // check binary-units (powers of 1024) printing
392   {string("0  "), 0,  PRETTY_UNITS_BINARY},
393   {string("1  "), pow2(0),  PRETTY_UNITS_BINARY},
394   {string("1 k"), pow2(10),  PRETTY_UNITS_BINARY},
395   {string("1 M"), pow2(20),  PRETTY_UNITS_BINARY},
396   {string("1 G"), pow2(30),  PRETTY_UNITS_BINARY},
397   {string("1 T"), pow2(40),  PRETTY_UNITS_BINARY},
398
399   {string("1023  "), pow2(10) - 1,  PRETTY_UNITS_BINARY},
400   {string("1024 k"), pow2(20) - 1,  PRETTY_UNITS_BINARY},
401   {string("1024 M"), pow2(30) - 1,  PRETTY_UNITS_BINARY},
402   {string("1024 G"), pow2(40) - 1,  PRETTY_UNITS_BINARY},
403
404   {string("0   "), 0,  PRETTY_UNITS_BINARY_IEC},
405   {string("1   "), pow2(0),  PRETTY_UNITS_BINARY_IEC},
406   {string("1 Ki"), pow2(10),  PRETTY_UNITS_BINARY_IEC},
407   {string("1 Mi"), pow2(20),  PRETTY_UNITS_BINARY_IEC},
408   {string("1 Gi"), pow2(30),  PRETTY_UNITS_BINARY_IEC},
409   {string("1 Ti"), pow2(40),  PRETTY_UNITS_BINARY_IEC},
410
411   {string("1023   "), pow2(10) - 1,  PRETTY_UNITS_BINARY_IEC},
412   {string("1024 Ki"), pow2(20) - 1,  PRETTY_UNITS_BINARY_IEC},
413   {string("1024 Mi"), pow2(30) - 1,  PRETTY_UNITS_BINARY_IEC},
414   {string("1024 Gi"), pow2(40) - 1,  PRETTY_UNITS_BINARY_IEC},
415
416   //check border SI cases
417
418   {string("1 Y"), 1e24,  PRETTY_SI},
419   {string("10 Y"), 1e25,  PRETTY_SI},
420   {string("1 y"), 1e-24,  PRETTY_SI},
421   {string("10 y"), 1e-23,  PRETTY_SI},
422
423   // check that negative values work
424   {string("-85.3 s "), -85.3,  PRETTY_TIME},
425   {string("-85.3 ms"), -85.3e-3,  PRETTY_TIME},
426   {string("-85.3 us"), -85.3e-6,  PRETTY_TIME},
427   {string("-85.3 ns"), -85.3e-9,  PRETTY_TIME},
428   // end of test
429   {string("endoftest"), 0, PRETTY_NUM_TYPES}
430 };
431
432 TEST(PrettyPrint, Basic) {
433   for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
434     const PrettyTestCase& prettyTest = prettyTestCases[i];
435     EXPECT_EQ(prettyTest.prettyString,
436               prettyPrint(prettyTest.realValue, prettyTest.prettyType));
437   }
438 }
439
440 TEST(PrettyToDouble, Basic) {
441   // check manually created tests
442   for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
443     PrettyTestCase testCase = prettyTestCases[i];
444     PrettyType formatType = testCase.prettyType;
445     double x = testCase.realValue;
446     std::string testString = testCase.prettyString;
447     double recoveredX;
448     try{
449       recoveredX = prettyToDouble(testString, formatType);
450     } catch (std::range_error &ex){
451       EXPECT_TRUE(false);
452     }
453     double relativeError = fabs(x) < 1e-5 ? (x-recoveredX) :
454                                             (x - recoveredX) / x;
455     EXPECT_NEAR(0, relativeError, 1e-3);
456   }
457
458   // checks for compatibility with prettyPrint over the whole parameter space
459   for (int i = 0 ; i < PRETTY_NUM_TYPES; ++i){
460     PrettyType formatType = static_cast<PrettyType>(i);
461     for (double x = 1e-18; x < 1e40; x *= 1.9){
462       bool addSpace = static_cast<PrettyType> (i) == PRETTY_SI;
463       for (int it = 0; it < 2; ++it, addSpace = true){
464         double recoveredX;
465         try{
466           recoveredX = prettyToDouble(prettyPrint(x, formatType, addSpace),
467                                              formatType);
468         } catch (std::range_error &ex){
469           EXPECT_TRUE(false);
470         }
471         double relativeError = (x - recoveredX) / x;
472         EXPECT_NEAR(0, relativeError, 1e-3);
473       }
474     }
475   }
476
477   // check for incorrect values
478   EXPECT_THROW(prettyToDouble("10Mx", PRETTY_SI), std::range_error);
479   EXPECT_THROW(prettyToDouble("10 Mx", PRETTY_SI), std::range_error);
480   EXPECT_THROW(prettyToDouble("10 M x", PRETTY_SI), std::range_error);
481
482   StringPiece testString = "10Mx";
483   EXPECT_DOUBLE_EQ(prettyToDouble(&testString, PRETTY_UNITS_METRIC), 10e6);
484   EXPECT_EQ(testString, "x");
485 }
486
487 TEST(PrettyPrint, HexDump) {
488   std::string a("abc\x00\x02\xa0", 6);  // embedded NUL
489   EXPECT_EQ(
490     "00000000  61 62 63 00 02 a0                                 "
491     "|abc...          |\n",
492     hexDump(a.data(), a.size()));
493
494   a = "abcdefghijklmnopqrstuvwxyz";
495   EXPECT_EQ(
496     "00000000  61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  "
497     "|abcdefghijklmnop|\n"
498     "00000010  71 72 73 74 75 76 77 78  79 7a                    "
499     "|qrstuvwxyz      |\n",
500     hexDump(a.data(), a.size()));
501 }
502
503 TEST(System, errnoStr) {
504   errno = EACCES;
505   EXPECT_EQ(EACCES, errno);
506   EXPECT_EQ(EACCES, errno);  // twice to make sure EXPECT_EQ doesn't change it
507
508   fbstring expected = strerror(ENOENT);
509
510   errno = EACCES;
511   EXPECT_EQ(expected, errnoStr(ENOENT));
512   // Ensure that errno isn't changed
513   EXPECT_EQ(EACCES, errno);
514
515   // Per POSIX, all errno values are positive, so -1 is invalid
516   errnoStr(-1);
517
518   // Ensure that errno isn't changed
519   EXPECT_EQ(EACCES, errno);
520 }
521
522 namespace folly_test {
523 struct ThisIsAVeryLongStructureName {
524 };
525 }  // namespace folly_test
526
527 #if FOLLY_HAVE_CPLUS_DEMANGLE_V3_CALLBACK
528 TEST(System, demangle) {
529   char expected[] = "folly_test::ThisIsAVeryLongStructureName";
530   EXPECT_STREQ(
531       expected,
532       demangle(typeid(folly_test::ThisIsAVeryLongStructureName)).c_str());
533
534   {
535     char buf[sizeof(expected)];
536     EXPECT_EQ(sizeof(expected) - 1,
537               demangle(typeid(folly_test::ThisIsAVeryLongStructureName),
538                        buf, sizeof(buf)));
539     EXPECT_STREQ(expected, buf);
540
541     EXPECT_EQ(sizeof(expected) - 1,
542               demangle(typeid(folly_test::ThisIsAVeryLongStructureName),
543                        buf, 11));
544     EXPECT_STREQ("folly_test", buf);
545   }
546 }
547 #endif
548
549 namespace {
550
551 template<template<class,class> class VectorType>
552 void splitTest() {
553   VectorType<string,std::allocator<string> > parts;
554
555   folly::split(',', "a,b,c", parts);
556   EXPECT_EQ(parts.size(), 3);
557   EXPECT_EQ(parts[0], "a");
558   EXPECT_EQ(parts[1], "b");
559   EXPECT_EQ(parts[2], "c");
560   parts.clear();
561
562   folly::split(',', StringPiece("a,b,c"), parts);
563   EXPECT_EQ(parts.size(), 3);
564   EXPECT_EQ(parts[0], "a");
565   EXPECT_EQ(parts[1], "b");
566   EXPECT_EQ(parts[2], "c");
567   parts.clear();
568
569   folly::split(',', string("a,b,c"), parts);
570   EXPECT_EQ(parts.size(), 3);
571   EXPECT_EQ(parts[0], "a");
572   EXPECT_EQ(parts[1], "b");
573   EXPECT_EQ(parts[2], "c");
574   parts.clear();
575
576   folly::split(',', "a,,c", parts);
577   EXPECT_EQ(parts.size(), 3);
578   EXPECT_EQ(parts[0], "a");
579   EXPECT_EQ(parts[1], "");
580   EXPECT_EQ(parts[2], "c");
581   parts.clear();
582
583   folly::split(',', string("a,,c"), parts);
584   EXPECT_EQ(parts.size(), 3);
585   EXPECT_EQ(parts[0], "a");
586   EXPECT_EQ(parts[1], "");
587   EXPECT_EQ(parts[2], "c");
588   parts.clear();
589
590   folly::split(',', "a,,c", parts, true);
591   EXPECT_EQ(parts.size(), 2);
592   EXPECT_EQ(parts[0], "a");
593   EXPECT_EQ(parts[1], "c");
594   parts.clear();
595
596   folly::split(',', string("a,,c"), parts, true);
597   EXPECT_EQ(parts.size(), 2);
598   EXPECT_EQ(parts[0], "a");
599   EXPECT_EQ(parts[1], "c");
600   parts.clear();
601
602   folly::split(',', string(",,a,,c,,,"), parts, true);
603   EXPECT_EQ(parts.size(), 2);
604   EXPECT_EQ(parts[0], "a");
605   EXPECT_EQ(parts[1], "c");
606   parts.clear();
607
608   // test multiple split w/o clear
609   folly::split(',', ",,a,,c,,,", parts, true);
610   EXPECT_EQ(parts.size(), 2);
611   EXPECT_EQ(parts[0], "a");
612   EXPECT_EQ(parts[1], "c");
613   folly::split(',', ",,a,,c,,,", parts, true);
614   EXPECT_EQ(parts.size(), 4);
615   EXPECT_EQ(parts[2], "a");
616   EXPECT_EQ(parts[3], "c");
617   parts.clear();
618
619   // test splits that with multi-line delimiter
620   folly::split("ab", "dabcabkdbkab", parts, true);
621   EXPECT_EQ(parts.size(), 3);
622   EXPECT_EQ(parts[0], "d");
623   EXPECT_EQ(parts[1], "c");
624   EXPECT_EQ(parts[2], "kdbk");
625   parts.clear();
626
627   // test last part is shorter than the delimiter
628   folly::split("bc", "abcd", parts, true);
629   EXPECT_EQ(parts.size(), 2);
630   EXPECT_EQ(parts[0], "a");
631   EXPECT_EQ(parts[1], "d");
632   parts.clear();
633
634   string orig = "ab2342asdfv~~!";
635   folly::split("", orig, parts, true);
636   EXPECT_EQ(parts.size(), 1);
637   EXPECT_EQ(parts[0], orig);
638   parts.clear();
639
640   folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
641   EXPECT_EQ(parts.size(), 1);
642   EXPECT_EQ(parts[0], "asfds");
643   parts.clear();
644
645   folly::split("a", "", parts, true);
646   EXPECT_EQ(parts.size(), 0);
647   parts.clear();
648
649   folly::split("a", "", parts);
650   EXPECT_EQ(parts.size(), 1);
651   EXPECT_EQ(parts[0], "");
652   parts.clear();
653
654   folly::split("a", StringPiece(), parts, true);
655   EXPECT_EQ(parts.size(), 0);
656   parts.clear();
657
658   folly::split("a", StringPiece(), parts);
659   EXPECT_EQ(parts.size(), 1);
660   EXPECT_EQ(parts[0], "");
661   parts.clear();
662
663   folly::split("a", "abcdefg", parts, true);
664   EXPECT_EQ(parts.size(), 1);
665   EXPECT_EQ(parts[0], "bcdefg");
666   parts.clear();
667
668   orig = "All, , your base, are , , belong to us";
669   folly::split(", ", orig, parts, true);
670   EXPECT_EQ(parts.size(), 4);
671   EXPECT_EQ(parts[0], "All");
672   EXPECT_EQ(parts[1], "your base");
673   EXPECT_EQ(parts[2], "are ");
674   EXPECT_EQ(parts[3], "belong to us");
675   parts.clear();
676   folly::split(", ", orig, parts);
677   EXPECT_EQ(parts.size(), 6);
678   EXPECT_EQ(parts[0], "All");
679   EXPECT_EQ(parts[1], "");
680   EXPECT_EQ(parts[2], "your base");
681   EXPECT_EQ(parts[3], "are ");
682   EXPECT_EQ(parts[4], "");
683   EXPECT_EQ(parts[5], "belong to us");
684   parts.clear();
685
686   orig = ", Facebook, rul,es!, ";
687   folly::split(", ", orig, parts, true);
688   EXPECT_EQ(parts.size(), 2);
689   EXPECT_EQ(parts[0], "Facebook");
690   EXPECT_EQ(parts[1], "rul,es!");
691   parts.clear();
692   folly::split(", ", orig, parts);
693   EXPECT_EQ(parts.size(), 4);
694   EXPECT_EQ(parts[0], "");
695   EXPECT_EQ(parts[1], "Facebook");
696   EXPECT_EQ(parts[2], "rul,es!");
697   EXPECT_EQ(parts[3], "");
698 }
699
700 template<template<class,class> class VectorType>
701 void piecesTest() {
702   VectorType<StringPiece,std::allocator<StringPiece> > pieces;
703   VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
704
705   folly::split(',', "a,b,c", pieces);
706   EXPECT_EQ(pieces.size(), 3);
707   EXPECT_EQ(pieces[0], "a");
708   EXPECT_EQ(pieces[1], "b");
709   EXPECT_EQ(pieces[2], "c");
710
711   pieces.clear();
712
713   folly::split(',', "a,,c", pieces);
714   EXPECT_EQ(pieces.size(), 3);
715   EXPECT_EQ(pieces[0], "a");
716   EXPECT_EQ(pieces[1], "");
717   EXPECT_EQ(pieces[2], "c");
718   pieces.clear();
719
720   folly::split(',', "a,,c", pieces, true);
721   EXPECT_EQ(pieces.size(), 2);
722   EXPECT_EQ(pieces[0], "a");
723   EXPECT_EQ(pieces[1], "c");
724   pieces.clear();
725
726   folly::split(',', ",,a,,c,,,", pieces, true);
727   EXPECT_EQ(pieces.size(), 2);
728   EXPECT_EQ(pieces[0], "a");
729   EXPECT_EQ(pieces[1], "c");
730   pieces.clear();
731
732   // test multiple split w/o clear
733   folly::split(',', ",,a,,c,,,", pieces, true);
734   EXPECT_EQ(pieces.size(), 2);
735   EXPECT_EQ(pieces[0], "a");
736   EXPECT_EQ(pieces[1], "c");
737   folly::split(',', ",,a,,c,,,", pieces, true);
738   EXPECT_EQ(pieces.size(), 4);
739   EXPECT_EQ(pieces[2], "a");
740   EXPECT_EQ(pieces[3], "c");
741   pieces.clear();
742
743   // test multiple split rounds
744   folly::split(",", "a_b,c_d", pieces);
745   EXPECT_EQ(pieces.size(), 2);
746   EXPECT_EQ(pieces[0], "a_b");
747   EXPECT_EQ(pieces[1], "c_d");
748   folly::split("_", pieces[0], pieces2);
749   EXPECT_EQ(pieces2.size(), 2);
750   EXPECT_EQ(pieces2[0], "a");
751   EXPECT_EQ(pieces2[1], "b");
752   pieces2.clear();
753   folly::split("_", pieces[1], pieces2);
754   EXPECT_EQ(pieces2.size(), 2);
755   EXPECT_EQ(pieces2[0], "c");
756   EXPECT_EQ(pieces2[1], "d");
757   pieces.clear();
758   pieces2.clear();
759
760   // test splits that with multi-line delimiter
761   folly::split("ab", "dabcabkdbkab", pieces, true);
762   EXPECT_EQ(pieces.size(), 3);
763   EXPECT_EQ(pieces[0], "d");
764   EXPECT_EQ(pieces[1], "c");
765   EXPECT_EQ(pieces[2], "kdbk");
766   pieces.clear();
767
768   string orig = "ab2342asdfv~~!";
769   folly::split("", orig.c_str(), pieces, true);
770   EXPECT_EQ(pieces.size(), 1);
771   EXPECT_EQ(pieces[0], orig);
772   pieces.clear();
773
774   folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
775   EXPECT_EQ(pieces.size(), 1);
776   EXPECT_EQ(pieces[0], "asfds");
777   pieces.clear();
778
779   folly::split("a", "", pieces, true);
780   EXPECT_EQ(pieces.size(), 0);
781   pieces.clear();
782
783   folly::split("a", "", pieces);
784   EXPECT_EQ(pieces.size(), 1);
785   EXPECT_EQ(pieces[0], "");
786   pieces.clear();
787
788   folly::split("a", "abcdefg", pieces, true);
789   EXPECT_EQ(pieces.size(), 1);
790   EXPECT_EQ(pieces[0], "bcdefg");
791   pieces.clear();
792
793   orig = "All, , your base, are , , belong to us";
794   folly::split(", ", orig, pieces, true);
795   EXPECT_EQ(pieces.size(), 4);
796   EXPECT_EQ(pieces[0], "All");
797   EXPECT_EQ(pieces[1], "your base");
798   EXPECT_EQ(pieces[2], "are ");
799   EXPECT_EQ(pieces[3], "belong to us");
800   pieces.clear();
801   folly::split(", ", orig, pieces);
802   EXPECT_EQ(pieces.size(), 6);
803   EXPECT_EQ(pieces[0], "All");
804   EXPECT_EQ(pieces[1], "");
805   EXPECT_EQ(pieces[2], "your base");
806   EXPECT_EQ(pieces[3], "are ");
807   EXPECT_EQ(pieces[4], "");
808   EXPECT_EQ(pieces[5], "belong to us");
809   pieces.clear();
810
811   orig = ", Facebook, rul,es!, ";
812   folly::split(", ", orig, pieces, true);
813   EXPECT_EQ(pieces.size(), 2);
814   EXPECT_EQ(pieces[0], "Facebook");
815   EXPECT_EQ(pieces[1], "rul,es!");
816   pieces.clear();
817   folly::split(", ", orig, pieces);
818   EXPECT_EQ(pieces.size(), 4);
819   EXPECT_EQ(pieces[0], "");
820   EXPECT_EQ(pieces[1], "Facebook");
821   EXPECT_EQ(pieces[2], "rul,es!");
822   EXPECT_EQ(pieces[3], "");
823   pieces.clear();
824
825   const char* str = "a,b";
826   folly::split(',', StringPiece(str), pieces);
827   EXPECT_EQ(pieces.size(), 2);
828   EXPECT_EQ(pieces[0], "a");
829   EXPECT_EQ(pieces[1], "b");
830   EXPECT_EQ(pieces[0].start(), str);
831   EXPECT_EQ(pieces[1].start(), str + 2);
832
833   std::set<StringPiece> unique;
834   folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
835     std::inserter(unique, unique.begin()), true);
836   EXPECT_EQ(unique.size(), 3);
837   if (unique.size() == 3) {
838     EXPECT_EQ(*unique.begin(), "asd");
839     EXPECT_EQ(*--unique.end(), "csd");
840   }
841
842   VectorType<fbstring,std::allocator<fbstring> > blah;
843   folly::split('-', "a-b-c-d-f-e", blah);
844   EXPECT_EQ(blah.size(), 6);
845 }
846
847 }
848
849 TEST(Split, split_vector) {
850   splitTest<std::vector>();
851 }
852 TEST(Split, split_fbvector) {
853   splitTest<folly::fbvector>();
854 }
855 TEST(Split, pieces_vector) {
856   piecesTest<std::vector>();
857 }
858 TEST(Split, pieces_fbvector) {
859   piecesTest<folly::fbvector>();
860 }
861
862 TEST(Split, fixed) {
863   StringPiece a, b, c, d;
864
865   EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
866   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
867   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
868   EXPECT_TRUE(folly::split<false>('.', "a", a));
869
870   EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
871   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
872   EXPECT_TRUE(folly::split('.', "a.b", a, b));
873   EXPECT_TRUE(folly::split('.', "a", a));
874
875   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
876   EXPECT_EQ("a", a);
877   EXPECT_EQ("b", b);
878   EXPECT_EQ("c", c);
879   EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
880   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
881   EXPECT_EQ("a", a);
882   EXPECT_EQ("b.c", b);
883
884   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
885   EXPECT_EQ("a", a);
886   EXPECT_EQ("b", b);
887   EXPECT_EQ("c", c);
888   EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
889   EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
890
891   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
892   EXPECT_EQ("a", a);
893   EXPECT_EQ("b", b);
894   EXPECT_FALSE(folly::split<false>('.', "a", a, b));
895   EXPECT_TRUE(folly::split<false>('.', "a.b", a));
896   EXPECT_EQ("a.b", a);
897
898   EXPECT_TRUE(folly::split('.', "a.b", a, b));
899   EXPECT_EQ("a", a);
900   EXPECT_EQ("b", b);
901   EXPECT_FALSE(folly::split('.', "a", a, b));
902   EXPECT_FALSE(folly::split('.', "a.b", a));
903 }
904
905 TEST(Split, std_string_fixed) {
906   std::string a, b, c, d;
907
908   EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
909   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
910   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
911   EXPECT_TRUE(folly::split<false>('.', "a", a));
912
913   EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
914   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
915   EXPECT_TRUE(folly::split('.', "a.b", a, b));
916   EXPECT_TRUE(folly::split('.', "a", a));
917
918   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
919   EXPECT_EQ("a", a);
920   EXPECT_EQ("b", b);
921   EXPECT_EQ("c", c);
922   EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
923   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
924   EXPECT_EQ("a", a);
925   EXPECT_EQ("b.c", b);
926
927   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
928   EXPECT_EQ("a", a);
929   EXPECT_EQ("b", b);
930   EXPECT_EQ("c", c);
931   EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
932   EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
933
934   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
935   EXPECT_EQ("a", a);
936   EXPECT_EQ("b", b);
937   EXPECT_FALSE(folly::split<false>('.', "a", a, b));
938   EXPECT_TRUE(folly::split<false>('.', "a.b", a));
939   EXPECT_EQ("a.b", a);
940
941   EXPECT_TRUE(folly::split('.', "a.b", a, b));
942   EXPECT_EQ("a", a);
943   EXPECT_EQ("b", b);
944   EXPECT_FALSE(folly::split('.', "a", a, b));
945   EXPECT_FALSE(folly::split('.', "a.b", a));
946 }
947
948 TEST(Split, fixed_convert) {
949   StringPiece a, d;
950   int b;
951   double c;
952
953   EXPECT_TRUE(folly::split(':', "a:13:14.7:b", a, b, c, d));
954   EXPECT_EQ("a", a);
955   EXPECT_EQ(13, b);
956   EXPECT_NEAR(14.7, c, 1e-10);
957   EXPECT_EQ("b", d);
958
959   EXPECT_TRUE(folly::split<false>(':', "b:14:15.3:c", a, b, c, d));
960   EXPECT_EQ("b", a);
961   EXPECT_EQ(14, b);
962   EXPECT_NEAR(15.3, c, 1e-10);
963   EXPECT_EQ("c", d);
964
965   EXPECT_FALSE(folly::split(':', "a:13:14.7:b", a, b, d));
966
967   EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, d));
968   EXPECT_EQ("a", a);
969   EXPECT_EQ(13, b);
970   EXPECT_EQ("14.7:b", d);
971
972   EXPECT_THROW(folly::split<false>(':', "a:13:14.7:b", a, b, c),
973                std::range_error);
974 }
975
976 TEST(String, join) {
977   string output;
978
979   std::vector<int> empty = { };
980   join(":", empty, output);
981   EXPECT_TRUE(output.empty());
982
983   std::vector<std::string> input1 = { "1", "23", "456", "" };
984   join(':', input1, output);
985   EXPECT_EQ(output, "1:23:456:");
986   output = join(':', input1);
987   EXPECT_EQ(output, "1:23:456:");
988
989   auto input2 = { 1, 23, 456 };
990   join("-*-", input2, output);
991   EXPECT_EQ(output, "1-*-23-*-456");
992   output = join("-*-", input2);
993   EXPECT_EQ(output, "1-*-23-*-456");
994
995   auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
996   join("", input3, output);
997   EXPECT_EQ(output, "facebook");
998
999   join("_", { "", "f", "a", "c", "e", "b", "o", "o", "k", "" }, output);
1000   EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
1001 }
1002
1003 TEST(String, hexlify) {
1004   string input1 = "0123";
1005   string output1;
1006   EXPECT_TRUE(hexlify(input1, output1));
1007   EXPECT_EQ(output1, "30313233");
1008
1009   fbstring input2 = "abcdefg";
1010   input2[1] = 0;
1011   input2[3] = 0xff;
1012   input2[5] = 0xb6;
1013   fbstring output2;
1014   EXPECT_TRUE(hexlify(input2, output2));
1015   EXPECT_EQ(output2, "610063ff65b667");
1016 }
1017
1018 TEST(String, unhexlify) {
1019   string input1 = "30313233";
1020   string output1;
1021   EXPECT_TRUE(unhexlify(input1, output1));
1022   EXPECT_EQ(output1, "0123");
1023
1024   fbstring input2 = "610063ff65b667";
1025   fbstring output2;
1026   EXPECT_TRUE(unhexlify(input2, output2));
1027   EXPECT_EQ(output2.size(), 7);
1028   EXPECT_EQ(output2[0], 'a');
1029   EXPECT_EQ(output2[1], 0);
1030   EXPECT_EQ(output2[2], 'c');
1031   EXPECT_EQ(output2[3] & 0xff, 0xff);
1032   EXPECT_EQ(output2[4], 'e');
1033   EXPECT_EQ(output2[5] & 0xff, 0xb6);
1034   EXPECT_EQ(output2[6], 'g');
1035
1036   string input3 = "x";
1037   string output3;
1038   EXPECT_FALSE(unhexlify(input3, output3));
1039
1040   string input4 = "xy";
1041   string output4;
1042   EXPECT_FALSE(unhexlify(input4, output4));
1043 }
1044
1045 TEST(String, backslashify) {
1046   EXPECT_EQ("abc", string("abc"));
1047   EXPECT_EQ("abc", backslashify(string("abc")));
1048   EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
1049   EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
1050   EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
1051 }
1052
1053 TEST(String, humanify) {
1054   // Simple cases; output is obvious.
1055   EXPECT_EQ("abc", humanify(string("abc")));
1056   EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
1057   EXPECT_EQ("0xff", humanify(string("\xff")));
1058   EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
1059   EXPECT_EQ("abc\\b", humanify(string("abc\b")));
1060   EXPECT_EQ("0x00", humanify(string(1, '\0')));
1061   EXPECT_EQ("0x0000", humanify(string(2, '\0')));
1062
1063
1064   // Mostly printable, so backslash!  80, 60, and 40% printable, respectively
1065   EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
1066   EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
1067   EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
1068
1069   // 20% printable, and the printable portion isn't the prefix; hexify!
1070   EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
1071
1072   // Same as previous, except swap first two chars; prefix is
1073   // printable and within the threshold, so backslashify.
1074   EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
1075
1076   // Just too much unprintable; hex, despite prefix.
1077   EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
1078 }
1079
1080 namespace {
1081
1082 /**
1083  * Copy bytes from src to somewhere in the buffer referenced by dst. The
1084  * actual starting position of the copy will be the first address in the
1085  * destination buffer whose address mod 8 is equal to the src address mod 8.
1086  * The caller is responsible for ensuring that the destination buffer has
1087  * enough extra space to accommodate the shifted copy.
1088  */
1089 char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
1090   const char* originalDst = dst;
1091   size_t dstOffset = size_t(dst) & 0x7;
1092   size_t srcOffset = size_t(src) & 0x7;
1093   while (dstOffset != srcOffset) {
1094     dst++;
1095     dstOffset++;
1096     dstOffset &= 0x7;
1097   }
1098   CHECK(dst <= originalDst + 7);
1099   CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
1100   memcpy(dst, src, length);
1101   return dst;
1102 }
1103
1104 void testToLowerAscii(Range<const char*> src) {
1105   // Allocate extra space so we can make copies that start at the
1106   // same alignment (byte, word, quadword, etc) as the source buffer.
1107   char controlBuf[src.size() + 7];
1108   char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
1109
1110   char testBuf[src.size() + 7];
1111   char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
1112
1113   for (size_t i = 0; i < src.size(); i++) {
1114     control[i] = tolower(control[i]);
1115   }
1116   toLowerAscii(test, src.size());
1117   for (size_t i = 0; i < src.size(); i++) {
1118     EXPECT_EQ(control[i], test[i]);
1119   }
1120 }
1121
1122 } // anon namespace
1123
1124 TEST(String, toLowerAsciiAligned) {
1125   static const size_t kSize = 256;
1126   char input[kSize];
1127   for (size_t i = 0; i < kSize; i++) {
1128     input[i] = (char)(i & 0xff);
1129   }
1130   testToLowerAscii(Range<const char*>(input, kSize));
1131 }
1132
1133 TEST(String, toLowerAsciiUnaligned) {
1134   static const size_t kSize = 256;
1135   char input[kSize];
1136   for (size_t i = 0; i < kSize; i++) {
1137     input[i] = (char)(i & 0xff);
1138   }
1139   // Test input buffers of several lengths to exercise all the
1140   // cases: buffer at the start/middle/end of an aligned block, plus
1141   // buffers that span multiple aligned blocks.  The longest test input
1142   // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
1143   // + 4 32-bit aligned + 3 unaligned = 22 bytes.
1144   for (size_t length = 1; length < 23; length++) {
1145     for (size_t offset = 0; offset + length <= kSize; offset++) {
1146       testToLowerAscii(Range<const char*>(input + offset, length));
1147     }
1148   }
1149 }
1150
1151 //////////////////////////////////////////////////////////////////////
1152
1153 BENCHMARK(splitOnSingleChar, iters) {
1154   static const std::string line = "one:two:three:four";
1155   for (int i = 0; i < iters << 4; ++i) {
1156     std::vector<StringPiece> pieces;
1157     folly::split(':', line, pieces);
1158   }
1159 }
1160
1161 BENCHMARK(splitOnSingleCharFixed, iters) {
1162   static const std::string line = "one:two:three:four";
1163   for (int i = 0; i < iters << 4; ++i) {
1164     StringPiece a, b, c, d;
1165     folly::split(':', line, a, b, c, d);
1166   }
1167 }
1168
1169 BENCHMARK(splitOnSingleCharFixedAllowExtra, iters) {
1170   static const std::string line = "one:two:three:four";
1171   for (int i = 0; i < iters << 4; ++i) {
1172     StringPiece a, b, c, d;
1173     folly::split<false>(':', line, a, b, c, d);
1174   }
1175 }
1176
1177 BENCHMARK(splitStr, iters) {
1178   static const std::string line = "one-*-two-*-three-*-four";
1179   for (int i = 0; i < iters << 4; ++i) {
1180     std::vector<StringPiece> pieces;
1181     folly::split("-*-", line, pieces);
1182   }
1183 }
1184
1185 BENCHMARK(splitStrFixed, iters) {
1186   static const std::string line = "one-*-two-*-three-*-four";
1187   for (int i = 0; i < iters << 4; ++i) {
1188     StringPiece a, b, c, d;
1189     folly::split("-*-", line, a, b, c, d);
1190   }
1191 }
1192
1193 BENCHMARK(boost_splitOnSingleChar, iters) {
1194   static const std::string line = "one:two:three:four";
1195   bool(*pred)(char) = [] (char c) -> bool { return c == ':'; };
1196   for (int i = 0; i < iters << 4; ++i) {
1197     std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
1198     boost::split(pieces, line, pred);
1199   }
1200 }
1201
1202 BENCHMARK(joinCharStr, iters) {
1203   static const std::vector<std::string> input = {
1204     "one", "two", "three", "four", "five", "six", "seven" };
1205   for (int i = 0; i < iters << 4; ++i) {
1206     std::string output;
1207     folly::join(':', input, output);
1208   }
1209 }
1210
1211 BENCHMARK(joinStrStr, iters) {
1212   static const std::vector<std::string> input = {
1213     "one", "two", "three", "four", "five", "six", "seven" };
1214   for (int i = 0; i < iters << 4; ++i) {
1215     std::string output;
1216     folly::join(":", input, output);
1217   }
1218 }
1219
1220 BENCHMARK(joinInt, iters) {
1221   static const auto input = {
1222     123, 456, 78910, 1112, 1314, 151, 61718 };
1223   for (int i = 0; i < iters << 4; ++i) {
1224     std::string output;
1225     folly::join(":", input, output);
1226   }
1227 }
1228
1229 int main(int argc, char *argv[]) {
1230   testing::InitGoogleTest(&argc, argv);
1231   gflags::ParseCommandLineFlags(&argc, &argv, true);
1232   auto ret = RUN_ALL_TESTS();
1233   if (!ret) {
1234     initBenchmark();
1235     if (FLAGS_benchmark) {
1236       folly::runBenchmarks();
1237     }
1238   }
1239   return ret;
1240 }