Use folly::Expected to implement folly::tryTo, a non-throwing variant of folly::to
[folly.git] / folly / test / StringTest.cpp
1 /*
2  * Copyright 2016 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 <boost/regex.hpp>
20 #include <gtest/gtest.h>
21
22 #include <folly/Array.h>
23
24 using namespace folly;
25 using namespace std;
26
27 TEST(StringPrintf, BasicTest) {
28   EXPECT_EQ("abc", stringPrintf("%s", "abc"));
29   EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
30   EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
31   EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
32
33   EXPECT_EQ("abc", stringPrintf("abc"));
34 }
35
36 TEST(StringPrintf, NumericFormats) {
37   EXPECT_EQ("12", stringPrintf("%d", 12));
38   EXPECT_EQ("2000000000", stringPrintf("%ld", 2000000000UL));
39   EXPECT_EQ("2000000000", stringPrintf("%ld", 2000000000L));
40   EXPECT_EQ("-2000000000", stringPrintf("%ld", -2000000000L));
41   EXPECT_EQ("5000000000", stringPrintf("%lld", 5000000000ULL));
42   EXPECT_EQ("5000000000", stringPrintf("%lld", 5000000000LL));
43   EXPECT_EQ("-5000000000", stringPrintf("%lld", -5000000000LL));
44   EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
45   EXPECT_EQ("-1", stringPrintf("%" PRId64, 0xffffffffffffffff));
46   EXPECT_EQ("-1", stringPrintf("%" PRId64, 0xffffffffffffffffUL));
47
48   EXPECT_EQ("7.7", stringPrintf("%1.1f", 7.7));
49   EXPECT_EQ("7.7", stringPrintf("%1.1lf", 7.7));
50   EXPECT_EQ("7.70000000000000018",
51             stringPrintf("%.17f", 7.7));
52   EXPECT_EQ("7.70000000000000018",
53             stringPrintf("%.17lf", 7.7));
54 }
55
56 TEST(StringPrintf, Appending) {
57   string s;
58   stringAppendf(&s, "a%s", "b");
59   stringAppendf(&s, "%c", 'c');
60   EXPECT_EQ(s, "abc");
61   stringAppendf(&s, " %d", 123);
62   EXPECT_EQ(s, "abc 123");
63 }
64
65 void vprintfCheck(const char* expected, const char* fmt, ...) {
66   va_list apOrig;
67   va_start(apOrig, fmt);
68   SCOPE_EXIT {
69     va_end(apOrig);
70   };
71   va_list ap;
72   va_copy(ap, apOrig);
73   SCOPE_EXIT {
74     va_end(ap);
75   };
76
77   // Check both APIs for calling stringVPrintf()
78   EXPECT_EQ(expected, stringVPrintf(fmt, ap));
79   va_end(ap);
80   va_copy(ap, apOrig);
81
82   std::string out;
83   stringVPrintf(&out, fmt, ap);
84   va_end(ap);
85   va_copy(ap, apOrig);
86   EXPECT_EQ(expected, out);
87
88   // Check stringVAppendf() as well
89   std::string prefix = "foobar";
90   out = prefix;
91   EXPECT_EQ(prefix + expected, stringVAppendf(&out, fmt, ap));
92   va_end(ap);
93   va_copy(ap, apOrig);
94 }
95
96 void vprintfError(const char* fmt, ...) {
97   va_list ap;
98   va_start(ap, fmt);
99   SCOPE_EXIT {
100     va_end(ap);
101   };
102
103   // OSX's sprintf family does not return a negative number on a bad format
104   // string, but Linux does. It's unclear to me which behavior is more
105   // correct.
106 #ifdef HAVE_VSNPRINTF_ERRORS
107   EXPECT_THROW({stringVPrintf(fmt, ap);},
108                std::runtime_error);
109 #endif
110 }
111
112 TEST(StringPrintf, VPrintf) {
113   vprintfCheck("foo", "%s", "foo");
114   vprintfCheck("long string requiring reallocation 1 2 3 0x12345678",
115                "%s %s %d %d %d %#x",
116                "long string", "requiring reallocation", 1, 2, 3, 0x12345678);
117   vprintfError("bogus%", "foo");
118 }
119
120 TEST(StringPrintf, VariousSizes) {
121   // Test a wide variety of output sizes, making sure to cross the
122   // vsnprintf buffer boundary implementation detail.
123   for (int i = 0; i < 4096; ++i) {
124     string expected(i + 1, 'a');
125     expected = "X" + expected + "X";
126     string result = stringPrintf("%s", expected.c_str());
127     EXPECT_EQ(expected.size(), result.size());
128     EXPECT_EQ(expected, result);
129   }
130
131   EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
132             stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
133                          "%d%d%d%d%d%d%d%d%d%d%dxyz",
134                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
135                          17, 18, 19, 20, 21, 22, 23, 24, 25));
136 }
137
138 TEST(StringPrintf, oldStringPrintfTests) {
139   EXPECT_EQ(string("a/b/c/d"),
140             stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
141
142   EXPECT_EQ(string("    5    10"),
143             stringPrintf("%5d %5d", 5, 10));
144
145   // check printing w/ a big buffer
146   for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
147     string a(size, 'z');
148     string b = stringPrintf("%s", a.c_str());
149     EXPECT_EQ(a.size(), b.size());
150   }
151 }
152
153 TEST(StringPrintf, oldStringAppendf) {
154   string s = "hello";
155   stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
156   EXPECT_EQ(string("helloa/b/c/d"), s);
157 }
158
159 TEST(Escape, cEscape) {
160   EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
161   EXPECT_EQ("hello \\\\world\\\" goodbye",
162             cEscape<std::string>("hello \\world\" goodbye"));
163   EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
164   EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
165 }
166
167 TEST(Escape, cUnescape) {
168   EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
169   EXPECT_EQ("hello \\world\" goodbye",
170             cUnescape<std::string>("hello \\\\world\\\" goodbye"));
171   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
172   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
173   EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
174   EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
175   EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
176
177   EXPECT_THROW({cUnescape<std::string>("hello\\");},
178                std::invalid_argument);
179   EXPECT_THROW({cUnescape<std::string>("hello\\x");},
180                std::invalid_argument);
181   EXPECT_THROW({cUnescape<std::string>("hello\\q");},
182                std::invalid_argument);
183 }
184
185 TEST(Escape, uriEscape) {
186   EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
187   EXPECT_EQ("hello%2c%20/world", uriEscape<std::string>("hello, /world",
188                                                         UriEscapeMode::PATH));
189   EXPECT_EQ("hello%2c+%2fworld", uriEscape<std::string>("hello, /world",
190                                                         UriEscapeMode::QUERY));
191   EXPECT_EQ(
192     "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~",
193     uriEscape<std::string>(
194       "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~")
195   );
196 }
197
198 TEST(Escape, uriUnescape) {
199   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
200   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
201   EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
202   EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c+%2fworld",
203                                                       UriEscapeMode::QUERY));
204   EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
205   EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
206   EXPECT_THROW({uriUnescape<std::string>("hello%");},
207                std::invalid_argument);
208   EXPECT_THROW({uriUnescape<std::string>("hello%2");},
209                std::invalid_argument);
210   EXPECT_THROW({uriUnescape<std::string>("hello%2g");},
211                std::invalid_argument);
212 }
213
214 namespace {
215 void expectPrintable(StringPiece s) {
216   for (char c : s) {
217     EXPECT_LE(32, c);
218     EXPECT_GE(127, c);
219   }
220 }
221 }  // namespace
222
223 TEST(Escape, uriEscapeAllCombinations) {
224   char c[3];
225   c[2] = '\0';
226   StringPiece in(c, 2);
227   fbstring tmp;
228   fbstring out;
229   for (int i = 0; i < 256; ++i) {
230     c[0] = i;
231     for (int j = 0; j < 256; ++j) {
232       c[1] = j;
233       tmp.clear();
234       out.clear();
235       uriEscape(in, tmp);
236       expectPrintable(tmp);
237       uriUnescape(tmp, out);
238       EXPECT_EQ(in, out);
239     }
240   }
241 }
242
243 namespace {
244 bool isHex(int v) {
245   return ((v >= '0' && v <= '9') ||
246           (v >= 'A' && v <= 'F') ||
247           (v >= 'a' && v <= 'f'));
248 }
249 }  // namespace
250
251 TEST(Escape, uriUnescapePercentDecoding) {
252   char c[4] = {'%', '\0', '\0', '\0'};
253   StringPiece in(c, 3);
254   fbstring out;
255   unsigned int expected = 0;
256   for (int i = 0; i < 256; ++i) {
257     c[1] = i;
258     for (int j = 0; j < 256; ++j) {
259       c[2] = j;
260       if (isHex(i) && isHex(j)) {
261         out.clear();
262         uriUnescape(in, out);
263         EXPECT_EQ(1, out.size());
264         EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
265         unsigned char v = out[0];
266         EXPECT_EQ(expected, v);
267       } else {
268         EXPECT_THROW({uriUnescape(in, out);}, std::invalid_argument);
269       }
270     }
271   }
272 }
273
274 namespace {
275
276 double pow2(int exponent) {
277   return double(int64_t(1) << exponent);
278 }
279
280 }  // namespace
281 struct PrettyTestCase{
282   std::string prettyString;
283   double realValue;
284   PrettyType prettyType;
285 };
286
287 PrettyTestCase prettyTestCases[] =
288 {
289   {string("8.53e+07 s "), 85.3e6,  PRETTY_TIME},
290   {string("8.53e+07 s "), 85.3e6,  PRETTY_TIME},
291   {string("85.3 ms"), 85.3e-3,  PRETTY_TIME},
292   {string("85.3 us"), 85.3e-6,  PRETTY_TIME},
293   {string("85.3 ns"), 85.3e-9,  PRETTY_TIME},
294   {string("85.3 ps"), 85.3e-12,  PRETTY_TIME},
295   {string("8.53e-14 s "), 85.3e-15,  PRETTY_TIME},
296
297   {string("0 s "), 0,  PRETTY_TIME},
298   {string("1 s "), 1.0,  PRETTY_TIME},
299   {string("1 ms"), 1.0e-3,  PRETTY_TIME},
300   {string("1 us"), 1.0e-6,  PRETTY_TIME},
301   {string("1 ns"), 1.0e-9,  PRETTY_TIME},
302   {string("1 ps"), 1.0e-12,  PRETTY_TIME},
303
304   // check bytes printing
305   {string("853 B "), 853.,  PRETTY_BYTES},
306   {string("833 kB"), 853.e3,  PRETTY_BYTES},
307   {string("813.5 MB"), 853.e6,  PRETTY_BYTES},
308   {string("7.944 GB"), 8.53e9,  PRETTY_BYTES},
309   {string("794.4 GB"), 853.e9,  PRETTY_BYTES},
310   {string("775.8 TB"), 853.e12,  PRETTY_BYTES},
311
312   {string("0 B "), 0,  PRETTY_BYTES},
313   {string("1 B "), pow2(0),  PRETTY_BYTES},
314   {string("1 kB"), pow2(10),  PRETTY_BYTES},
315   {string("1 MB"), pow2(20),  PRETTY_BYTES},
316   {string("1 GB"), pow2(30),  PRETTY_BYTES},
317   {string("1 TB"), pow2(40),  PRETTY_BYTES},
318
319   {string("853 B  "), 853.,  PRETTY_BYTES_IEC},
320   {string("833 KiB"), 853.e3,  PRETTY_BYTES_IEC},
321   {string("813.5 MiB"), 853.e6,  PRETTY_BYTES_IEC},
322   {string("7.944 GiB"), 8.53e9,  PRETTY_BYTES_IEC},
323   {string("794.4 GiB"), 853.e9,  PRETTY_BYTES_IEC},
324   {string("775.8 TiB"), 853.e12,  PRETTY_BYTES_IEC},
325
326   {string("0 B  "), 0,  PRETTY_BYTES_IEC},
327   {string("1 B  "), pow2(0),  PRETTY_BYTES_IEC},
328   {string("1 KiB"), pow2(10),  PRETTY_BYTES_IEC},
329   {string("1 MiB"), pow2(20),  PRETTY_BYTES_IEC},
330   {string("1 GiB"), pow2(30),  PRETTY_BYTES_IEC},
331   {string("1 TiB"), pow2(40),  PRETTY_BYTES_IEC},
332
333   // check bytes metric printing
334   {string("853 B "), 853.,  PRETTY_BYTES_METRIC},
335   {string("853 kB"), 853.e3,  PRETTY_BYTES_METRIC},
336   {string("853 MB"), 853.e6,  PRETTY_BYTES_METRIC},
337   {string("8.53 GB"), 8.53e9,  PRETTY_BYTES_METRIC},
338   {string("853 GB"), 853.e9,  PRETTY_BYTES_METRIC},
339   {string("853 TB"), 853.e12,  PRETTY_BYTES_METRIC},
340
341   {string("0 B "), 0,  PRETTY_BYTES_METRIC},
342   {string("1 B "), 1.0,  PRETTY_BYTES_METRIC},
343   {string("1 kB"), 1.0e+3,  PRETTY_BYTES_METRIC},
344   {string("1 MB"), 1.0e+6,  PRETTY_BYTES_METRIC},
345
346   {string("1 GB"), 1.0e+9,  PRETTY_BYTES_METRIC},
347   {string("1 TB"), 1.0e+12,  PRETTY_BYTES_METRIC},
348
349   // check metric-units (powers of 1000) printing
350   {string("853  "), 853.,  PRETTY_UNITS_METRIC},
351   {string("853 k"), 853.e3,  PRETTY_UNITS_METRIC},
352   {string("853 M"), 853.e6,  PRETTY_UNITS_METRIC},
353   {string("8.53 bil"), 8.53e9,  PRETTY_UNITS_METRIC},
354   {string("853 bil"), 853.e9,  PRETTY_UNITS_METRIC},
355   {string("853 tril"), 853.e12,  PRETTY_UNITS_METRIC},
356
357   // check binary-units (powers of 1024) printing
358   {string("0  "), 0,  PRETTY_UNITS_BINARY},
359   {string("1  "), pow2(0),  PRETTY_UNITS_BINARY},
360   {string("1 k"), pow2(10),  PRETTY_UNITS_BINARY},
361   {string("1 M"), pow2(20),  PRETTY_UNITS_BINARY},
362   {string("1 G"), pow2(30),  PRETTY_UNITS_BINARY},
363   {string("1 T"), pow2(40),  PRETTY_UNITS_BINARY},
364
365   {string("1023  "), pow2(10) - 1,  PRETTY_UNITS_BINARY},
366   {string("1024 k"), pow2(20) - 1,  PRETTY_UNITS_BINARY},
367   {string("1024 M"), pow2(30) - 1,  PRETTY_UNITS_BINARY},
368   {string("1024 G"), pow2(40) - 1,  PRETTY_UNITS_BINARY},
369
370   {string("0   "), 0,  PRETTY_UNITS_BINARY_IEC},
371   {string("1   "), pow2(0),  PRETTY_UNITS_BINARY_IEC},
372   {string("1 Ki"), pow2(10),  PRETTY_UNITS_BINARY_IEC},
373   {string("1 Mi"), pow2(20),  PRETTY_UNITS_BINARY_IEC},
374   {string("1 Gi"), pow2(30),  PRETTY_UNITS_BINARY_IEC},
375   {string("1 Ti"), pow2(40),  PRETTY_UNITS_BINARY_IEC},
376
377   {string("1023   "), pow2(10) - 1,  PRETTY_UNITS_BINARY_IEC},
378   {string("1024 Ki"), pow2(20) - 1,  PRETTY_UNITS_BINARY_IEC},
379   {string("1024 Mi"), pow2(30) - 1,  PRETTY_UNITS_BINARY_IEC},
380   {string("1024 Gi"), pow2(40) - 1,  PRETTY_UNITS_BINARY_IEC},
381
382   //check border SI cases
383
384   {string("1 Y"), 1e24,  PRETTY_SI},
385   {string("10 Y"), 1e25,  PRETTY_SI},
386   {string("1 y"), 1e-24,  PRETTY_SI},
387   {string("10 y"), 1e-23,  PRETTY_SI},
388
389   // check that negative values work
390   {string("-85.3 s "), -85.3,  PRETTY_TIME},
391   {string("-85.3 ms"), -85.3e-3,  PRETTY_TIME},
392   {string("-85.3 us"), -85.3e-6,  PRETTY_TIME},
393   {string("-85.3 ns"), -85.3e-9,  PRETTY_TIME},
394   // end of test
395   {string("endoftest"), 0, PRETTY_NUM_TYPES}
396 };
397
398 TEST(PrettyPrint, Basic) {
399   for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
400     const PrettyTestCase& prettyTest = prettyTestCases[i];
401     EXPECT_EQ(prettyTest.prettyString,
402               prettyPrint(prettyTest.realValue, prettyTest.prettyType));
403   }
404 }
405
406 TEST(PrettyToDouble, Basic) {
407   // check manually created tests
408   for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
409     PrettyTestCase testCase = prettyTestCases[i];
410     PrettyType formatType = testCase.prettyType;
411     double x = testCase.realValue;
412     std::string testString = testCase.prettyString;
413     double recoveredX = 0;
414     try{
415       recoveredX = prettyToDouble(testString, formatType);
416     } catch (const std::range_error& ex) {
417       EXPECT_TRUE(false) << testCase.prettyString << " -> " << ex.what();
418     }
419     double relativeError = fabs(x) < 1e-5 ? (x-recoveredX) :
420                                             (x - recoveredX) / x;
421     EXPECT_NEAR(0, relativeError, 1e-3);
422   }
423
424   // checks for compatibility with prettyPrint over the whole parameter space
425   for (int i = 0 ; i < PRETTY_NUM_TYPES; ++i){
426     PrettyType formatType = static_cast<PrettyType>(i);
427     for (double x = 1e-18; x < 1e40; x *= 1.9){
428       bool addSpace = static_cast<PrettyType> (i) == PRETTY_SI;
429       for (int it = 0; it < 2; ++it, addSpace = true){
430         double recoveredX = 0;
431         try{
432           recoveredX = prettyToDouble(prettyPrint(x, formatType, addSpace),
433                                              formatType);
434         } catch (std::range_error &ex){
435           EXPECT_TRUE(false);
436         }
437         double relativeError = (x - recoveredX) / x;
438         EXPECT_NEAR(0, relativeError, 1e-3);
439       }
440     }
441   }
442
443   // check for incorrect values
444   EXPECT_THROW(prettyToDouble("10Mx", PRETTY_SI), std::range_error);
445   EXPECT_THROW(prettyToDouble("10 Mx", PRETTY_SI), std::range_error);
446   EXPECT_THROW(prettyToDouble("10 M x", PRETTY_SI), std::range_error);
447
448   StringPiece testString = "10Mx";
449   EXPECT_DOUBLE_EQ(prettyToDouble(&testString, PRETTY_UNITS_METRIC), 10e6);
450   EXPECT_EQ(testString, "x");
451 }
452
453 TEST(PrettyPrint, HexDump) {
454   std::string a("abc\x00\x02\xa0", 6);  // embedded NUL
455   EXPECT_EQ(
456     "00000000  61 62 63 00 02 a0                                 "
457     "|abc...          |\n",
458     hexDump(a.data(), a.size()));
459
460   a = "abcdefghijklmnopqrstuvwxyz";
461   EXPECT_EQ(
462     "00000000  61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  "
463     "|abcdefghijklmnop|\n"
464     "00000010  71 72 73 74 75 76 77 78  79 7a                    "
465     "|qrstuvwxyz      |\n",
466     hexDump(a.data(), a.size()));
467 }
468
469 TEST(System, errnoStr) {
470   errno = EACCES;
471   EXPECT_EQ(EACCES, errno);
472   EXPECT_EQ(EACCES, errno);  // twice to make sure EXPECT_EQ doesn't change it
473
474   fbstring expected = strerror(ENOENT);
475
476   errno = EACCES;
477   EXPECT_EQ(expected, errnoStr(ENOENT));
478   // Ensure that errno isn't changed
479   EXPECT_EQ(EACCES, errno);
480
481   // Per POSIX, all errno values are positive, so -1 is invalid
482   errnoStr(-1);
483
484   // Ensure that errno isn't changed
485   EXPECT_EQ(EACCES, errno);
486 }
487
488 namespace {
489
490 template<template<class,class> class VectorType>
491 void splitTest() {
492   VectorType<string,std::allocator<string> > parts;
493
494   folly::split(',', "a,b,c", parts);
495   EXPECT_EQ(parts.size(), 3);
496   EXPECT_EQ(parts[0], "a");
497   EXPECT_EQ(parts[1], "b");
498   EXPECT_EQ(parts[2], "c");
499   parts.clear();
500
501   folly::split(',', StringPiece("a,b,c"), parts);
502   EXPECT_EQ(parts.size(), 3);
503   EXPECT_EQ(parts[0], "a");
504   EXPECT_EQ(parts[1], "b");
505   EXPECT_EQ(parts[2], "c");
506   parts.clear();
507
508   folly::split(',', string("a,b,c"), parts);
509   EXPECT_EQ(parts.size(), 3);
510   EXPECT_EQ(parts[0], "a");
511   EXPECT_EQ(parts[1], "b");
512   EXPECT_EQ(parts[2], "c");
513   parts.clear();
514
515   folly::split(',', "a,,c", parts);
516   EXPECT_EQ(parts.size(), 3);
517   EXPECT_EQ(parts[0], "a");
518   EXPECT_EQ(parts[1], "");
519   EXPECT_EQ(parts[2], "c");
520   parts.clear();
521
522   folly::split(',', string("a,,c"), parts);
523   EXPECT_EQ(parts.size(), 3);
524   EXPECT_EQ(parts[0], "a");
525   EXPECT_EQ(parts[1], "");
526   EXPECT_EQ(parts[2], "c");
527   parts.clear();
528
529   folly::split(',', "a,,c", parts, true);
530   EXPECT_EQ(parts.size(), 2);
531   EXPECT_EQ(parts[0], "a");
532   EXPECT_EQ(parts[1], "c");
533   parts.clear();
534
535   folly::split(',', string("a,,c"), parts, true);
536   EXPECT_EQ(parts.size(), 2);
537   EXPECT_EQ(parts[0], "a");
538   EXPECT_EQ(parts[1], "c");
539   parts.clear();
540
541   folly::split(',', string(",,a,,c,,,"), parts, true);
542   EXPECT_EQ(parts.size(), 2);
543   EXPECT_EQ(parts[0], "a");
544   EXPECT_EQ(parts[1], "c");
545   parts.clear();
546
547   // test multiple split w/o clear
548   folly::split(',', ",,a,,c,,,", parts, true);
549   EXPECT_EQ(parts.size(), 2);
550   EXPECT_EQ(parts[0], "a");
551   EXPECT_EQ(parts[1], "c");
552   folly::split(',', ",,a,,c,,,", parts, true);
553   EXPECT_EQ(parts.size(), 4);
554   EXPECT_EQ(parts[2], "a");
555   EXPECT_EQ(parts[3], "c");
556   parts.clear();
557
558   // test splits that with multi-line delimiter
559   folly::split("ab", "dabcabkdbkab", parts, true);
560   EXPECT_EQ(parts.size(), 3);
561   EXPECT_EQ(parts[0], "d");
562   EXPECT_EQ(parts[1], "c");
563   EXPECT_EQ(parts[2], "kdbk");
564   parts.clear();
565
566   // test last part is shorter than the delimiter
567   folly::split("bc", "abcd", parts, true);
568   EXPECT_EQ(parts.size(), 2);
569   EXPECT_EQ(parts[0], "a");
570   EXPECT_EQ(parts[1], "d");
571   parts.clear();
572
573   string orig = "ab2342asdfv~~!";
574   folly::split("", orig, parts, true);
575   EXPECT_EQ(parts.size(), 1);
576   EXPECT_EQ(parts[0], orig);
577   parts.clear();
578
579   folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
580   EXPECT_EQ(parts.size(), 1);
581   EXPECT_EQ(parts[0], "asfds");
582   parts.clear();
583
584   folly::split("a", "", parts, true);
585   EXPECT_EQ(parts.size(), 0);
586   parts.clear();
587
588   folly::split("a", "", parts);
589   EXPECT_EQ(parts.size(), 1);
590   EXPECT_EQ(parts[0], "");
591   parts.clear();
592
593   folly::split("a", StringPiece(), parts, true);
594   EXPECT_EQ(parts.size(), 0);
595   parts.clear();
596
597   folly::split("a", StringPiece(), parts);
598   EXPECT_EQ(parts.size(), 1);
599   EXPECT_EQ(parts[0], "");
600   parts.clear();
601
602   folly::split("a", "abcdefg", parts, true);
603   EXPECT_EQ(parts.size(), 1);
604   EXPECT_EQ(parts[0], "bcdefg");
605   parts.clear();
606
607   orig = "All, , your base, are , , belong to us";
608   folly::split(", ", orig, parts, true);
609   EXPECT_EQ(parts.size(), 4);
610   EXPECT_EQ(parts[0], "All");
611   EXPECT_EQ(parts[1], "your base");
612   EXPECT_EQ(parts[2], "are ");
613   EXPECT_EQ(parts[3], "belong to us");
614   parts.clear();
615   folly::split(", ", orig, parts);
616   EXPECT_EQ(parts.size(), 6);
617   EXPECT_EQ(parts[0], "All");
618   EXPECT_EQ(parts[1], "");
619   EXPECT_EQ(parts[2], "your base");
620   EXPECT_EQ(parts[3], "are ");
621   EXPECT_EQ(parts[4], "");
622   EXPECT_EQ(parts[5], "belong to us");
623   parts.clear();
624
625   orig = ", Facebook, rul,es!, ";
626   folly::split(", ", orig, parts, true);
627   EXPECT_EQ(parts.size(), 2);
628   EXPECT_EQ(parts[0], "Facebook");
629   EXPECT_EQ(parts[1], "rul,es!");
630   parts.clear();
631   folly::split(", ", orig, parts);
632   EXPECT_EQ(parts.size(), 4);
633   EXPECT_EQ(parts[0], "");
634   EXPECT_EQ(parts[1], "Facebook");
635   EXPECT_EQ(parts[2], "rul,es!");
636   EXPECT_EQ(parts[3], "");
637 }
638
639 template<template<class,class> class VectorType>
640 void piecesTest() {
641   VectorType<StringPiece,std::allocator<StringPiece> > pieces;
642   VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
643
644   folly::split(',', "a,b,c", pieces);
645   EXPECT_EQ(pieces.size(), 3);
646   EXPECT_EQ(pieces[0], "a");
647   EXPECT_EQ(pieces[1], "b");
648   EXPECT_EQ(pieces[2], "c");
649
650   pieces.clear();
651
652   folly::split(',', "a,,c", pieces);
653   EXPECT_EQ(pieces.size(), 3);
654   EXPECT_EQ(pieces[0], "a");
655   EXPECT_EQ(pieces[1], "");
656   EXPECT_EQ(pieces[2], "c");
657   pieces.clear();
658
659   folly::split(',', "a,,c", pieces, true);
660   EXPECT_EQ(pieces.size(), 2);
661   EXPECT_EQ(pieces[0], "a");
662   EXPECT_EQ(pieces[1], "c");
663   pieces.clear();
664
665   folly::split(',', ",,a,,c,,,", pieces, true);
666   EXPECT_EQ(pieces.size(), 2);
667   EXPECT_EQ(pieces[0], "a");
668   EXPECT_EQ(pieces[1], "c");
669   pieces.clear();
670
671   // test multiple split w/o clear
672   folly::split(',', ",,a,,c,,,", pieces, true);
673   EXPECT_EQ(pieces.size(), 2);
674   EXPECT_EQ(pieces[0], "a");
675   EXPECT_EQ(pieces[1], "c");
676   folly::split(',', ",,a,,c,,,", pieces, true);
677   EXPECT_EQ(pieces.size(), 4);
678   EXPECT_EQ(pieces[2], "a");
679   EXPECT_EQ(pieces[3], "c");
680   pieces.clear();
681
682   // test multiple split rounds
683   folly::split(",", "a_b,c_d", pieces);
684   EXPECT_EQ(pieces.size(), 2);
685   EXPECT_EQ(pieces[0], "a_b");
686   EXPECT_EQ(pieces[1], "c_d");
687   folly::split("_", pieces[0], pieces2);
688   EXPECT_EQ(pieces2.size(), 2);
689   EXPECT_EQ(pieces2[0], "a");
690   EXPECT_EQ(pieces2[1], "b");
691   pieces2.clear();
692   folly::split("_", pieces[1], pieces2);
693   EXPECT_EQ(pieces2.size(), 2);
694   EXPECT_EQ(pieces2[0], "c");
695   EXPECT_EQ(pieces2[1], "d");
696   pieces.clear();
697   pieces2.clear();
698
699   // test splits that with multi-line delimiter
700   folly::split("ab", "dabcabkdbkab", pieces, true);
701   EXPECT_EQ(pieces.size(), 3);
702   EXPECT_EQ(pieces[0], "d");
703   EXPECT_EQ(pieces[1], "c");
704   EXPECT_EQ(pieces[2], "kdbk");
705   pieces.clear();
706
707   string orig = "ab2342asdfv~~!";
708   folly::split("", orig.c_str(), pieces, true);
709   EXPECT_EQ(pieces.size(), 1);
710   EXPECT_EQ(pieces[0], orig);
711   pieces.clear();
712
713   folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
714   EXPECT_EQ(pieces.size(), 1);
715   EXPECT_EQ(pieces[0], "asfds");
716   pieces.clear();
717
718   folly::split("a", "", pieces, true);
719   EXPECT_EQ(pieces.size(), 0);
720   pieces.clear();
721
722   folly::split("a", "", pieces);
723   EXPECT_EQ(pieces.size(), 1);
724   EXPECT_EQ(pieces[0], "");
725   pieces.clear();
726
727   folly::split("a", "abcdefg", pieces, true);
728   EXPECT_EQ(pieces.size(), 1);
729   EXPECT_EQ(pieces[0], "bcdefg");
730   pieces.clear();
731
732   orig = "All, , your base, are , , belong to us";
733   folly::split(", ", orig, pieces, true);
734   EXPECT_EQ(pieces.size(), 4);
735   EXPECT_EQ(pieces[0], "All");
736   EXPECT_EQ(pieces[1], "your base");
737   EXPECT_EQ(pieces[2], "are ");
738   EXPECT_EQ(pieces[3], "belong to us");
739   pieces.clear();
740   folly::split(", ", orig, pieces);
741   EXPECT_EQ(pieces.size(), 6);
742   EXPECT_EQ(pieces[0], "All");
743   EXPECT_EQ(pieces[1], "");
744   EXPECT_EQ(pieces[2], "your base");
745   EXPECT_EQ(pieces[3], "are ");
746   EXPECT_EQ(pieces[4], "");
747   EXPECT_EQ(pieces[5], "belong to us");
748   pieces.clear();
749
750   orig = ", Facebook, rul,es!, ";
751   folly::split(", ", orig, pieces, true);
752   EXPECT_EQ(pieces.size(), 2);
753   EXPECT_EQ(pieces[0], "Facebook");
754   EXPECT_EQ(pieces[1], "rul,es!");
755   pieces.clear();
756   folly::split(", ", orig, pieces);
757   EXPECT_EQ(pieces.size(), 4);
758   EXPECT_EQ(pieces[0], "");
759   EXPECT_EQ(pieces[1], "Facebook");
760   EXPECT_EQ(pieces[2], "rul,es!");
761   EXPECT_EQ(pieces[3], "");
762   pieces.clear();
763
764   const char* str = "a,b";
765   folly::split(',', StringPiece(str), pieces);
766   EXPECT_EQ(pieces.size(), 2);
767   EXPECT_EQ(pieces[0], "a");
768   EXPECT_EQ(pieces[1], "b");
769   EXPECT_EQ(pieces[0].start(), str);
770   EXPECT_EQ(pieces[1].start(), str + 2);
771
772   std::set<StringPiece> unique;
773   folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
774     std::inserter(unique, unique.begin()), true);
775   EXPECT_EQ(unique.size(), 3);
776   if (unique.size() == 3) {
777     EXPECT_EQ(*unique.begin(), "asd");
778     EXPECT_EQ(*--unique.end(), "csd");
779   }
780
781   VectorType<fbstring,std::allocator<fbstring> > blah;
782   folly::split('-', "a-b-c-d-f-e", blah);
783   EXPECT_EQ(blah.size(), 6);
784 }
785
786 }
787
788 TEST(Split, split_vector) {
789   splitTest<std::vector>();
790 }
791 TEST(Split, split_fbvector) {
792   splitTest<folly::fbvector>();
793 }
794 TEST(Split, pieces_vector) {
795   piecesTest<std::vector>();
796 }
797 TEST(Split, pieces_fbvector) {
798   piecesTest<folly::fbvector>();
799 }
800
801 TEST(Split, fixed) {
802   StringPiece a, b, c, d;
803
804   EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
805   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
806   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
807   EXPECT_TRUE(folly::split<false>('.', "a", a));
808
809   EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
810   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
811   EXPECT_TRUE(folly::split('.', "a.b", a, b));
812   EXPECT_TRUE(folly::split('.', "a", a));
813
814   EXPECT_TRUE(folly::split<false>('.', "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<false>('.', "a.b", a, b, c));
819   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
820   EXPECT_EQ("a", a);
821   EXPECT_EQ("b.c", b);
822
823   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
824   EXPECT_EQ("a", a);
825   EXPECT_EQ("b", b);
826   EXPECT_EQ("c", c);
827   EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
828   EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
829
830   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
831   EXPECT_EQ("a", a);
832   EXPECT_EQ("b", b);
833   EXPECT_FALSE(folly::split<false>('.', "a", a, b));
834   EXPECT_TRUE(folly::split<false>('.', "a.b", a));
835   EXPECT_EQ("a.b", a);
836
837   EXPECT_TRUE(folly::split('.', "a.b", a, b));
838   EXPECT_EQ("a", a);
839   EXPECT_EQ("b", b);
840   EXPECT_FALSE(folly::split('.', "a", a, b));
841   EXPECT_FALSE(folly::split('.', "a.b", a));
842 }
843
844 TEST(Split, std_string_fixed) {
845   std::string a, b, c, d;
846
847   EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
848   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
849   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
850   EXPECT_TRUE(folly::split<false>('.', "a", a));
851
852   EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
853   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
854   EXPECT_TRUE(folly::split('.', "a.b", a, b));
855   EXPECT_TRUE(folly::split('.', "a", a));
856
857   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
858   EXPECT_EQ("a", a);
859   EXPECT_EQ("b", b);
860   EXPECT_EQ("c", c);
861   EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
862   EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
863   EXPECT_EQ("a", a);
864   EXPECT_EQ("b.c", b);
865
866   EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
867   EXPECT_EQ("a", a);
868   EXPECT_EQ("b", b);
869   EXPECT_EQ("c", c);
870   EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
871   EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
872
873   EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
874   EXPECT_EQ("a", a);
875   EXPECT_EQ("b", b);
876   EXPECT_FALSE(folly::split<false>('.', "a", a, b));
877   EXPECT_TRUE(folly::split<false>('.', "a.b", a));
878   EXPECT_EQ("a.b", a);
879
880   EXPECT_TRUE(folly::split('.', "a.b", a, b));
881   EXPECT_EQ("a", a);
882   EXPECT_EQ("b", b);
883   EXPECT_FALSE(folly::split('.', "a", a, b));
884   EXPECT_FALSE(folly::split('.', "a.b", a));
885 }
886
887 TEST(Split, fixed_convert) {
888   StringPiece a, d;
889   int b;
890   double c = 0;
891
892   EXPECT_TRUE(folly::split(':', "a:13:14.7:b", a, b, c, d));
893   EXPECT_EQ("a", a);
894   EXPECT_EQ(13, b);
895   EXPECT_NEAR(14.7, c, 1e-10);
896   EXPECT_EQ("b", d);
897
898   EXPECT_TRUE(folly::split<false>(':', "b:14:15.3:c", a, b, c, d));
899   EXPECT_EQ("b", a);
900   EXPECT_EQ(14, b);
901   EXPECT_NEAR(15.3, c, 1e-10);
902   EXPECT_EQ("c", d);
903
904   EXPECT_FALSE(folly::split(':', "a:13:14.7:b", a, b, d));
905
906   EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, d));
907   EXPECT_EQ("a", a);
908   EXPECT_EQ(13, b);
909   EXPECT_EQ("14.7:b", d);
910
911
912   // Enable verifying that a line only contains one field
913   EXPECT_TRUE(folly::split(' ', "hello", a));
914   EXPECT_FALSE(folly::split(' ', "hello world", a));
915 }
916
917 namespace my {
918
919 enum class Color {
920   Red,
921   Blue,
922 };
923
924 enum class ColorErrorCode { INVALID_COLOR };
925
926 struct ColorError : std::runtime_error {
927   using std::runtime_error::runtime_error;
928 };
929
930 ColorError makeConversionError(ColorErrorCode, StringPiece sp) {
931   return ColorError("Invalid my::Color representation : " + sp.str());
932 }
933
934 Expected<StringPiece, ColorErrorCode> parseTo(
935     StringPiece in,
936     Color& out) noexcept {
937   if (in == "R") {
938     out = Color::Red;
939   } else if (in == "B") {
940     out = Color::Blue;
941   } else {
942     return makeUnexpected(ColorErrorCode::INVALID_COLOR);
943   }
944   return StringPiece(in.end(), in.end());
945 }
946 }
947
948 TEST(Split, fixed_convert_custom) {
949   my::Color c1, c2;
950
951   EXPECT_TRUE(folly::split(',', "R,B", c1, c2));
952   EXPECT_EQ(c1, my::Color::Red);
953   EXPECT_EQ(c2, my::Color::Blue);
954
955   EXPECT_THROW(folly::split(',', "B,G", c1, c2), my::ColorError);
956 }
957
958 TEST(String, join) {
959   string output;
960
961   std::vector<int> empty = { };
962   join(":", empty, output);
963   EXPECT_TRUE(output.empty());
964
965   std::vector<std::string> input1 = { "1", "23", "456", "" };
966   join(':', input1, output);
967   EXPECT_EQ(output, "1:23:456:");
968   output = join(':', input1);
969   EXPECT_EQ(output, "1:23:456:");
970
971   auto input2 = { 1, 23, 456 };
972   join("-*-", input2, output);
973   EXPECT_EQ(output, "1-*-23-*-456");
974   output = join("-*-", input2);
975   EXPECT_EQ(output, "1-*-23-*-456");
976
977   auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
978   join("", input3, output);
979   EXPECT_EQ(output, "facebook");
980
981   join("_", { "", "f", "a", "c", "e", "b", "o", "o", "k", "" }, output);
982   EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
983
984   output = join("", input3.begin(), input3.end());
985   EXPECT_EQ(output, "facebook");
986 }
987
988 TEST(String, hexlify) {
989   string input1 = "0123";
990   string output1;
991   EXPECT_TRUE(hexlify(input1, output1));
992   EXPECT_EQ("30313233", output1);
993
994   fbstring input2 = "abcdefg";
995   input2[1] = 0;
996   input2[3] = 0xff;
997   input2[5] = 0xb6;
998   fbstring output2;
999   EXPECT_TRUE(hexlify(input2, output2));
1000   EXPECT_EQ("610063ff65b667", output2);
1001
1002   EXPECT_EQ("666f6f626172", hexlify("foobar"));
1003   auto bytes = folly::make_array<uint8_t>(1, 2, 3, 4);
1004   EXPECT_EQ("01020304", hexlify(ByteRange{bytes.data(), bytes.size()}));
1005 }
1006
1007 TEST(String, unhexlify) {
1008   string input1 = "30313233";
1009   string output1;
1010   EXPECT_TRUE(unhexlify(input1, output1));
1011   EXPECT_EQ(output1, "0123");
1012
1013   fbstring input2 = "610063ff65b667";
1014   fbstring output2;
1015   EXPECT_TRUE(unhexlify(input2, output2));
1016   EXPECT_EQ(output2.size(), 7);
1017   EXPECT_EQ(output2[0], 'a');
1018   EXPECT_EQ(output2[1], 0);
1019   EXPECT_EQ(output2[2], 'c');
1020   EXPECT_EQ(output2[3] & 0xff, 0xff);
1021   EXPECT_EQ(output2[4], 'e');
1022   EXPECT_EQ(output2[5] & 0xff, 0xb6);
1023   EXPECT_EQ(output2[6], 'g');
1024
1025   string input3 = "x";
1026   string output3;
1027   EXPECT_FALSE(unhexlify(input3, output3));
1028
1029   string input4 = "xy";
1030   string output4;
1031   EXPECT_FALSE(unhexlify(input4, output4));
1032
1033   EXPECT_EQ("foobar", unhexlify("666f6f626172"));
1034   EXPECT_EQ(StringPiece("foo\0bar", 7), unhexlify("666f6f00626172"));
1035   EXPECT_THROW(unhexlify("666f6fzz626172"), std::domain_error);
1036 }
1037
1038 TEST(String, backslashify) {
1039   EXPECT_EQ("abc", string("abc"));
1040   EXPECT_EQ("abc", backslashify(string("abc")));
1041   EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
1042   EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
1043   EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
1044 }
1045
1046 TEST(String, humanify) {
1047   // Simple cases; output is obvious.
1048   EXPECT_EQ("abc", humanify(string("abc")));
1049   EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
1050   EXPECT_EQ("0xff", humanify(string("\xff")));
1051   EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
1052   EXPECT_EQ("abc\\b", humanify(string("abc\b")));
1053   EXPECT_EQ("0x00", humanify(string(1, '\0')));
1054   EXPECT_EQ("0x0000", humanify(string(2, '\0')));
1055
1056
1057   // Mostly printable, so backslash!  80, 60, and 40% printable, respectively
1058   EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
1059   EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
1060   EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
1061
1062   // 20% printable, and the printable portion isn't the prefix; hexify!
1063   EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
1064
1065   // Same as previous, except swap first two chars; prefix is
1066   // printable and within the threshold, so backslashify.
1067   EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
1068
1069   // Just too much unprintable; hex, despite prefix.
1070   EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
1071 }
1072
1073 namespace {
1074
1075 /**
1076  * Copy bytes from src to somewhere in the buffer referenced by dst. The
1077  * actual starting position of the copy will be the first address in the
1078  * destination buffer whose address mod 8 is equal to the src address mod 8.
1079  * The caller is responsible for ensuring that the destination buffer has
1080  * enough extra space to accommodate the shifted copy.
1081  */
1082 char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
1083   const char* originalDst = dst;
1084   size_t dstOffset = size_t(dst) & 0x7;
1085   size_t srcOffset = size_t(src) & 0x7;
1086   while (dstOffset != srcOffset) {
1087     dst++;
1088     dstOffset++;
1089     dstOffset &= 0x7;
1090   }
1091   CHECK(dst <= originalDst + 7);
1092   CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
1093   memcpy(dst, src, length);
1094   return dst;
1095 }
1096
1097 void testToLowerAscii(Range<const char*> src) {
1098   // Allocate extra space so we can make copies that start at the
1099   // same alignment (byte, word, quadword, etc) as the source buffer.
1100   char controlBuf[src.size() + 7];
1101   char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
1102
1103   char testBuf[src.size() + 7];
1104   char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
1105
1106   for (size_t i = 0; i < src.size(); i++) {
1107     control[i] = tolower(control[i]);
1108   }
1109   toLowerAscii(test, src.size());
1110   for (size_t i = 0; i < src.size(); i++) {
1111     EXPECT_EQ(control[i], test[i]);
1112   }
1113 }
1114
1115 } // anon namespace
1116
1117 TEST(String, toLowerAsciiAligned) {
1118   static const size_t kSize = 256;
1119   char input[kSize];
1120   for (size_t i = 0; i < kSize; i++) {
1121     input[i] = (char)(i & 0xff);
1122   }
1123   testToLowerAscii(Range<const char*>(input, kSize));
1124 }
1125
1126 TEST(String, toLowerAsciiUnaligned) {
1127   static const size_t kSize = 256;
1128   char input[kSize];
1129   for (size_t i = 0; i < kSize; i++) {
1130     input[i] = (char)(i & 0xff);
1131   }
1132   // Test input buffers of several lengths to exercise all the
1133   // cases: buffer at the start/middle/end of an aligned block, plus
1134   // buffers that span multiple aligned blocks.  The longest test input
1135   // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
1136   // + 4 32-bit aligned + 3 unaligned = 22 bytes.
1137   for (size_t length = 1; length < 23; length++) {
1138     for (size_t offset = 0; offset + length <= kSize; offset++) {
1139       testToLowerAscii(Range<const char*>(input + offset, length));
1140     }
1141   }
1142 }
1143
1144 TEST(String, whitespace) {
1145   // trimWhitespace:
1146   EXPECT_EQ("kavabanga",
1147         trimWhitespace("kavabanga"));
1148   EXPECT_EQ("kavabanga",
1149         trimWhitespace("kavabanga \t \n  "));
1150   EXPECT_EQ("kavabanga",
1151         trimWhitespace("   \t \r \n \n kavabanga"));
1152   EXPECT_EQ("kavabanga",
1153         trimWhitespace("\t \r \n   kavabanga \t \n  "));
1154   EXPECT_EQ("kavabanga",
1155         trimWhitespace("   \t \r \n \n kavabanga"));
1156   EXPECT_EQ("kavabanga",
1157         trimWhitespace("\t \r \n   kavabanga \t \n  "));
1158   EXPECT_EQ(
1159     ltrimWhitespace(rtrimWhitespace("kavabanga")),
1160     rtrimWhitespace(ltrimWhitespace("kavabanga")));
1161   EXPECT_EQ(
1162     ltrimWhitespace(rtrimWhitespace("kavabanga  \r\t\n")),
1163     rtrimWhitespace(ltrimWhitespace("kavabanga  \r\t\n")));
1164   EXPECT_EQ("", trimWhitespace("\t \r \n   \t \n  "));
1165   EXPECT_EQ("", trimWhitespace(""));
1166   EXPECT_EQ("", trimWhitespace("\t"));
1167   EXPECT_EQ("", trimWhitespace("\r"));
1168   EXPECT_EQ("", trimWhitespace("\n"));
1169   EXPECT_EQ("", trimWhitespace("\t "));
1170   EXPECT_EQ("", trimWhitespace("\r  "));
1171   EXPECT_EQ("", trimWhitespace("\n   "));
1172   EXPECT_EQ("", trimWhitespace("    \t"));
1173   EXPECT_EQ("", trimWhitespace("    \r"));
1174   EXPECT_EQ("", trimWhitespace("    \n"));
1175
1176   // ltrimWhitespace:
1177   EXPECT_EQ("kavabanga", ltrimWhitespace("\t kavabanga"));
1178   EXPECT_EQ("kavabanga \r\n", ltrimWhitespace("\t kavabanga \r\n"));
1179   EXPECT_EQ("", ltrimWhitespace("\r "));
1180   EXPECT_EQ("", ltrimWhitespace("\n   "));
1181   EXPECT_EQ("", ltrimWhitespace("\r   "));
1182
1183   // rtrimWhitespace:
1184   EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga"));
1185   EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga \r\n"));
1186   EXPECT_EQ("", rtrimWhitespace("\r "));
1187   EXPECT_EQ("", rtrimWhitespace("\n   "));
1188   EXPECT_EQ("", rtrimWhitespace("\r   "));
1189 }
1190
1191 TEST(String, stripLeftMargin_really_empty) {
1192   auto input = "";
1193   auto expected = "";
1194   EXPECT_EQ(expected, stripLeftMargin(input));
1195 }
1196
1197 TEST(String, stripLeftMargin_empty) {
1198   auto input = R"TEXT(
1199   )TEXT";
1200   auto expected = "";
1201   EXPECT_EQ(expected, stripLeftMargin(input));
1202 }
1203
1204 TEST(String, stripLeftMargin_only_whitespace) {
1205   //  using ~ as a marker
1206   string input = R"TEXT(
1207     ~
1208   )TEXT";
1209   input = boost::regex_replace(input, boost::regex("~"), "");
1210   EXPECT_EQ("\n    \n  ", input);
1211   auto expected = "\n";
1212   EXPECT_EQ(expected, stripLeftMargin(input));
1213 }
1214
1215 TEST(String, stripLeftMargin_only_uneven_whitespace) {
1216   //  using ~ as a marker1
1217   string input = R"TEXT(
1218     ~
1219       ~
1220   )TEXT";
1221   input = boost::regex_replace(input, boost::regex("~"), "");
1222   EXPECT_EQ("\n    \n      \n  ", input);
1223   auto expected = "\n\n";
1224
1225   EXPECT_EQ(expected, stripLeftMargin(input));
1226 }
1227
1228 TEST(String, stripLeftMargin_one_line) {
1229   auto input = R"TEXT(
1230     hi there bob!
1231   )TEXT";
1232   auto expected = "hi there bob!\n";
1233   EXPECT_EQ(expected, stripLeftMargin(input));
1234 }
1235
1236 TEST(String, stripLeftMargin_two_lines) {
1237   auto input = R"TEXT(
1238     hi there bob!
1239     nice weather today!
1240   )TEXT";
1241   auto expected = "hi there bob!\nnice weather today!\n";
1242   EXPECT_EQ(expected, stripLeftMargin(input));
1243 }
1244
1245 TEST(String, stripLeftMargin_three_lines_uneven) {
1246   auto input = R"TEXT(
1247       hi there bob!
1248     nice weather today!
1249       so long!
1250   )TEXT";
1251   auto expected = "  hi there bob!\nnice weather today!\n  so long!\n";
1252   EXPECT_EQ(expected, stripLeftMargin(input));
1253 }
1254
1255 TEST(String, stripLeftMargin_preceding_blank_lines) {
1256   auto input = R"TEXT(
1257
1258
1259     hi there bob!
1260   )TEXT";
1261   auto expected = "\n\nhi there bob!\n";
1262   EXPECT_EQ(expected, stripLeftMargin(input));
1263 }
1264
1265 TEST(String, stripLeftMargin_succeeding_blank_lines) {
1266   auto input = R"TEXT(
1267     hi there bob!
1268
1269
1270   )TEXT";
1271   auto expected = "hi there bob!\n\n\n";
1272   EXPECT_EQ(expected, stripLeftMargin(input));
1273 }
1274
1275 TEST(String, stripLeftMargin_interstitial_undented_whiteline) {
1276   //  using ~ as a marker
1277   string input = R"TEXT(
1278       hi there bob!
1279     ~
1280       so long!
1281   )TEXT";
1282   input = boost::regex_replace(input, boost::regex(" +~"), "");
1283   EXPECT_EQ("\n      hi there bob!\n\n      so long!\n  ", input);
1284   auto expected = "hi there bob!\n\nso long!\n";
1285   EXPECT_EQ(expected, stripLeftMargin(input));
1286 }
1287
1288 TEST(String, stripLeftMargin_interstitial_dedented_whiteline) {
1289   //  using ~ as a marker
1290   string input = R"TEXT(
1291       hi there bob!
1292     ~
1293       so long!
1294   )TEXT";
1295   input = boost::regex_replace(input, boost::regex("~"), "");
1296   EXPECT_EQ("\n      hi there bob!\n    \n      so long!\n  ", input);
1297   auto expected = "hi there bob!\n\nso long!\n";
1298   EXPECT_EQ(expected, stripLeftMargin(input));
1299 }
1300
1301 TEST(String, stripLeftMargin_interstitial_equidented_whiteline) {
1302   //  using ~ as a marker
1303   string input = R"TEXT(
1304       hi there bob!
1305       ~
1306       so long!
1307   )TEXT";
1308   input = boost::regex_replace(input, boost::regex("~"), "");
1309   EXPECT_EQ("\n      hi there bob!\n      \n      so long!\n  ", input);
1310   auto expected = "hi there bob!\n\nso long!\n";
1311   EXPECT_EQ(expected, stripLeftMargin(input));
1312 }
1313
1314 TEST(String, stripLeftMargin_interstitial_indented_whiteline) {
1315   //  using ~ as a marker
1316   string input = R"TEXT(
1317       hi there bob!
1318         ~
1319       so long!
1320   )TEXT";
1321   input = boost::regex_replace(input, boost::regex("~"), "");
1322   EXPECT_EQ("\n      hi there bob!\n        \n      so long!\n  ", input);
1323   auto expected = "hi there bob!\n  \nso long!\n";
1324   EXPECT_EQ(expected, stripLeftMargin(input));
1325 }
1326
1327 TEST(String, stripLeftMargin_no_pre_whitespace) {
1328   //  using ~ as a marker
1329   string input = R"TEXT(      hi there bob!
1330         ~
1331       so long!
1332   )TEXT";
1333   input = boost::regex_replace(input, boost::regex("~"), "");
1334   EXPECT_EQ("      hi there bob!\n        \n      so long!\n  ", input);
1335   auto expected = "hi there bob!\n  \nso long!\n";
1336   EXPECT_EQ(expected, stripLeftMargin(input));
1337 }
1338
1339 TEST(String, stripLeftMargin_no_post_whitespace) {
1340   //  using ~ as a marker
1341   string input = R"TEXT(
1342       hi there bob!
1343         ~
1344       so long!  )TEXT";
1345   input = boost::regex_replace(input, boost::regex("~"), "");
1346   EXPECT_EQ("\n      hi there bob!\n        \n      so long!  ", input);
1347   auto expected = "hi there bob!\n  \nso long!  ";
1348   EXPECT_EQ(expected, stripLeftMargin(input));
1349 }
1350
1351 const folly::StringPiece kTestUTF8 = u8"This is \U0001F602 stuff!";
1352
1353 TEST(UTF8StringPiece, valid_utf8) {
1354   folly::StringPiece sp = kTestUTF8;
1355   UTF8StringPiece utf8 = sp;
1356   // utf8.size() not available since it's not a random-access range
1357   EXPECT_EQ(16, utf8.walk_size());
1358 }
1359
1360 TEST(UTF8StringPiece, valid_suffix) {
1361   UTF8StringPiece utf8 = kTestUTF8.subpiece(8);
1362   EXPECT_EQ(8, utf8.walk_size());
1363 }
1364
1365 TEST(UTF8StringPiece, empty_mid_codepoint) {
1366   UTF8StringPiece utf8 = kTestUTF8.subpiece(9, 0); // okay since it's empty
1367   EXPECT_EQ(0, utf8.walk_size());
1368 }
1369
1370 TEST(UTF8StringPiece, invalid_mid_codepoint) {
1371   EXPECT_THROW(UTF8StringPiece(kTestUTF8.subpiece(9, 1)), std::out_of_range);
1372 }
1373
1374 TEST(UTF8StringPiece, valid_implicit_conversion) {
1375   std::string input = u8"\U0001F602\U0001F602\U0001F602";
1376   auto checkImplicitCtor = [](UTF8StringPiece implicitCtor) {
1377     return implicitCtor.walk_size();
1378   };
1379   EXPECT_EQ(3, checkImplicitCtor(input));
1380 }