Set O_CLOEXEC by default when creating pipes to avoid race conditions resulting from...
[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
443   auto x = p.split_step(' ');
444   EXPECT_EQ(std::next(s, 5), p.begin());
445   EXPECT_EQ(e, p.end());
446   EXPECT_EQ("this", x);
447
448   x = p.split_step(' ');
449   EXPECT_EQ(std::next(s, 8), p.begin());
450   EXPECT_EQ(e, p.end());
451   EXPECT_EQ("is", x);
452
453   x = p.split_step('u');
454   EXPECT_EQ(std::next(s, 10), p.begin());
455   EXPECT_EQ(e, p.end());
456   EXPECT_EQ("j", x);
457
458   x = p.split_step(' ');
459   EXPECT_EQ(std::next(s, 13), p.begin());
460   EXPECT_EQ(e, p.end());
461   EXPECT_EQ("st", x);
462
463   x = p.split_step(' ');
464   EXPECT_EQ(std::next(s, 14), p.begin());
465   EXPECT_EQ(e, p.end());
466   EXPECT_EQ("", x);
467
468   x = p.split_step(' ');
469   EXPECT_EQ(std::next(s, 16), p.begin());
470   EXPECT_EQ(e, p.end());
471   EXPECT_EQ("a", x);
472
473   x = p.split_step(' ');
474   EXPECT_EQ(std::next(s, 21), p.begin());
475   EXPECT_EQ(e, p.end());
476   EXPECT_EQ("test", x);
477
478   x = p.split_step(' ');
479   EXPECT_EQ(e, p.begin());
480   EXPECT_EQ(e, p.end());
481   EXPECT_EQ("string", x);
482
483   x = p.split_step(' ');
484   EXPECT_EQ(e, p.begin());
485   EXPECT_EQ(e, p.end());
486   EXPECT_EQ("", x);
487 }
488
489 TEST(StringPiece, split_step_range_delimiter) {
490   //              0         1         2         3
491   //              0123456789012345678901234567890123
492   auto const s = "this  is  just    a   test  string";
493   auto const e = std::next(s, std::strlen(s));
494   EXPECT_EQ('\0', *e);
495
496   folly::StringPiece p(s);
497   EXPECT_EQ(s, p.begin());
498   EXPECT_EQ(e, p.end());
499
500   auto x = p.split_step("  ");
501   EXPECT_EQ(std::next(s, 6), p.begin());
502   EXPECT_EQ(e, p.end());
503   EXPECT_EQ("this", x);
504
505   x = p.split_step("  ");
506   EXPECT_EQ(std::next(s, 10), p.begin());
507   EXPECT_EQ(e, p.end());
508   EXPECT_EQ("is", x);
509
510   x = p.split_step("u");
511   EXPECT_EQ(std::next(s, 12), p.begin());
512   EXPECT_EQ(e, p.end());
513   EXPECT_EQ("j", x);
514
515   x = p.split_step("  ");
516   EXPECT_EQ(std::next(s, 16), p.begin());
517   EXPECT_EQ(e, p.end());
518   EXPECT_EQ("st", x);
519
520   x = p.split_step("  ");
521   EXPECT_EQ(std::next(s, 18), p.begin());
522   EXPECT_EQ(e, p.end());
523   EXPECT_EQ("", x);
524
525   x = p.split_step("  ");
526   EXPECT_EQ(std::next(s, 21), p.begin());
527   EXPECT_EQ(e, p.end());
528   EXPECT_EQ("a", x);
529
530   x = p.split_step("  ");
531   EXPECT_EQ(std::next(s, 28), p.begin());
532   EXPECT_EQ(e, p.end());
533   EXPECT_EQ(" test", x);
534
535   x = p.split_step("  ");
536   EXPECT_EQ(e, p.begin());
537   EXPECT_EQ(e, p.end());
538   EXPECT_EQ("string", x);
539
540   x = p.split_step("  ");
541   EXPECT_EQ(e, p.begin());
542   EXPECT_EQ(e, p.end());
543   EXPECT_EQ("", x);
544
545   x = p.split_step(" ");
546   EXPECT_EQ(e, p.begin());
547   EXPECT_EQ(e, p.end());
548   EXPECT_EQ("", x);
549 }
550
551 void split_step_with_process_noop(folly::StringPiece) {}
552
553 TEST(StringPiece, split_step_with_process_char_delimiter) {
554   //              0         1         2
555   //              012345678901234567890123456
556   auto const s = "this is just  a test string";
557   auto const e = std::next(s, std::strlen(s));
558   EXPECT_EQ('\0', *e);
559
560   folly::StringPiece p(s);
561   EXPECT_EQ(s, p.begin());
562   EXPECT_EQ(e, p.end());
563
564   EXPECT_EQ(1, (p.split_step(' ', [&](folly::StringPiece x) {
565     EXPECT_EQ(std::next(s, 5), p.begin());
566     EXPECT_EQ(e, p.end());
567     EXPECT_EQ("this", x);
568     return 1;
569   })));
570
571   EXPECT_EQ(2, (p.split_step(' ', [&](folly::StringPiece x) {
572     EXPECT_EQ(std::next(s, 8), p.begin());
573     EXPECT_EQ(e, p.end());
574     EXPECT_EQ("is", x);
575     return 2;
576   })));
577
578   EXPECT_EQ(3, (p.split_step('u', [&](folly::StringPiece x) {
579     EXPECT_EQ(std::next(s, 10), p.begin());
580     EXPECT_EQ(e, p.end());
581     EXPECT_EQ("j", x);
582     return 3;
583   })));
584
585   EXPECT_EQ(4, (p.split_step(' ', [&](folly::StringPiece x) {
586     EXPECT_EQ(std::next(s, 13), p.begin());
587     EXPECT_EQ(e, p.end());
588     EXPECT_EQ("st", x);
589     return 4;
590   })));
591
592   EXPECT_EQ(5, (p.split_step(' ', [&](folly::StringPiece x) {
593     EXPECT_EQ(std::next(s, 14), p.begin());
594     EXPECT_EQ(e, p.end());
595     EXPECT_EQ("", x);
596     return 5;
597   })));
598
599   EXPECT_EQ(6, (p.split_step(' ', [&](folly::StringPiece x) {
600     EXPECT_EQ(std::next(s, 16), p.begin());
601     EXPECT_EQ(e, p.end());
602     EXPECT_EQ("a", x);
603     return 6;
604   })));
605
606   EXPECT_EQ(7, (p.split_step(' ', [&](folly::StringPiece x) {
607     EXPECT_EQ(std::next(s, 21), p.begin());
608     EXPECT_EQ(e, p.end());
609     EXPECT_EQ("test", x);
610     return 7;
611   })));
612
613   EXPECT_EQ(8, (p.split_step(' ', [&](folly::StringPiece x) {
614     EXPECT_EQ(e, p.begin());
615     EXPECT_EQ(e, p.end());
616     EXPECT_EQ("string", x);
617     return 8;
618   })));
619
620   EXPECT_EQ(9, (p.split_step(' ', [&](folly::StringPiece x) {
621     EXPECT_EQ(e, p.begin());
622     EXPECT_EQ(e, p.end());
623     EXPECT_EQ("", x);
624     return 9;
625   })));
626
627   EXPECT_TRUE((std::is_same<
628     void,
629     decltype(p.split_step(' ', split_step_with_process_noop))
630   >::value));
631
632   EXPECT_NO_THROW(p.split_step(' ', split_step_with_process_noop));
633 }
634
635 TEST(StringPiece, split_step_with_process_range_delimiter) {
636   //              0         1         2         3
637   //              0123456789012345678901234567890123
638   auto const s = "this  is  just    a   test  string";
639   auto const e = std::next(s, std::strlen(s));
640   EXPECT_EQ('\0', *e);
641
642   folly::StringPiece p(s);
643   EXPECT_EQ(s, p.begin());
644   EXPECT_EQ(e, p.end());
645
646   EXPECT_EQ(1, (p.split_step("  ", [&](folly::StringPiece x) {
647     EXPECT_EQ(std::next(s, 6), p.begin());
648     EXPECT_EQ(e, p.end());
649     EXPECT_EQ("this", x);
650     return 1;
651   })));
652
653   EXPECT_EQ(2, (p.split_step("  ", [&](folly::StringPiece x) {
654     EXPECT_EQ(std::next(s, 10), p.begin());
655     EXPECT_EQ(e, p.end());
656     EXPECT_EQ("is", x);
657     return 2;
658   })));
659
660   EXPECT_EQ(3, (p.split_step("u", [&](folly::StringPiece x) {
661     EXPECT_EQ(std::next(s, 12), p.begin());
662     EXPECT_EQ(e, p.end());
663     EXPECT_EQ("j", x);
664     return 3;
665   })));
666
667   EXPECT_EQ(4, (p.split_step("  ", [&](folly::StringPiece x) {
668     EXPECT_EQ(std::next(s, 16), p.begin());
669     EXPECT_EQ(e, p.end());
670     EXPECT_EQ("st", x);
671     return 4;
672   })));
673
674   EXPECT_EQ(5, (p.split_step("  ", [&](folly::StringPiece x) {
675     EXPECT_EQ(std::next(s, 18), p.begin());
676     EXPECT_EQ(e, p.end());
677     EXPECT_EQ("", x);
678     return 5;
679   })));
680
681   EXPECT_EQ(6, (p.split_step("  ", [&](folly::StringPiece x) {
682     EXPECT_EQ(std::next(s, 21), p.begin());
683     EXPECT_EQ(e, p.end());
684     EXPECT_EQ("a", x);
685     return 6;
686   })));
687
688   EXPECT_EQ(7, (p.split_step("  ", [&](folly::StringPiece x) {
689     EXPECT_EQ(std::next(s, 28), p.begin());
690     EXPECT_EQ(e, p.end());
691     EXPECT_EQ(" test", x);
692     return 7;
693   })));
694
695   EXPECT_EQ(8, (p.split_step("  ", [&](folly::StringPiece x) {
696     EXPECT_EQ(e, p.begin());
697     EXPECT_EQ(e, p.end());
698     EXPECT_EQ("string", x);
699     return 8;
700   })));
701
702   EXPECT_EQ(9, (p.split_step("  ", [&](folly::StringPiece x) {
703     EXPECT_EQ(e, p.begin());
704     EXPECT_EQ(e, p.end());
705     EXPECT_EQ("", x);
706     return 9;
707   })));
708
709   EXPECT_EQ(10, (p.split_step("  ", [&](folly::StringPiece x) {
710     EXPECT_EQ(e, p.begin());
711     EXPECT_EQ(e, p.end());
712     EXPECT_EQ("", x);
713     return 10;
714   })));
715
716   EXPECT_TRUE((std::is_same<
717     void,
718     decltype(p.split_step(' ', split_step_with_process_noop))
719   >::value));
720
721   EXPECT_NO_THROW(p.split_step(' ', split_step_with_process_noop));
722 }
723
724 TEST(qfind, UInt32_Ranges) {
725   vector<uint32_t> a({1, 2, 3, 260, 5});
726   vector<uint32_t> b({2, 3, 4});
727
728   auto a_range = folly::Range<const uint32_t*>(&a[0], a.size());
729   auto b_range = folly::Range<const uint32_t*>(&b[0], b.size());
730
731   EXPECT_EQ(qfind(a_range, b_range), string::npos);
732
733   a[3] = 4;
734   EXPECT_EQ(qfind(a_range, b_range), 1);
735 }
736
737 template <typename NeedleFinder>
738 class NeedleFinderTest : public ::testing::Test {
739  public:
740   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
741     return NeedleFinder::find_first_byte_of(haystack, needles);
742   }
743 };
744
745 struct SseNeedleFinder {
746   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
747     // This will only use the SSE version if it is supported on this CPU
748     // (selected using ifunc).
749     return detail::qfind_first_byte_of(haystack, needles);
750   }
751 };
752
753 struct NoSseNeedleFinder {
754   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
755     return detail::qfind_first_byte_of_nosse(haystack, needles);
756   }
757 };
758
759 struct MemchrNeedleFinder {
760   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
761     return detail::qfind_first_byte_of_memchr(haystack, needles);
762   }
763 };
764
765 struct ByteSetNeedleFinder {
766   static size_t find_first_byte_of(StringPiece haystack, StringPiece needles) {
767     return detail::qfind_first_byte_of_byteset(haystack, needles);
768   }
769 };
770
771 typedef ::testing::Types<SseNeedleFinder, NoSseNeedleFinder, MemchrNeedleFinder,
772                          ByteSetNeedleFinder> NeedleFinders;
773 TYPED_TEST_CASE(NeedleFinderTest, NeedleFinders);
774
775 TYPED_TEST(NeedleFinderTest, Null) {
776   { // null characters in the string
777     string s(10, char(0));
778     s[5] = 'b';
779     string delims("abc");
780     EXPECT_EQ(5, this->find_first_byte_of(s, delims));
781   }
782   { // null characters in delim
783     string s("abc");
784     string delims(10, char(0));
785     delims[3] = 'c';
786     delims[7] = 'b';
787     EXPECT_EQ(1, this->find_first_byte_of(s, delims));
788   }
789   { // range not terminated by null character
790     string buf = "abcdefghijklmnopqrstuvwxyz";
791     StringPiece s(buf.data() + 5, 3);
792     StringPiece delims("z");
793     EXPECT_EQ(string::npos, this->find_first_byte_of(s, delims));
794   }
795 }
796
797 TYPED_TEST(NeedleFinderTest, DelimDuplicates) {
798   string delims(1000, 'b');
799   EXPECT_EQ(1, this->find_first_byte_of("abc", delims));
800   EXPECT_EQ(string::npos, this->find_first_byte_of("ac", delims));
801 }
802
803 TYPED_TEST(NeedleFinderTest, Empty) {
804   string a = "abc";
805   string b = "";
806   EXPECT_EQ(string::npos, this->find_first_byte_of(a, b));
807   EXPECT_EQ(string::npos, this->find_first_byte_of(b, a));
808   EXPECT_EQ(string::npos, this->find_first_byte_of(b, b));
809 }
810
811 TYPED_TEST(NeedleFinderTest, Unaligned) {
812   // works correctly even if input buffers are not 16-byte aligned
813   string s = "0123456789ABCDEFGH";
814   for (int i = 0; i < s.size(); ++i) {
815     StringPiece a(s.c_str() + i);
816     for (int j = 0; j < s.size(); ++j) {
817       StringPiece b(s.c_str() + j);
818       EXPECT_EQ((i > j) ? 0 : j - i, this->find_first_byte_of(a, b));
819     }
820   }
821 }
822
823 // for some algorithms (specifically those that create a set of needles),
824 // we check for the edge-case of _all_ possible needles being sought.
825 TYPED_TEST(NeedleFinderTest, Needles256) {
826   string needles;
827   const auto minValue = std::numeric_limits<StringPiece::value_type>::min();
828   const auto maxValue = std::numeric_limits<StringPiece::value_type>::max();
829   // make the size ~big to avoid any edge-case branches for tiny haystacks
830   const int haystackSize = 50;
831   for (int i = minValue; i <= maxValue; i++) {  // <=
832     needles.push_back(i);
833   }
834   EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
835   for (int i = minValue; i <= maxValue; i++) {
836     EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
837   }
838
839   needles.append("these are redundant characters");
840   EXPECT_EQ(StringPiece::npos, this->find_first_byte_of("", needles));
841   for (int i = minValue; i <= maxValue; i++) {
842     EXPECT_EQ(0, this->find_first_byte_of(string(haystackSize, i), needles));
843   }
844 }
845
846 TYPED_TEST(NeedleFinderTest, Base) {
847   for (int i = 0; i < 32; ++i) {
848     for (int j = 0; j < 32; ++j) {
849       string s = string(i, 'X') + "abca" + string(i, 'X');
850       string delims = string(j, 'Y') + "a" + string(j, 'Y');
851       EXPECT_EQ(i, this->find_first_byte_of(s, delims));
852     }
853   }
854 }
855
856 const size_t kPageSize = 4096;
857 // Updates contents so that any read accesses past the last byte will
858 // cause a SIGSEGV.  It accomplishes this by changing access to the page that
859 // begins immediately after the end of the contents (as allocators and mmap()
860 // all operate on page boundaries, this is a reasonable assumption).
861 // This function will also initialize buf, which caller must free().
862 void createProtectedBuf(StringPiece& contents, char** buf) {
863   ASSERT_LE(contents.size(), kPageSize);
864   const size_t kSuccess = 0;
865   if (kSuccess != posix_memalign((void**)buf, kPageSize, 4 * kPageSize)) {
866     ASSERT_FALSE(true);
867   }
868   mprotect(*buf + kPageSize, kPageSize, PROT_NONE);
869   size_t newBegin = kPageSize - contents.size();
870   memcpy(*buf + newBegin, contents.data(), contents.size());
871   contents.reset(*buf + newBegin, contents.size());
872 }
873
874 void freeProtectedBuf(char* buf) {
875   mprotect(buf + kPageSize, kPageSize, PROT_READ | PROT_WRITE);
876   free(buf);
877 }
878
879 TYPED_TEST(NeedleFinderTest, NoSegFault) {
880   const string base = string(32, 'a') + string("b");
881   const string delims = string(32, 'c') + string("b");
882   for (int i = 0; i <= 32; i++) {
883     for (int j = 0; j <= 33; j++) {
884       for (int shouldFind = 0; shouldFind <= 1; ++shouldFind) {
885         StringPiece s1(base);
886         s1.advance(i);
887         ASSERT_TRUE(!s1.empty());
888         if (!shouldFind) {
889           s1.pop_back();
890         }
891         StringPiece s2(delims);
892         s2.advance(j);
893         char* buf1;
894         char* buf2;
895         createProtectedBuf(s1, &buf1);
896         createProtectedBuf(s2, &buf2);
897         // printf("s1: '%s' (%ld) \ts2: '%s' (%ld)\n",
898         //        string(s1.data(), s1.size()).c_str(), s1.size(),
899         //        string(s2.data(), s2.size()).c_str(), s2.size());
900         auto r1 = this->find_first_byte_of(s1, s2);
901         auto f1 = std::find_first_of(s1.begin(), s1.end(),
902                                      s2.begin(), s2.end());
903         auto e1 = (f1 == s1.end()) ? StringPiece::npos : f1 - s1.begin();
904         EXPECT_EQ(r1, e1);
905         auto r2 = this->find_first_byte_of(s2, s1);
906         auto f2 = std::find_first_of(s2.begin(), s2.end(),
907                                      s1.begin(), s1.end());
908         auto e2 = (f2 == s2.end()) ? StringPiece::npos : f2 - s2.begin();
909         EXPECT_EQ(r2, e2);
910         freeProtectedBuf(buf1);
911         freeProtectedBuf(buf2);
912       }
913     }
914   }
915 }
916
917 TEST(NonConstTest, StringPiece) {
918   std::string hello("hello");
919   MutableStringPiece sp(&hello.front(), hello.size());
920   sp[0] = 'x';
921   EXPECT_EQ("xello", hello);
922   {
923     StringPiece s(sp);
924     EXPECT_EQ("xello", s);
925   }
926   {
927     ByteRange r1(sp);
928     MutableByteRange r2(sp);
929   }
930 }
931
932 template<class C>
933 void testRangeFunc(C&& x, size_t n) {
934   const auto& cx = x;
935   // type, conversion checks
936   Range<int*> r1 = range(std::forward<C>(x));
937   Range<const int*> r2 = range(std::forward<C>(x));
938   Range<const int*> r3 = range(cx);
939   Range<const int*> r5 = range(std::move(cx));
940   EXPECT_EQ(r1.begin(), &x[0]);
941   EXPECT_EQ(r1.end(), &x[n]);
942   EXPECT_EQ(n, r1.size());
943   EXPECT_EQ(n, r2.size());
944   EXPECT_EQ(n, r3.size());
945   EXPECT_EQ(n, r5.size());
946 }
947
948 TEST(RangeFunc, Vector) {
949   std::vector<int> x;
950   testRangeFunc(x, 0);
951   x.push_back(2);
952   testRangeFunc(x, 1);
953   testRangeFunc(std::vector<int>{1, 2}, 2);
954 }
955
956 TEST(RangeFunc, Array) {
957   std::array<int, 3> x;
958   testRangeFunc(x, 3);
959 }
960
961 TEST(RangeFunc, CArray) {
962   int x[] {1, 2, 3, 4};
963   testRangeFunc(x, 4);
964 }