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