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