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