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