2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/String.h>
21 #include <boost/algorithm/string.hpp>
22 #include <gtest/gtest.h>
24 #include <folly/Benchmark.h>
26 using namespace folly;
29 TEST(StringPrintf, BasicTest) {
30 EXPECT_EQ("abc", stringPrintf("%s", "abc"));
31 EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
32 EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
33 EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
35 EXPECT_EQ("abc", stringPrintf("abc"));
38 TEST(StringPrintf, NumericFormats) {
39 EXPECT_EQ("12", stringPrintf("%d", 12));
40 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000UL));
41 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000L));
42 EXPECT_EQ("-5000000000", stringPrintf("%ld", -5000000000L));
43 EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
44 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffff));
45 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffffUL));
47 EXPECT_EQ("7.7", stringPrintf("%1.1f", 7.7));
48 EXPECT_EQ("7.7", stringPrintf("%1.1lf", 7.7));
49 EXPECT_EQ("7.70000000000000018",
50 stringPrintf("%.17f", 7.7));
51 EXPECT_EQ("7.70000000000000018",
52 stringPrintf("%.17lf", 7.7));
55 TEST(StringPrintf, Appending) {
57 stringAppendf(&s, "a%s", "b");
58 stringAppendf(&s, "%c", 'c');
60 stringAppendf(&s, " %d", 123);
61 EXPECT_EQ(s, "abc 123");
64 void vprintfCheck(const char* expected, const char* fmt, ...) {
66 va_start(apOrig, fmt);
76 // Check both APIs for calling stringVPrintf()
77 EXPECT_EQ(expected, stringVPrintf(fmt, ap));
82 stringVPrintf(&out, fmt, ap);
85 EXPECT_EQ(expected, out);
87 // Check stringVAppendf() as well
88 std::string prefix = "foobar";
90 EXPECT_EQ(prefix + expected, stringVAppendf(&out, fmt, ap));
95 void vprintfError(const char* fmt, ...) {
102 // OSX's sprintf family does not return a negative number on a bad format
103 // string, but Linux does. It's unclear to me which behavior is more
105 #ifdef HAVE_VSNPRINTF_ERRORS
106 EXPECT_THROW({stringVPrintf(fmt, ap);},
111 TEST(StringPrintf, VPrintf) {
112 vprintfCheck("foo", "%s", "foo");
113 vprintfCheck("long string requiring reallocation 1 2 3 0x12345678",
114 "%s %s %d %d %d %#x",
115 "long string", "requiring reallocation", 1, 2, 3, 0x12345678);
116 vprintfError("bogus%", "foo");
119 TEST(StringPrintf, VariousSizes) {
120 // Test a wide variety of output sizes, making sure to cross the
121 // vsnprintf buffer boundary implementation detail.
122 for (int i = 0; i < 4096; ++i) {
123 string expected(i + 1, 'a');
124 expected = "X" + expected + "X";
125 string result = stringPrintf("%s", expected.c_str());
126 EXPECT_EQ(expected.size(), result.size());
127 EXPECT_EQ(expected, result);
130 EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
131 stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
132 "%d%d%d%d%d%d%d%d%d%d%dxyz",
133 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
134 17, 18, 19, 20, 21, 22, 23, 24, 25));
137 TEST(StringPrintf, oldStringPrintfTests) {
138 EXPECT_EQ(string("a/b/c/d"),
139 stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
141 EXPECT_EQ(string(" 5 10"),
142 stringPrintf("%5d %5d", 5, 10));
144 // check printing w/ a big buffer
145 for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
147 string b = stringPrintf("%s", a.c_str());
148 EXPECT_EQ(a.size(), b.size());
152 TEST(StringPrintf, oldStringAppendf) {
154 stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
155 EXPECT_EQ(string("helloa/b/c/d"), s);
158 // A simple benchmark that tests various output sizes for a simple
159 // input; the goal is to measure the output buffer resize code cost.
160 void stringPrintfOutputSize(int iters, int param) {
162 BENCHMARK_SUSPEND { buffer.resize(param, 'x'); }
164 for (int64_t i = 0; i < iters; ++i) {
165 string s = stringPrintf("msg: %d, %d, %s", 10, 20, buffer.c_str());
169 // The first few of these tend to fit in the inline buffer, while the
170 // subsequent ones cross that limit, trigger a second vsnprintf, and
171 // exercise a different codepath.
172 BENCHMARK_PARAM(stringPrintfOutputSize, 1)
173 BENCHMARK_PARAM(stringPrintfOutputSize, 4)
174 BENCHMARK_PARAM(stringPrintfOutputSize, 16)
175 BENCHMARK_PARAM(stringPrintfOutputSize, 64)
176 BENCHMARK_PARAM(stringPrintfOutputSize, 256)
177 BENCHMARK_PARAM(stringPrintfOutputSize, 1024)
179 // Benchmark simple stringAppendf behavior to show a pathology Lovro
180 // reported (t5735468).
181 BENCHMARK(stringPrintfAppendfBenchmark, iters) {
182 for (unsigned int i = 0; i < iters; ++i) {
184 BENCHMARK_SUSPEND { s.reserve(300000); }
185 for (int j = 0; j < 300000; ++j) {
186 stringAppendf(&s, "%d", 1);
191 TEST(Escape, cEscape) {
192 EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
193 EXPECT_EQ("hello \\\\world\\\" goodbye",
194 cEscape<std::string>("hello \\world\" goodbye"));
195 EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
196 EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
199 TEST(Escape, cUnescape) {
200 EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
201 EXPECT_EQ("hello \\world\" goodbye",
202 cUnescape<std::string>("hello \\\\world\\\" goodbye"));
203 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
204 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
205 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
206 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
207 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
209 EXPECT_THROW({cUnescape<std::string>("hello\\");},
210 std::invalid_argument);
211 EXPECT_THROW({cUnescape<std::string>("hello\\x");},
212 std::invalid_argument);
213 EXPECT_THROW({cUnescape<std::string>("hello\\q");},
214 std::invalid_argument);
217 TEST(Escape, uriEscape) {
218 EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
219 EXPECT_EQ("hello%2c%20/world", uriEscape<std::string>("hello, /world",
220 UriEscapeMode::PATH));
221 EXPECT_EQ("hello%2c+%2fworld", uriEscape<std::string>("hello, /world",
222 UriEscapeMode::QUERY));
224 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~",
225 uriEscape<std::string>(
226 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~")
230 TEST(Escape, uriUnescape) {
231 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
232 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
233 EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
234 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c+%2fworld",
235 UriEscapeMode::QUERY));
236 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
237 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
238 EXPECT_THROW({uriUnescape<std::string>("hello%");},
239 std::invalid_argument);
240 EXPECT_THROW({uriUnescape<std::string>("hello%2");},
241 std::invalid_argument);
242 EXPECT_THROW({uriUnescape<std::string>("hello%2g");},
243 std::invalid_argument);
247 void expectPrintable(StringPiece s) {
255 TEST(Escape, uriEscapeAllCombinations) {
258 StringPiece in(c, 2);
261 for (int i = 0; i < 256; ++i) {
263 for (int j = 0; j < 256; ++j) {
268 expectPrintable(tmp);
269 uriUnescape(tmp, out);
277 return ((v >= '0' && v <= '9') ||
278 (v >= 'A' && v <= 'F') ||
279 (v >= 'a' && v <= 'f'));
283 TEST(Escape, uriUnescapePercentDecoding) {
284 char c[4] = {'%', '\0', '\0', '\0'};
285 StringPiece in(c, 3);
287 unsigned int expected = 0;
288 for (int i = 0; i < 256; ++i) {
290 for (int j = 0; j < 256; ++j) {
292 if (isHex(i) && isHex(j)) {
294 uriUnescape(in, out);
295 EXPECT_EQ(1, out.size());
296 EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
297 unsigned char v = out[0];
298 EXPECT_EQ(expected, v);
300 EXPECT_THROW({uriUnescape(in, out);}, std::invalid_argument);
308 fbstring cbmEscapedString;
309 fbstring cEscapedString;
310 fbstring cUnescapedString;
311 const size_t kCBmStringLength = 64 << 10;
312 const uint32_t kCPrintablePercentage = 90;
314 fbstring uribmString;
315 fbstring uribmEscapedString;
316 fbstring uriEscapedString;
317 fbstring uriUnescapedString;
318 const size_t kURIBmStringLength = 256;
319 const uint32_t kURIPassThroughPercentage = 50;
321 void initBenchmark() {
325 std::uniform_int_distribution<uint32_t> printable(32, 126);
326 std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
327 std::uniform_int_distribution<uint32_t> percentage(0, 99);
329 cbmString.reserve(kCBmStringLength);
330 for (size_t i = 0; i < kCBmStringLength; ++i) {
332 if (percentage(rnd) < kCPrintablePercentage) {
335 c = nonPrintable(rnd);
336 // Generate characters in both non-printable ranges:
337 // 0..31 and 127..255
342 cbmString.push_back(c);
345 cbmEscapedString = cEscape<fbstring>(cbmString);
348 std::uniform_int_distribution<uint32_t> passthrough('a', 'z');
349 std::string encodeChars = " ?!\"',+[]";
350 std::uniform_int_distribution<uint32_t> encode(0, encodeChars.size() - 1);
352 uribmString.reserve(kURIBmStringLength);
353 for (size_t i = 0; i < kURIBmStringLength; ++i) {
355 if (percentage(rnd) < kURIPassThroughPercentage) {
356 c = passthrough(rnd);
358 c = encodeChars[encode(rnd)];
360 uribmString.push_back(c);
363 uribmEscapedString = uriEscape<fbstring>(uribmString);
366 BENCHMARK(BM_cEscape, iters) {
368 cEscapedString = cEscape<fbstring>(cbmString);
369 doNotOptimizeAway(cEscapedString.size());
373 BENCHMARK(BM_cUnescape, iters) {
375 cUnescapedString = cUnescape<fbstring>(cbmEscapedString);
376 doNotOptimizeAway(cUnescapedString.size());
380 BENCHMARK(BM_uriEscape, iters) {
382 uriEscapedString = uriEscape<fbstring>(uribmString);
383 doNotOptimizeAway(uriEscapedString.size());
387 BENCHMARK(BM_uriUnescape, iters) {
389 uriUnescapedString = uriUnescape<fbstring>(uribmEscapedString);
390 doNotOptimizeAway(uriUnescapedString.size());
398 double pow2(int exponent) {
399 return double(int64_t(1) << exponent);
403 struct PrettyTestCase{
404 std::string prettyString;
406 PrettyType prettyType;
409 PrettyTestCase prettyTestCases[] =
411 {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
412 {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
413 {string("85.3 ms"), 85.3e-3, PRETTY_TIME},
414 {string("85.3 us"), 85.3e-6, PRETTY_TIME},
415 {string("85.3 ns"), 85.3e-9, PRETTY_TIME},
416 {string("85.3 ps"), 85.3e-12, PRETTY_TIME},
417 {string("8.53e-14 s "), 85.3e-15, PRETTY_TIME},
419 {string("0 s "), 0, PRETTY_TIME},
420 {string("1 s "), 1.0, PRETTY_TIME},
421 {string("1 ms"), 1.0e-3, PRETTY_TIME},
422 {string("1 us"), 1.0e-6, PRETTY_TIME},
423 {string("1 ns"), 1.0e-9, PRETTY_TIME},
424 {string("1 ps"), 1.0e-12, PRETTY_TIME},
426 // check bytes printing
427 {string("853 B "), 853., PRETTY_BYTES},
428 {string("833 kB"), 853.e3, PRETTY_BYTES},
429 {string("813.5 MB"), 853.e6, PRETTY_BYTES},
430 {string("7.944 GB"), 8.53e9, PRETTY_BYTES},
431 {string("794.4 GB"), 853.e9, PRETTY_BYTES},
432 {string("775.8 TB"), 853.e12, PRETTY_BYTES},
434 {string("0 B "), 0, PRETTY_BYTES},
435 {string("1 B "), pow2(0), PRETTY_BYTES},
436 {string("1 kB"), pow2(10), PRETTY_BYTES},
437 {string("1 MB"), pow2(20), PRETTY_BYTES},
438 {string("1 GB"), pow2(30), PRETTY_BYTES},
439 {string("1 TB"), pow2(40), PRETTY_BYTES},
441 {string("853 B "), 853., PRETTY_BYTES_IEC},
442 {string("833 KiB"), 853.e3, PRETTY_BYTES_IEC},
443 {string("813.5 MiB"), 853.e6, PRETTY_BYTES_IEC},
444 {string("7.944 GiB"), 8.53e9, PRETTY_BYTES_IEC},
445 {string("794.4 GiB"), 853.e9, PRETTY_BYTES_IEC},
446 {string("775.8 TiB"), 853.e12, PRETTY_BYTES_IEC},
448 {string("0 B "), 0, PRETTY_BYTES_IEC},
449 {string("1 B "), pow2(0), PRETTY_BYTES_IEC},
450 {string("1 KiB"), pow2(10), PRETTY_BYTES_IEC},
451 {string("1 MiB"), pow2(20), PRETTY_BYTES_IEC},
452 {string("1 GiB"), pow2(30), PRETTY_BYTES_IEC},
453 {string("1 TiB"), pow2(40), PRETTY_BYTES_IEC},
455 // check bytes metric printing
456 {string("853 B "), 853., PRETTY_BYTES_METRIC},
457 {string("853 kB"), 853.e3, PRETTY_BYTES_METRIC},
458 {string("853 MB"), 853.e6, PRETTY_BYTES_METRIC},
459 {string("8.53 GB"), 8.53e9, PRETTY_BYTES_METRIC},
460 {string("853 GB"), 853.e9, PRETTY_BYTES_METRIC},
461 {string("853 TB"), 853.e12, PRETTY_BYTES_METRIC},
463 {string("0 B "), 0, PRETTY_BYTES_METRIC},
464 {string("1 B "), 1.0, PRETTY_BYTES_METRIC},
465 {string("1 kB"), 1.0e+3, PRETTY_BYTES_METRIC},
466 {string("1 MB"), 1.0e+6, PRETTY_BYTES_METRIC},
468 {string("1 GB"), 1.0e+9, PRETTY_BYTES_METRIC},
469 {string("1 TB"), 1.0e+12, PRETTY_BYTES_METRIC},
471 // check metric-units (powers of 1000) printing
472 {string("853 "), 853., PRETTY_UNITS_METRIC},
473 {string("853 k"), 853.e3, PRETTY_UNITS_METRIC},
474 {string("853 M"), 853.e6, PRETTY_UNITS_METRIC},
475 {string("8.53 bil"), 8.53e9, PRETTY_UNITS_METRIC},
476 {string("853 bil"), 853.e9, PRETTY_UNITS_METRIC},
477 {string("853 tril"), 853.e12, PRETTY_UNITS_METRIC},
479 // check binary-units (powers of 1024) printing
480 {string("0 "), 0, PRETTY_UNITS_BINARY},
481 {string("1 "), pow2(0), PRETTY_UNITS_BINARY},
482 {string("1 k"), pow2(10), PRETTY_UNITS_BINARY},
483 {string("1 M"), pow2(20), PRETTY_UNITS_BINARY},
484 {string("1 G"), pow2(30), PRETTY_UNITS_BINARY},
485 {string("1 T"), pow2(40), PRETTY_UNITS_BINARY},
487 {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY},
488 {string("1024 k"), pow2(20) - 1, PRETTY_UNITS_BINARY},
489 {string("1024 M"), pow2(30) - 1, PRETTY_UNITS_BINARY},
490 {string("1024 G"), pow2(40) - 1, PRETTY_UNITS_BINARY},
492 {string("0 "), 0, PRETTY_UNITS_BINARY_IEC},
493 {string("1 "), pow2(0), PRETTY_UNITS_BINARY_IEC},
494 {string("1 Ki"), pow2(10), PRETTY_UNITS_BINARY_IEC},
495 {string("1 Mi"), pow2(20), PRETTY_UNITS_BINARY_IEC},
496 {string("1 Gi"), pow2(30), PRETTY_UNITS_BINARY_IEC},
497 {string("1 Ti"), pow2(40), PRETTY_UNITS_BINARY_IEC},
499 {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY_IEC},
500 {string("1024 Ki"), pow2(20) - 1, PRETTY_UNITS_BINARY_IEC},
501 {string("1024 Mi"), pow2(30) - 1, PRETTY_UNITS_BINARY_IEC},
502 {string("1024 Gi"), pow2(40) - 1, PRETTY_UNITS_BINARY_IEC},
504 //check border SI cases
506 {string("1 Y"), 1e24, PRETTY_SI},
507 {string("10 Y"), 1e25, PRETTY_SI},
508 {string("1 y"), 1e-24, PRETTY_SI},
509 {string("10 y"), 1e-23, PRETTY_SI},
511 // check that negative values work
512 {string("-85.3 s "), -85.3, PRETTY_TIME},
513 {string("-85.3 ms"), -85.3e-3, PRETTY_TIME},
514 {string("-85.3 us"), -85.3e-6, PRETTY_TIME},
515 {string("-85.3 ns"), -85.3e-9, PRETTY_TIME},
517 {string("endoftest"), 0, PRETTY_NUM_TYPES}
520 TEST(PrettyPrint, Basic) {
521 for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
522 const PrettyTestCase& prettyTest = prettyTestCases[i];
523 EXPECT_EQ(prettyTest.prettyString,
524 prettyPrint(prettyTest.realValue, prettyTest.prettyType));
528 TEST(PrettyToDouble, Basic) {
529 // check manually created tests
530 for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
531 PrettyTestCase testCase = prettyTestCases[i];
532 PrettyType formatType = testCase.prettyType;
533 double x = testCase.realValue;
534 std::string testString = testCase.prettyString;
535 double recoveredX = 0;
537 recoveredX = prettyToDouble(testString, formatType);
538 } catch (std::range_error &ex){
541 double relativeError = fabs(x) < 1e-5 ? (x-recoveredX) :
542 (x - recoveredX) / x;
543 EXPECT_NEAR(0, relativeError, 1e-3);
546 // checks for compatibility with prettyPrint over the whole parameter space
547 for (int i = 0 ; i < PRETTY_NUM_TYPES; ++i){
548 PrettyType formatType = static_cast<PrettyType>(i);
549 for (double x = 1e-18; x < 1e40; x *= 1.9){
550 bool addSpace = static_cast<PrettyType> (i) == PRETTY_SI;
551 for (int it = 0; it < 2; ++it, addSpace = true){
552 double recoveredX = 0;
554 recoveredX = prettyToDouble(prettyPrint(x, formatType, addSpace),
556 } catch (std::range_error &ex){
559 double relativeError = (x - recoveredX) / x;
560 EXPECT_NEAR(0, relativeError, 1e-3);
565 // check for incorrect values
566 EXPECT_THROW(prettyToDouble("10Mx", PRETTY_SI), std::range_error);
567 EXPECT_THROW(prettyToDouble("10 Mx", PRETTY_SI), std::range_error);
568 EXPECT_THROW(prettyToDouble("10 M x", PRETTY_SI), std::range_error);
570 StringPiece testString = "10Mx";
571 EXPECT_DOUBLE_EQ(prettyToDouble(&testString, PRETTY_UNITS_METRIC), 10e6);
572 EXPECT_EQ(testString, "x");
575 TEST(PrettyPrint, HexDump) {
576 std::string a("abc\x00\x02\xa0", 6); // embedded NUL
578 "00000000 61 62 63 00 02 a0 "
580 hexDump(a.data(), a.size()));
582 a = "abcdefghijklmnopqrstuvwxyz";
584 "00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 "
585 "|abcdefghijklmnop|\n"
586 "00000010 71 72 73 74 75 76 77 78 79 7a "
588 hexDump(a.data(), a.size()));
591 TEST(System, errnoStr) {
593 EXPECT_EQ(EACCES, errno);
594 EXPECT_EQ(EACCES, errno); // twice to make sure EXPECT_EQ doesn't change it
596 fbstring expected = strerror(ENOENT);
599 EXPECT_EQ(expected, errnoStr(ENOENT));
600 // Ensure that errno isn't changed
601 EXPECT_EQ(EACCES, errno);
603 // Per POSIX, all errno values are positive, so -1 is invalid
606 // Ensure that errno isn't changed
607 EXPECT_EQ(EACCES, errno);
612 template<template<class,class> class VectorType>
614 VectorType<string,std::allocator<string> > parts;
616 folly::split(',', "a,b,c", parts);
617 EXPECT_EQ(parts.size(), 3);
618 EXPECT_EQ(parts[0], "a");
619 EXPECT_EQ(parts[1], "b");
620 EXPECT_EQ(parts[2], "c");
623 folly::split(',', StringPiece("a,b,c"), parts);
624 EXPECT_EQ(parts.size(), 3);
625 EXPECT_EQ(parts[0], "a");
626 EXPECT_EQ(parts[1], "b");
627 EXPECT_EQ(parts[2], "c");
630 folly::split(',', string("a,b,c"), parts);
631 EXPECT_EQ(parts.size(), 3);
632 EXPECT_EQ(parts[0], "a");
633 EXPECT_EQ(parts[1], "b");
634 EXPECT_EQ(parts[2], "c");
637 folly::split(',', "a,,c", parts);
638 EXPECT_EQ(parts.size(), 3);
639 EXPECT_EQ(parts[0], "a");
640 EXPECT_EQ(parts[1], "");
641 EXPECT_EQ(parts[2], "c");
644 folly::split(',', string("a,,c"), parts);
645 EXPECT_EQ(parts.size(), 3);
646 EXPECT_EQ(parts[0], "a");
647 EXPECT_EQ(parts[1], "");
648 EXPECT_EQ(parts[2], "c");
651 folly::split(',', "a,,c", parts, true);
652 EXPECT_EQ(parts.size(), 2);
653 EXPECT_EQ(parts[0], "a");
654 EXPECT_EQ(parts[1], "c");
657 folly::split(',', string("a,,c"), parts, true);
658 EXPECT_EQ(parts.size(), 2);
659 EXPECT_EQ(parts[0], "a");
660 EXPECT_EQ(parts[1], "c");
663 folly::split(',', string(",,a,,c,,,"), parts, true);
664 EXPECT_EQ(parts.size(), 2);
665 EXPECT_EQ(parts[0], "a");
666 EXPECT_EQ(parts[1], "c");
669 // test multiple split w/o clear
670 folly::split(',', ",,a,,c,,,", parts, true);
671 EXPECT_EQ(parts.size(), 2);
672 EXPECT_EQ(parts[0], "a");
673 EXPECT_EQ(parts[1], "c");
674 folly::split(',', ",,a,,c,,,", parts, true);
675 EXPECT_EQ(parts.size(), 4);
676 EXPECT_EQ(parts[2], "a");
677 EXPECT_EQ(parts[3], "c");
680 // test splits that with multi-line delimiter
681 folly::split("ab", "dabcabkdbkab", parts, true);
682 EXPECT_EQ(parts.size(), 3);
683 EXPECT_EQ(parts[0], "d");
684 EXPECT_EQ(parts[1], "c");
685 EXPECT_EQ(parts[2], "kdbk");
688 // test last part is shorter than the delimiter
689 folly::split("bc", "abcd", parts, true);
690 EXPECT_EQ(parts.size(), 2);
691 EXPECT_EQ(parts[0], "a");
692 EXPECT_EQ(parts[1], "d");
695 string orig = "ab2342asdfv~~!";
696 folly::split("", orig, parts, true);
697 EXPECT_EQ(parts.size(), 1);
698 EXPECT_EQ(parts[0], orig);
701 folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
702 EXPECT_EQ(parts.size(), 1);
703 EXPECT_EQ(parts[0], "asfds");
706 folly::split("a", "", parts, true);
707 EXPECT_EQ(parts.size(), 0);
710 folly::split("a", "", parts);
711 EXPECT_EQ(parts.size(), 1);
712 EXPECT_EQ(parts[0], "");
715 folly::split("a", StringPiece(), parts, true);
716 EXPECT_EQ(parts.size(), 0);
719 folly::split("a", StringPiece(), parts);
720 EXPECT_EQ(parts.size(), 1);
721 EXPECT_EQ(parts[0], "");
724 folly::split("a", "abcdefg", parts, true);
725 EXPECT_EQ(parts.size(), 1);
726 EXPECT_EQ(parts[0], "bcdefg");
729 orig = "All, , your base, are , , belong to us";
730 folly::split(", ", orig, parts, true);
731 EXPECT_EQ(parts.size(), 4);
732 EXPECT_EQ(parts[0], "All");
733 EXPECT_EQ(parts[1], "your base");
734 EXPECT_EQ(parts[2], "are ");
735 EXPECT_EQ(parts[3], "belong to us");
737 folly::split(", ", orig, parts);
738 EXPECT_EQ(parts.size(), 6);
739 EXPECT_EQ(parts[0], "All");
740 EXPECT_EQ(parts[1], "");
741 EXPECT_EQ(parts[2], "your base");
742 EXPECT_EQ(parts[3], "are ");
743 EXPECT_EQ(parts[4], "");
744 EXPECT_EQ(parts[5], "belong to us");
747 orig = ", Facebook, rul,es!, ";
748 folly::split(", ", orig, parts, true);
749 EXPECT_EQ(parts.size(), 2);
750 EXPECT_EQ(parts[0], "Facebook");
751 EXPECT_EQ(parts[1], "rul,es!");
753 folly::split(", ", orig, parts);
754 EXPECT_EQ(parts.size(), 4);
755 EXPECT_EQ(parts[0], "");
756 EXPECT_EQ(parts[1], "Facebook");
757 EXPECT_EQ(parts[2], "rul,es!");
758 EXPECT_EQ(parts[3], "");
761 template<template<class,class> class VectorType>
763 VectorType<StringPiece,std::allocator<StringPiece> > pieces;
764 VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
766 folly::split(',', "a,b,c", pieces);
767 EXPECT_EQ(pieces.size(), 3);
768 EXPECT_EQ(pieces[0], "a");
769 EXPECT_EQ(pieces[1], "b");
770 EXPECT_EQ(pieces[2], "c");
774 folly::split(',', "a,,c", pieces);
775 EXPECT_EQ(pieces.size(), 3);
776 EXPECT_EQ(pieces[0], "a");
777 EXPECT_EQ(pieces[1], "");
778 EXPECT_EQ(pieces[2], "c");
781 folly::split(',', "a,,c", pieces, true);
782 EXPECT_EQ(pieces.size(), 2);
783 EXPECT_EQ(pieces[0], "a");
784 EXPECT_EQ(pieces[1], "c");
787 folly::split(',', ",,a,,c,,,", pieces, true);
788 EXPECT_EQ(pieces.size(), 2);
789 EXPECT_EQ(pieces[0], "a");
790 EXPECT_EQ(pieces[1], "c");
793 // test multiple split w/o clear
794 folly::split(',', ",,a,,c,,,", pieces, true);
795 EXPECT_EQ(pieces.size(), 2);
796 EXPECT_EQ(pieces[0], "a");
797 EXPECT_EQ(pieces[1], "c");
798 folly::split(',', ",,a,,c,,,", pieces, true);
799 EXPECT_EQ(pieces.size(), 4);
800 EXPECT_EQ(pieces[2], "a");
801 EXPECT_EQ(pieces[3], "c");
804 // test multiple split rounds
805 folly::split(",", "a_b,c_d", pieces);
806 EXPECT_EQ(pieces.size(), 2);
807 EXPECT_EQ(pieces[0], "a_b");
808 EXPECT_EQ(pieces[1], "c_d");
809 folly::split("_", pieces[0], pieces2);
810 EXPECT_EQ(pieces2.size(), 2);
811 EXPECT_EQ(pieces2[0], "a");
812 EXPECT_EQ(pieces2[1], "b");
814 folly::split("_", pieces[1], pieces2);
815 EXPECT_EQ(pieces2.size(), 2);
816 EXPECT_EQ(pieces2[0], "c");
817 EXPECT_EQ(pieces2[1], "d");
821 // test splits that with multi-line delimiter
822 folly::split("ab", "dabcabkdbkab", pieces, true);
823 EXPECT_EQ(pieces.size(), 3);
824 EXPECT_EQ(pieces[0], "d");
825 EXPECT_EQ(pieces[1], "c");
826 EXPECT_EQ(pieces[2], "kdbk");
829 string orig = "ab2342asdfv~~!";
830 folly::split("", orig.c_str(), pieces, true);
831 EXPECT_EQ(pieces.size(), 1);
832 EXPECT_EQ(pieces[0], orig);
835 folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
836 EXPECT_EQ(pieces.size(), 1);
837 EXPECT_EQ(pieces[0], "asfds");
840 folly::split("a", "", pieces, true);
841 EXPECT_EQ(pieces.size(), 0);
844 folly::split("a", "", pieces);
845 EXPECT_EQ(pieces.size(), 1);
846 EXPECT_EQ(pieces[0], "");
849 folly::split("a", "abcdefg", pieces, true);
850 EXPECT_EQ(pieces.size(), 1);
851 EXPECT_EQ(pieces[0], "bcdefg");
854 orig = "All, , your base, are , , belong to us";
855 folly::split(", ", orig, pieces, true);
856 EXPECT_EQ(pieces.size(), 4);
857 EXPECT_EQ(pieces[0], "All");
858 EXPECT_EQ(pieces[1], "your base");
859 EXPECT_EQ(pieces[2], "are ");
860 EXPECT_EQ(pieces[3], "belong to us");
862 folly::split(", ", orig, pieces);
863 EXPECT_EQ(pieces.size(), 6);
864 EXPECT_EQ(pieces[0], "All");
865 EXPECT_EQ(pieces[1], "");
866 EXPECT_EQ(pieces[2], "your base");
867 EXPECT_EQ(pieces[3], "are ");
868 EXPECT_EQ(pieces[4], "");
869 EXPECT_EQ(pieces[5], "belong to us");
872 orig = ", Facebook, rul,es!, ";
873 folly::split(", ", orig, pieces, true);
874 EXPECT_EQ(pieces.size(), 2);
875 EXPECT_EQ(pieces[0], "Facebook");
876 EXPECT_EQ(pieces[1], "rul,es!");
878 folly::split(", ", orig, pieces);
879 EXPECT_EQ(pieces.size(), 4);
880 EXPECT_EQ(pieces[0], "");
881 EXPECT_EQ(pieces[1], "Facebook");
882 EXPECT_EQ(pieces[2], "rul,es!");
883 EXPECT_EQ(pieces[3], "");
886 const char* str = "a,b";
887 folly::split(',', StringPiece(str), pieces);
888 EXPECT_EQ(pieces.size(), 2);
889 EXPECT_EQ(pieces[0], "a");
890 EXPECT_EQ(pieces[1], "b");
891 EXPECT_EQ(pieces[0].start(), str);
892 EXPECT_EQ(pieces[1].start(), str + 2);
894 std::set<StringPiece> unique;
895 folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
896 std::inserter(unique, unique.begin()), true);
897 EXPECT_EQ(unique.size(), 3);
898 if (unique.size() == 3) {
899 EXPECT_EQ(*unique.begin(), "asd");
900 EXPECT_EQ(*--unique.end(), "csd");
903 VectorType<fbstring,std::allocator<fbstring> > blah;
904 folly::split('-', "a-b-c-d-f-e", blah);
905 EXPECT_EQ(blah.size(), 6);
910 TEST(Split, split_vector) {
911 splitTest<std::vector>();
913 TEST(Split, split_fbvector) {
914 splitTest<folly::fbvector>();
916 TEST(Split, pieces_vector) {
917 piecesTest<std::vector>();
919 TEST(Split, pieces_fbvector) {
920 piecesTest<folly::fbvector>();
924 StringPiece a, b, c, d;
926 EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
927 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
928 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
929 EXPECT_TRUE(folly::split<false>('.', "a", a));
931 EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
932 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
933 EXPECT_TRUE(folly::split('.', "a.b", a, b));
934 EXPECT_TRUE(folly::split('.', "a", a));
936 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
940 EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
941 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
945 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
949 EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
950 EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
952 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
955 EXPECT_FALSE(folly::split<false>('.', "a", a, b));
956 EXPECT_TRUE(folly::split<false>('.', "a.b", a));
959 EXPECT_TRUE(folly::split('.', "a.b", a, b));
962 EXPECT_FALSE(folly::split('.', "a", a, b));
963 EXPECT_FALSE(folly::split('.', "a.b", a));
966 TEST(Split, std_string_fixed) {
967 std::string a, b, c, d;
969 EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
970 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
971 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
972 EXPECT_TRUE(folly::split<false>('.', "a", a));
974 EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
975 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
976 EXPECT_TRUE(folly::split('.', "a.b", a, b));
977 EXPECT_TRUE(folly::split('.', "a", a));
979 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
983 EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
984 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
988 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
992 EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
993 EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
995 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
998 EXPECT_FALSE(folly::split<false>('.', "a", a, b));
999 EXPECT_TRUE(folly::split<false>('.', "a.b", a));
1000 EXPECT_EQ("a.b", a);
1002 EXPECT_TRUE(folly::split('.', "a.b", a, b));
1005 EXPECT_FALSE(folly::split('.', "a", a, b));
1006 EXPECT_FALSE(folly::split('.', "a.b", a));
1009 TEST(Split, fixed_convert) {
1014 EXPECT_TRUE(folly::split(':', "a:13:14.7:b", a, b, c, d));
1017 EXPECT_NEAR(14.7, c, 1e-10);
1020 EXPECT_TRUE(folly::split<false>(':', "b:14:15.3:c", a, b, c, d));
1023 EXPECT_NEAR(15.3, c, 1e-10);
1026 EXPECT_FALSE(folly::split(':', "a:13:14.7:b", a, b, d));
1028 EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, d));
1031 EXPECT_EQ("14.7:b", d);
1033 EXPECT_THROW(folly::split<false>(':', "a:13:14.7:b", a, b, c),
1037 TEST(String, join) {
1040 std::vector<int> empty = { };
1041 join(":", empty, output);
1042 EXPECT_TRUE(output.empty());
1044 std::vector<std::string> input1 = { "1", "23", "456", "" };
1045 join(':', input1, output);
1046 EXPECT_EQ(output, "1:23:456:");
1047 output = join(':', input1);
1048 EXPECT_EQ(output, "1:23:456:");
1050 auto input2 = { 1, 23, 456 };
1051 join("-*-", input2, output);
1052 EXPECT_EQ(output, "1-*-23-*-456");
1053 output = join("-*-", input2);
1054 EXPECT_EQ(output, "1-*-23-*-456");
1056 auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
1057 join("", input3, output);
1058 EXPECT_EQ(output, "facebook");
1060 join("_", { "", "f", "a", "c", "e", "b", "o", "o", "k", "" }, output);
1061 EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
1063 output = join("", input3.begin(), input3.end());
1064 EXPECT_EQ(output, "facebook");
1067 TEST(String, hexlify) {
1068 string input1 = "0123";
1070 EXPECT_TRUE(hexlify(input1, output1));
1071 EXPECT_EQ(output1, "30313233");
1073 fbstring input2 = "abcdefg";
1078 EXPECT_TRUE(hexlify(input2, output2));
1079 EXPECT_EQ(output2, "610063ff65b667");
1082 TEST(String, unhexlify) {
1083 string input1 = "30313233";
1085 EXPECT_TRUE(unhexlify(input1, output1));
1086 EXPECT_EQ(output1, "0123");
1088 fbstring input2 = "610063ff65b667";
1090 EXPECT_TRUE(unhexlify(input2, output2));
1091 EXPECT_EQ(output2.size(), 7);
1092 EXPECT_EQ(output2[0], 'a');
1093 EXPECT_EQ(output2[1], 0);
1094 EXPECT_EQ(output2[2], 'c');
1095 EXPECT_EQ(output2[3] & 0xff, 0xff);
1096 EXPECT_EQ(output2[4], 'e');
1097 EXPECT_EQ(output2[5] & 0xff, 0xb6);
1098 EXPECT_EQ(output2[6], 'g');
1100 string input3 = "x";
1102 EXPECT_FALSE(unhexlify(input3, output3));
1104 string input4 = "xy";
1106 EXPECT_FALSE(unhexlify(input4, output4));
1109 TEST(String, backslashify) {
1110 EXPECT_EQ("abc", string("abc"));
1111 EXPECT_EQ("abc", backslashify(string("abc")));
1112 EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
1113 EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
1114 EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
1117 TEST(String, humanify) {
1118 // Simple cases; output is obvious.
1119 EXPECT_EQ("abc", humanify(string("abc")));
1120 EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
1121 EXPECT_EQ("0xff", humanify(string("\xff")));
1122 EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
1123 EXPECT_EQ("abc\\b", humanify(string("abc\b")));
1124 EXPECT_EQ("0x00", humanify(string(1, '\0')));
1125 EXPECT_EQ("0x0000", humanify(string(2, '\0')));
1128 // Mostly printable, so backslash! 80, 60, and 40% printable, respectively
1129 EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
1130 EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
1131 EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
1133 // 20% printable, and the printable portion isn't the prefix; hexify!
1134 EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
1136 // Same as previous, except swap first two chars; prefix is
1137 // printable and within the threshold, so backslashify.
1138 EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
1140 // Just too much unprintable; hex, despite prefix.
1141 EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
1147 * Copy bytes from src to somewhere in the buffer referenced by dst. The
1148 * actual starting position of the copy will be the first address in the
1149 * destination buffer whose address mod 8 is equal to the src address mod 8.
1150 * The caller is responsible for ensuring that the destination buffer has
1151 * enough extra space to accommodate the shifted copy.
1153 char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
1154 const char* originalDst = dst;
1155 size_t dstOffset = size_t(dst) & 0x7;
1156 size_t srcOffset = size_t(src) & 0x7;
1157 while (dstOffset != srcOffset) {
1162 CHECK(dst <= originalDst + 7);
1163 CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
1164 memcpy(dst, src, length);
1168 void testToLowerAscii(Range<const char*> src) {
1169 // Allocate extra space so we can make copies that start at the
1170 // same alignment (byte, word, quadword, etc) as the source buffer.
1171 char controlBuf[src.size() + 7];
1172 char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
1174 char testBuf[src.size() + 7];
1175 char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
1177 for (size_t i = 0; i < src.size(); i++) {
1178 control[i] = tolower(control[i]);
1180 toLowerAscii(test, src.size());
1181 for (size_t i = 0; i < src.size(); i++) {
1182 EXPECT_EQ(control[i], test[i]);
1188 TEST(String, toLowerAsciiAligned) {
1189 static const size_t kSize = 256;
1191 for (size_t i = 0; i < kSize; i++) {
1192 input[i] = (char)(i & 0xff);
1194 testToLowerAscii(Range<const char*>(input, kSize));
1197 TEST(String, toLowerAsciiUnaligned) {
1198 static const size_t kSize = 256;
1200 for (size_t i = 0; i < kSize; i++) {
1201 input[i] = (char)(i & 0xff);
1203 // Test input buffers of several lengths to exercise all the
1204 // cases: buffer at the start/middle/end of an aligned block, plus
1205 // buffers that span multiple aligned blocks. The longest test input
1206 // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
1207 // + 4 32-bit aligned + 3 unaligned = 22 bytes.
1208 for (size_t length = 1; length < 23; length++) {
1209 for (size_t offset = 0; offset + length <= kSize; offset++) {
1210 testToLowerAscii(Range<const char*>(input + offset, length));
1215 //////////////////////////////////////////////////////////////////////
1217 BENCHMARK(splitOnSingleChar, iters) {
1218 static const std::string line = "one:two:three:four";
1219 for (size_t i = 0; i < iters << 4; ++i) {
1220 std::vector<StringPiece> pieces;
1221 folly::split(':', line, pieces);
1225 BENCHMARK(splitOnSingleCharFixed, iters) {
1226 static const std::string line = "one:two:three:four";
1227 for (size_t i = 0; i < iters << 4; ++i) {
1228 StringPiece a, b, c, d;
1229 folly::split(':', line, a, b, c, d);
1233 BENCHMARK(splitOnSingleCharFixedAllowExtra, iters) {
1234 static const std::string line = "one:two:three:four";
1235 for (size_t i = 0; i < iters << 4; ++i) {
1236 StringPiece a, b, c, d;
1237 folly::split<false>(':', line, a, b, c, d);
1241 BENCHMARK(splitStr, iters) {
1242 static const std::string line = "one-*-two-*-three-*-four";
1243 for (size_t i = 0; i < iters << 4; ++i) {
1244 std::vector<StringPiece> pieces;
1245 folly::split("-*-", line, pieces);
1249 BENCHMARK(splitStrFixed, iters) {
1250 static const std::string line = "one-*-two-*-three-*-four";
1251 for (size_t i = 0; i < iters << 4; ++i) {
1252 StringPiece a, b, c, d;
1253 folly::split("-*-", line, a, b, c, d);
1257 BENCHMARK(boost_splitOnSingleChar, iters) {
1258 static const std::string line = "one:two:three:four";
1259 bool(*pred)(char) = [] (char c) -> bool { return c == ':'; };
1260 for (size_t i = 0; i < iters << 4; ++i) {
1261 std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
1262 boost::split(pieces, line, pred);
1266 BENCHMARK(joinCharStr, iters) {
1267 static const std::vector<std::string> input = {
1268 "one", "two", "three", "four", "five", "six", "seven" };
1269 for (size_t i = 0; i < iters << 4; ++i) {
1271 folly::join(':', input, output);
1275 BENCHMARK(joinStrStr, iters) {
1276 static const std::vector<std::string> input = {
1277 "one", "two", "three", "four", "five", "six", "seven" };
1278 for (size_t i = 0; i < iters << 4; ++i) {
1280 folly::join(":", input, output);
1284 BENCHMARK(joinInt, iters) {
1285 static const auto input = {
1286 123, 456, 78910, 1112, 1314, 151, 61718 };
1287 for (size_t i = 0; i < iters << 4; ++i) {
1289 folly::join(":", input, output);
1293 TEST(String, whitespace) {
1295 EXPECT_EQ("kavabanga",
1296 trimWhitespace("kavabanga"));
1297 EXPECT_EQ("kavabanga",
1298 trimWhitespace("kavabanga \t \n "));
1299 EXPECT_EQ("kavabanga",
1300 trimWhitespace(" \t \r \n \n kavabanga"));
1301 EXPECT_EQ("kavabanga",
1302 trimWhitespace("\t \r \n kavabanga \t \n "));
1303 EXPECT_EQ("kavabanga",
1304 trimWhitespace(" \t \r \n \n kavabanga"));
1305 EXPECT_EQ("kavabanga",
1306 trimWhitespace("\t \r \n kavabanga \t \n "));
1308 ltrimWhitespace(rtrimWhitespace("kavabanga")),
1309 rtrimWhitespace(ltrimWhitespace("kavabanga")));
1311 ltrimWhitespace(rtrimWhitespace("kavabanga \r\t\n")),
1312 rtrimWhitespace(ltrimWhitespace("kavabanga \r\t\n")));
1313 EXPECT_EQ("", trimWhitespace("\t \r \n \t \n "));
1314 EXPECT_EQ("", trimWhitespace(""));
1315 EXPECT_EQ("", trimWhitespace("\t"));
1316 EXPECT_EQ("", trimWhitespace("\r"));
1317 EXPECT_EQ("", trimWhitespace("\n"));
1318 EXPECT_EQ("", trimWhitespace("\t "));
1319 EXPECT_EQ("", trimWhitespace("\r "));
1320 EXPECT_EQ("", trimWhitespace("\n "));
1321 EXPECT_EQ("", trimWhitespace(" \t"));
1322 EXPECT_EQ("", trimWhitespace(" \r"));
1323 EXPECT_EQ("", trimWhitespace(" \n"));
1326 EXPECT_EQ("kavabanga", ltrimWhitespace("\t kavabanga"));
1327 EXPECT_EQ("kavabanga \r\n", ltrimWhitespace("\t kavabanga \r\n"));
1328 EXPECT_EQ("", ltrimWhitespace("\r "));
1329 EXPECT_EQ("", ltrimWhitespace("\n "));
1330 EXPECT_EQ("", ltrimWhitespace("\r "));
1333 EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga"));
1334 EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga \r\n"));
1335 EXPECT_EQ("", rtrimWhitespace("\r "));
1336 EXPECT_EQ("", rtrimWhitespace("\n "));
1337 EXPECT_EQ("", rtrimWhitespace("\r "));
1340 int main(int argc, char *argv[]) {
1341 testing::InitGoogleTest(&argc, argv);
1342 gflags::ParseCommandLineFlags(&argc, &argv, true);
1343 auto ret = RUN_ALL_TESTS();
1346 if (FLAGS_benchmark) {
1347 folly::runBenchmarks();