proxygen
RangeTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // @author Kristina Holst (kholst@fb.com)
18 // @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
19 
20 #include <folly/Range.h>
21 
22 #include <array>
23 #include <deque>
24 #include <iterator>
25 #include <limits>
26 #include <random>
27 #include <string>
28 #include <type_traits>
29 #include <vector>
30 
31 #include <boost/algorithm/string/trim.hpp>
32 #include <boost/range/concepts.hpp>
33 
34 #include <folly/Memory.h>
38 
39 using namespace folly;
40 using namespace folly::detail;
41 using namespace std;
42 
44 
45 BOOST_CONCEPT_ASSERT((boost::RandomAccessRangeConcept<StringPiece>));
46 
48  const char* foo = "foo";
49  const char* foo2 = "foo";
50  string fooStr(foo);
51  string foo2Str(foo2);
52 
53  // we expect the compiler to optimize things so that there's only one copy
54  // of the string literal "foo", even though we've got it in multiple places
55  EXPECT_EQ(foo, foo2); // remember, this uses ==, not strcmp, so it's a ptr
56  // comparison rather than lexical
57 
58  // the string object creates copies though, so the c_str of these should be
59  // distinct
60  EXPECT_NE(fooStr.c_str(), foo2Str.c_str());
61 
62  // test the basic StringPiece functionality
63  StringPiece s(foo);
64  EXPECT_EQ(s.size(), 3);
65 
66  EXPECT_EQ(s.start(), foo); // ptr comparison
67  EXPECT_NE(s.start(), fooStr.c_str()); // ptr comparison
68  EXPECT_NE(s.start(), foo2Str.c_str()); // ptr comparison
69 
70  EXPECT_EQ(s.toString(), foo); // lexical comparison
71  EXPECT_EQ(s.toString(), fooStr.c_str()); // lexical comparison
72  EXPECT_EQ(s.toString(), foo2Str.c_str()); // lexical comparison
73 
74  EXPECT_EQ(s, foo); // lexical comparison
75  EXPECT_EQ(s, fooStr); // lexical comparison
76  EXPECT_EQ(s, foo2Str); // lexical comparison
77  EXPECT_EQ(foo, s);
78 
79  // check using StringPiece to reference substrings
80  const char* foobarbaz = "foobarbaz";
81 
82  // the full "foobarbaz"
83  s.reset(foobarbaz, strlen(foobarbaz));
84  EXPECT_EQ(s.size(), 9);
85  EXPECT_EQ(s.start(), foobarbaz);
86  EXPECT_EQ(s, "foobarbaz");
87 
88  // only the 'foo'
89  s.assign(foobarbaz, foobarbaz + 3);
90  EXPECT_EQ(s.size(), 3);
91  EXPECT_EQ(s.start(), foobarbaz);
92  EXPECT_EQ(s, "foo");
93 
94  // find
95  s.reset(foobarbaz, strlen(foobarbaz));
96  EXPECT_EQ(s.find("bar"), 3);
97  EXPECT_EQ(s.find("ba", 3), 3);
98  EXPECT_EQ(s.find("ba", 4), 6);
99  EXPECT_EQ(s.find("notfound"), StringPiece::npos);
100  EXPECT_EQ(s.find("notfound", 1), StringPiece::npos);
101  EXPECT_EQ(s.find("bar", 4), StringPiece::npos); // starting position too far
102  // starting pos that is obviously past the end -- This works for std::string
103  EXPECT_EQ(s.toString().find("notfound", 55), StringPiece::npos);
104  EXPECT_EQ(s.find("z", s.size()), StringPiece::npos);
105  EXPECT_EQ(s.find("z", 55), StringPiece::npos);
106  // empty needle
107  EXPECT_EQ(s.find(""), std::string().find(""));
108  EXPECT_EQ(s.find(""), 0);
109 
110  // single char finds
111  EXPECT_EQ(s.find('b'), 3);
112  EXPECT_EQ(s.find('b', 3), 3);
113  EXPECT_EQ(s.find('b', 4), 6);
114  EXPECT_EQ(s.find('o', 2), 2);
115  EXPECT_EQ(s.find('y'), StringPiece::npos);
116  EXPECT_EQ(s.find('y', 1), StringPiece::npos);
117  EXPECT_EQ(s.find('o', 4), StringPiece::npos); // starting position too far
118  EXPECT_TRUE(s.contains('z'));
119  // starting pos that is obviously past the end -- This works for std::string
120  EXPECT_EQ(s.toString().find('y', 55), StringPiece::npos);
121  EXPECT_EQ(s.find('z', s.size()), StringPiece::npos);
122  EXPECT_EQ(s.find('z', 55), StringPiece::npos);
123  // null char
124  EXPECT_EQ(s.find('\0'), std::string().find('\0'));
125  EXPECT_EQ(s.find('\0'), StringPiece::npos);
126  EXPECT_FALSE(s.contains('\0'));
127 
128  // single char rfinds
129  EXPECT_EQ(s.rfind('b'), 6);
130  EXPECT_EQ(s.rfind('y'), StringPiece::npos);
131  EXPECT_EQ(s.str().rfind('y'), StringPiece::npos);
132  EXPECT_EQ(ByteRange(s).rfind('b'), 6);
134  // null char
135  EXPECT_EQ(s.rfind('\0'), s.str().rfind('\0'));
136  EXPECT_EQ(s.rfind('\0'), StringPiece::npos);
137 
138  // find_first_of
139  s.reset(foobarbaz, strlen(foobarbaz));
140  EXPECT_EQ(s.find_first_of("bar"), 3);
141  EXPECT_EQ(s.find_first_of("ba", 3), 3);
142  EXPECT_EQ(s.find_first_of("ba", 4), 4);
143  EXPECT_TRUE(s.contains("bar"));
144  EXPECT_EQ(s.find_first_of("xyxy"), StringPiece::npos);
145  EXPECT_EQ(s.find_first_of("xyxy", 1), StringPiece::npos);
146  EXPECT_FALSE(s.contains("xyxy"));
147  // starting position too far
148  EXPECT_EQ(s.find_first_of("foo", 4), StringPiece::npos);
149  // starting pos that is obviously past the end -- This works for std::string
150  EXPECT_EQ(s.toString().find_first_of("xyxy", 55), StringPiece::npos);
151  EXPECT_EQ(s.find_first_of("z", s.size()), StringPiece::npos);
152  EXPECT_EQ(s.find_first_of("z", 55), StringPiece::npos);
153  // empty needle. Note that this returns npos, while find() returns 0!
154  EXPECT_EQ(s.find_first_of(""), std::string().find_first_of(""));
155  EXPECT_EQ(s.find_first_of(""), StringPiece::npos);
156 
157  // single char find_first_ofs
158  EXPECT_EQ(s.find_first_of('b'), 3);
159  EXPECT_EQ(s.find_first_of('b', 3), 3);
160  EXPECT_EQ(s.find_first_of('b', 4), 6);
161  EXPECT_EQ(s.find_first_of('o', 2), 2);
162  EXPECT_EQ(s.find_first_of('y'), StringPiece::npos);
163  EXPECT_EQ(s.find_first_of('y', 1), StringPiece::npos);
164  // starting position too far
165  EXPECT_EQ(s.find_first_of('o', 4), StringPiece::npos);
166  // starting pos that is obviously past the end -- This works for std::string
167  EXPECT_EQ(s.toString().find_first_of('y', 55), StringPiece::npos);
168  EXPECT_EQ(s.find_first_of('z', s.size()), StringPiece::npos);
169  EXPECT_EQ(s.find_first_of('z', 55), StringPiece::npos);
170  // null char
171  EXPECT_EQ(s.find_first_of('\0'), std::string().find_first_of('\0'));
172  EXPECT_EQ(s.find_first_of('\0'), StringPiece::npos);
173 
174  // just "barbaz"
175  s.reset(foobarbaz + 3, strlen(foobarbaz + 3));
176  EXPECT_EQ(s.size(), 6);
177  EXPECT_EQ(s.start(), foobarbaz + 3);
178  EXPECT_EQ(s, "barbaz");
179 
180  // just "bar"
181  s.reset(foobarbaz + 3, 3);
182  EXPECT_EQ(s.size(), 3);
183  EXPECT_EQ(s, "bar");
184 
185  // clear
186  s.clear();
187  EXPECT_EQ(s.toString(), "");
188 
189  // test an empty StringPiece
190  StringPiece s2;
191  EXPECT_EQ(s2.size(), 0);
192 
193  // Test comparison operators
194  foo = "";
195  EXPECT_LE(s, foo);
196  EXPECT_LE(foo, s);
197  EXPECT_GE(s, foo);
198  EXPECT_GE(foo, s);
199  EXPECT_EQ(s, foo);
200  EXPECT_EQ(foo, s);
201 
202  foo = "abc";
203  EXPECT_LE(s, foo);
204  EXPECT_LT(s, foo);
205  EXPECT_GE(foo, s);
206  EXPECT_GT(foo, s);
207  EXPECT_NE(s, foo);
208 
209  EXPECT_LE(s, s);
210  EXPECT_LE(s, s);
211  EXPECT_GE(s, s);
212  EXPECT_GE(s, s);
213  EXPECT_EQ(s, s);
214  EXPECT_EQ(s, s);
215 
216  s = "abc";
217  s2 = "abc";
218  EXPECT_LE(s, s2);
219  EXPECT_LE(s2, s);
220  EXPECT_GE(s, s2);
221  EXPECT_GE(s2, s);
222  EXPECT_EQ(s, s2);
223  EXPECT_EQ(s2, s);
224 }
225 
226 template <class T>
227 void expectLT(const T& a, const T& b) {
228  EXPECT_TRUE(a < b);
229  EXPECT_TRUE(a <= b);
230  EXPECT_FALSE(a == b);
231  EXPECT_FALSE(a >= b);
232  EXPECT_FALSE(a > b);
233 
234  EXPECT_FALSE(b < a);
235  EXPECT_FALSE(b <= a);
236  EXPECT_TRUE(b >= a);
237  EXPECT_TRUE(b > a);
238 }
239 
240 template <class T>
241 void expectEQ(const T& a, const T& b) {
242  EXPECT_FALSE(a < b);
243  EXPECT_TRUE(a <= b);
244  EXPECT_TRUE(a == b);
245  EXPECT_TRUE(a >= b);
246  EXPECT_FALSE(a > b);
247 }
248 
249 TEST(StringPiece, EightBitComparisons) {
250  char values[] = {'\x00', '\x20', '\x40', '\x7f', '\x80', '\xc0', '\xff'};
251  constexpr size_t count = sizeof(values) / sizeof(values[0]);
252  for (size_t i = 0; i < count; ++i) {
253  std::string a(1, values[i]);
254  // Defeat copy-on-write
255  std::string aCopy(a.data(), a.size());
256  expectEQ(a, aCopy);
257  expectEQ(StringPiece(a), StringPiece(aCopy));
258 
259  for (size_t j = i + 1; j < count; ++j) {
260  std::string b(1, values[j]);
261  expectLT(a, b);
263  }
264  }
265 }
266 
267 TEST(StringPiece, ToByteRange) {
268  StringPiece a("hello");
269  ByteRange b(a);
270  EXPECT_EQ(
271  static_cast<const void*>(a.begin()), static_cast<const void*>(b.begin()));
272  EXPECT_EQ(
273  static_cast<const void*>(a.end()), static_cast<const void*>(b.end()));
274 
275  // and convert back again
276  StringPiece c(b);
277  EXPECT_EQ(a.begin(), c.begin());
278  EXPECT_EQ(a.end(), c.end());
279 }
280 
281 TEST(StringPiece, InvalidRange) {
282  StringPiece a("hello");
283  EXPECT_EQ(a, a.subpiece(0, 10));
284  EXPECT_EQ(StringPiece("ello"), a.subpiece(1));
285  EXPECT_EQ(StringPiece("ello"), a.subpiece(1, std::string::npos));
286  EXPECT_EQ(StringPiece("ell"), a.subpiece(1, 3));
287  EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
288  EXPECT_THROW(a.subpiece(6), std::out_of_range);
289 
290  std::string b("hello");
291  EXPECT_EQ(a, StringPiece(b, 0, 10));
292  EXPECT_EQ("ello", a.subpiece(1));
293  EXPECT_EQ("ello", a.subpiece(1, std::string::npos));
294  EXPECT_EQ("ell", a.subpiece(1, 3));
295  EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
296  EXPECT_THROW(a.subpiece(6), std::out_of_range);
297 }
298 
299 TEST(StringPiece, Constexpr) {
300  constexpr const char* helloArray = "hello";
301 
302  constexpr StringPiece hello1("hello");
303  EXPECT_EQ("hello", hello1);
304  static_assert(hello1.size() == 5, "hello size should be 5 at compile time");
305 
306  constexpr StringPiece hello2(helloArray);
307  EXPECT_EQ("hello", hello2);
308  static_assert(hello2.size() == 5, "hello size should be 5 at compile time");
309 }
310 
311 TEST(StringPiece, Prefix) {
312  StringPiece a("hello");
313  EXPECT_TRUE(a.startsWith(""));
314  EXPECT_TRUE(a.startsWith("h"));
315  EXPECT_TRUE(a.startsWith('h'));
316  EXPECT_TRUE(a.startsWith("hello"));
317  EXPECT_FALSE(a.startsWith("hellox"));
318  EXPECT_FALSE(a.startsWith('x'));
319  EXPECT_FALSE(a.startsWith("x"));
320 
329 
330  {
331  auto b = a;
332  EXPECT_TRUE(b.removePrefix(""));
333  EXPECT_EQ("hello", b);
334  }
335  {
336  auto b = a;
337  EXPECT_TRUE(b.removePrefix("h"));
338  EXPECT_EQ("ello", b);
339  }
340  {
341  auto b = a;
342  EXPECT_TRUE(b.removePrefix('h'));
343  EXPECT_EQ("ello", b);
344  }
345  {
346  auto b = a;
347  EXPECT_TRUE(b.removePrefix("hello"));
348  EXPECT_EQ("", b);
349  }
350  {
351  auto b = a;
352  EXPECT_FALSE(b.removePrefix("hellox"));
353  EXPECT_EQ("hello", b);
354  }
355  {
356  auto b = a;
357  EXPECT_FALSE(b.removePrefix("x"));
358  EXPECT_EQ("hello", b);
359  }
360  {
361  auto b = a;
362  EXPECT_FALSE(b.removePrefix('x'));
363  EXPECT_EQ("hello", b);
364  }
365 }
366 
367 TEST(StringPiece, Suffix) {
368  StringPiece a("hello");
369  EXPECT_TRUE(a.endsWith(""));
370  EXPECT_TRUE(a.endsWith("o"));
371  EXPECT_TRUE(a.endsWith('o'));
372  EXPECT_TRUE(a.endsWith("hello"));
373  EXPECT_FALSE(a.endsWith("xhello"));
374  EXPECT_FALSE(a.endsWith("x"));
375  EXPECT_FALSE(a.endsWith('x'));
376 
386 
387  {
388  auto b = a;
389  EXPECT_TRUE(b.removeSuffix(""));
390  EXPECT_EQ("hello", b);
391  }
392  {
393  auto b = a;
394  EXPECT_TRUE(b.removeSuffix("o"));
395  EXPECT_EQ("hell", b);
396  }
397  {
398  auto b = a;
399  EXPECT_TRUE(b.removeSuffix('o'));
400  EXPECT_EQ("hell", b);
401  }
402  {
403  auto b = a;
404  EXPECT_TRUE(b.removeSuffix("hello"));
405  EXPECT_EQ("", b);
406  }
407  {
408  auto b = a;
409  EXPECT_FALSE(b.removeSuffix("xhello"));
410  EXPECT_EQ("hello", b);
411  }
412  {
413  auto b = a;
414  EXPECT_FALSE(b.removeSuffix("x"));
415  EXPECT_EQ("hello", b);
416  }
417  {
418  auto b = a;
419  EXPECT_FALSE(b.removeSuffix('x'));
420  EXPECT_EQ("hello", b);
421  }
422 }
423 
424 TEST(StringPiece, Equals) {
425  StringPiece a("hello");
426 
427  EXPECT_TRUE(a.equals("HELLO", AsciiCaseInsensitive()));
428  EXPECT_FALSE(a.equals("HELLOX", AsciiCaseInsensitive()));
429 }
430 
431 TEST(StringPiece, PrefixEmpty) {
432  StringPiece a;
433  EXPECT_TRUE(a.startsWith(""));
434  EXPECT_FALSE(a.startsWith("a"));
435  EXPECT_FALSE(a.startsWith('a'));
436  EXPECT_TRUE(a.removePrefix(""));
437  EXPECT_EQ("", a);
438  EXPECT_FALSE(a.removePrefix("a"));
439  EXPECT_EQ("", a);
440  EXPECT_FALSE(a.removePrefix('a'));
441  EXPECT_EQ("", a);
442 }
443 
444 TEST(StringPiece, SuffixEmpty) {
445  StringPiece a;
446  EXPECT_TRUE(a.endsWith(""));
447  EXPECT_FALSE(a.endsWith("a"));
448  EXPECT_FALSE(a.endsWith('a'));
449  EXPECT_TRUE(a.removeSuffix(""));
450  EXPECT_EQ("", a);
451  EXPECT_FALSE(a.removeSuffix("a"));
452  EXPECT_EQ("", a);
453  EXPECT_FALSE(a.removeSuffix('a'));
454  EXPECT_EQ("", a);
455 }
456 
457 TEST(StringPiece, erase) {
458  StringPiece a("hello");
459  auto b = a.begin();
460  auto e = b + 1;
461  a.erase(b, e);
462  EXPECT_EQ("ello", a);
463 
464  e = a.end();
465  b = e - 1;
466  a.erase(b, e);
467  EXPECT_EQ("ell", a);
468 
469  b = a.end() - 1;
470  e = a.end() - 1;
471  EXPECT_THROW(a.erase(b, e), std::out_of_range);
472 
473  b = a.begin();
474  e = a.end();
475  a.erase(b, e);
476  EXPECT_EQ("", a);
477 
478  a = "hello";
479  b = a.begin();
480  e = b + 2;
481  a.erase(b, e);
482  EXPECT_EQ("llo", a);
483 
484  b = a.end() - 2;
485  e = a.end();
486  a.erase(b, e);
487  EXPECT_EQ("l", a);
488 
489  a = " hello ";
490  boost::algorithm::trim(a);
491  EXPECT_EQ(a, "hello");
492 }
493 
494 TEST(StringPiece, split_step_char_delimiter) {
495  // 0 1 2
496  // 012345678901234567890123456
497  auto const s = "this is just a test string";
498  auto const e = std::next(s, std::strlen(s));
499  EXPECT_EQ('\0', *e);
500 
502  EXPECT_EQ(s, p.begin());
503  EXPECT_EQ(e, p.end());
504  EXPECT_EQ(s, p);
505 
506  auto x = p.split_step(' ');
507  EXPECT_EQ(std::next(s, 5), p.begin());
508  EXPECT_EQ(e, p.end());
509  EXPECT_EQ("this", x);
510 
511  x = p.split_step(' ');
512  EXPECT_EQ(std::next(s, 8), p.begin());
513  EXPECT_EQ(e, p.end());
514  EXPECT_EQ("is", x);
515 
516  x = p.split_step('u');
517  EXPECT_EQ(std::next(s, 10), p.begin());
518  EXPECT_EQ(e, p.end());
519  EXPECT_EQ("j", x);
520 
521  x = p.split_step(' ');
522  EXPECT_EQ(std::next(s, 13), p.begin());
523  EXPECT_EQ(e, p.end());
524  EXPECT_EQ("st", x);
525 
526  x = p.split_step(' ');
527  EXPECT_EQ(std::next(s, 14), p.begin());
528  EXPECT_EQ(e, p.end());
529  EXPECT_EQ("", x);
530 
531  x = p.split_step(' ');
532  EXPECT_EQ(std::next(s, 16), p.begin());
533  EXPECT_EQ(e, p.end());
534  EXPECT_EQ("a", x);
535 
536  x = p.split_step(' ');
537  EXPECT_EQ(std::next(s, 21), p.begin());
538  EXPECT_EQ(e, p.end());
539  EXPECT_EQ("test", x);
540 
541  x = p.split_step(' ');
542  EXPECT_EQ(e, p.begin());
543  EXPECT_EQ(e, p.end());
544  EXPECT_EQ("string", x);
545 
546  x = p.split_step(' ');
547  EXPECT_EQ(e, p.begin());
548  EXPECT_EQ(e, p.end());
549  EXPECT_EQ("", x);
550 }
551 
552 TEST(StringPiece, split_step_range_delimiter) {
553  // 0 1 2 3
554  // 0123456789012345678901234567890123
555  auto const s = "this is just a test string";
556  auto const e = std::next(s, std::strlen(s));
557  EXPECT_EQ('\0', *e);
558 
560  EXPECT_EQ(s, p.begin());
561  EXPECT_EQ(e, p.end());
562  EXPECT_EQ(s, p);
563 
564  auto x = p.split_step(" ");
565  EXPECT_EQ(std::next(s, 6), p.begin());
566  EXPECT_EQ(e, p.end());
567  EXPECT_EQ("this", x);
568 
569  x = p.split_step(" ");
570  EXPECT_EQ(std::next(s, 10), p.begin());
571  EXPECT_EQ(e, p.end());
572  EXPECT_EQ("is", x);
573 
574  x = p.split_step("u");
575  EXPECT_EQ(std::next(s, 12), p.begin());
576  EXPECT_EQ(e, p.end());
577  EXPECT_EQ("j", x);
578 
579  x = p.split_step(" ");
580  EXPECT_EQ(std::next(s, 16), p.begin());
581  EXPECT_EQ(e, p.end());
582  EXPECT_EQ("st", x);
583 
584  x = p.split_step(" ");
585  EXPECT_EQ(std::next(s, 18), p.begin());
586  EXPECT_EQ(e, p.end());
587  EXPECT_EQ("", x);
588 
589  x = p.split_step(" ");
590  EXPECT_EQ(std::next(s, 21), p.begin());
591  EXPECT_EQ(e, p.end());
592  EXPECT_EQ("a", x);
593 
594  x = p.split_step(" ");
595  EXPECT_EQ(std::next(s, 28), p.begin());
596  EXPECT_EQ(e, p.end());
597  EXPECT_EQ(" test", x);
598 
599  x = p.split_step(" ");
600  EXPECT_EQ(e, p.begin());
601  EXPECT_EQ(e, p.end());
602  EXPECT_EQ("string", x);
603 
604  x = p.split_step(" ");
605  EXPECT_EQ(e, p.begin());
606  EXPECT_EQ(e, p.end());
607  EXPECT_EQ("", x);
608 
609  x = p.split_step(" ");
610  EXPECT_EQ(e, p.begin());
611  EXPECT_EQ(e, p.end());
612  EXPECT_EQ("", x);
613 }
614 
616 
617 TEST(StringPiece, split_step_with_process_char_delimiter) {
618  // 0 1 2
619  // 012345678901234567890123456
620  auto const s = "this is just a test string";
621  auto const e = std::next(s, std::strlen(s));
622  EXPECT_EQ('\0', *e);
623 
625  EXPECT_EQ(s, p.begin());
626  EXPECT_EQ(e, p.end());
627  EXPECT_EQ(s, p);
628 
629  EXPECT_EQ(1, (p.split_step(' ', [&](folly::StringPiece x) {
630  EXPECT_EQ(std::next(s, 5), p.begin());
631  EXPECT_EQ(e, p.end());
632  EXPECT_EQ("this", x);
633  return 1;
634  })));
635 
636  EXPECT_EQ(2, (p.split_step(' ', [&](folly::StringPiece x) {
637  EXPECT_EQ(std::next(s, 8), p.begin());
638  EXPECT_EQ(e, p.end());
639  EXPECT_EQ("is", x);
640  return 2;
641  })));
642 
643  EXPECT_EQ(3, (p.split_step('u', [&](folly::StringPiece x) {
644  EXPECT_EQ(std::next(s, 10), p.begin());
645  EXPECT_EQ(e, p.end());
646  EXPECT_EQ("j", x);
647  return 3;
648  })));
649 
650  EXPECT_EQ(4, (p.split_step(' ', [&](folly::StringPiece x) {
651  EXPECT_EQ(std::next(s, 13), p.begin());
652  EXPECT_EQ(e, p.end());
653  EXPECT_EQ("st", x);
654  return 4;
655  })));
656 
657  EXPECT_EQ(5, (p.split_step(' ', [&](folly::StringPiece x) {
658  EXPECT_EQ(std::next(s, 14), p.begin());
659  EXPECT_EQ(e, p.end());
660  EXPECT_EQ("", x);
661  return 5;
662  })));
663 
664  EXPECT_EQ(6, (p.split_step(' ', [&](folly::StringPiece x) {
665  EXPECT_EQ(std::next(s, 16), p.begin());
666  EXPECT_EQ(e, p.end());
667  EXPECT_EQ("a", x);
668  return 6;
669  })));
670 
671  EXPECT_EQ(7, (p.split_step(' ', [&](folly::StringPiece x) {
672  EXPECT_EQ(std::next(s, 21), p.begin());
673  EXPECT_EQ(e, p.end());
674  EXPECT_EQ("test", x);
675  return 7;
676  })));
677 
678  EXPECT_EQ(8, (p.split_step(' ', [&](folly::StringPiece x) {
679  EXPECT_EQ(e, p.begin());
680  EXPECT_EQ(e, p.end());
681  EXPECT_EQ("string", x);
682  return 8;
683  })));
684 
685  EXPECT_EQ(9, (p.split_step(' ', [&](folly::StringPiece x) {
686  EXPECT_EQ(e, p.begin());
687  EXPECT_EQ(e, p.end());
688  EXPECT_EQ("", x);
689  return 9;
690  })));
691 
692  EXPECT_TRUE(
693  (std::is_same<
694  void,
695  decltype(p.split_step(' ', split_step_with_process_noop))>::value));
696 
698 }
699 
700 TEST(StringPiece, split_step_with_process_range_delimiter) {
701  // 0 1 2 3
702  // 0123456789012345678901234567890123
703  auto const s = "this is just a test string";
704  auto const e = std::next(s, std::strlen(s));
705  EXPECT_EQ('\0', *e);
706 
708  EXPECT_EQ(s, p.begin());
709  EXPECT_EQ(e, p.end());
710  EXPECT_EQ(s, p);
711 
712  EXPECT_EQ(1, (p.split_step(" ", [&](folly::StringPiece x) {
713  EXPECT_EQ(std::next(s, 6), p.begin());
714  EXPECT_EQ(e, p.end());
715  EXPECT_EQ("this", x);
716  return 1;
717  })));
718 
719  EXPECT_EQ(2, (p.split_step(" ", [&](folly::StringPiece x) {
720  EXPECT_EQ(std::next(s, 10), p.begin());
721  EXPECT_EQ(e, p.end());
722  EXPECT_EQ("is", x);
723  return 2;
724  })));
725 
726  EXPECT_EQ(3, (p.split_step("u", [&](folly::StringPiece x) {
727  EXPECT_EQ(std::next(s, 12), p.begin());
728  EXPECT_EQ(e, p.end());
729  EXPECT_EQ("j", x);
730  return 3;
731  })));
732 
733  EXPECT_EQ(4, (p.split_step(" ", [&](folly::StringPiece x) {
734  EXPECT_EQ(std::next(s, 16), p.begin());
735  EXPECT_EQ(e, p.end());
736  EXPECT_EQ("st", x);
737  return 4;
738  })));
739 
740  EXPECT_EQ(5, (p.split_step(" ", [&](folly::StringPiece x) {
741  EXPECT_EQ(std::next(s, 18), p.begin());
742  EXPECT_EQ(e, p.end());
743  EXPECT_EQ("", x);
744  return 5;
745  })));
746 
747  EXPECT_EQ(6, (p.split_step(" ", [&](folly::StringPiece x) {
748  EXPECT_EQ(std::next(s, 21), p.begin());
749  EXPECT_EQ(e, p.end());
750  EXPECT_EQ("a", x);
751  return 6;
752  })));
753 
754  EXPECT_EQ(7, (p.split_step(" ", [&](folly::StringPiece x) {
755  EXPECT_EQ(std::next(s, 28), p.begin());
756  EXPECT_EQ(e, p.end());
757  EXPECT_EQ(" test", x);
758  return 7;
759  })));
760 
761  EXPECT_EQ(8, (p.split_step(" ", [&](folly::StringPiece x) {
762  EXPECT_EQ(e, p.begin());
763  EXPECT_EQ(e, p.end());
764  EXPECT_EQ("string", x);
765  return 8;
766  })));
767 
768  EXPECT_EQ(9, (p.split_step(" ", [&](folly::StringPiece x) {
769  EXPECT_EQ(e, p.begin());
770  EXPECT_EQ(e, p.end());
771  EXPECT_EQ("", x);
772  return 9;
773  })));
774 
775  EXPECT_EQ(10, (p.split_step(" ", [&](folly::StringPiece x) {
776  EXPECT_EQ(e, p.begin());
777  EXPECT_EQ(e, p.end());
778  EXPECT_EQ("", x);
779  return 10;
780  })));
781 
782  EXPECT_TRUE(
783  (std::is_same<
784  void,
785  decltype(p.split_step(' ', split_step_with_process_noop))>::value));
786 
788 }
789 
790 TEST(StringPiece, split_step_with_process_char_delimiter_additional_args) {
791  // 0 1 2
792  // 012345678901234567890123456
793  auto const s = "this is just a test string";
794  auto const e = std::next(s, std::strlen(s));
795  auto const delimiter = ' ';
796  EXPECT_EQ('\0', *e);
797 
799  EXPECT_EQ(s, p.begin());
800  EXPECT_EQ(e, p.end());
801  EXPECT_EQ(s, p);
802 
803  auto const functor = [](folly::StringPiece s_, folly::StringPiece expected) {
804  EXPECT_EQ(expected, s_);
805  return expected;
806  };
807 
808  auto const checker = [&](folly::StringPiece expected) {
809  EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
810  };
811 
812  checker("this");
813  checker("is");
814  checker("just");
815  checker("");
816  checker("a");
817  checker("test");
818  checker("string");
819  checker("");
820  checker("");
821 
822  EXPECT_TRUE(p.empty());
823 }
824 
825 TEST(StringPiece, split_step_with_process_range_delimiter_additional_args) {
826  // 0 1 2 3
827  // 0123456789012345678901234567890123
828  auto const s = "this is just a test string";
829  auto const e = std::next(s, std::strlen(s));
830  auto const delimiter = " ";
831  EXPECT_EQ('\0', *e);
832 
834  EXPECT_EQ(s, p.begin());
835  EXPECT_EQ(e, p.end());
836  EXPECT_EQ(s, p);
837 
838  auto const functor = [](folly::StringPiece s_, folly::StringPiece expected) {
839  EXPECT_EQ(expected, s_);
840  return expected;
841  };
842 
843  auto const checker = [&](folly::StringPiece expected) {
844  EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
845  };
846 
847  checker("this");
848  checker("is");
849  checker("just");
850  checker("");
851  checker("a");
852  checker(" test");
853  checker("string");
854  checker("");
855  checker("");
856 
857  EXPECT_TRUE(p.empty());
858 }
859 
860 TEST(StringPiece, NoInvalidImplicitConversions) {
861  struct IsString {
862  bool operator()(folly::Range<int*>) {
863  return false;
864  }
865  bool operator()(folly::StringPiece) {
866  return true;
867  }
868  };
869 
870  std::string s = "hello";
871  EXPECT_TRUE(IsString()(s));
872 }
873 
874 TEST(qfind, UInt32_Ranges) {
875  vector<uint32_t> a({1, 2, 3, 260, 5});
876  vector<uint32_t> b({2, 3, 4});
877 
878  auto a_range = folly::Range<const uint32_t*>(&a[0], a.size());
879  auto b_range = folly::Range<const uint32_t*>(&b[0], b.size());
880 
881  EXPECT_EQ(qfind(a_range, b_range), string::npos);
882 
883  a[3] = 4;
884  EXPECT_EQ(qfind(a_range, b_range), 1);
885 }
886 
887 template <typename NeedleFinder>
889  public:
890  static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
891  return NeedleFinder::find_first_byte_of(haystack, needles);
892  }
893 };
894 
896  static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
897  // This will only use the SSE version if it is supported on this CPU
898  // (selected using ifunc).
899  return detail::qfind_first_byte_of(haystack, needles);
900  }
901 };
902 
904  static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
905  return detail::qfind_first_byte_of_nosse(haystack, needles);
906  }
907 };
908 
910  static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
911  return detail::qfind_first_byte_of_byteset(haystack, needles);
912  }
913 };
914 
915 using NeedleFinders =
916  ::testing::Types<SseNeedleFinder, NoSseNeedleFinder, ByteSetNeedleFinder>;
918 
920  { // null characters in the string
921  string s(10, char(0));
922  s[5] = 'b';
923  string delims("abc");
924  EXPECT_EQ(5, this->find_first_byte_of(s, delims));
925  }
926  { // null characters in delim
927  string s("abc");
928  string delims(10, char(0));
929  delims[3] = 'c';
930  delims[7] = 'b';
931  EXPECT_EQ(1, this->find_first_byte_of(s, delims));
932  }
933  { // range not terminated by null character
934  string buf = "abcdefghijklmnopqrstuvwxyz";
935  StringPiece s(buf.data() + 5, 3);
936  StringPiece delims("z");
937  EXPECT_EQ(string::npos, this->find_first_byte_of(s, delims));
938  }
939 }
940 
941 TYPED_TEST(NeedleFinderTest, DelimDuplicates) {
942  string delims(1000, 'b');
943  EXPECT_EQ(1, this->find_first_byte_of("abc", delims));
944  EXPECT_EQ(string::npos, this->find_first_byte_of("ac", delims));
945 }
946 
948  string a = "abc";
949  string b = "";
950  EXPECT_EQ(string::npos, this->find_first_byte_of(a, b));
951  EXPECT_EQ(string::npos, this->find_first_byte_of(b, a));
952  EXPECT_EQ(string::npos, this->find_first_byte_of(b, b));
953 }
954 
956  // works correctly even if input buffers are not 16-byte aligned
957  string s = "0123456789ABCDEFGH";
958  for (size_t i = 0; i < s.size(); ++i) {
959  StringPiece a(s.c_str() + i);
960  for (size_t j = 0; j < s.size(); ++j) {
961  StringPiece b(s.c_str() + j);
962  EXPECT_EQ((i > j) ? 0 : j - i, this->find_first_byte_of(a, b));
963  }
964  }
965 }
966 
967 // for some algorithms (specifically those that create a set of needles),
968 // we check for the edge-case of _all_ possible needles being sought.
970  string needles;
973  // make the size ~big to avoid any edge-case branches for tiny haystacks
974  const int haystackSize = 50;
975  for (int i = minValue; i <= maxValue; i++) { // <=
976  needles.push_back(i);
977  }
978  EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
979  for (int i = minValue; i <= maxValue; i++) {
980  EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
981  }
982 
983  needles.append("these are redundant characters");
984  EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
985  for (int i = minValue; i <= maxValue; i++) {
986  EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
987  }
988 }
989 
991  for (size_t i = 0; i < 32; ++i) {
992  for (int j = 0; j < 32; ++j) {
993  string s = string(i, 'X') + "abca" + string(i, 'X');
994  string delims = string(j, 'Y') + "a" + string(j, 'Y');
995  EXPECT_EQ(i, this->find_first_byte_of(s, delims));
996  }
997  }
998 }
999 
1000 const size_t kPageSize = 4096;
1001 // Updates contents so that any read accesses past the last byte will
1002 // cause a SIGSEGV. It accomplishes this by changing access to the page that
1003 // begins immediately after the end of the contents (as allocators and mmap()
1004 // all operate on page boundaries, this is a reasonable assumption).
1005 // This function will also initialize buf, which caller must free().
1006 void createProtectedBuf(StringPiece& contents, char** buf) {
1007  ASSERT_LE(contents.size(), kPageSize);
1008  char* pageAlignedBuf = (char*)aligned_malloc(2 * kPageSize, kPageSize);
1009  if (pageAlignedBuf == nullptr) {
1010  FAIL();
1011  }
1012  // Protect the page after the first full page-aligned region of the
1013  // malloc'ed buffer
1014  mprotect(pageAlignedBuf + kPageSize, kPageSize, PROT_NONE);
1015  size_t newBegin = kPageSize - contents.size();
1016  memcpy(pageAlignedBuf + newBegin, contents.data(), contents.size());
1017  contents.reset(pageAlignedBuf + newBegin, contents.size());
1018  *buf = pageAlignedBuf;
1019 }
1020 
1021 void freeProtectedBuf(char* buf) {
1022  mprotect(buf + kPageSize, kPageSize, PROT_READ | PROT_WRITE);
1023  aligned_free(buf);
1024 }
1025 
1027  const string base = string(32, 'a') + string("b");
1028  const string delims = string(32, 'c') + string("b");
1029  for (int i = 0; i <= 32; i++) {
1030  for (int j = 0; j <= 33; j++) {
1031  for (int shouldFind = 0; shouldFind <= 1; ++shouldFind) {
1032  StringPiece s1(base);
1033  s1.advance(i);
1034  ASSERT_TRUE(!s1.empty());
1035  if (!shouldFind) {
1036  s1.pop_back();
1037  }
1038  StringPiece s2(delims);
1039  s2.advance(j);
1040  char* buf1;
1041  char* buf2;
1042  createProtectedBuf(s1, &buf1);
1043  createProtectedBuf(s2, &buf2);
1044  // printf("s1: '%s' (%ld) \ts2: '%s' (%ld)\n",
1045  // string(s1.data(), s1.size()).c_str(), s1.size(),
1046  // string(s2.data(), s2.size()).c_str(), s2.size());
1047  auto r1 = this->find_first_byte_of(s1, s2);
1048  auto f1 =
1049  std::find_first_of(s1.begin(), s1.end(), s2.begin(), s2.end());
1050  auto e1 = (f1 == s1.end()) ? StringPiece::npos : f1 - s1.begin();
1051  EXPECT_EQ(r1, e1);
1052  auto r2 = this->find_first_byte_of(s2, s1);
1053  auto f2 =
1054  std::find_first_of(s2.begin(), s2.end(), s1.begin(), s1.end());
1055  auto e2 = (f2 == s2.end()) ? StringPiece::npos : f2 - s2.begin();
1056  EXPECT_EQ(r2, e2);
1057  freeProtectedBuf(buf1);
1058  freeProtectedBuf(buf2);
1059  }
1060  }
1061  }
1062 }
1063 
1064 TEST(NonConstTest, StringPiece) {
1065  std::string hello("hello");
1066  MutableStringPiece sp(&hello.front(), hello.size());
1067  sp[0] = 'x';
1068  EXPECT_EQ("xello", hello);
1069  {
1070  StringPiece s(sp);
1071  EXPECT_EQ("xello", s);
1072  }
1073  {
1074  ByteRange r1(sp);
1075  MutableByteRange r2(sp);
1076  }
1077 }
1078 
1079 // Similar to the begin() template functions, but instread of returing
1080 // an iterator, return a pointer to data.
1081 template <class Container>
1082 typename Container::value_type* dataPtr(Container& cont) {
1083  // NOTE: &cont[0] is undefined if cont is empty (it creates a
1084  // reference to nullptr - which is not dereferenced, but still UBSAN).
1085  return cont.data();
1086 }
1087 template <class T, size_t N>
1088 constexpr T* dataPtr(T (&arr)[N]) noexcept {
1089  return &arr[0];
1090 }
1091 
1092 template <class C>
1093 void testRangeFunc(C&& x, size_t n) {
1094  const auto& cx = x;
1095  // type, conversion checks
1096  using R1Iter =
1098  Range<R1Iter> r1 = range(std::forward<C>(x));
1099  Range<const int*> r2 = range(std::forward<C>(x));
1100  Range<const int*> r3 = range(cx);
1101  Range<const int*> r5 = range(std::move(cx));
1102  EXPECT_EQ(r1.begin(), dataPtr(x));
1103  EXPECT_EQ(r1.end(), dataPtr(x) + n);
1104  EXPECT_EQ(n, r1.size());
1105  EXPECT_EQ(n, r2.size());
1106  EXPECT_EQ(n, r3.size());
1107  EXPECT_EQ(n, r5.size());
1108 }
1109 
1110 TEST(RangeFunc, Vector) {
1111  std::vector<int> x;
1112  testRangeFunc(x, 0);
1113  x.push_back(2);
1114  testRangeFunc(x, 1);
1115  testRangeFunc(std::vector<int>{1, 2}, 2);
1116 }
1117 
1118 TEST(RangeFunc, Array) {
1119  std::array<int, 3> x;
1120  testRangeFunc(x, 3);
1121 }
1122 
1123 TEST(RangeFunc, CArray) {
1124  int x[]{1, 2, 3, 4};
1125  testRangeFunc(x, 4);
1126 }
1127 
1128 TEST(RangeFunc, ConstexprCArray) {
1129  static constexpr const int numArray[4] = {3, 17, 1, 9};
1130  constexpr const auto numArrayRange = range(numArray);
1131  EXPECT_EQ(17, numArrayRange[1]);
1132  constexpr const auto numArrayRangeSize = numArrayRange.size();
1133  EXPECT_EQ(4, numArrayRangeSize);
1134 }
1135 
1136 TEST(RangeFunc, ConstexprStdArray) {
1137  static constexpr const std::array<int, 4> numArray = {{3, 17, 1, 9}};
1138  constexpr const auto numArrayRange = range(numArray);
1139  EXPECT_EQ(17, numArrayRange[1]);
1140  constexpr const auto numArrayRangeSize = numArrayRange.size();
1141  EXPECT_EQ(4, numArrayRangeSize);
1142 }
1143 
1144 TEST(RangeFunc, ConstexprStdArrayZero) {
1145  static constexpr const std::array<int, 0> numArray = {};
1146  constexpr const auto numArrayRange = range(numArray);
1147  constexpr const auto numArrayRangeSize = numArrayRange.size();
1148  EXPECT_EQ(0, numArrayRangeSize);
1149 }
1150 
1151 TEST(RangeFunc, ConstexprIteratorPair) {
1152  static constexpr const int numArray[4] = {3, 17, 1, 9};
1153  constexpr const auto numPtr = static_cast<const int*>(numArray);
1154  constexpr const auto numIterRange = range(numPtr + 1, numPtr + 3);
1155  EXPECT_EQ(1, numIterRange[1]);
1156  constexpr const auto numIterRangeSize = numIterRange.size();
1157  EXPECT_EQ(2, numIterRangeSize);
1158 }
1159 
1160 TEST(RangeFunc, ConstexprCollection) {
1161  class IntCollection {
1162  public:
1163  constexpr IntCollection(const int* d, size_t s) : data_(d), size_(s) {}
1164  constexpr const int* data() const {
1165  return data_;
1166  }
1167  constexpr size_t size() const {
1168  return size_;
1169  }
1170 
1171  private:
1172  const int* data_;
1173  size_t size_;
1174  };
1175  static constexpr const int numArray[4] = {3, 17, 1, 9};
1176  constexpr const auto numPtr = static_cast<const int*>(numArray);
1177  constexpr const auto numColl = IntCollection(numPtr + 1, 2);
1178  constexpr const auto numCollRange = range(numColl);
1179  EXPECT_EQ(1, numCollRange[1]);
1180  constexpr const auto numCollRangeSize = numCollRange.size();
1181  EXPECT_EQ(2, numCollRangeSize);
1182 }
1183 
1184 TEST(CRangeFunc, CArray) {
1185  int numArray[4] = {3, 17, 1, 9};
1186  auto const numArrayRange = crange(numArray);
1187  EXPECT_TRUE(
1188  (std::is_same<int const*, decltype(numArrayRange)::iterator>::value));
1189  EXPECT_THAT(numArrayRange, testing::ElementsAreArray(numArray));
1190 }
1191 
1192 TEST(CRangeFunc, StdArray) {
1193  std::array<int, 4> numArray = {{3, 17, 1, 9}};
1194  auto const numArrayRange = crange(numArray);
1195  EXPECT_TRUE(
1196  (std::is_same<int const*, decltype(numArrayRange)::iterator>::value));
1197  EXPECT_THAT(numArrayRange, testing::ElementsAreArray(numArray));
1198 }
1199 
1200 TEST(CRangeFunc, StdArrayZero) {
1201  std::array<int, 0> numArray = {};
1202  auto const numArrayRange = crange(numArray);
1203  EXPECT_TRUE(
1204  (std::is_same<int const*, decltype(numArrayRange)::iterator>::value));
1205  EXPECT_THAT(numArrayRange, testing::IsEmpty());
1206 }
1207 
1208 TEST(CRangeFunc, Collection) {
1209  class IntCollection {
1210  public:
1211  constexpr IntCollection(int* d, size_t s) : data_(d), size_(s) {}
1212  constexpr int const* data() const {
1213  return data_;
1214  }
1215  constexpr size_t size() const {
1216  return size_;
1217  }
1218 
1219  private:
1220  int* data_;
1221  size_t size_;
1222  };
1223  int numArray[4] = {3, 17, 1, 9};
1224  auto numPtr = static_cast<int*>(numArray);
1225  auto numColl = IntCollection(numPtr + 1, 2);
1226  auto const numCollRange = crange(numColl);
1227  EXPECT_TRUE(
1228  (std::is_same<int const*, decltype(numCollRange)::iterator>::value));
1229  EXPECT_THAT(numCollRange, testing::ElementsAreArray({17, 1}));
1230 }
1231 
1233  size_t size,
1234  std::uniform_int_distribution<>& dist,
1235  std::mt19937& gen) {
1236  std::string ret(size, '\0');
1237  for (size_t i = 0; i < size; ++i) {
1238  ret[i] = static_cast<char>(dist(gen));
1239  }
1240 
1241  return ret;
1242 }
1243 
1244 namespace folly {
1246  return mp.compare(sp) == 0;
1247 }
1248 
1250  return mp.compare(sp) == 0;
1251 }
1252 } // namespace folly
1253 
1254 TEST(ReplaceAt, exhaustiveTest) {
1255  char input[] = "this is nice and long input";
1256  auto msp = MutableStringPiece(input);
1257  auto str = std::string(input);
1258  std::random_device rd;
1259  std::mt19937 gen(rd());
1260  std::uniform_int_distribution<> dist('a', 'z');
1261 
1262  for (int i = 0; i < 100; ++i) {
1263  for (size_t j = 1; j <= msp.size(); ++j) {
1264  auto replacement = get_rand_str(j, dist, gen);
1265  for (size_t pos = 0; pos < msp.size() - j; ++pos) {
1266  msp.replaceAt(pos, replacement);
1267  str.replace(pos, replacement.size(), replacement);
1268  EXPECT_EQ(msp.compare(str), 0);
1269  }
1270  }
1271  }
1272 
1273  // too far
1274  EXPECT_EQ(msp.replaceAt(msp.size() - 2, StringPiece("meh")), false);
1275 }
1276 
1277 TEST(ReplaceAll, basicTest) {
1278  char input[] = "this is nice and long input";
1279  auto orig = std::string(input);
1280  auto msp = MutableStringPiece(input);
1281 
1282  EXPECT_EQ(msp.replaceAll("is", "si"), 2);
1283  EXPECT_EQ("thsi si nice and long input", msp);
1284  EXPECT_EQ(msp.replaceAll("si", "is"), 2);
1285  EXPECT_EQ(msp, orig);
1286 
1287  EXPECT_EQ(msp.replaceAll("abcd", "efgh"), 0); // nothing to replace
1288  EXPECT_EQ(msp, orig);
1289 
1290  // at the very beginning
1291  EXPECT_EQ(msp.replaceAll("this", "siht"), 1);
1292  EXPECT_EQ("siht is nice and long input", msp);
1293  EXPECT_EQ(msp.replaceAll("siht", "this"), 1);
1294  EXPECT_EQ(msp, orig);
1295 
1296  // at the very end
1297  EXPECT_EQ(msp.replaceAll("input", "soput"), 1);
1298  EXPECT_EQ("this is nice and long soput", msp);
1299  EXPECT_EQ(msp.replaceAll("soput", "input"), 1);
1300  EXPECT_EQ(msp, orig);
1301 
1302  // all spaces
1303  EXPECT_EQ(msp.replaceAll(" ", "@"), 5);
1304  EXPECT_EQ("this@is@nice@and@long@input", msp);
1305  EXPECT_EQ(msp.replaceAll("@", " "), 5);
1306  EXPECT_EQ(msp, orig);
1307 }
1308 
1309 TEST(ReplaceAll, randomTest) {
1310  char input[] = "abcdefghijklmnoprstuwqz"; // no pattern repeata inside
1311  auto orig = std::string(input);
1312  auto msp = MutableStringPiece(input);
1313 
1314  std::random_device rd;
1315  std::mt19937 gen(rd());
1316  std::uniform_int_distribution<> dist('A', 'Z');
1317 
1318  for (int i = 0; i < 100; ++i) {
1319  for (size_t j = 1; j <= orig.size(); ++j) {
1320  auto replacement = get_rand_str(j, dist, gen);
1321  for (size_t pos = 0; pos < msp.size() - j; ++pos) {
1322  auto piece = orig.substr(pos, j);
1323  EXPECT_EQ(msp.replaceAll(piece, replacement), 1);
1324  EXPECT_EQ(msp.find(replacement), pos);
1325  EXPECT_EQ(msp.replaceAll(replacement, piece), 1);
1326  EXPECT_EQ(msp, orig);
1327  }
1328  }
1329  }
1330 }
1331 
1332 TEST(ReplaceAll, BadArg) {
1333  int count = 0;
1334  auto fst = "longer";
1335  auto snd = "small";
1336  char input[] = "meh meh meh";
1337  auto all = MutableStringPiece(input);
1338 
1339  try {
1340  all.replaceAll(fst, snd);
1341  } catch (std::invalid_argument&) {
1342  ++count;
1343  }
1344 
1345  try {
1346  all.replaceAll(snd, fst);
1347  } catch (std::invalid_argument&) {
1348  ++count;
1349  }
1350 
1351  EXPECT_EQ(count, 2);
1352 }
1353 
1354 TEST(Range, Constructors) {
1355  vector<int> c = {1, 2, 3};
1356  typedef Range<vector<int>::iterator> RangeType;
1357  typedef Range<vector<int>::const_iterator> ConstRangeType;
1358  RangeType cr(c.begin(), c.end());
1359  auto subpiece1 = ConstRangeType(cr, 1, 5);
1360  auto subpiece2 = ConstRangeType(cr, 1);
1361  EXPECT_EQ(subpiece1.size(), 2);
1362  EXPECT_EQ(subpiece1.begin(), subpiece2.begin());
1363  EXPECT_EQ(subpiece1.end(), subpiece2.end());
1364 }
1365 
1366 TEST(Range, ArrayConstructors) {
1367  auto charArray = std::array<char, 4>{{'t', 'e', 's', 't'}};
1368  auto constCharArray = std::array<char, 6>{{'f', 'o', 'o', 'b', 'a', 'r'}};
1369  auto emptyArray = std::array<char, 0>{};
1370 
1371  auto sp1 = StringPiece{charArray};
1372  EXPECT_EQ(4, sp1.size());
1373  EXPECT_EQ(charArray.data(), sp1.data());
1374 
1375  auto sp2 = StringPiece(constCharArray);
1376  EXPECT_EQ(6, sp2.size());
1377  EXPECT_EQ(constCharArray.data(), sp2.data());
1378 
1379  auto msp = MutableStringPiece(charArray);
1380  EXPECT_EQ(4, msp.size());
1381  EXPECT_EQ(charArray.data(), msp.data());
1382 
1383  auto esp = StringPiece(emptyArray);
1384  EXPECT_EQ(0, esp.size());
1385  EXPECT_EQ(nullptr, esp.data());
1386 
1387  auto emsp = MutableStringPiece(emptyArray);
1388  EXPECT_EQ(0, emsp.size());
1389  EXPECT_EQ(nullptr, emsp.data());
1390 
1391  static constexpr std::array<int, 4> numArray = {{3, 17, 1, 9}};
1392  constexpr auto numRange = Range<const int*>{numArray};
1393  EXPECT_EQ(17, numRange[1]);
1394 
1395  static constexpr std::array<int, 0> emptyNumArray{};
1396  constexpr auto emptyNumRange = Range<const int*>{emptyNumArray};
1397  EXPECT_EQ(0, emptyNumRange.size());
1398 }
1399 
1400 TEST(Range, ConstexprAccessors) {
1401  constexpr StringPiece piece = range("hello");
1402  static_assert(piece.size() == 6u, "");
1403  static_assert(piece.end() - piece.begin() == 6u, "");
1404  static_assert(piece.data() == piece.begin(), "");
1405  static_assert(piece.start() == piece.begin(), "");
1406  static_assert(piece.cbegin() == piece.begin(), "");
1407  static_assert(piece.cend() == piece.end(), "");
1408  static_assert(*piece.begin() == 'h', "");
1409  static_assert(*(piece.end() - 1) == '\0', "");
1410 }
1411 
1412 TEST(Range, LiteralSuffix) {
1413  constexpr auto literalPiece = "hello"_sp;
1414  constexpr StringPiece piece = "hello";
1415  EXPECT_EQ(literalPiece, piece);
1416  constexpr auto literalPiece8 = u8"hello"_sp;
1417  constexpr Range<char const*> piece8 = u8"hello";
1418  EXPECT_EQ(literalPiece8, piece8);
1419  constexpr auto literalPiece16 = u"hello"_sp;
1420  constexpr Range<char16_t const*> piece16{u"hello", 5};
1421  EXPECT_EQ(literalPiece16, piece16);
1422  constexpr auto literalPiece32 = U"hello"_sp;
1423  constexpr Range<char32_t const*> piece32{U"hello", 5};
1424  EXPECT_EQ(literalPiece32, piece32);
1425  constexpr auto literalPieceW = L"hello"_sp;
1426  constexpr Range<wchar_t const*> pieceW{L"hello", 5};
1427  EXPECT_EQ(literalPieceW, pieceW);
1428 }
1429 
1430 TEST(Range, LiteralSuffixContainsNulBytes) {
1431  constexpr auto literalPiece = "\0foo\0"_sp;
1432  EXPECT_EQ(5u, literalPiece.size());
1433 }
1434 
1435 class tag {};
1437  private:
1439 
1440  public:
1441  using size_type = std::size_t;
1442  explicit fake_string_view(char const* s, size_type c, tag = {})
1443  : piece_(s, c) {}
1444  /* implicit */ operator StringPiece() const {
1445  return piece_;
1446  }
1447  friend bool operator==(char const* rhs, fake_string_view lhs) {
1448  return rhs == lhs.piece_;
1449  }
1450 };
1451 
1452 TEST(Range, StringPieceExplicitConversionOperator) {
1453  using PieceM = StringPiece;
1454  using PieceC = StringPiece const;
1455 
1458  EXPECT_FALSE((std::is_convertible<PieceM, std::vector<char>>::value));
1462  EXPECT_TRUE((std::is_constructible<std::vector<char>, PieceM>::value));
1464 
1467  EXPECT_FALSE((std::is_convertible<PieceC, std::vector<char>>::value));
1471  EXPECT_TRUE((std::is_constructible<std::vector<char>, PieceC>::value));
1473 
1475  std::array<char, 5> array = {{'h', 'e', 'l', 'l', 'o'}};
1476  PieceM piecem{array};
1477  PieceC piecec{array};
1478  std::allocator<char> alloc;
1479 
1480  EXPECT_EQ("hello", std::string(piecem));
1481  EXPECT_EQ("hello", std::string(piecec));
1482  EXPECT_EQ("hello", std::string{piecem});
1483  EXPECT_EQ("hello", std::string{piecec});
1484  EXPECT_EQ("hello", piecem.to<std::string>());
1485  EXPECT_EQ("hello", piecec.to<std::string>());
1486  EXPECT_EQ("hello", piecem.to<std::string>(alloc));
1487  EXPECT_EQ("hello", piecec.to<std::string>(alloc));
1488 
1489  EXPECT_THAT(std::vector<char>(piecem), ElementsAreArray(array));
1490  EXPECT_THAT(std::vector<char>(piecec), ElementsAreArray(array));
1491  EXPECT_THAT(std::vector<char>{piecem}, ElementsAreArray(array));
1492  EXPECT_THAT(std::vector<char>{piecec}, ElementsAreArray(array));
1493  EXPECT_THAT(piecem.to<std::vector<char>>(), ElementsAreArray(array));
1494  EXPECT_THAT(piecec.to<std::vector<char>>(), ElementsAreArray(array));
1495  EXPECT_THAT(piecem.to<std::vector<char>>(alloc), ElementsAreArray(array));
1496  EXPECT_THAT(piecec.to<std::vector<char>>(alloc), ElementsAreArray(array));
1497 
1498  EXPECT_EQ("hello", fake_string_view(piecem));
1499  EXPECT_EQ("hello", fake_string_view(piecec));
1500  EXPECT_EQ("hello", fake_string_view{piecem});
1501  EXPECT_EQ("hello", fake_string_view{piecec});
1502  EXPECT_EQ("hello", piecem.to<fake_string_view>());
1503  EXPECT_EQ("hello", piecec.to<fake_string_view>());
1504  EXPECT_EQ("hello", piecem.to<fake_string_view>(tag{}));
1505  EXPECT_EQ("hello", piecec.to<fake_string_view>(tag{}));
1506 }
1507 
1508 TEST(Range, MutableStringPieceExplicitConversionOperator) {
1509  using PieceM = MutableStringPiece;
1510  using PieceC = MutableStringPiece const;
1511 
1514  EXPECT_FALSE((std::is_convertible<PieceM, std::vector<char>>::value));
1518  EXPECT_TRUE((std::is_constructible<std::vector<char>, PieceM>::value));
1520 
1523  EXPECT_FALSE((std::is_convertible<PieceC, std::vector<char>>::value));
1527  EXPECT_TRUE((std::is_constructible<std::vector<char>, PieceC>::value));
1529 
1531  std::array<char, 5> array = {{'h', 'e', 'l', 'l', 'o'}};
1532  PieceM piecem{array};
1533  PieceC piecec{array};
1534  std::allocator<char> alloc;
1535 
1536  EXPECT_EQ("hello", std::string(piecem));
1537  EXPECT_EQ("hello", std::string(piecec));
1538  EXPECT_EQ("hello", std::string{piecem});
1539  EXPECT_EQ("hello", std::string{piecec});
1540  EXPECT_EQ("hello", piecem.to<std::string>());
1541  EXPECT_EQ("hello", piecec.to<std::string>());
1542  EXPECT_EQ("hello", piecem.to<std::string>(alloc));
1543  EXPECT_EQ("hello", piecec.to<std::string>(alloc));
1544 
1545  EXPECT_THAT(std::vector<char>(piecem), ElementsAreArray(array));
1546  EXPECT_THAT(std::vector<char>(piecec), ElementsAreArray(array));
1547  EXPECT_THAT(std::vector<char>{piecem}, ElementsAreArray(array));
1548  EXPECT_THAT(std::vector<char>{piecec}, ElementsAreArray(array));
1549  EXPECT_THAT(piecem.to<std::vector<char>>(), ElementsAreArray(array));
1550  EXPECT_THAT(piecec.to<std::vector<char>>(), ElementsAreArray(array));
1551  EXPECT_THAT(piecem.to<std::vector<char>>(alloc), ElementsAreArray(array));
1552  EXPECT_THAT(piecec.to<std::vector<char>>(alloc), ElementsAreArray(array));
1553 
1554  EXPECT_EQ("hello", fake_string_view(piecem));
1555  EXPECT_EQ("hello", fake_string_view(piecec));
1556  EXPECT_EQ("hello", fake_string_view{piecem});
1557  EXPECT_EQ("hello", fake_string_view{piecec});
1558  EXPECT_EQ("hello", piecem.to<fake_string_view>());
1559  EXPECT_EQ("hello", piecec.to<fake_string_view>());
1560  EXPECT_EQ("hello", piecem.to<fake_string_view>(tag{}));
1561  EXPECT_EQ("hello", piecec.to<fake_string_view>(tag{}));
1562 }
1563 
1564 #if FOLLY_HAS_STRING_VIEW
1565 namespace {
1566 std::size_t stringViewSize(std::string_view s) {
1567  return s.size();
1568 }
1569 
1570 std::size_t stringPieceSize(StringPiece s) {
1571  return s.size();
1572 }
1573 
1574 struct TrickyTarget {
1575  TrickyTarget(char const*, char const*) : which{1} {}
1576  TrickyTarget(char const*, std::size_t) : which{2} {}
1577  TrickyTarget(std::string_view) : which{3} {}
1578 
1579  int which;
1580 };
1581 
1582 struct TrickierTarget {
1583  TrickierTarget(std::deque<char>::const_iterator, std::size_t) : which{1} {}
1584  TrickierTarget(std::string_view) : which{2} {}
1585 
1586  int which;
1587 };
1588 } // namespace
1589 
1590 TEST(StringPiece, StringViewConversion) {
1591  StringPiece piece("foo");
1592  std::string str("bar");
1593  MutableStringPiece mut(str.data(), str.size());
1594  std::string_view view("baz");
1595 
1596  EXPECT_EQ(stringViewSize(piece), 3);
1597  EXPECT_EQ(stringViewSize(str), 3);
1598  EXPECT_EQ(stringViewSize(mut), 3);
1599  EXPECT_EQ(stringPieceSize(mut), 3);
1600  EXPECT_EQ(stringPieceSize(str), 3);
1601  EXPECT_EQ(stringPieceSize(view), 3);
1602 
1603  view = mut;
1604  piece = view;
1605  EXPECT_EQ(piece[2], 'r');
1606  piece = "quux";
1607  view = piece;
1608  EXPECT_EQ(view.size(), 4);
1609 
1610  TrickyTarget tt1(piece);
1611  EXPECT_EQ(tt1.which, 3);
1612  TrickyTarget tt2(view);
1613  EXPECT_EQ(tt2.which, 3);
1614 
1615  std::deque<char> deq;
1616  deq.push_back('a');
1617  deq.push_back('b');
1618  deq.push_back('c');
1619  Range<std::deque<char>::const_iterator> deqRange{deq.begin(), deq.end()};
1620  TrickierTarget tt3(deqRange);
1621  EXPECT_EQ(tt3.which, 1);
1622 }
1623 
1624 namespace {
1625 
1626 // Range with non-pod value type should not cause compile errors.
1627 class NonPOD {
1628  public:
1629  NonPOD() {}
1630 };
1631 void test_func(Range<const NonPOD*>) {}
1632 
1633 } // anonymous namespace
1634 
1635 #endif
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
void createProtectedBuf(StringPiece &contents, char **buf)
Definition: RangeTest.cpp:1006
Definition: InvokeTest.cpp:58
#define FAIL()
Definition: gtest.h:1822
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
std::string s_
char b
LogLevel max
Definition: LogLevel.cpp:31
StringPiece piece_
Definition: RangeTest.cpp:1438
void expectLT(const T &a, const T &b)
Definition: RangeTest.cpp:227
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::string get_rand_str(size_t size, std::uniform_int_distribution<> &dist, std::mt19937 &gen)
Definition: RangeTest.cpp:1232
void aligned_free(void *aligned_ptr)
Definition: Memory.h:89
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
size_t qfind_first_byte_of_byteset(const StringPieceLite haystack, const StringPieceLite needles)
Definition: RangeCommon.cpp:42
const int x
void advance(size_type n)
Definition: Range.h:672
static size_t find_first_byte_of(StringPiece haystack, StringPiece needles)
Definition: RangeTest.cpp:904
STL namespace.
#define ASSERT_LE(val1, val2)
Definition: gtest.h:1964
constexpr size_type size() const
Definition: Range.h:431
FOLLY_NOINLINE void foo2()
fake_string_view(char const *s, size_type c, tag={})
Definition: RangeTest.cpp:1442
void freeProtectedBuf(char *buf)
Definition: RangeTest.cpp:1021
Range< char * > MutableStringPiece
Definition: Range.h:1162
void pop_back()
Definition: Range.h:715
Range split_step(value_type delimiter)
Definition: Range.h:1001
folly::std T
TYPED_TEST_CASE(SynchronizedTest, SynchronizedTestTypes)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
bool equals(const const_range_type &other, Comp &&eq) const
Definition: Range.h:868
BOOST_CONCEPT_ASSERT((boost::RandomAccessRangeConcept< StringPiece >))
FOLLY_PUSH_WARNING RHS rhs
Definition: Traits.h:649
bool removeSuffix(const const_range_type &suffix)
Definition: Range.h:904
::testing::Types< SseNeedleFinder, NoSseNeedleFinder, ByteSetNeedleFinder > NeedleFinders
Definition: RangeTest.cpp:916
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
constexpr bool empty() const
Definition: Range.h:443
auto const foo
Definition: LazyTest.cpp:49
std::size_t size_type
Definition: RangeTest.cpp:1441
LogLevel min
Definition: LogLevel.cpp:30
internal::ElementsAreArrayMatcher< typename::std::iterator_traits< Iter >::value_type > ElementsAreArray(Iter first, Iter last)
void * aligned_malloc(size_t size, size_t align)
Definition: Memory.h:85
size_t qfind_first_byte_of(const StringPiece haystack, const StringPiece needles)
Definition: Range.h:1349
typename T::type _t
Definition: Traits.h:171
size_t qfind_first_byte_of_nosse(const StringPieceLite haystack, const StringPieceLite needles)
Definition: RangeCommon.h:92
static size_t find_first_byte_of(StringPiece haystack, StringPiece needles)
Definition: RangeTest.cpp:910
TYPED_TEST(SynchronizedTest, Basic)
constexpr Iter data() const
Definition: Range.h:446
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
size_t rfind(const Range< Iter > &haystack, const typename Range< Iter >::value_type &needle)
Definition: Range.h:1404
Range subpiece(size_type first, size_type length=npos) const
Definition: Range.h:686
constexpr Range< Iter > range(Iter first, Iter last)
Definition: Range.h:1114
int compare(const const_range_type &o) const
Definition: Range.h:602
AtomicCounter< T, DeterministicAtomic > Base
std::uniform_int_distribution< milliseconds::rep > dist
char a
#define C(name, bit)
Definition: CpuId.h:204
static const char *const value
Definition: Conv.cpp:50
size_t qfind(const Range< Iter > &haystack, const Range< Iter > &needle, Comp eq=Comp())
Definition: Range.h:1292
bool removePrefix(const const_range_type &prefix)
Definition: Range.h:893
std::random_device rd
constexpr Iter end() const
Definition: Range.h:455
const size_t kPageSize
Definition: RangeTest.cpp:1000
int * count
constexpr Iter begin() const
Definition: Range.h:452
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_THAT(value, matcher)
bool startsWith(const const_range_type &other) const
Definition: Range.h:828
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:758
static const size_type npos
Definition: Range.h:197
const char * string
Definition: Conv.cpp:212
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
void testRangeFunc(C &&x, size_t n)
Definition: RangeTest.cpp:1093
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
Container::value_type * dataPtr(Container &cont)
Definition: RangeTest.cpp:1082
friend bool operator==(char const *rhs, fake_string_view lhs)
Definition: RangeTest.cpp:1447
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
void basicTest()
void split_step_with_process_noop(folly::StringPiece)
Definition: RangeTest.cpp:615
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
bool endsWith(const const_range_type &other) const
Definition: Range.h:849
Range< const char * > StringPiece
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
void expectEQ(const T &a, const T &b)
Definition: RangeTest.cpp:241
static size_t find_first_byte_of(StringPiece haystack, StringPiece needles)
Definition: RangeTest.cpp:890
constexpr auto crange(Collection const &v) -> Range< decltype(v.data())>
Definition: Range.h:1131
char c
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
void erase(Iter b, Iter e)
Definition: Range.h:879
TEST(SequencedExecutor, CPUThreadPoolExecutor)
StringPiece data_
void reset(Iter start, size_type size)
Definition: Range.h:421
std::vector< int > values(1'000)
Composed all(Predicate pred=Predicate())
Definition: Base.h:786
def next(obj)
Definition: ast.py:58
static size_t find_first_byte_of(StringPiece haystack, StringPiece needles)
Definition: RangeTest.cpp:896
#define EXPECT_GT(val1, val2)
Definition: gtest.h:1934