Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / test / RangeTest.cpp
1 /*
2  * Copyright 2014 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 <boost/range/concepts.hpp>
24 #include <cstdlib>
25 #include <gtest/gtest.h>
26 #include <iterator>
27 #include <limits>
28 #include <string>
29 #include <sys/mman.h>
30 #include <vector>
31
32 namespace folly { namespace detail {
33
34 // declaration of functions in Range.cpp
35 size_t qfind_first_byte_of_memchr(const StringPiece& haystack,
36                                   const StringPiece& needles);
37
38 size_t qfind_first_byte_of_byteset(const StringPiece& haystack,
39                                    const StringPiece& needles);
40
41 }}  // namespaces
42
43 using namespace folly;
44 using namespace std;
45
46 BOOST_CONCEPT_ASSERT((boost::RandomAccessRangeConcept<StringPiece>));
47
48 TEST(StringPiece, All) {
49   const char* foo = "foo";
50   const char* foo2 = "foo";
51   string fooStr(foo);
52   string foo2Str(foo2);
53
54   // we expect the compiler to optimize things so that there's only one copy
55   // of the string literal "foo", even though we've got it in multiple places
56   EXPECT_EQ(foo, foo2);  // remember, this uses ==, not strcmp, so it's a ptr
57                          // comparison rather than lexical
58
59   // the string object creates copies though, so the c_str of these should be
60   // distinct
61   EXPECT_NE(fooStr.c_str(), foo2Str.c_str());
62
63   // test the basic StringPiece functionality
64   StringPiece s(foo);
65   EXPECT_EQ(s.size(), 3);
66
67   EXPECT_EQ(s.start(), foo);              // ptr comparison
68   EXPECT_NE(s.start(), fooStr.c_str());   // ptr comparison
69   EXPECT_NE(s.start(), foo2Str.c_str());  // ptr comparison
70
71   EXPECT_EQ(s.toString(), foo);              // lexical comparison
72   EXPECT_EQ(s.toString(), fooStr.c_str());   // lexical comparison
73   EXPECT_EQ(s.toString(), foo2Str.c_str());  // lexical comparison
74
75   EXPECT_EQ(s, foo);                      // lexical comparison
76   EXPECT_EQ(s, fooStr);                   // lexical comparison
77   EXPECT_EQ(s, foo2Str);                  // lexical comparison
78   EXPECT_EQ(foo, s);
79
80   // check using StringPiece to reference substrings
81   const char* foobarbaz = "foobarbaz";
82
83   // the full "foobarbaz"
84   s.reset(foobarbaz, strlen(foobarbaz));
85   EXPECT_EQ(s.size(), 9);
86   EXPECT_EQ(s.start(), foobarbaz);
87   EXPECT_EQ(s, "foobarbaz");
88
89   // only the 'foo'
90   s.assign(foobarbaz, foobarbaz + 3);
91   EXPECT_EQ(s.size(), 3);
92   EXPECT_EQ(s.start(), foobarbaz);
93   EXPECT_EQ(s, "foo");
94
95   // find
96   s.reset(foobarbaz, strlen(foobarbaz));
97   EXPECT_EQ(s.find("bar"), 3);
98   EXPECT_EQ(s.find("ba", 3), 3);
99   EXPECT_EQ(s.find("ba", 4), 6);
100   EXPECT_EQ(s.find("notfound"), StringPiece::npos);
101   EXPECT_EQ(s.find("notfound", 1), StringPiece::npos);
102   EXPECT_EQ(s.find("bar", 4), StringPiece::npos);  // starting position too far
103   // starting pos that is obviously past the end -- This works for std::string
104   EXPECT_EQ(s.toString().find("notfound", 55), StringPiece::npos);
105   EXPECT_EQ(s.find("z", s.size()), StringPiece::npos);
106   EXPECT_EQ(s.find("z", 55), StringPiece::npos);
107   // empty needle
108   EXPECT_EQ(s.find(""), std::string().find(""));
109   EXPECT_EQ(s.find(""), 0);
110
111   // single char finds
112   EXPECT_EQ(s.find('b'), 3);
113   EXPECT_EQ(s.find('b', 3), 3);
114   EXPECT_EQ(s.find('b', 4), 6);
115   EXPECT_EQ(s.find('o', 2), 2);
116   EXPECT_EQ(s.find('y'), StringPiece::npos);
117   EXPECT_EQ(s.find('y', 1), StringPiece::npos);
118   EXPECT_EQ(s.find('o', 4), StringPiece::npos);  // starting position too far
119   EXPECT_TRUE(s.contains('z'));
120   // starting pos that is obviously past the end -- This works for std::string
121   EXPECT_EQ(s.toString().find('y', 55), StringPiece::npos);
122   EXPECT_EQ(s.find('z', s.size()), StringPiece::npos);
123   EXPECT_EQ(s.find('z', 55), StringPiece::npos);
124   // null char
125   EXPECT_EQ(s.find('\0'), std::string().find('\0'));
126   EXPECT_EQ(s.find('\0'), StringPiece::npos);
127   EXPECT_FALSE(s.contains('\0'));
128
129   // single char rfinds
130   EXPECT_EQ(s.rfind('b'), 6);
131   EXPECT_EQ(s.rfind('y'), StringPiece::npos);
132   EXPECT_EQ(s.str().rfind('y'), StringPiece::npos);
133   EXPECT_EQ(ByteRange(s).rfind('b'), 6);
134   EXPECT_EQ(ByteRange(s).rfind('y'), StringPiece::npos);
135   // null char
136   EXPECT_EQ(s.rfind('\0'), s.str().rfind('\0'));
137   EXPECT_EQ(s.rfind('\0'), StringPiece::npos);
138
139   // find_first_of
140   s.reset(foobarbaz, strlen(foobarbaz));
141   EXPECT_EQ(s.find_first_of("bar"), 3);
142   EXPECT_EQ(s.find_first_of("ba", 3), 3);
143   EXPECT_EQ(s.find_first_of("ba", 4), 4);
144   EXPECT_TRUE(s.contains("bar"));
145   EXPECT_EQ(s.find_first_of("xyxy"), StringPiece::npos);
146   EXPECT_EQ(s.find_first_of("xyxy", 1), StringPiece::npos);
147   EXPECT_FALSE(s.contains("xyxy"));
148   // starting position too far
149   EXPECT_EQ(s.find_first_of("foo", 4), StringPiece::npos);
150   // starting pos that is obviously past the end -- This works for std::string
151   EXPECT_EQ(s.toString().find_first_of("xyxy", 55), StringPiece::npos);
152   EXPECT_EQ(s.find_first_of("z", s.size()), StringPiece::npos);
153   EXPECT_EQ(s.find_first_of("z", 55), StringPiece::npos);
154   // empty needle. Note that this returns npos, while find() returns 0!
155   EXPECT_EQ(s.find_first_of(""), std::string().find_first_of(""));
156   EXPECT_EQ(s.find_first_of(""), StringPiece::npos);
157
158   // single char find_first_ofs
159   EXPECT_EQ(s.find_first_of('b'), 3);
160   EXPECT_EQ(s.find_first_of('b', 3), 3);
161   EXPECT_EQ(s.find_first_of('b', 4), 6);
162   EXPECT_EQ(s.find_first_of('o', 2), 2);
163   EXPECT_EQ(s.find_first_of('y'), StringPiece::npos);
164   EXPECT_EQ(s.find_first_of('y', 1), StringPiece::npos);
165   // starting position too far
166   EXPECT_EQ(s.find_first_of('o', 4), StringPiece::npos);
167   // starting pos that is obviously past the end -- This works for std::string
168   EXPECT_EQ(s.toString().find_first_of('y', 55), StringPiece::npos);
169   EXPECT_EQ(s.find_first_of('z', s.size()), StringPiece::npos);
170   EXPECT_EQ(s.find_first_of('z', 55), StringPiece::npos);
171   // null char
172   EXPECT_EQ(s.find_first_of('\0'), std::string().find_first_of('\0'));
173   EXPECT_EQ(s.find_first_of('\0'), StringPiece::npos);
174
175   // just "barbaz"
176   s.reset(foobarbaz + 3, strlen(foobarbaz + 3));
177   EXPECT_EQ(s.size(), 6);
178   EXPECT_EQ(s.start(), foobarbaz + 3);
179   EXPECT_EQ(s, "barbaz");
180
181   // just "bar"
182   s.reset(foobarbaz + 3, 3);
183   EXPECT_EQ(s.size(), 3);
184   EXPECT_EQ(s, "bar");
185
186   // clear
187   s.clear();
188   EXPECT_EQ(s.toString(), "");
189
190   // test an empty StringPiece
191   StringPiece s2;
192   EXPECT_EQ(s2.size(), 0);
193
194   // Test comparison operators
195   foo = "";
196   EXPECT_LE(s, foo);
197   EXPECT_LE(foo, s);
198   EXPECT_GE(s, foo);
199   EXPECT_GE(foo, s);
200   EXPECT_EQ(s, foo);
201   EXPECT_EQ(foo, s);
202
203   foo = "abc";
204   EXPECT_LE(s, foo);
205   EXPECT_LT(s, foo);
206   EXPECT_GE(foo, s);
207   EXPECT_GT(foo, s);
208   EXPECT_NE(s, foo);
209
210   EXPECT_LE(s, s);
211   EXPECT_LE(s, s);
212   EXPECT_GE(s, s);
213   EXPECT_GE(s, s);
214   EXPECT_EQ(s, s);
215   EXPECT_EQ(s, s);
216
217   s = "abc";
218   s2 = "abc";
219   EXPECT_LE(s, s2);
220   EXPECT_LE(s2, s);
221   EXPECT_GE(s, s2);
222   EXPECT_GE(s2, s);
223   EXPECT_EQ(s, s2);
224   EXPECT_EQ(s2, s);
225 }
226
227 template <class T>
228 void expectLT(const T& a, const T& b) {
229   EXPECT_TRUE(a < b);
230   EXPECT_TRUE(a <= b);
231   EXPECT_FALSE(a == b);
232   EXPECT_FALSE(a >= b);
233   EXPECT_FALSE(a > b);
234
235   EXPECT_FALSE(b < a);
236   EXPECT_FALSE(b <= a);
237   EXPECT_TRUE(b >= a);
238   EXPECT_TRUE(b > a);
239 }
240
241 template <class T>
242 void expectEQ(const T& a, const T& b) {
243   EXPECT_FALSE(a < b);
244   EXPECT_TRUE(a <= b);
245   EXPECT_TRUE(a == b);
246   EXPECT_TRUE(a >= b);
247   EXPECT_FALSE(a > b);
248 }
249
250 TEST(StringPiece, EightBitComparisons) {
251   char values[] = {'\x00', '\x20', '\x40', '\x7f', '\x80', '\xc0', '\xff'};
252   constexpr size_t count = sizeof(values) / sizeof(values[0]);
253   for (size_t i = 0; i < count; ++i) {
254     std::string a(1, values[i]);
255     // Defeat copy-on-write
256     std::string aCopy(a.data(), a.size());
257     expectEQ(a, aCopy);
258     expectEQ(StringPiece(a), StringPiece(aCopy));
259
260     for (size_t j = i + 1; j < count; ++j) {
261       std::string b(1, values[j]);
262       expectLT(a, b);
263       expectLT(StringPiece(a), StringPiece(b));
264     }
265   }
266 }
267
268 TEST(StringPiece, ToByteRange) {
269   StringPiece a("hello");
270   ByteRange b(a);
271   EXPECT_EQ(static_cast<const void*>(a.begin()),
272             static_cast<const void*>(b.begin()));
273   EXPECT_EQ(static_cast<const void*>(a.end()),
274             static_cast<const void*>(b.end()));
275
276   // and convert back again
277   StringPiece c(b);
278   EXPECT_EQ(a.begin(), c.begin());
279   EXPECT_EQ(a.end(), c.end());
280 }
281
282 TEST(StringPiece, InvalidRange) {
283   StringPiece a("hello");
284   EXPECT_EQ(a, a.subpiece(0, 10));
285   EXPECT_EQ(StringPiece("ello"), a.subpiece(1));
286   EXPECT_EQ(StringPiece("ello"), a.subpiece(1, std::string::npos));
287   EXPECT_EQ(StringPiece("ell"), a.subpiece(1, 3));
288   EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
289   EXPECT_THROW(a.subpiece(6), std::out_of_range);
290
291   std::string b("hello");
292   EXPECT_EQ(a, StringPiece(b, 0, 10));
293   EXPECT_EQ("ello", a.subpiece(1));
294   EXPECT_EQ("ello", a.subpiece(1, std::string::npos));
295   EXPECT_EQ("ell", a.subpiece(1, 3));
296   EXPECT_THROW(a.subpiece(6, 7), std::out_of_range);
297   EXPECT_THROW(a.subpiece(6), std::out_of_range);
298 }
299
300 #if FOLLY_HAVE_CONSTEXPR_STRLEN
301 constexpr char helloArray[] = "hello";
302
303 TEST(StringPiece, Constexpr) {
304   constexpr StringPiece hello1("hello");
305   EXPECT_EQ("hello", hello1);
306
307   constexpr StringPiece hello2(helloArray);
308   EXPECT_EQ("hello", hello2);
309 }
310 #endif
311
312 TEST(StringPiece, Prefix) {
313   StringPiece a("hello");
314   EXPECT_TRUE(a.startsWith(""));
315   EXPECT_TRUE(a.startsWith("h"));
316   EXPECT_TRUE(a.startsWith('h'));
317   EXPECT_TRUE(a.startsWith("hello"));
318   EXPECT_FALSE(a.startsWith("hellox"));
319   EXPECT_FALSE(a.startsWith('x'));
320   EXPECT_FALSE(a.startsWith("x"));
321
322   {
323     auto b = a;
324     EXPECT_TRUE(b.removePrefix(""));
325     EXPECT_EQ("hello", b);
326   }
327   {
328     auto b = a;
329     EXPECT_TRUE(b.removePrefix("h"));
330     EXPECT_EQ("ello", b);
331   }
332   {
333     auto b = a;
334     EXPECT_TRUE(b.removePrefix('h'));
335     EXPECT_EQ("ello", b);
336   }
337   {
338     auto b = a;
339     EXPECT_TRUE(b.removePrefix("hello"));
340     EXPECT_EQ("", b);
341   }
342   {
343     auto b = a;
344     EXPECT_FALSE(b.removePrefix("hellox"));
345     EXPECT_EQ("hello", b);
346   }
347   {
348     auto b = a;
349     EXPECT_FALSE(b.removePrefix("x"));
350     EXPECT_EQ("hello", b);
351   }
352   {
353     auto b = a;
354     EXPECT_FALSE(b.removePrefix('x'));
355     EXPECT_EQ("hello", b);
356   }
357 }
358
359 TEST(StringPiece, Suffix) {
360   StringPiece a("hello");
361   EXPECT_TRUE(a.endsWith(""));
362   EXPECT_TRUE(a.endsWith("o"));
363   EXPECT_TRUE(a.endsWith('o'));
364   EXPECT_TRUE(a.endsWith("hello"));
365   EXPECT_FALSE(a.endsWith("xhello"));
366   EXPECT_FALSE(a.endsWith("x"));
367   EXPECT_FALSE(a.endsWith('x'));
368
369   {
370     auto b = a;
371     EXPECT_TRUE(b.removeSuffix(""));
372     EXPECT_EQ("hello", b);
373   }
374   {
375     auto b = a;
376     EXPECT_TRUE(b.removeSuffix("o"));
377     EXPECT_EQ("hell", b);
378   }
379   {
380     auto b = a;
381     EXPECT_TRUE(b.removeSuffix('o'));
382     EXPECT_EQ("hell", b);
383   }
384   {
385     auto b = a;
386     EXPECT_TRUE(b.removeSuffix("hello"));
387     EXPECT_EQ("", b);
388   }
389   {
390     auto b = a;
391     EXPECT_FALSE(b.removeSuffix("xhello"));
392     EXPECT_EQ("hello", b);
393   }
394   {
395     auto b = a;
396     EXPECT_FALSE(b.removeSuffix("x"));
397     EXPECT_EQ("hello", b);
398   }
399   {
400     auto b = a;
401     EXPECT_FALSE(b.removeSuffix('x'));
402     EXPECT_EQ("hello", b);
403   }
404 }
405
406 TEST(StringPiece, PrefixEmpty) {
407   StringPiece a;
408   EXPECT_TRUE(a.startsWith(""));
409   EXPECT_FALSE(a.startsWith("a"));
410   EXPECT_FALSE(a.startsWith('a'));
411   EXPECT_TRUE(a.removePrefix(""));
412   EXPECT_EQ("", a);
413   EXPECT_FALSE(a.removePrefix("a"));
414   EXPECT_EQ("", a);
415   EXPECT_FALSE(a.removePrefix('a'));
416   EXPECT_EQ("", a);
417 }
418
419 TEST(StringPiece, SuffixEmpty) {
420   StringPiece a;
421   EXPECT_TRUE(a.endsWith(""));
422   EXPECT_FALSE(a.endsWith("a"));
423   EXPECT_FALSE(a.endsWith('a'));
424   EXPECT_TRUE(a.removeSuffix(""));
425   EXPECT_EQ("", a);
426   EXPECT_FALSE(a.removeSuffix("a"));
427   EXPECT_EQ("", a);
428   EXPECT_FALSE(a.removeSuffix('a'));
429   EXPECT_EQ("", a);
430 }
431
432 TEST(StringPiece, split_step_char_delimiter) {
433   //              0         1         2
434   //              012345678901234567890123456
435   auto const s = "this is just  a test string";
436   auto const e = std::next(s, std::strlen(s));
437   EXPECT_EQ('\0', *e);
438
439   folly::StringPiece p(s);
440   EXPECT_EQ(s, p.begin());
441   EXPECT_EQ(e, p.end());
442   EXPECT_EQ(s, p);
443
444   auto x = p.split_step(' ');
445   EXPECT_EQ(std::next(s, 5), p.begin());
446   EXPECT_EQ(e, p.end());
447   EXPECT_EQ("this", x);
448
449   x = p.split_step(' ');
450   EXPECT_EQ(std::next(s, 8), p.begin());
451   EXPECT_EQ(e, p.end());
452   EXPECT_EQ("is", x);
453
454   x = p.split_step('u');
455   EXPECT_EQ(std::next(s, 10), p.begin());
456   EXPECT_EQ(e, p.end());
457   EXPECT_EQ("j", x);
458
459   x = p.split_step(' ');
460   EXPECT_EQ(std::next(s, 13), p.begin());
461   EXPECT_EQ(e, p.end());
462   EXPECT_EQ("st", x);
463
464   x = p.split_step(' ');
465   EXPECT_EQ(std::next(s, 14), p.begin());
466   EXPECT_EQ(e, p.end());
467   EXPECT_EQ("", x);
468
469   x = p.split_step(' ');
470   EXPECT_EQ(std::next(s, 16), p.begin());
471   EXPECT_EQ(e, p.end());
472   EXPECT_EQ("a", x);
473
474   x = p.split_step(' ');
475   EXPECT_EQ(std::next(s, 21), p.begin());
476   EXPECT_EQ(e, p.end());
477   EXPECT_EQ("test", x);
478
479   x = p.split_step(' ');
480   EXPECT_EQ(e, p.begin());
481   EXPECT_EQ(e, p.end());
482   EXPECT_EQ("string", x);
483
484   x = p.split_step(' ');
485   EXPECT_EQ(e, p.begin());
486   EXPECT_EQ(e, p.end());
487   EXPECT_EQ("", x);
488 }
489
490 TEST(StringPiece, split_step_range_delimiter) {
491   //              0         1         2         3
492   //              0123456789012345678901234567890123
493   auto const s = "this  is  just    a   test  string";
494   auto const e = std::next(s, std::strlen(s));
495   EXPECT_EQ('\0', *e);
496
497   folly::StringPiece p(s);
498   EXPECT_EQ(s, p.begin());
499   EXPECT_EQ(e, p.end());
500   EXPECT_EQ(s, p);
501
502   auto x = p.split_step("  ");
503   EXPECT_EQ(std::next(s, 6), p.begin());
504   EXPECT_EQ(e, p.end());
505   EXPECT_EQ("this", x);
506
507   x = p.split_step("  ");
508   EXPECT_EQ(std::next(s, 10), p.begin());
509   EXPECT_EQ(e, p.end());
510   EXPECT_EQ("is", x);
511
512   x = p.split_step("u");
513   EXPECT_EQ(std::next(s, 12), p.begin());
514   EXPECT_EQ(e, p.end());
515   EXPECT_EQ("j", x);
516
517   x = p.split_step("  ");
518   EXPECT_EQ(std::next(s, 16), p.begin());
519   EXPECT_EQ(e, p.end());
520   EXPECT_EQ("st", x);
521
522   x = p.split_step("  ");
523   EXPECT_EQ(std::next(s, 18), p.begin());
524   EXPECT_EQ(e, p.end());
525   EXPECT_EQ("", x);
526
527   x = p.split_step("  ");
528   EXPECT_EQ(std::next(s, 21), p.begin());
529   EXPECT_EQ(e, p.end());
530   EXPECT_EQ("a", x);
531
532   x = p.split_step("  ");
533   EXPECT_EQ(std::next(s, 28), p.begin());
534   EXPECT_EQ(e, p.end());
535   EXPECT_EQ(" test", x);
536
537   x = p.split_step("  ");
538   EXPECT_EQ(e, p.begin());
539   EXPECT_EQ(e, p.end());
540   EXPECT_EQ("string", x);
541
542   x = p.split_step("  ");
543   EXPECT_EQ(e, p.begin());
544   EXPECT_EQ(e, p.end());
545   EXPECT_EQ("", x);
546
547   x = p.split_step(" ");
548   EXPECT_EQ(e, p.begin());
549   EXPECT_EQ(e, p.end());
550   EXPECT_EQ("", x);
551 }
552
553 void split_step_with_process_noop(folly::StringPiece) {}
554
555 TEST(StringPiece, split_step_with_process_char_delimiter) {
556   //              0         1         2
557   //              012345678901234567890123456
558   auto const s = "this is just  a test string";
559   auto const e = std::next(s, std::strlen(s));
560   EXPECT_EQ('\0', *e);
561
562   folly::StringPiece p(s);
563   EXPECT_EQ(s, p.begin());
564   EXPECT_EQ(e, p.end());
565   EXPECT_EQ(s, p);
566
567   EXPECT_EQ(1, (p.split_step(' ', [&](folly::StringPiece x) {
568     EXPECT_EQ(std::next(s, 5), p.begin());
569     EXPECT_EQ(e, p.end());
570     EXPECT_EQ("this", x);
571     return 1;
572   })));
573
574   EXPECT_EQ(2, (p.split_step(' ', [&](folly::StringPiece x) {
575     EXPECT_EQ(std::next(s, 8), p.begin());
576     EXPECT_EQ(e, p.end());
577     EXPECT_EQ("is", x);
578     return 2;
579   })));
580
581   EXPECT_EQ(3, (p.split_step('u', [&](folly::StringPiece x) {
582     EXPECT_EQ(std::next(s, 10), p.begin());
583     EXPECT_EQ(e, p.end());
584     EXPECT_EQ("j", x);
585     return 3;
586   })));
587
588   EXPECT_EQ(4, (p.split_step(' ', [&](folly::StringPiece x) {
589     EXPECT_EQ(std::next(s, 13), p.begin());
590     EXPECT_EQ(e, p.end());
591     EXPECT_EQ("st", x);
592     return 4;
593   })));
594
595   EXPECT_EQ(5, (p.split_step(' ', [&](folly::StringPiece x) {
596     EXPECT_EQ(std::next(s, 14), p.begin());
597     EXPECT_EQ(e, p.end());
598     EXPECT_EQ("", x);
599     return 5;
600   })));
601
602   EXPECT_EQ(6, (p.split_step(' ', [&](folly::StringPiece x) {
603     EXPECT_EQ(std::next(s, 16), p.begin());
604     EXPECT_EQ(e, p.end());
605     EXPECT_EQ("a", x);
606     return 6;
607   })));
608
609   EXPECT_EQ(7, (p.split_step(' ', [&](folly::StringPiece x) {
610     EXPECT_EQ(std::next(s, 21), p.begin());
611     EXPECT_EQ(e, p.end());
612     EXPECT_EQ("test", x);
613     return 7;
614   })));
615
616   EXPECT_EQ(8, (p.split_step(' ', [&](folly::StringPiece x) {
617     EXPECT_EQ(e, p.begin());
618     EXPECT_EQ(e, p.end());
619     EXPECT_EQ("string", x);
620     return 8;
621   })));
622
623   EXPECT_EQ(9, (p.split_step(' ', [&](folly::StringPiece x) {
624     EXPECT_EQ(e, p.begin());
625     EXPECT_EQ(e, p.end());
626     EXPECT_EQ("", x);
627     return 9;
628   })));
629
630   EXPECT_TRUE((std::is_same<
631     void,
632     decltype(p.split_step(' ', split_step_with_process_noop))
633   >::value));
634
635   EXPECT_NO_THROW(p.split_step(' ', split_step_with_process_noop));
636 }
637
638 TEST(StringPiece, split_step_with_process_range_delimiter) {
639   //              0         1         2         3
640   //              0123456789012345678901234567890123
641   auto const s = "this  is  just    a   test  string";
642   auto const e = std::next(s, std::strlen(s));
643   EXPECT_EQ('\0', *e);
644
645   folly::StringPiece p(s);
646   EXPECT_EQ(s, p.begin());
647   EXPECT_EQ(e, p.end());
648   EXPECT_EQ(s, p);
649
650   EXPECT_EQ(1, (p.split_step("  ", [&](folly::StringPiece x) {
651     EXPECT_EQ(std::next(s, 6), p.begin());
652     EXPECT_EQ(e, p.end());
653     EXPECT_EQ("this", x);
654     return 1;
655   })));
656
657   EXPECT_EQ(2, (p.split_step("  ", [&](folly::StringPiece x) {
658     EXPECT_EQ(std::next(s, 10), p.begin());
659     EXPECT_EQ(e, p.end());
660     EXPECT_EQ("is", x);
661     return 2;
662   })));
663
664   EXPECT_EQ(3, (p.split_step("u", [&](folly::StringPiece x) {
665     EXPECT_EQ(std::next(s, 12), p.begin());
666     EXPECT_EQ(e, p.end());
667     EXPECT_EQ("j", x);
668     return 3;
669   })));
670
671   EXPECT_EQ(4, (p.split_step("  ", [&](folly::StringPiece x) {
672     EXPECT_EQ(std::next(s, 16), p.begin());
673     EXPECT_EQ(e, p.end());
674     EXPECT_EQ("st", x);
675     return 4;
676   })));
677
678   EXPECT_EQ(5, (p.split_step("  ", [&](folly::StringPiece x) {
679     EXPECT_EQ(std::next(s, 18), p.begin());
680     EXPECT_EQ(e, p.end());
681     EXPECT_EQ("", x);
682     return 5;
683   })));
684
685   EXPECT_EQ(6, (p.split_step("  ", [&](folly::StringPiece x) {
686     EXPECT_EQ(std::next(s, 21), p.begin());
687     EXPECT_EQ(e, p.end());
688     EXPECT_EQ("a", x);
689     return 6;
690   })));
691
692   EXPECT_EQ(7, (p.split_step("  ", [&](folly::StringPiece x) {
693     EXPECT_EQ(std::next(s, 28), p.begin());
694     EXPECT_EQ(e, p.end());
695     EXPECT_EQ(" test", x);
696     return 7;
697   })));
698
699   EXPECT_EQ(8, (p.split_step("  ", [&](folly::StringPiece x) {
700     EXPECT_EQ(e, p.begin());
701     EXPECT_EQ(e, p.end());
702     EXPECT_EQ("string", x);
703     return 8;
704   })));
705
706   EXPECT_EQ(9, (p.split_step("  ", [&](folly::StringPiece x) {
707     EXPECT_EQ(e, p.begin());
708     EXPECT_EQ(e, p.end());
709     EXPECT_EQ("", x);
710     return 9;
711   })));
712
713   EXPECT_EQ(10, (p.split_step("  ", [&](folly::StringPiece x) {
714     EXPECT_EQ(e, p.begin());
715     EXPECT_EQ(e, p.end());
716     EXPECT_EQ("", x);
717     return 10;
718   })));
719
720   EXPECT_TRUE((std::is_same<
721     void,
722     decltype(p.split_step(' ', split_step_with_process_noop))
723   >::value));
724
725   EXPECT_NO_THROW(p.split_step(' ', split_step_with_process_noop));
726 }
727
728 TEST(StringPiece, split_step_with_process_char_delimiter_additional_args) {
729   //              0         1         2
730   //              012345678901234567890123456
731   auto const s = "this is just  a test string";
732   auto const e = std::next(s, std::strlen(s));
733   auto const delimiter = ' ';
734   EXPECT_EQ('\0', *e);
735
736   folly::StringPiece p(s);
737   EXPECT_EQ(s, p.begin());
738   EXPECT_EQ(e, p.end());
739   EXPECT_EQ(s, p);
740
741   auto const functor = [](
742     folly::StringPiece s,
743     folly::StringPiece expected
744   ) {
745     EXPECT_EQ(expected, s);
746     return expected;
747   };
748
749   auto const checker = [&](folly::StringPiece expected) {
750     EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
751   };
752
753   checker("this");
754   checker("is");
755   checker("just");
756   checker("");
757   checker("a");
758   checker("test");
759   checker("string");
760   checker("");
761   checker("");
762
763   EXPECT_TRUE(p.empty());
764 }
765
766 TEST(StringPiece, split_step_with_process_range_delimiter_additional_args) {
767   //              0         1         2         3
768   //              0123456789012345678901234567890123
769   auto const s = "this  is  just    a   test  string";
770   auto const e = std::next(s, std::strlen(s));
771   auto const delimiter = "  ";
772   EXPECT_EQ('\0', *e);
773
774   folly::StringPiece p(s);
775   EXPECT_EQ(s, p.begin());
776   EXPECT_EQ(e, p.end());
777   EXPECT_EQ(s, p);
778
779   auto const functor = [](
780     folly::StringPiece s,
781     folly::StringPiece expected
782   ) {
783     EXPECT_EQ(expected, s);
784     return expected;
785   };
786
787   auto const checker = [&](folly::StringPiece expected) {
788     EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
789   };
790
791   checker("this");
792   checker("is");
793   checker("just");
794   checker("");
795   checker("a");
796   checker(" test");
797   checker("string");
798   checker("");
799   checker("");
800
801   EXPECT_TRUE(p.empty());
802 }
803
804 TEST(qfind, UInt32_Ranges) {
805   vector<uint32_t> a({1, 2, 3, 260, 5});
806   vector<uint32_t> b({2, 3, 4});
807
808   auto a_range = folly::Range<const uint32_t*>(&a[0], a.size());
809   auto b_range = folly::Range<const uint32_t*>(&b[0], b.size());
810
811   EXPECT_EQ(qfind(a_range, b_range), string::npos);
812
813   a[3] = 4;
814   EXPECT_EQ(qfind(a_range, b_range), 1);
815 }
816
817 template <typename NeedleFinder>
818 class NeedleFinderTest : public ::testing::Test {
819  public:
820   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
821     return NeedleFinder::find_first_byte_of(haystack, needles);
822   }
823 };
824
825 struct SseNeedleFinder {
826   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
827     // This will only use the SSE version if it is supported on this CPU
828     // (selected using ifunc).
829     return detail::qfind_first_byte_of(haystack, needles);
830   }
831 };
832
833 struct NoSseNeedleFinder {
834   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
835     return detail::qfind_first_byte_of_nosse(haystack, needles);
836   }
837 };
838
839 struct MemchrNeedleFinder {
840   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
841     return detail::qfind_first_byte_of_memchr(haystack, needles);
842   }
843 };
844
845 struct ByteSetNeedleFinder {
846   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
847     return detail::qfind_first_byte_of_byteset(haystack, needles);
848   }
849 };
850
851 typedef ::testing::Types<SseNeedleFinder, NoSseNeedleFinder, MemchrNeedleFinder,
852                          ByteSetNeedleFinder> NeedleFinders;
853 TYPED_TEST_CASE(NeedleFinderTest, NeedleFinders);
854
855 TYPED_TEST(NeedleFinderTest, Null) {
856   { // null characters in the string
857     string s(10, char(0));
858     s[5] = 'b';
859     string delims("abc");
860     EXPECT_EQ(5, this->find_first_byte_of(s, delims));
861   }
862   { // null characters in delim
863     string s("abc");
864     string delims(10, char(0));
865     delims[3] = 'c';
866     delims[7] = 'b';
867     EXPECT_EQ(1, this->find_first_byte_of(s, delims));
868   }
869   { // range not terminated by null character
870     string buf = "abcdefghijklmnopqrstuvwxyz";
871     StringPiece s(buf.data() + 5, 3);
872     StringPiece delims("z");
873     EXPECT_EQ(string::npos, this->find_first_byte_of(s, delims));
874   }
875 }
876
877 TYPED_TEST(NeedleFinderTest, DelimDuplicates) {
878   string delims(1000, 'b');
879   EXPECT_EQ(1, this->find_first_byte_of("abc", delims));
880   EXPECT_EQ(string::npos, this->find_first_byte_of("ac", delims));
881 }
882
883 TYPED_TEST(NeedleFinderTest, Empty) {
884   string a = "abc";
885   string b = "";
886   EXPECT_EQ(string::npos, this->find_first_byte_of(a, b));
887   EXPECT_EQ(string::npos, this->find_first_byte_of(b, a));
888   EXPECT_EQ(string::npos, this->find_first_byte_of(b, b));
889 }
890
891 TYPED_TEST(NeedleFinderTest, Unaligned) {
892   // works correctly even if input buffers are not 16-byte aligned
893   string s = "0123456789ABCDEFGH";
894   for (int i = 0; i < s.size(); ++i) {
895     StringPiece a(s.c_str() + i);
896     for (int j = 0; j < s.size(); ++j) {
897       StringPiece b(s.c_str() + j);
898       EXPECT_EQ((i > j) ? 0 : j - i, this->find_first_byte_of(a, b));
899     }
900   }
901 }
902
903 // for some algorithms (specifically those that create a set of needles),
904 // we check for the edge-case of _all_ possible needles being sought.
905 TYPED_TEST(NeedleFinderTest, Needles256) {
906   string needles;
907   const auto minValue = std::numeric_limits<StringPiece::value_type>::min();
908   const auto maxValue = std::numeric_limits<StringPiece::value_type>::max();
909   // make the size ~big to avoid any edge-case branches for tiny haystacks
910   const int haystackSize = 50;
911   for (int i = minValue; i <= maxValue; i++) {  // <=
912     needles.push_back(i);
913   }
914   EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
915   for (int i = minValue; i <= maxValue; i++) {
916     EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
917   }
918
919   needles.append("these are redundant characters");
920   EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
921   for (int i = minValue; i <= maxValue; i++) {
922     EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
923   }
924 }
925
926 TYPED_TEST(NeedleFinderTest, Base) {
927   for (int i = 0; i < 32; ++i) {
928     for (int j = 0; j < 32; ++j) {
929       string s = string(i, 'X') + "abca" + string(i, 'X');
930       string delims = string(j, 'Y') + "a" + string(j, 'Y');
931       EXPECT_EQ(i, this->find_first_byte_of(s, delims));
932     }
933   }
934 }
935
936 const size_t kPageSize = 4096;
937 // Updates contents so that any read accesses past the last byte will
938 // cause a SIGSEGV.  It accomplishes this by changing access to the page that
939 // begins immediately after the end of the contents (as allocators and mmap()
940 // all operate on page boundaries, this is a reasonable assumption).
941 // This function will also initialize buf, which caller must free().
942 void createProtectedBuf(StringPiece& contents, char** buf) {
943   ASSERT_LE(contents.size(), kPageSize);
944   const size_t kSuccess = 0;
945   if (kSuccess != posix_memalign((void**)buf, kPageSize, 4 * kPageSize)) {
946     ASSERT_FALSE(true);
947   }
948   mprotect(*buf + kPageSize, kPageSize, PROT_NONE);
949   size_t newBegin = kPageSize - contents.size();
950   memcpy(*buf + newBegin, contents.data(), contents.size());
951   contents.reset(*buf + newBegin, contents.size());
952 }
953
954 void freeProtectedBuf(char* buf) {
955   mprotect(buf + kPageSize, kPageSize, PROT_READ | PROT_WRITE);
956   free(buf);
957 }
958
959 TYPED_TEST(NeedleFinderTest, NoSegFault) {
960   const string base = string(32, 'a') + string("b");
961   const string delims = string(32, 'c') + string("b");
962   for (int i = 0; i <= 32; i++) {
963     for (int j = 0; j <= 33; j++) {
964       for (int shouldFind = 0; shouldFind <= 1; ++shouldFind) {
965         StringPiece s1(base);
966         s1.advance(i);
967         ASSERT_TRUE(!s1.empty());
968         if (!shouldFind) {
969           s1.pop_back();
970         }
971         StringPiece s2(delims);
972         s2.advance(j);
973         char* buf1;
974         char* buf2;
975         createProtectedBuf(s1, &buf1);
976         createProtectedBuf(s2, &buf2);
977         // printf("s1: '%s' (%ld) \ts2: '%s' (%ld)\n",
978         //        string(s1.data(), s1.size()).c_str(), s1.size(),
979         //        string(s2.data(), s2.size()).c_str(), s2.size());
980         auto r1 = this->find_first_byte_of(s1, s2);
981         auto f1 = std::find_first_of(s1.begin(), s1.end(),
982                                      s2.begin(), s2.end());
983         auto e1 = (f1 == s1.end()) ? StringPiece::npos : f1 - s1.begin();
984         EXPECT_EQ(r1, e1);
985         auto r2 = this->find_first_byte_of(s2, s1);
986         auto f2 = std::find_first_of(s2.begin(), s2.end(),
987                                      s1.begin(), s1.end());
988         auto e2 = (f2 == s2.end()) ? StringPiece::npos : f2 - s2.begin();
989         EXPECT_EQ(r2, e2);
990         freeProtectedBuf(buf1);
991         freeProtectedBuf(buf2);
992       }
993     }
994   }
995 }
996
997 TEST(NonConstTest, StringPiece) {
998   std::string hello("hello");
999   MutableStringPiece sp(&hello.front(), hello.size());
1000   sp[0] = 'x';
1001   EXPECT_EQ("xello", hello);
1002   {
1003     StringPiece s(sp);
1004     EXPECT_EQ("xello", s);
1005   }
1006   {
1007     ByteRange r1(sp);
1008     MutableByteRange r2(sp);
1009   }
1010 }
1011
1012 template<class C>
1013 void testRangeFunc(C&& x, size_t n) {
1014   const auto& cx = x;
1015   // type, conversion checks
1016   Range<int*> r1 = range(std::forward<C>(x));
1017   Range<const int*> r2 = range(std::forward<C>(x));
1018   Range<const int*> r3 = range(cx);
1019   Range<const int*> r5 = range(std::move(cx));
1020   EXPECT_EQ(r1.begin(), &x[0]);
1021   EXPECT_EQ(r1.end(), &x[n]);
1022   EXPECT_EQ(n, r1.size());
1023   EXPECT_EQ(n, r2.size());
1024   EXPECT_EQ(n, r3.size());
1025   EXPECT_EQ(n, r5.size());
1026 }
1027
1028 TEST(RangeFunc, Vector) {
1029   std::vector<int> x;
1030   testRangeFunc(x, 0);
1031   x.push_back(2);
1032   testRangeFunc(x, 1);
1033   testRangeFunc(std::vector<int>{1, 2}, 2);
1034 }
1035
1036 TEST(RangeFunc, Array) {
1037   std::array<int, 3> x;
1038   testRangeFunc(x, 3);
1039 }
1040
1041 TEST(RangeFunc, CArray) {
1042   int x[] {1, 2, 3, 4};
1043   testRangeFunc(x, 4);
1044 }