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>
19 #include <gtest/gtest.h>
21 using namespace folly;
24 TEST(StringPrintf, BasicTest) {
25 EXPECT_EQ("abc", stringPrintf("%s", "abc"));
26 EXPECT_EQ("abc", stringPrintf("%sbc", "a"));
27 EXPECT_EQ("abc", stringPrintf("a%sc", "b"));
28 EXPECT_EQ("abc", stringPrintf("ab%s", "c"));
30 EXPECT_EQ("abc", stringPrintf("abc"));
33 TEST(StringPrintf, NumericFormats) {
34 EXPECT_EQ("12", stringPrintf("%d", 12));
35 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000UL));
36 EXPECT_EQ("5000000000", stringPrintf("%ld", 5000000000L));
37 EXPECT_EQ("-5000000000", stringPrintf("%ld", -5000000000L));
38 EXPECT_EQ("-1", stringPrintf("%d", 0xffffffff));
39 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffff));
40 EXPECT_EQ("-1", stringPrintf("%ld", 0xffffffffffffffffUL));
42 EXPECT_EQ("7.7", stringPrintf("%1.1f", 7.7));
43 EXPECT_EQ("7.7", stringPrintf("%1.1lf", 7.7));
44 EXPECT_EQ("7.70000000000000018",
45 stringPrintf("%.17f", 7.7));
46 EXPECT_EQ("7.70000000000000018",
47 stringPrintf("%.17lf", 7.7));
50 TEST(StringPrintf, Appending) {
52 stringAppendf(&s, "a%s", "b");
53 stringAppendf(&s, "%c", 'c');
55 stringAppendf(&s, " %d", 123);
56 EXPECT_EQ(s, "abc 123");
59 void vprintfCheck(const char* expected, const char* fmt, ...) {
61 va_start(apOrig, fmt);
71 // Check both APIs for calling stringVPrintf()
72 EXPECT_EQ(expected, stringVPrintf(fmt, ap));
77 stringVPrintf(&out, fmt, ap);
80 EXPECT_EQ(expected, out);
82 // Check stringVAppendf() as well
83 std::string prefix = "foobar";
85 EXPECT_EQ(prefix + expected, stringVAppendf(&out, fmt, ap));
90 void vprintfError(const char* fmt, ...) {
97 // OSX's sprintf family does not return a negative number on a bad format
98 // string, but Linux does. It's unclear to me which behavior is more
100 #ifdef HAVE_VSNPRINTF_ERRORS
101 EXPECT_THROW({stringVPrintf(fmt, ap);},
106 TEST(StringPrintf, VPrintf) {
107 vprintfCheck("foo", "%s", "foo");
108 vprintfCheck("long string requiring reallocation 1 2 3 0x12345678",
109 "%s %s %d %d %d %#x",
110 "long string", "requiring reallocation", 1, 2, 3, 0x12345678);
111 vprintfError("bogus%", "foo");
114 TEST(StringPrintf, VariousSizes) {
115 // Test a wide variety of output sizes, making sure to cross the
116 // vsnprintf buffer boundary implementation detail.
117 for (int i = 0; i < 4096; ++i) {
118 string expected(i + 1, 'a');
119 expected = "X" + expected + "X";
120 string result = stringPrintf("%s", expected.c_str());
121 EXPECT_EQ(expected.size(), result.size());
122 EXPECT_EQ(expected, result);
125 EXPECT_EQ("abc12345678910111213141516171819202122232425xyz",
126 stringPrintf("abc%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
127 "%d%d%d%d%d%d%d%d%d%d%dxyz",
128 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
129 17, 18, 19, 20, 21, 22, 23, 24, 25));
132 TEST(StringPrintf, oldStringPrintfTests) {
133 EXPECT_EQ(string("a/b/c/d"),
134 stringPrintf("%s/%s/%s/%s", "a", "b", "c", "d"));
136 EXPECT_EQ(string(" 5 10"),
137 stringPrintf("%5d %5d", 5, 10));
139 // check printing w/ a big buffer
140 for (int size = (1 << 8); size <= (1 << 15); size <<= 1) {
142 string b = stringPrintf("%s", a.c_str());
143 EXPECT_EQ(a.size(), b.size());
147 TEST(StringPrintf, oldStringAppendf) {
149 stringAppendf(&s, "%s/%s/%s/%s", "a", "b", "c", "d");
150 EXPECT_EQ(string("helloa/b/c/d"), s);
153 TEST(Escape, cEscape) {
154 EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
155 EXPECT_EQ("hello \\\\world\\\" goodbye",
156 cEscape<std::string>("hello \\world\" goodbye"));
157 EXPECT_EQ("hello\\nworld", cEscape<std::string>("hello\nworld"));
158 EXPECT_EQ("hello\\377\\376", cEscape<std::string>("hello\xff\xfe"));
161 TEST(Escape, cUnescape) {
162 EXPECT_EQ("hello world", cUnescape<std::string>("hello world"));
163 EXPECT_EQ("hello \\world\" goodbye",
164 cUnescape<std::string>("hello \\\\world\\\" goodbye"));
165 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\nworld"));
166 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\012world"));
167 EXPECT_EQ("hello\nworld", cUnescape<std::string>("hello\\x0aworld"));
168 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\377\\376"));
169 EXPECT_EQ("hello\xff\xfe", cUnescape<std::string>("hello\\xff\\xfe"));
171 EXPECT_THROW({cUnescape<std::string>("hello\\");},
172 std::invalid_argument);
173 EXPECT_THROW({cUnescape<std::string>("hello\\x");},
174 std::invalid_argument);
175 EXPECT_THROW({cUnescape<std::string>("hello\\q");},
176 std::invalid_argument);
179 TEST(Escape, uriEscape) {
180 EXPECT_EQ("hello%2c%20%2fworld", uriEscape<std::string>("hello, /world"));
181 EXPECT_EQ("hello%2c%20/world", uriEscape<std::string>("hello, /world",
182 UriEscapeMode::PATH));
183 EXPECT_EQ("hello%2c+%2fworld", uriEscape<std::string>("hello, /world",
184 UriEscapeMode::QUERY));
186 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~",
187 uriEscape<std::string>(
188 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~")
192 TEST(Escape, uriUnescape) {
193 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello, /world"));
194 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c%20%2fworld"));
195 EXPECT_EQ("hello,+/world", uriUnescape<std::string>("hello%2c+%2fworld"));
196 EXPECT_EQ("hello, /world", uriUnescape<std::string>("hello%2c+%2fworld",
197 UriEscapeMode::QUERY));
198 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2f"));
199 EXPECT_EQ("hello/", uriUnescape<std::string>("hello%2F"));
200 EXPECT_THROW({uriUnescape<std::string>("hello%");},
201 std::invalid_argument);
202 EXPECT_THROW({uriUnescape<std::string>("hello%2");},
203 std::invalid_argument);
204 EXPECT_THROW({uriUnescape<std::string>("hello%2g");},
205 std::invalid_argument);
209 void expectPrintable(StringPiece s) {
217 TEST(Escape, uriEscapeAllCombinations) {
220 StringPiece in(c, 2);
223 for (int i = 0; i < 256; ++i) {
225 for (int j = 0; j < 256; ++j) {
230 expectPrintable(tmp);
231 uriUnescape(tmp, out);
239 return ((v >= '0' && v <= '9') ||
240 (v >= 'A' && v <= 'F') ||
241 (v >= 'a' && v <= 'f'));
245 TEST(Escape, uriUnescapePercentDecoding) {
246 char c[4] = {'%', '\0', '\0', '\0'};
247 StringPiece in(c, 3);
249 unsigned int expected = 0;
250 for (int i = 0; i < 256; ++i) {
252 for (int j = 0; j < 256; ++j) {
254 if (isHex(i) && isHex(j)) {
256 uriUnescape(in, out);
257 EXPECT_EQ(1, out.size());
258 EXPECT_EQ(1, sscanf(c + 1, "%x", &expected));
259 unsigned char v = out[0];
260 EXPECT_EQ(expected, v);
262 EXPECT_THROW({uriUnescape(in, out);}, std::invalid_argument);
270 double pow2(int exponent) {
271 return double(int64_t(1) << exponent);
275 struct PrettyTestCase{
276 std::string prettyString;
278 PrettyType prettyType;
281 PrettyTestCase prettyTestCases[] =
283 {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
284 {string("8.53e+07 s "), 85.3e6, PRETTY_TIME},
285 {string("85.3 ms"), 85.3e-3, PRETTY_TIME},
286 {string("85.3 us"), 85.3e-6, PRETTY_TIME},
287 {string("85.3 ns"), 85.3e-9, PRETTY_TIME},
288 {string("85.3 ps"), 85.3e-12, PRETTY_TIME},
289 {string("8.53e-14 s "), 85.3e-15, PRETTY_TIME},
291 {string("0 s "), 0, PRETTY_TIME},
292 {string("1 s "), 1.0, PRETTY_TIME},
293 {string("1 ms"), 1.0e-3, PRETTY_TIME},
294 {string("1 us"), 1.0e-6, PRETTY_TIME},
295 {string("1 ns"), 1.0e-9, PRETTY_TIME},
296 {string("1 ps"), 1.0e-12, PRETTY_TIME},
298 // check bytes printing
299 {string("853 B "), 853., PRETTY_BYTES},
300 {string("833 kB"), 853.e3, PRETTY_BYTES},
301 {string("813.5 MB"), 853.e6, PRETTY_BYTES},
302 {string("7.944 GB"), 8.53e9, PRETTY_BYTES},
303 {string("794.4 GB"), 853.e9, PRETTY_BYTES},
304 {string("775.8 TB"), 853.e12, PRETTY_BYTES},
306 {string("0 B "), 0, PRETTY_BYTES},
307 {string("1 B "), pow2(0), PRETTY_BYTES},
308 {string("1 kB"), pow2(10), PRETTY_BYTES},
309 {string("1 MB"), pow2(20), PRETTY_BYTES},
310 {string("1 GB"), pow2(30), PRETTY_BYTES},
311 {string("1 TB"), pow2(40), PRETTY_BYTES},
313 {string("853 B "), 853., PRETTY_BYTES_IEC},
314 {string("833 KiB"), 853.e3, PRETTY_BYTES_IEC},
315 {string("813.5 MiB"), 853.e6, PRETTY_BYTES_IEC},
316 {string("7.944 GiB"), 8.53e9, PRETTY_BYTES_IEC},
317 {string("794.4 GiB"), 853.e9, PRETTY_BYTES_IEC},
318 {string("775.8 TiB"), 853.e12, PRETTY_BYTES_IEC},
320 {string("0 B "), 0, PRETTY_BYTES_IEC},
321 {string("1 B "), pow2(0), PRETTY_BYTES_IEC},
322 {string("1 KiB"), pow2(10), PRETTY_BYTES_IEC},
323 {string("1 MiB"), pow2(20), PRETTY_BYTES_IEC},
324 {string("1 GiB"), pow2(30), PRETTY_BYTES_IEC},
325 {string("1 TiB"), pow2(40), PRETTY_BYTES_IEC},
327 // check bytes metric printing
328 {string("853 B "), 853., PRETTY_BYTES_METRIC},
329 {string("853 kB"), 853.e3, PRETTY_BYTES_METRIC},
330 {string("853 MB"), 853.e6, PRETTY_BYTES_METRIC},
331 {string("8.53 GB"), 8.53e9, PRETTY_BYTES_METRIC},
332 {string("853 GB"), 853.e9, PRETTY_BYTES_METRIC},
333 {string("853 TB"), 853.e12, PRETTY_BYTES_METRIC},
335 {string("0 B "), 0, PRETTY_BYTES_METRIC},
336 {string("1 B "), 1.0, PRETTY_BYTES_METRIC},
337 {string("1 kB"), 1.0e+3, PRETTY_BYTES_METRIC},
338 {string("1 MB"), 1.0e+6, PRETTY_BYTES_METRIC},
340 {string("1 GB"), 1.0e+9, PRETTY_BYTES_METRIC},
341 {string("1 TB"), 1.0e+12, PRETTY_BYTES_METRIC},
343 // check metric-units (powers of 1000) printing
344 {string("853 "), 853., PRETTY_UNITS_METRIC},
345 {string("853 k"), 853.e3, PRETTY_UNITS_METRIC},
346 {string("853 M"), 853.e6, PRETTY_UNITS_METRIC},
347 {string("8.53 bil"), 8.53e9, PRETTY_UNITS_METRIC},
348 {string("853 bil"), 853.e9, PRETTY_UNITS_METRIC},
349 {string("853 tril"), 853.e12, PRETTY_UNITS_METRIC},
351 // check binary-units (powers of 1024) printing
352 {string("0 "), 0, PRETTY_UNITS_BINARY},
353 {string("1 "), pow2(0), PRETTY_UNITS_BINARY},
354 {string("1 k"), pow2(10), PRETTY_UNITS_BINARY},
355 {string("1 M"), pow2(20), PRETTY_UNITS_BINARY},
356 {string("1 G"), pow2(30), PRETTY_UNITS_BINARY},
357 {string("1 T"), pow2(40), PRETTY_UNITS_BINARY},
359 {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY},
360 {string("1024 k"), pow2(20) - 1, PRETTY_UNITS_BINARY},
361 {string("1024 M"), pow2(30) - 1, PRETTY_UNITS_BINARY},
362 {string("1024 G"), pow2(40) - 1, PRETTY_UNITS_BINARY},
364 {string("0 "), 0, PRETTY_UNITS_BINARY_IEC},
365 {string("1 "), pow2(0), PRETTY_UNITS_BINARY_IEC},
366 {string("1 Ki"), pow2(10), PRETTY_UNITS_BINARY_IEC},
367 {string("1 Mi"), pow2(20), PRETTY_UNITS_BINARY_IEC},
368 {string("1 Gi"), pow2(30), PRETTY_UNITS_BINARY_IEC},
369 {string("1 Ti"), pow2(40), PRETTY_UNITS_BINARY_IEC},
371 {string("1023 "), pow2(10) - 1, PRETTY_UNITS_BINARY_IEC},
372 {string("1024 Ki"), pow2(20) - 1, PRETTY_UNITS_BINARY_IEC},
373 {string("1024 Mi"), pow2(30) - 1, PRETTY_UNITS_BINARY_IEC},
374 {string("1024 Gi"), pow2(40) - 1, PRETTY_UNITS_BINARY_IEC},
376 //check border SI cases
378 {string("1 Y"), 1e24, PRETTY_SI},
379 {string("10 Y"), 1e25, PRETTY_SI},
380 {string("1 y"), 1e-24, PRETTY_SI},
381 {string("10 y"), 1e-23, PRETTY_SI},
383 // check that negative values work
384 {string("-85.3 s "), -85.3, PRETTY_TIME},
385 {string("-85.3 ms"), -85.3e-3, PRETTY_TIME},
386 {string("-85.3 us"), -85.3e-6, PRETTY_TIME},
387 {string("-85.3 ns"), -85.3e-9, PRETTY_TIME},
389 {string("endoftest"), 0, PRETTY_NUM_TYPES}
392 TEST(PrettyPrint, Basic) {
393 for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
394 const PrettyTestCase& prettyTest = prettyTestCases[i];
395 EXPECT_EQ(prettyTest.prettyString,
396 prettyPrint(prettyTest.realValue, prettyTest.prettyType));
400 TEST(PrettyToDouble, Basic) {
401 // check manually created tests
402 for (int i = 0; prettyTestCases[i].prettyType != PRETTY_NUM_TYPES; ++i){
403 PrettyTestCase testCase = prettyTestCases[i];
404 PrettyType formatType = testCase.prettyType;
405 double x = testCase.realValue;
406 std::string testString = testCase.prettyString;
407 double recoveredX = 0;
409 recoveredX = prettyToDouble(testString, formatType);
410 } catch (std::range_error &ex){
413 double relativeError = fabs(x) < 1e-5 ? (x-recoveredX) :
414 (x - recoveredX) / x;
415 EXPECT_NEAR(0, relativeError, 1e-3);
418 // checks for compatibility with prettyPrint over the whole parameter space
419 for (int i = 0 ; i < PRETTY_NUM_TYPES; ++i){
420 PrettyType formatType = static_cast<PrettyType>(i);
421 for (double x = 1e-18; x < 1e40; x *= 1.9){
422 bool addSpace = static_cast<PrettyType> (i) == PRETTY_SI;
423 for (int it = 0; it < 2; ++it, addSpace = true){
424 double recoveredX = 0;
426 recoveredX = prettyToDouble(prettyPrint(x, formatType, addSpace),
428 } catch (std::range_error &ex){
431 double relativeError = (x - recoveredX) / x;
432 EXPECT_NEAR(0, relativeError, 1e-3);
437 // check for incorrect values
438 EXPECT_THROW(prettyToDouble("10Mx", PRETTY_SI), std::range_error);
439 EXPECT_THROW(prettyToDouble("10 Mx", PRETTY_SI), std::range_error);
440 EXPECT_THROW(prettyToDouble("10 M x", PRETTY_SI), std::range_error);
442 StringPiece testString = "10Mx";
443 EXPECT_DOUBLE_EQ(prettyToDouble(&testString, PRETTY_UNITS_METRIC), 10e6);
444 EXPECT_EQ(testString, "x");
447 TEST(PrettyPrint, HexDump) {
448 std::string a("abc\x00\x02\xa0", 6); // embedded NUL
450 "00000000 61 62 63 00 02 a0 "
452 hexDump(a.data(), a.size()));
454 a = "abcdefghijklmnopqrstuvwxyz";
456 "00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 "
457 "|abcdefghijklmnop|\n"
458 "00000010 71 72 73 74 75 76 77 78 79 7a "
460 hexDump(a.data(), a.size()));
463 TEST(System, errnoStr) {
465 EXPECT_EQ(EACCES, errno);
466 EXPECT_EQ(EACCES, errno); // twice to make sure EXPECT_EQ doesn't change it
468 fbstring expected = strerror(ENOENT);
471 EXPECT_EQ(expected, errnoStr(ENOENT));
472 // Ensure that errno isn't changed
473 EXPECT_EQ(EACCES, errno);
475 // Per POSIX, all errno values are positive, so -1 is invalid
478 // Ensure that errno isn't changed
479 EXPECT_EQ(EACCES, errno);
484 template<template<class,class> class VectorType>
486 VectorType<string,std::allocator<string> > parts;
488 folly::split(',', "a,b,c", parts);
489 EXPECT_EQ(parts.size(), 3);
490 EXPECT_EQ(parts[0], "a");
491 EXPECT_EQ(parts[1], "b");
492 EXPECT_EQ(parts[2], "c");
495 folly::split(',', StringPiece("a,b,c"), parts);
496 EXPECT_EQ(parts.size(), 3);
497 EXPECT_EQ(parts[0], "a");
498 EXPECT_EQ(parts[1], "b");
499 EXPECT_EQ(parts[2], "c");
502 folly::split(',', string("a,b,c"), parts);
503 EXPECT_EQ(parts.size(), 3);
504 EXPECT_EQ(parts[0], "a");
505 EXPECT_EQ(parts[1], "b");
506 EXPECT_EQ(parts[2], "c");
509 folly::split(',', "a,,c", parts);
510 EXPECT_EQ(parts.size(), 3);
511 EXPECT_EQ(parts[0], "a");
512 EXPECT_EQ(parts[1], "");
513 EXPECT_EQ(parts[2], "c");
516 folly::split(',', string("a,,c"), parts);
517 EXPECT_EQ(parts.size(), 3);
518 EXPECT_EQ(parts[0], "a");
519 EXPECT_EQ(parts[1], "");
520 EXPECT_EQ(parts[2], "c");
523 folly::split(',', "a,,c", parts, true);
524 EXPECT_EQ(parts.size(), 2);
525 EXPECT_EQ(parts[0], "a");
526 EXPECT_EQ(parts[1], "c");
529 folly::split(',', string("a,,c"), parts, true);
530 EXPECT_EQ(parts.size(), 2);
531 EXPECT_EQ(parts[0], "a");
532 EXPECT_EQ(parts[1], "c");
535 folly::split(',', string(",,a,,c,,,"), parts, true);
536 EXPECT_EQ(parts.size(), 2);
537 EXPECT_EQ(parts[0], "a");
538 EXPECT_EQ(parts[1], "c");
541 // test multiple split w/o clear
542 folly::split(',', ",,a,,c,,,", parts, true);
543 EXPECT_EQ(parts.size(), 2);
544 EXPECT_EQ(parts[0], "a");
545 EXPECT_EQ(parts[1], "c");
546 folly::split(',', ",,a,,c,,,", parts, true);
547 EXPECT_EQ(parts.size(), 4);
548 EXPECT_EQ(parts[2], "a");
549 EXPECT_EQ(parts[3], "c");
552 // test splits that with multi-line delimiter
553 folly::split("ab", "dabcabkdbkab", parts, true);
554 EXPECT_EQ(parts.size(), 3);
555 EXPECT_EQ(parts[0], "d");
556 EXPECT_EQ(parts[1], "c");
557 EXPECT_EQ(parts[2], "kdbk");
560 // test last part is shorter than the delimiter
561 folly::split("bc", "abcd", parts, true);
562 EXPECT_EQ(parts.size(), 2);
563 EXPECT_EQ(parts[0], "a");
564 EXPECT_EQ(parts[1], "d");
567 string orig = "ab2342asdfv~~!";
568 folly::split("", orig, parts, true);
569 EXPECT_EQ(parts.size(), 1);
570 EXPECT_EQ(parts[0], orig);
573 folly::split("452x;o38asfsajsdlfdf.j", "asfds", parts, true);
574 EXPECT_EQ(parts.size(), 1);
575 EXPECT_EQ(parts[0], "asfds");
578 folly::split("a", "", parts, true);
579 EXPECT_EQ(parts.size(), 0);
582 folly::split("a", "", parts);
583 EXPECT_EQ(parts.size(), 1);
584 EXPECT_EQ(parts[0], "");
587 folly::split("a", StringPiece(), parts, true);
588 EXPECT_EQ(parts.size(), 0);
591 folly::split("a", StringPiece(), parts);
592 EXPECT_EQ(parts.size(), 1);
593 EXPECT_EQ(parts[0], "");
596 folly::split("a", "abcdefg", parts, true);
597 EXPECT_EQ(parts.size(), 1);
598 EXPECT_EQ(parts[0], "bcdefg");
601 orig = "All, , your base, are , , belong to us";
602 folly::split(", ", orig, parts, true);
603 EXPECT_EQ(parts.size(), 4);
604 EXPECT_EQ(parts[0], "All");
605 EXPECT_EQ(parts[1], "your base");
606 EXPECT_EQ(parts[2], "are ");
607 EXPECT_EQ(parts[3], "belong to us");
609 folly::split(", ", orig, parts);
610 EXPECT_EQ(parts.size(), 6);
611 EXPECT_EQ(parts[0], "All");
612 EXPECT_EQ(parts[1], "");
613 EXPECT_EQ(parts[2], "your base");
614 EXPECT_EQ(parts[3], "are ");
615 EXPECT_EQ(parts[4], "");
616 EXPECT_EQ(parts[5], "belong to us");
619 orig = ", Facebook, rul,es!, ";
620 folly::split(", ", orig, parts, true);
621 EXPECT_EQ(parts.size(), 2);
622 EXPECT_EQ(parts[0], "Facebook");
623 EXPECT_EQ(parts[1], "rul,es!");
625 folly::split(", ", orig, parts);
626 EXPECT_EQ(parts.size(), 4);
627 EXPECT_EQ(parts[0], "");
628 EXPECT_EQ(parts[1], "Facebook");
629 EXPECT_EQ(parts[2], "rul,es!");
630 EXPECT_EQ(parts[3], "");
633 template<template<class,class> class VectorType>
635 VectorType<StringPiece,std::allocator<StringPiece> > pieces;
636 VectorType<StringPiece,std::allocator<StringPiece> > pieces2;
638 folly::split(',', "a,b,c", pieces);
639 EXPECT_EQ(pieces.size(), 3);
640 EXPECT_EQ(pieces[0], "a");
641 EXPECT_EQ(pieces[1], "b");
642 EXPECT_EQ(pieces[2], "c");
646 folly::split(',', "a,,c", pieces);
647 EXPECT_EQ(pieces.size(), 3);
648 EXPECT_EQ(pieces[0], "a");
649 EXPECT_EQ(pieces[1], "");
650 EXPECT_EQ(pieces[2], "c");
653 folly::split(',', "a,,c", pieces, true);
654 EXPECT_EQ(pieces.size(), 2);
655 EXPECT_EQ(pieces[0], "a");
656 EXPECT_EQ(pieces[1], "c");
659 folly::split(',', ",,a,,c,,,", pieces, true);
660 EXPECT_EQ(pieces.size(), 2);
661 EXPECT_EQ(pieces[0], "a");
662 EXPECT_EQ(pieces[1], "c");
665 // test multiple split w/o clear
666 folly::split(',', ",,a,,c,,,", pieces, true);
667 EXPECT_EQ(pieces.size(), 2);
668 EXPECT_EQ(pieces[0], "a");
669 EXPECT_EQ(pieces[1], "c");
670 folly::split(',', ",,a,,c,,,", pieces, true);
671 EXPECT_EQ(pieces.size(), 4);
672 EXPECT_EQ(pieces[2], "a");
673 EXPECT_EQ(pieces[3], "c");
676 // test multiple split rounds
677 folly::split(",", "a_b,c_d", pieces);
678 EXPECT_EQ(pieces.size(), 2);
679 EXPECT_EQ(pieces[0], "a_b");
680 EXPECT_EQ(pieces[1], "c_d");
681 folly::split("_", pieces[0], pieces2);
682 EXPECT_EQ(pieces2.size(), 2);
683 EXPECT_EQ(pieces2[0], "a");
684 EXPECT_EQ(pieces2[1], "b");
686 folly::split("_", pieces[1], pieces2);
687 EXPECT_EQ(pieces2.size(), 2);
688 EXPECT_EQ(pieces2[0], "c");
689 EXPECT_EQ(pieces2[1], "d");
693 // test splits that with multi-line delimiter
694 folly::split("ab", "dabcabkdbkab", pieces, true);
695 EXPECT_EQ(pieces.size(), 3);
696 EXPECT_EQ(pieces[0], "d");
697 EXPECT_EQ(pieces[1], "c");
698 EXPECT_EQ(pieces[2], "kdbk");
701 string orig = "ab2342asdfv~~!";
702 folly::split("", orig.c_str(), pieces, true);
703 EXPECT_EQ(pieces.size(), 1);
704 EXPECT_EQ(pieces[0], orig);
707 folly::split("452x;o38asfsajsdlfdf.j", "asfds", pieces, true);
708 EXPECT_EQ(pieces.size(), 1);
709 EXPECT_EQ(pieces[0], "asfds");
712 folly::split("a", "", pieces, true);
713 EXPECT_EQ(pieces.size(), 0);
716 folly::split("a", "", pieces);
717 EXPECT_EQ(pieces.size(), 1);
718 EXPECT_EQ(pieces[0], "");
721 folly::split("a", "abcdefg", pieces, true);
722 EXPECT_EQ(pieces.size(), 1);
723 EXPECT_EQ(pieces[0], "bcdefg");
726 orig = "All, , your base, are , , belong to us";
727 folly::split(", ", orig, pieces, true);
728 EXPECT_EQ(pieces.size(), 4);
729 EXPECT_EQ(pieces[0], "All");
730 EXPECT_EQ(pieces[1], "your base");
731 EXPECT_EQ(pieces[2], "are ");
732 EXPECT_EQ(pieces[3], "belong to us");
734 folly::split(", ", orig, pieces);
735 EXPECT_EQ(pieces.size(), 6);
736 EXPECT_EQ(pieces[0], "All");
737 EXPECT_EQ(pieces[1], "");
738 EXPECT_EQ(pieces[2], "your base");
739 EXPECT_EQ(pieces[3], "are ");
740 EXPECT_EQ(pieces[4], "");
741 EXPECT_EQ(pieces[5], "belong to us");
744 orig = ", Facebook, rul,es!, ";
745 folly::split(", ", orig, pieces, true);
746 EXPECT_EQ(pieces.size(), 2);
747 EXPECT_EQ(pieces[0], "Facebook");
748 EXPECT_EQ(pieces[1], "rul,es!");
750 folly::split(", ", orig, pieces);
751 EXPECT_EQ(pieces.size(), 4);
752 EXPECT_EQ(pieces[0], "");
753 EXPECT_EQ(pieces[1], "Facebook");
754 EXPECT_EQ(pieces[2], "rul,es!");
755 EXPECT_EQ(pieces[3], "");
758 const char* str = "a,b";
759 folly::split(',', StringPiece(str), pieces);
760 EXPECT_EQ(pieces.size(), 2);
761 EXPECT_EQ(pieces[0], "a");
762 EXPECT_EQ(pieces[1], "b");
763 EXPECT_EQ(pieces[0].start(), str);
764 EXPECT_EQ(pieces[1].start(), str + 2);
766 std::set<StringPiece> unique;
767 folly::splitTo<StringPiece>(":", "asd:bsd:asd:asd:bsd:csd::asd",
768 std::inserter(unique, unique.begin()), true);
769 EXPECT_EQ(unique.size(), 3);
770 if (unique.size() == 3) {
771 EXPECT_EQ(*unique.begin(), "asd");
772 EXPECT_EQ(*--unique.end(), "csd");
775 VectorType<fbstring,std::allocator<fbstring> > blah;
776 folly::split('-', "a-b-c-d-f-e", blah);
777 EXPECT_EQ(blah.size(), 6);
782 TEST(Split, split_vector) {
783 splitTest<std::vector>();
785 TEST(Split, split_fbvector) {
786 splitTest<folly::fbvector>();
788 TEST(Split, pieces_vector) {
789 piecesTest<std::vector>();
791 TEST(Split, pieces_fbvector) {
792 piecesTest<folly::fbvector>();
796 StringPiece a, b, c, d;
798 EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
799 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
800 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
801 EXPECT_TRUE(folly::split<false>('.', "a", a));
803 EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
804 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
805 EXPECT_TRUE(folly::split('.', "a.b", a, b));
806 EXPECT_TRUE(folly::split('.', "a", a));
808 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
812 EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
813 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
817 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
821 EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
822 EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
824 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
827 EXPECT_FALSE(folly::split<false>('.', "a", a, b));
828 EXPECT_TRUE(folly::split<false>('.', "a.b", a));
831 EXPECT_TRUE(folly::split('.', "a.b", a, b));
834 EXPECT_FALSE(folly::split('.', "a", a, b));
835 EXPECT_FALSE(folly::split('.', "a.b", a));
838 TEST(Split, std_string_fixed) {
839 std::string a, b, c, d;
841 EXPECT_TRUE(folly::split<false>('.', "a.b.c.d", a, b, c, d));
842 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
843 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
844 EXPECT_TRUE(folly::split<false>('.', "a", a));
846 EXPECT_TRUE(folly::split('.', "a.b.c.d", a, b, c, d));
847 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
848 EXPECT_TRUE(folly::split('.', "a.b", a, b));
849 EXPECT_TRUE(folly::split('.', "a", a));
851 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b, c));
855 EXPECT_FALSE(folly::split<false>('.', "a.b", a, b, c));
856 EXPECT_TRUE(folly::split<false>('.', "a.b.c", a, b));
860 EXPECT_TRUE(folly::split('.', "a.b.c", a, b, c));
864 EXPECT_FALSE(folly::split('.', "a.b.c", a, b));
865 EXPECT_FALSE(folly::split('.', "a.b", a, b, c));
867 EXPECT_TRUE(folly::split<false>('.', "a.b", a, b));
870 EXPECT_FALSE(folly::split<false>('.', "a", a, b));
871 EXPECT_TRUE(folly::split<false>('.', "a.b", a));
874 EXPECT_TRUE(folly::split('.', "a.b", a, b));
877 EXPECT_FALSE(folly::split('.', "a", a, b));
878 EXPECT_FALSE(folly::split('.', "a.b", a));
881 TEST(Split, fixed_convert) {
886 EXPECT_TRUE(folly::split(':', "a:13:14.7:b", a, b, c, d));
889 EXPECT_NEAR(14.7, c, 1e-10);
892 EXPECT_TRUE(folly::split<false>(':', "b:14:15.3:c", a, b, c, d));
895 EXPECT_NEAR(15.3, c, 1e-10);
898 EXPECT_FALSE(folly::split(':', "a:13:14.7:b", a, b, d));
900 EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, d));
903 EXPECT_EQ("14.7:b", d);
905 EXPECT_THROW(folly::split<false>(':', "a:13:14.7:b", a, b, c),
912 std::vector<int> empty = { };
913 join(":", empty, output);
914 EXPECT_TRUE(output.empty());
916 std::vector<std::string> input1 = { "1", "23", "456", "" };
917 join(':', input1, output);
918 EXPECT_EQ(output, "1:23:456:");
919 output = join(':', input1);
920 EXPECT_EQ(output, "1:23:456:");
922 auto input2 = { 1, 23, 456 };
923 join("-*-", input2, output);
924 EXPECT_EQ(output, "1-*-23-*-456");
925 output = join("-*-", input2);
926 EXPECT_EQ(output, "1-*-23-*-456");
928 auto input3 = { 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k' };
929 join("", input3, output);
930 EXPECT_EQ(output, "facebook");
932 join("_", { "", "f", "a", "c", "e", "b", "o", "o", "k", "" }, output);
933 EXPECT_EQ(output, "_f_a_c_e_b_o_o_k_");
935 output = join("", input3.begin(), input3.end());
936 EXPECT_EQ(output, "facebook");
939 TEST(String, hexlify) {
940 string input1 = "0123";
942 EXPECT_TRUE(hexlify(input1, output1));
943 EXPECT_EQ(output1, "30313233");
945 fbstring input2 = "abcdefg";
950 EXPECT_TRUE(hexlify(input2, output2));
951 EXPECT_EQ(output2, "610063ff65b667");
954 TEST(String, unhexlify) {
955 string input1 = "30313233";
957 EXPECT_TRUE(unhexlify(input1, output1));
958 EXPECT_EQ(output1, "0123");
960 fbstring input2 = "610063ff65b667";
962 EXPECT_TRUE(unhexlify(input2, output2));
963 EXPECT_EQ(output2.size(), 7);
964 EXPECT_EQ(output2[0], 'a');
965 EXPECT_EQ(output2[1], 0);
966 EXPECT_EQ(output2[2], 'c');
967 EXPECT_EQ(output2[3] & 0xff, 0xff);
968 EXPECT_EQ(output2[4], 'e');
969 EXPECT_EQ(output2[5] & 0xff, 0xb6);
970 EXPECT_EQ(output2[6], 'g');
974 EXPECT_FALSE(unhexlify(input3, output3));
976 string input4 = "xy";
978 EXPECT_FALSE(unhexlify(input4, output4));
981 TEST(String, backslashify) {
982 EXPECT_EQ("abc", string("abc"));
983 EXPECT_EQ("abc", backslashify(string("abc")));
984 EXPECT_EQ("abc\\r", backslashify(string("abc\r")));
985 EXPECT_EQ("abc\\x0d", backslashify(string("abc\r"), true));
986 EXPECT_EQ("\\0\\0", backslashify(string(2, '\0')));
989 TEST(String, humanify) {
990 // Simple cases; output is obvious.
991 EXPECT_EQ("abc", humanify(string("abc")));
992 EXPECT_EQ("abc\\\\r", humanify(string("abc\\r")));
993 EXPECT_EQ("0xff", humanify(string("\xff")));
994 EXPECT_EQ("abc\\xff", humanify(string("abc\xff")));
995 EXPECT_EQ("abc\\b", humanify(string("abc\b")));
996 EXPECT_EQ("0x00", humanify(string(1, '\0')));
997 EXPECT_EQ("0x0000", humanify(string(2, '\0')));
1000 // Mostly printable, so backslash! 80, 60, and 40% printable, respectively
1001 EXPECT_EQ("aaaa\\xff", humanify(string("aaaa\xff")));
1002 EXPECT_EQ("aaa\\xff\\xff", humanify(string("aaa\xff\xff")));
1003 EXPECT_EQ("aa\\xff\\xff\\xff", humanify(string("aa\xff\xff\xff")));
1005 // 20% printable, and the printable portion isn't the prefix; hexify!
1006 EXPECT_EQ("0xff61ffffff", humanify(string("\xff" "a\xff\xff\xff")));
1008 // Same as previous, except swap first two chars; prefix is
1009 // printable and within the threshold, so backslashify.
1010 EXPECT_EQ("a\\xff\\xff\\xff\\xff", humanify(string("a\xff\xff\xff\xff")));
1012 // Just too much unprintable; hex, despite prefix.
1013 EXPECT_EQ("0x61ffffffffff", humanify(string("a\xff\xff\xff\xff\xff")));
1019 * Copy bytes from src to somewhere in the buffer referenced by dst. The
1020 * actual starting position of the copy will be the first address in the
1021 * destination buffer whose address mod 8 is equal to the src address mod 8.
1022 * The caller is responsible for ensuring that the destination buffer has
1023 * enough extra space to accommodate the shifted copy.
1025 char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
1026 const char* originalDst = dst;
1027 size_t dstOffset = size_t(dst) & 0x7;
1028 size_t srcOffset = size_t(src) & 0x7;
1029 while (dstOffset != srcOffset) {
1034 CHECK(dst <= originalDst + 7);
1035 CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
1036 memcpy(dst, src, length);
1040 void testToLowerAscii(Range<const char*> src) {
1041 // Allocate extra space so we can make copies that start at the
1042 // same alignment (byte, word, quadword, etc) as the source buffer.
1043 char controlBuf[src.size() + 7];
1044 char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
1046 char testBuf[src.size() + 7];
1047 char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
1049 for (size_t i = 0; i < src.size(); i++) {
1050 control[i] = tolower(control[i]);
1052 toLowerAscii(test, src.size());
1053 for (size_t i = 0; i < src.size(); i++) {
1054 EXPECT_EQ(control[i], test[i]);
1060 TEST(String, toLowerAsciiAligned) {
1061 static const size_t kSize = 256;
1063 for (size_t i = 0; i < kSize; i++) {
1064 input[i] = (char)(i & 0xff);
1066 testToLowerAscii(Range<const char*>(input, kSize));
1069 TEST(String, toLowerAsciiUnaligned) {
1070 static const size_t kSize = 256;
1072 for (size_t i = 0; i < kSize; i++) {
1073 input[i] = (char)(i & 0xff);
1075 // Test input buffers of several lengths to exercise all the
1076 // cases: buffer at the start/middle/end of an aligned block, plus
1077 // buffers that span multiple aligned blocks. The longest test input
1078 // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
1079 // + 4 32-bit aligned + 3 unaligned = 22 bytes.
1080 for (size_t length = 1; length < 23; length++) {
1081 for (size_t offset = 0; offset + length <= kSize; offset++) {
1082 testToLowerAscii(Range<const char*>(input + offset, length));
1087 TEST(String, whitespace) {
1089 EXPECT_EQ("kavabanga",
1090 trimWhitespace("kavabanga"));
1091 EXPECT_EQ("kavabanga",
1092 trimWhitespace("kavabanga \t \n "));
1093 EXPECT_EQ("kavabanga",
1094 trimWhitespace(" \t \r \n \n kavabanga"));
1095 EXPECT_EQ("kavabanga",
1096 trimWhitespace("\t \r \n kavabanga \t \n "));
1097 EXPECT_EQ("kavabanga",
1098 trimWhitespace(" \t \r \n \n kavabanga"));
1099 EXPECT_EQ("kavabanga",
1100 trimWhitespace("\t \r \n kavabanga \t \n "));
1102 ltrimWhitespace(rtrimWhitespace("kavabanga")),
1103 rtrimWhitespace(ltrimWhitespace("kavabanga")));
1105 ltrimWhitespace(rtrimWhitespace("kavabanga \r\t\n")),
1106 rtrimWhitespace(ltrimWhitespace("kavabanga \r\t\n")));
1107 EXPECT_EQ("", trimWhitespace("\t \r \n \t \n "));
1108 EXPECT_EQ("", trimWhitespace(""));
1109 EXPECT_EQ("", trimWhitespace("\t"));
1110 EXPECT_EQ("", trimWhitespace("\r"));
1111 EXPECT_EQ("", trimWhitespace("\n"));
1112 EXPECT_EQ("", trimWhitespace("\t "));
1113 EXPECT_EQ("", trimWhitespace("\r "));
1114 EXPECT_EQ("", trimWhitespace("\n "));
1115 EXPECT_EQ("", trimWhitespace(" \t"));
1116 EXPECT_EQ("", trimWhitespace(" \r"));
1117 EXPECT_EQ("", trimWhitespace(" \n"));
1120 EXPECT_EQ("kavabanga", ltrimWhitespace("\t kavabanga"));
1121 EXPECT_EQ("kavabanga \r\n", ltrimWhitespace("\t kavabanga \r\n"));
1122 EXPECT_EQ("", ltrimWhitespace("\r "));
1123 EXPECT_EQ("", ltrimWhitespace("\n "));
1124 EXPECT_EQ("", ltrimWhitespace("\r "));
1127 EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga"));
1128 EXPECT_EQ("\t kavabanga", rtrimWhitespace("\t kavabanga \r\n"));
1129 EXPECT_EQ("", rtrimWhitespace("\r "));
1130 EXPECT_EQ("", rtrimWhitespace("\n "));
1131 EXPECT_EQ("", rtrimWhitespace("\r "));
1134 const folly::StringPiece kTestUTF8 = "This is \U0001F602 stuff!";
1136 TEST(UTF8StringPiece, valid_utf8) {
1137 folly::StringPiece sp = kTestUTF8;
1138 UTF8StringPiece utf8 = sp;
1139 // utf8.size() not available since it's not a random-access range
1140 EXPECT_EQ(16, utf8.walk_size());
1143 TEST(UTF8StringPiece, valid_suffix) {
1144 UTF8StringPiece utf8 = kTestUTF8.subpiece(8);
1145 EXPECT_EQ(8, utf8.walk_size());
1148 TEST(UTF8StringPiece, empty_mid_codepoint) {
1149 UTF8StringPiece utf8 = kTestUTF8.subpiece(9, 0); // okay since it's empty
1150 EXPECT_EQ(0, utf8.walk_size());
1153 TEST(UTF8StringPiece, invalid_mid_codepoint) {
1154 EXPECT_THROW(UTF8StringPiece(kTestUTF8.subpiece(9, 1)), std::out_of_range);