2 * Copyright 2013 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"
20 #include <boost/algorithm/string.hpp>
21 #include <gtest/gtest.h>
23 #include "folly/Benchmark.h"
25 using namespace folly;
28 TEST(StringPrintf, BasicTest) {
29 EXPECT_EQ("abc", stringPrintf("%s", "abc"));
30 EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
31 EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
32 EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
34 EXPECT_EQ("abc", stringPrintf("abc"));
37 TEST(StringPrintf, NumericFormats) {
38 EXPECT_EQ("12", stringPrintf("%d", 12));
39 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000UL));
40 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000L));
41 EXPECT_EQ("-5000000000", stringPrintf("%ld", -5000000000L));
42 EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
43 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffff));
44 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffffUL));
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));
54 TEST(StringPrintf, Appending) {
56 stringAppendf(&s, "a%s", "b");
57 stringAppendf(&s, "%c", 'c');
59 stringAppendf(&s, " %d", 123);
60 EXPECT_EQ(s, "abc 123");
63 TEST(StringPrintf, VariousSizes) {
64 // Test a wide variety of output sizes
65 for (int i = 0; i < 100; ++i) {
66 string expected(i + 1, 'a');
67 EXPECT_EQ("X" + expected + "X", stringPrintf("X%sX", expected.c_str()));
70 EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
71 stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
72 "%d%d%d%d%d%d%d%d%d%d%dxyz",
73 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
74 17, 18, 19, 20, 21, 22, 23, 24, 25));
77 TEST(StringPrintf, oldStringPrintfTests) {
78 EXPECT_EQ(string("a/b/c/d"),
79 stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
81 EXPECT_EQ(string(" 5 10"),
82 stringPrintf("%5d %5d", 5, 10));
84 // check printing w/ a big buffer
85 for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
87 string b = stringPrintf("%s", a.c_str());
88 EXPECT_EQ(a.size(), b.size());
92 TEST(StringPrintf, oldStringAppendf) {
94 stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
95 EXPECT_EQ(string("helloa/b/c/d"), s);
98 BENCHMARK(new_stringPrintfSmall, iters) {
99 for (int64_t i = 0; i < iters; ++i) {
100 int32_t x = int32_t(i);
101 int32_t y = int32_t(i + 1);
103 stringPrintf("msg msg msg msg msg msg msg msg: %d, %d, %s",
108 TEST(Escape, cEscape) {
109 EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
110 EXPECT_EQ("hello \\\\world\\\" goodbye",
111 cEscape<std::string>("hello \\world\" goodbye"));
112 EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
113 EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
116 TEST(Escape, cUnescape) {
117 EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
118 EXPECT_EQ("hello \\world\" goodbye",
119 cUnescape<std::string>("hello \\\\world\\\" goodbye"));
120 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
121 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
122 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
123 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
124 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
126 EXPECT_THROW({cUnescape<std::string>("hello\\");},
127 std::invalid_argument);
128 EXPECT_THROW({cUnescape<std::string>("hello\\x");},
129 std::invalid_argument);
130 EXPECT_THROW({cUnescape<std::string>("hello\\q");},
131 std::invalid_argument);
134 TEST(Escape, uriEscape) {
135 EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
136 EXPECT_EQ("hello%2c%20/world", uriEscape<std::string>("hello, /world",
137 UriEscapeMode::PATH));
138 EXPECT_EQ("hello%2c+%2fworld", uriEscape<std::string>("hello, /world",
139 UriEscapeMode::QUERY));
142 TEST(Escape, uriUnescape) {
143 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
144 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
145 EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
146 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c+%2fworld",
147 UriEscapeMode::QUERY));
148 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
149 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
150 EXPECT_THROW({uriUnescape<std::string>("hello%");},
151 std::invalid_argument);
152 EXPECT_THROW({uriUnescape<std::string>("hello%2");},
153 std::invalid_argument);
154 EXPECT_THROW({uriUnescape<std::string>("hello%2g");},
155 std::invalid_argument);
159 void expectPrintable(StringPiece s) {
167 TEST(Escape, uriEscapeAllCombinations) {
170 StringPiece in(c, 2);
173 for (int i = 0; i < 256; ++i) {
175 for (int j = 0; j < 256; ++j) {
180 expectPrintable(tmp);
181 uriUnescape(tmp, out);
189 return ((v >= '0' && v <= '9') ||
190 (v >= 'A' && v <= 'F') ||
191 (v >= 'a' && v <= 'f'));
195 TEST(Escape, uriUnescapePercentDecoding) {
196 char c[4] = {'%', '\0', '\0', '\0'};
197 StringPiece in(c, 3);
199 unsigned int expected = 0;
200 for (int i = 0; i < 256; ++i) {
202 for (int j = 0; j < 256; ++j) {
204 if (isHex(i) && isHex(j)) {
206 uriUnescape(in, out);
207 EXPECT_EQ(1, out.size());
208 EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
209 unsigned char v = out[0];
210 EXPECT_EQ(expected, v);
212 EXPECT_THROW({uriUnescape(in, out);}, std::invalid_argument);
220 fbstring cbmEscapedString;
221 fbstring cEscapedString;
222 fbstring cUnescapedString;
223 const size_t kCBmStringLength = 64 << 10;
224 const uint32_t kCPrintablePercentage = 90;
226 fbstring uribmString;
227 fbstring uribmEscapedString;
228 fbstring uriEscapedString;
229 fbstring uriUnescapedString;
230 const size_t kURIBmStringLength = 256;
231 const uint32_t kURIPassThroughPercentage = 50;
233 void initBenchmark() {
237 std::uniform_int_distribution<uint32_t> printable(32, 126);
238 std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
239 std::uniform_int_distribution<uint32_t> percentage(0, 99);
241 cbmString.reserve(kCBmStringLength);
242 for (size_t i = 0; i < kCBmStringLength; ++i) {
244 if (percentage(rnd) < kCPrintablePercentage) {
247 c = nonPrintable(rnd);
248 // Generate characters in both non-printable ranges:
249 // 0..31 and 127..255
254 cbmString.push_back(c);
257 cbmEscapedString = cEscape<fbstring>(cbmString);
260 std::uniform_int_distribution<uint32_t> passthrough('a', 'z');
261 std::string encodeChars = " ?!\"',+[]";
262 std::uniform_int_distribution<uint32_t> encode(0, encodeChars.size() - 1);
264 uribmString.reserve(kURIBmStringLength);
265 for (size_t i = 0; i < kURIBmStringLength; ++i) {
267 if (percentage(rnd) < kURIPassThroughPercentage) {
268 c = passthrough(rnd);
270 c = encodeChars[encode(rnd)];
272 uribmString.push_back(c);
275 uribmEscapedString = uriEscape<fbstring>(uribmString);
278 BENCHMARK(BM_cEscape, iters) {
280 cEscapedString = cEscape<fbstring>(cbmString);
281 doNotOptimizeAway(cEscapedString.size());
285 BENCHMARK(BM_cUnescape, iters) {
287 cUnescapedString = cUnescape<fbstring>(cbmEscapedString);
288 doNotOptimizeAway(cUnescapedString.size());
292 BENCHMARK(BM_uriEscape, iters) {
294 uriEscapedString = uriEscape<fbstring>(uribmString);
295 doNotOptimizeAway(uriEscapedString.size());
299 BENCHMARK(BM_uriUnescape, iters) {
301 uriUnescapedString = uriUnescape<fbstring>(uribmEscapedString);
302 doNotOptimizeAway(uriUnescapedString.size());
310 double pow2(int exponent) {
311 return double(int64_t(1) << exponent);
316 TEST(PrettyPrint, Basic) {
317 // check time printing
318 EXPECT_EQ(string("8.53e+07 s "), prettyPrint(85.3e6, PRETTY_TIME));
319 EXPECT_EQ(string("85.3 s "), prettyPrint(85.3, PRETTY_TIME));
320 EXPECT_EQ(string("85.3 ms"), prettyPrint(85.3e-3, PRETTY_TIME));
321 EXPECT_EQ(string("85.3 us"), prettyPrint(85.3e-6, PRETTY_TIME));
322 EXPECT_EQ(string("85.3 ns"), prettyPrint(85.3e-9, PRETTY_TIME));
323 EXPECT_EQ(string("85.3 ps"), prettyPrint(85.3e-12, PRETTY_TIME));
324 EXPECT_EQ(string("8.53e-14 s "), prettyPrint(85.3e-15, PRETTY_TIME));
326 EXPECT_EQ(string("0 s "), prettyPrint(0, PRETTY_TIME));
327 EXPECT_EQ(string("1 s "), prettyPrint(1.0, PRETTY_TIME));
328 EXPECT_EQ(string("1 ms"), prettyPrint(1.0e-3, PRETTY_TIME));
329 EXPECT_EQ(string("1 us"), prettyPrint(1.0e-6, PRETTY_TIME));
330 EXPECT_EQ(string("1 ns"), prettyPrint(1.0e-9, PRETTY_TIME));
331 EXPECT_EQ(string("1 ps"), prettyPrint(1.0e-12, PRETTY_TIME));
333 // check bytes printing
334 EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES));
335 EXPECT_EQ(string("833 kB"), prettyPrint(853.e3, PRETTY_BYTES));
336 EXPECT_EQ(string("813.5 MB"), prettyPrint(853.e6, PRETTY_BYTES));
337 EXPECT_EQ(string("7.944 GB"), prettyPrint(8.53e9, PRETTY_BYTES));
338 EXPECT_EQ(string("794.4 GB"), prettyPrint(853.e9, PRETTY_BYTES));
339 EXPECT_EQ(string("775.8 TB"), prettyPrint(853.e12, PRETTY_BYTES));
341 EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES));
342 EXPECT_EQ(string("1 B "), prettyPrint(pow2(0), PRETTY_BYTES));
343 EXPECT_EQ(string("1 kB"), prettyPrint(pow2(10), PRETTY_BYTES));
344 EXPECT_EQ(string("1 MB"), prettyPrint(pow2(20), PRETTY_BYTES));
345 EXPECT_EQ(string("1 GB"), prettyPrint(pow2(30), PRETTY_BYTES));
346 EXPECT_EQ(string("1 TB"), prettyPrint(pow2(40), PRETTY_BYTES));
348 EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES_IEC));
349 EXPECT_EQ(string("833 KiB"), prettyPrint(853.e3, PRETTY_BYTES_IEC));
350 EXPECT_EQ(string("813.5 MiB"), prettyPrint(853.e6, PRETTY_BYTES_IEC));
351 EXPECT_EQ(string("7.944 GiB"), prettyPrint(8.53e9, PRETTY_BYTES_IEC));
352 EXPECT_EQ(string("794.4 GiB"), prettyPrint(853.e9, PRETTY_BYTES_IEC));
353 EXPECT_EQ(string("775.8 TiB"), prettyPrint(853.e12, PRETTY_BYTES_IEC));
355 EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES_IEC));
356 EXPECT_EQ(string("1 B "), prettyPrint(pow2(0), PRETTY_BYTES_IEC));
357 EXPECT_EQ(string("1 KiB"), prettyPrint(pow2(10), PRETTY_BYTES_IEC));
358 EXPECT_EQ(string("1 MiB"), prettyPrint(pow2(20), PRETTY_BYTES_IEC));
359 EXPECT_EQ(string("1 GiB"), prettyPrint(pow2(30), PRETTY_BYTES_IEC));
360 EXPECT_EQ(string("1 TiB"), prettyPrint(pow2(40), PRETTY_BYTES_IEC));
362 // check bytes metric printing
363 EXPECT_EQ(string("853 B "), prettyPrint(853., PRETTY_BYTES_METRIC));
364 EXPECT_EQ(string("853 kB"), prettyPrint(853.e3, PRETTY_BYTES_METRIC));
365 EXPECT_EQ(string("853 MB"), prettyPrint(853.e6, PRETTY_BYTES_METRIC));
366 EXPECT_EQ(string("8.53 GB"), prettyPrint(8.53e9, PRETTY_BYTES_METRIC));
367 EXPECT_EQ(string("853 GB"), prettyPrint(853.e9, PRETTY_BYTES_METRIC));
368 EXPECT_EQ(string("853 TB"), prettyPrint(853.e12, PRETTY_BYTES_METRIC));
370 EXPECT_EQ(string("0 B "), prettyPrint(0, PRETTY_BYTES_METRIC));
371 EXPECT_EQ(string("1 B "), prettyPrint(1.0, PRETTY_BYTES_METRIC));
372 EXPECT_EQ(string("1 kB"), prettyPrint(1.0e+3, PRETTY_BYTES_METRIC));
373 EXPECT_EQ(string("1 MB"), prettyPrint(1.0e+6, PRETTY_BYTES_METRIC));
375 EXPECT_EQ(string("1 GB"), prettyPrint(1.0e+9, PRETTY_BYTES_METRIC));
376 EXPECT_EQ(string("1 TB"), prettyPrint(1.0e+12, PRETTY_BYTES_METRIC));
378 // check metric-units (powers of 1000) printing
379 EXPECT_EQ(string("853 "), prettyPrint(853., PRETTY_UNITS_METRIC));
380 EXPECT_EQ(string("853 k"), prettyPrint(853.e3, PRETTY_UNITS_METRIC));
381 EXPECT_EQ(string("853 M"), prettyPrint(853.e6, PRETTY_UNITS_METRIC));
382 EXPECT_EQ(string("8.53 bil"), prettyPrint(8.53e9, PRETTY_UNITS_METRIC));
383 EXPECT_EQ(string("853 bil"), prettyPrint(853.e9, PRETTY_UNITS_METRIC));
384 EXPECT_EQ(string("853 tril"), prettyPrint(853.e12, PRETTY_UNITS_METRIC));
386 // check binary-units (powers of 1024) printing
387 EXPECT_EQ(string("0 "), prettyPrint(0, PRETTY_UNITS_BINARY));
388 EXPECT_EQ(string("1 "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY));
389 EXPECT_EQ(string("1 k"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY));
390 EXPECT_EQ(string("1 M"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY));
391 EXPECT_EQ(string("1 G"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY));
392 EXPECT_EQ(string("1 T"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY));
394 EXPECT_EQ(string("1023 "),
395 prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY));
396 EXPECT_EQ(string("1024 k"),
397 prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY));
398 EXPECT_EQ(string("1024 M"),
399 prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY));
400 EXPECT_EQ(string("1024 G"),
401 prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY));
403 EXPECT_EQ(string("0 "), prettyPrint(0, PRETTY_UNITS_BINARY_IEC));
404 EXPECT_EQ(string("1 "), prettyPrint(pow2(0), PRETTY_UNITS_BINARY_IEC));
405 EXPECT_EQ(string("1 Ki"), prettyPrint(pow2(10), PRETTY_UNITS_BINARY_IEC));
406 EXPECT_EQ(string("1 Mi"), prettyPrint(pow2(20), PRETTY_UNITS_BINARY_IEC));
407 EXPECT_EQ(string("1 Gi"), prettyPrint(pow2(30), PRETTY_UNITS_BINARY_IEC));
408 EXPECT_EQ(string("1 Ti"), prettyPrint(pow2(40), PRETTY_UNITS_BINARY_IEC));
410 EXPECT_EQ(string("1023 "),
411 prettyPrint(pow2(10) - 1, PRETTY_UNITS_BINARY_IEC));
412 EXPECT_EQ(string("1024 Ki"),
413 prettyPrint(pow2(20) - 1, PRETTY_UNITS_BINARY_IEC));
414 EXPECT_EQ(string("1024 Mi"),
415 prettyPrint(pow2(30) - 1, PRETTY_UNITS_BINARY_IEC));
416 EXPECT_EQ(string("1024 Gi"),
417 prettyPrint(pow2(40) - 1, PRETTY_UNITS_BINARY_IEC));
419 // check that negative values work
420 EXPECT_EQ(string("-85.3 s "), prettyPrint(-85.3, PRETTY_TIME));
421 EXPECT_EQ(string("-85.3 ms"), prettyPrint(-85.3e-3, PRETTY_TIME));
422 EXPECT_EQ(string("-85.3 us"), prettyPrint(-85.3e-6, PRETTY_TIME));
423 EXPECT_EQ(string("-85.3 ns"), prettyPrint(-85.3e-9, PRETTY_TIME));
426 TEST(PrettyPrint, HexDump) {
427 std::string a("abc\x00\x02\xa0", 6); // embedded NUL
429 "00000000 61 62 63 00 02 a0 "
431 hexDump(a.data(), a.size()));
433 a = "abcdefghijklmnopqrstuvwxyz";
435 "00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 "
436 "|abcdefghijklmnop|\n"
437 "00000010 71 72 73 74 75 76 77 78 79 7a "
439 hexDump(a.data(), a.size()));
442 TEST(System, errnoStr) {
444 EXPECT_EQ(EACCES, errno);
445 EXPECT_EQ(EACCES, errno); // twice to make sure EXPECT_EQ doesn't change it
447 fbstring expected = strerror(ENOENT);
450 EXPECT_EQ(expected, errnoStr(ENOENT));
451 // Ensure that errno isn't changed
452 EXPECT_EQ(EACCES, errno);
454 // Per POSIX, all errno values are positive, so -1 is invalid
457 // Ensure that errno isn't changed
458 EXPECT_EQ(EACCES, errno);
461 namespace folly_test {
462 struct ThisIsAVeryLongStructureName {
464 } // namespace folly_test
466 TEST(System, demangle) {
467 EXPECT_EQ("folly_test::ThisIsAVeryLongStructureName",
468 demangle(typeid(folly_test::ThisIsAVeryLongStructureName)));
473 template<template<class,class> class VectorType>
475 VectorType<string,std::allocator<string> > parts;
477 folly::split(',', "a,b,c", parts);
478 EXPECT_EQ(parts.size(), 3);
479 EXPECT_EQ(parts[0], "a");
480 EXPECT_EQ(parts[1], "b");
481 EXPECT_EQ(parts[2], "c");
484 folly::split(',', string("a,b,c"), parts);
485 EXPECT_EQ(parts.size(), 3);
486 EXPECT_EQ(parts[0], "a");
487 EXPECT_EQ(parts[1], "b");
488 EXPECT_EQ(parts[2], "c");
491 folly::split(',', "a,,c", parts);
492 EXPECT_EQ(parts.size(), 3);
493 EXPECT_EQ(parts[0], "a");
494 EXPECT_EQ(parts[1], "");
495 EXPECT_EQ(parts[2], "c");
498 folly::split(',', string("a,,c"), parts);
499 EXPECT_EQ(parts.size(), 3);
500 EXPECT_EQ(parts[0], "a");
501 EXPECT_EQ(parts[1], "");
502 EXPECT_EQ(parts[2], "c");
505 folly::split(',', "a,,c", parts, true);
506 EXPECT_EQ(parts.size(), 2);
507 EXPECT_EQ(parts[0], "a");
508 EXPECT_EQ(parts[1], "c");
511 folly::split(',', string("a,,c"), parts, true);
512 EXPECT_EQ(parts.size(), 2);
513 EXPECT_EQ(parts[0], "a");
514 EXPECT_EQ(parts[1], "c");
517 folly::split(',', string(",,a,,c,,,"), parts, true);
518 EXPECT_EQ(parts.size(), 2);
519 EXPECT_EQ(parts[0], "a");
520 EXPECT_EQ(parts[1], "c");
523 // test multiple split w/o clear
524 folly::split(',', ",,a,,c,,,", parts, true);
525 EXPECT_EQ(parts.size(), 2);
526 EXPECT_EQ(parts[0], "a");
527 EXPECT_EQ(parts[1], "c");
528 folly::split(',', ",,a,,c,,,", parts, true);
529 EXPECT_EQ(parts.size(), 4);
530 EXPECT_EQ(parts[2], "a");
531 EXPECT_EQ(parts[3], "c");
534 // test splits that with multi-line delimiter
535 folly::split("ab", "dabcabkdbkab", parts, true);
536 EXPECT_EQ(parts.size(), 3);
537 EXPECT_EQ(parts[0], "d");
538 EXPECT_EQ(parts[1], "c");
539 EXPECT_EQ(parts[2], "kdbk");
542 string orig = "ab2342asdfv~~!";
543 folly::split("", orig, parts, true);
544 EXPECT_EQ(parts.size(), 1);
545 EXPECT_EQ(parts[0], orig);
548 folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
549 EXPECT_EQ(parts.size(), 1);
550 EXPECT_EQ(parts[0], "asfds");
553 folly::split("a", "", parts, true);
554 EXPECT_EQ(parts.size(), 0);
557 folly::split("a", "", parts);
558 EXPECT_EQ(parts.size(), 1);
559 EXPECT_EQ(parts[0], "");
562 folly::split("a", "abcdefg", parts, true);
563 EXPECT_EQ(parts.size(), 1);
564 EXPECT_EQ(parts[0], "bcdefg");
567 orig = "All, , your bases, are , , belong to us";
568 folly::split(", ", orig, parts, true);
569 EXPECT_EQ(parts.size(), 4);
570 EXPECT_EQ(parts[0], "All");
571 EXPECT_EQ(parts[1], "your bases");
572 EXPECT_EQ(parts[2], "are ");
573 EXPECT_EQ(parts[3], "belong to us");
575 folly::split(", ", orig, parts);
576 EXPECT_EQ(parts.size(), 6);
577 EXPECT_EQ(parts[0], "All");
578 EXPECT_EQ(parts[1], "");
579 EXPECT_EQ(parts[2], "your bases");
580 EXPECT_EQ(parts[3], "are ");
581 EXPECT_EQ(parts[4], "");
582 EXPECT_EQ(parts[5], "belong to us");
585 orig = ", Facebook, rul,es!, ";
586 folly::split(", ", orig, parts, true);
587 EXPECT_EQ(parts.size(), 2);
588 EXPECT_EQ(parts[0], "Facebook");
589 EXPECT_EQ(parts[1], "rul,es!");
591 folly::split(", ", orig, parts);
592 EXPECT_EQ(parts.size(), 4);
593 EXPECT_EQ(parts[0], "");
594 EXPECT_EQ(parts[1], "Facebook");
595 EXPECT_EQ(parts[2], "rul,es!");
596 EXPECT_EQ(parts[3], "");
599 template<template<class,class> class VectorType>
601 VectorType<StringPiece,std::allocator<StringPiece> > pieces;
602 VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
604 folly::split(',', "a,b,c", pieces);
605 EXPECT_EQ(pieces.size(), 3);
606 EXPECT_EQ(pieces[0], "a");
607 EXPECT_EQ(pieces[1], "b");
608 EXPECT_EQ(pieces[2], "c");
612 folly::split(',', "a,,c", pieces);
613 EXPECT_EQ(pieces.size(), 3);
614 EXPECT_EQ(pieces[0], "a");
615 EXPECT_EQ(pieces[1], "");
616 EXPECT_EQ(pieces[2], "c");
619 folly::split(',', "a,,c", pieces, true);
620 EXPECT_EQ(pieces.size(), 2);
621 EXPECT_EQ(pieces[0], "a");
622 EXPECT_EQ(pieces[1], "c");
625 folly::split(',', ",,a,,c,,,", pieces, true);
626 EXPECT_EQ(pieces.size(), 2);
627 EXPECT_EQ(pieces[0], "a");
628 EXPECT_EQ(pieces[1], "c");
631 // test multiple split w/o clear
632 folly::split(',', ",,a,,c,,,", pieces, true);
633 EXPECT_EQ(pieces.size(), 2);
634 EXPECT_EQ(pieces[0], "a");
635 EXPECT_EQ(pieces[1], "c");
636 folly::split(',', ",,a,,c,,,", pieces, true);
637 EXPECT_EQ(pieces.size(), 4);
638 EXPECT_EQ(pieces[2], "a");
639 EXPECT_EQ(pieces[3], "c");
642 // test multiple split rounds
643 folly::split(",", "a_b,c_d", pieces);
644 EXPECT_EQ(pieces.size(), 2);
645 EXPECT_EQ(pieces[0], "a_b");
646 EXPECT_EQ(pieces[1], "c_d");
647 folly::split("_", pieces[0], pieces2);
648 EXPECT_EQ(pieces2.size(), 2);
649 EXPECT_EQ(pieces2[0], "a");
650 EXPECT_EQ(pieces2[1], "b");
652 folly::split("_", pieces[1], pieces2);
653 EXPECT_EQ(pieces2.size(), 2);
654 EXPECT_EQ(pieces2[0], "c");
655 EXPECT_EQ(pieces2[1], "d");
659 // test splits that with multi-line delimiter
660 folly::split("ab", "dabcabkdbkab", pieces, true);
661 EXPECT_EQ(pieces.size(), 3);
662 EXPECT_EQ(pieces[0], "d");
663 EXPECT_EQ(pieces[1], "c");
664 EXPECT_EQ(pieces[2], "kdbk");
667 string orig = "ab2342asdfv~~!";
668 folly::split("", orig.c_str(), pieces, true);
669 EXPECT_EQ(pieces.size(), 1);
670 EXPECT_EQ(pieces[0], orig);
673 folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
674 EXPECT_EQ(pieces.size(), 1);
675 EXPECT_EQ(pieces[0], "asfds");
678 folly::split("a", "", pieces, true);
679 EXPECT_EQ(pieces.size(), 0);
682 folly::split("a", "", pieces);
683 EXPECT_EQ(pieces.size(), 1);
684 EXPECT_EQ(pieces[0], "");
687 folly::split("a", "abcdefg", pieces, true);
688 EXPECT_EQ(pieces.size(), 1);
689 EXPECT_EQ(pieces[0], "bcdefg");
692 orig = "All, , your bases, are , , belong to us";
693 folly::split(", ", orig, pieces, true);
694 EXPECT_EQ(pieces.size(), 4);
695 EXPECT_EQ(pieces[0], "All");
696 EXPECT_EQ(pieces[1], "your bases");
697 EXPECT_EQ(pieces[2], "are ");
698 EXPECT_EQ(pieces[3], "belong to us");
700 folly::split(", ", orig, pieces);
701 EXPECT_EQ(pieces.size(), 6);
702 EXPECT_EQ(pieces[0], "All");
703 EXPECT_EQ(pieces[1], "");
704 EXPECT_EQ(pieces[2], "your bases");
705 EXPECT_EQ(pieces[3], "are ");
706 EXPECT_EQ(pieces[4], "");
707 EXPECT_EQ(pieces[5], "belong to us");
710 orig = ", Facebook, rul,es!, ";
711 folly::split(", ", orig, pieces, true);
712 EXPECT_EQ(pieces.size(), 2);
713 EXPECT_EQ(pieces[0], "Facebook");
714 EXPECT_EQ(pieces[1], "rul,es!");
716 folly::split(", ", orig, pieces);
717 EXPECT_EQ(pieces.size(), 4);
718 EXPECT_EQ(pieces[0], "");
719 EXPECT_EQ(pieces[1], "Facebook");
720 EXPECT_EQ(pieces[2], "rul,es!");
721 EXPECT_EQ(pieces[3], "");
724 const char* str = "a,b";
725 folly::split(',', StringPiece(str), pieces);
726 EXPECT_EQ(pieces.size(), 2);
727 EXPECT_EQ(pieces[0], "a");
728 EXPECT_EQ(pieces[1], "b");
729 EXPECT_EQ(pieces[0].start(), str);
730 EXPECT_EQ(pieces[1].start(), str + 2);
732 std::set<StringPiece> unique;
733 folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
734 std::inserter(unique, unique.begin()), true);
735 EXPECT_EQ(unique.size(), 3);
736 if (unique.size() == 3) {
737 EXPECT_EQ(*unique.begin(), "asd");
738 EXPECT_EQ(*--unique.end(), "csd");
741 VectorType<fbstring,std::allocator<fbstring> > blah;
742 folly::split('-', "a-b-c-d-f-e", blah);
743 EXPECT_EQ(blah.size(), 6);
748 TEST(Split, split_vector) {
749 splitTest<std::vector>();
751 TEST(Split, split_fbvector) {
752 splitTest<folly::fbvector>();
754 TEST(Split, pieces_vector) {
755 piecesTest<std::vector>();
757 TEST(Split, pieces_fbvector) {
758 piecesTest<folly::fbvector>();
764 std::vector<int> empty = { };
765 join(":", empty, output);
766 EXPECT_TRUE(output.empty());
768 std::vector<std::string> input1 = { "1", "23", "456", "" };
769 join(':', input1, output);
770 EXPECT_EQ(output, "1:23:456:");
771 output = join(':', input1);
772 EXPECT_EQ(output, "1:23:456:");
774 auto input2 = { 1, 23, 456 };
775 join("-*-", input2, output);
776 EXPECT_EQ(output, "1-*-23-*-456");
777 output = join("-*-", input2);
778 EXPECT_EQ(output, "1-*-23-*-456");
780 auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
781 join("", input3, output);
782 EXPECT_EQ(output, "facebook");
785 TEST(String, hexlify) {
786 string input1 = "0123";
788 EXPECT_TRUE(hexlify(input1, output1));
789 EXPECT_EQ(output1, "30313233");
791 fbstring input2 = "abcdefg";
796 EXPECT_TRUE(hexlify(input2, output2));
797 EXPECT_EQ(output2, "610063ff65b667");
800 TEST(String, unhexlify) {
801 string input1 = "30313233";
803 EXPECT_TRUE(unhexlify(input1, output1));
804 EXPECT_EQ(output1, "0123");
806 fbstring input2 = "610063ff65b667";
808 EXPECT_TRUE(unhexlify(input2, output2));
809 EXPECT_EQ(output2.size(), 7);
810 EXPECT_EQ(output2[0], 'a');
811 EXPECT_EQ(output2[1], 0);
812 EXPECT_EQ(output2[2], 'c');
813 EXPECT_EQ(output2[3] & 0xff, 0xff);
814 EXPECT_EQ(output2[4], 'e');
815 EXPECT_EQ(output2[5] & 0xff, 0xb6);
816 EXPECT_EQ(output2[6], 'g');
820 EXPECT_FALSE(unhexlify(input3, output3));
822 string input4 = "xy";
824 EXPECT_FALSE(unhexlify(input4, output4));
827 TEST(String, backslashify) {
828 EXPECT_EQ("abc", string("abc"));
829 EXPECT_EQ("abc", backslashify(string("abc")));
830 EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
831 EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
832 EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
835 TEST(String, humanify) {
836 // Simple cases; output is obvious.
837 EXPECT_EQ("abc", humanify(string("abc")));
838 EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
839 EXPECT_EQ("0xff", humanify(string("\xff")));
840 EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
841 EXPECT_EQ("abc\\b", humanify(string("abc\b")));
842 EXPECT_EQ("0x00", humanify(string(1, '\0')));
843 EXPECT_EQ("0x0000", humanify(string(2, '\0')));
846 // Mostly printable, so backslash! 80, 60, and 40% printable, respectively
847 EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
848 EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
849 EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
851 // 20% printable, and the printable portion isn't the prefix; hexify!
852 EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
854 // Same as previous, except swap first two chars; prefix is
855 // printable and within the threshold, so backslashify.
856 EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
858 // Just too much unprintable; hex, despite prefix.
859 EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
862 //////////////////////////////////////////////////////////////////////
864 BENCHMARK(splitOnSingleChar, iters) {
865 static const std::string line = "one:two:three:four";
866 for (int i = 0; i < iters << 4; ++i) {
867 std::vector<StringPiece> pieces;
868 folly::split(':', line, pieces);
872 BENCHMARK(splitStr, iters) {
873 static const std::string line = "one-*-two-*-three-*-four";
874 for (int i = 0; i < iters << 4; ++i) {
875 std::vector<StringPiece> pieces;
876 folly::split("-*-", line, pieces);
880 BENCHMARK(boost_splitOnSingleChar, iters) {
881 static const std::string line = "one:two:three:four";
882 for (int i = 0; i < iters << 4; ++i) {
883 std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
884 boost::split(pieces, line, [] (char c) { return c == ':'; });
888 BENCHMARK(joinCharStr, iters) {
889 static const std::vector<std::string> input = {
890 "one", "two", "three", "four", "five", "six", "seven" };
891 for (int i = 0; i < iters << 4; ++i) {
893 folly::join(':', input, output);
897 BENCHMARK(joinStrStr, iters) {
898 static const std::vector<std::string> input = {
899 "one", "two", "three", "four", "five", "six", "seven" };
900 for (int i = 0; i < iters << 4; ++i) {
902 folly::join(":", input, output);
906 BENCHMARK(joinInt, iters) {
907 static const auto input = {
908 123, 456, 78910, 1112, 1314, 151, 61718 };
909 for (int i = 0; i < iters << 4; ++i) {
911 folly::join(":", input, output);
915 int main(int argc, char *argv[]) {
916 testing::InitGoogleTest(&argc, argv);
917 google::ParseCommandLineFlags(&argc, &argv, true);
918 auto ret = RUN_ALL_TESTS();
921 if (FLAGS_benchmark) {
922 folly::runBenchmarks();