Fix fbstring hash
[folly.git] / folly / test / FBStringTest.cpp
1 /*
2  * Copyright 2012 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 //
18 // Author: andrei.alexandrescu@fb.com
19
20 #include "folly/FBString.h"
21
22 #include <cstdlib>
23
24 #include <list>
25 #include <fstream>
26 #include <boost/algorithm/string.hpp>
27 #include <boost/random.hpp>
28 #include <gtest/gtest.h>
29
30 #include <gflags/gflags.h>
31
32 #include "folly/Foreach.h"
33 #include "folly/Random.h"
34
35 using namespace std;
36 using namespace folly;
37
38 static const int seed = folly::randomNumberSeed();
39 typedef boost::mt19937 RandomT;
40 static RandomT rng(seed);
41 static const size_t maxString = 100;
42 static const bool avoidAliasing = true;
43
44 template <class Integral1, class Integral2>
45 Integral2 random(Integral1 low, Integral2 up) {
46   boost::uniform_int<> range(low, up);
47   return range(rng);
48 }
49
50 template <class String>
51 void randomString(String* toFill, unsigned int maxSize = 1000) {
52   assert(toFill);
53   toFill->resize(random(0, maxSize));
54   FOR_EACH (i, *toFill) {
55     *i = random('a', 'z');
56   }
57 }
58
59 template <class String, class Integral>
60 void Num2String(String& str, Integral n) {
61   str.resize(30, '\0');
62   sprintf(&str[0], "%lu", static_cast<unsigned long>(n));
63   str.resize(strlen(str.c_str()));
64 }
65
66 std::list<char> RandomList(unsigned int maxSize) {
67   std::list<char> lst(random(0u, maxSize));
68   std::list<char>::iterator i = lst.begin();
69   for (; i != lst.end(); ++i) {
70     *i = random('a', 'z');
71  }
72   return lst;
73 }
74
75 ////////////////////////////////////////////////////////////////////////////////
76 // Tests begin here
77 ////////////////////////////////////////////////////////////////////////////////
78
79 template <class String> void clause_21_3_1_a(String & test) {
80   test.String::~String();
81   new(&test) String();
82 }
83 template <class String> void clause_21_3_1_b(String & test) {
84   // Copy constructor
85   const size_t pos = random(0, test.size());
86   String s(test, pos, random(0, (size_t)(test.size() - pos)));
87   test = s;
88 }
89 template <class String> void clause_21_3_1_c(String & test) {
90   // Constructor from char*, size_t
91   const size_t
92     pos = random(0, test.size()),
93     n = random(0, test.size() - pos);
94   std::string before(test.data(), test.size());
95   String s(test.c_str() + pos, n);
96   std::string after(test.data(), test.size());
97   EXPECT_EQ(before, after);
98
99   // Constructor from char*, char*
100   String s1(test.begin(), test.end());
101   EXPECT_EQ(test, s1);
102   String s2(test.data(), test.data() + test.size());
103   EXPECT_EQ(test, s2);
104
105   // Constructor from iterators
106   std::list<char> lst;
107   for (auto c : test) lst.push_back(c);
108   String s3(lst.begin(), lst.end());
109   EXPECT_EQ(test, s3);
110
111   // Constructor from wchar_t iterators
112   std::list<wchar_t> lst1;
113   for (auto c : test) lst1.push_back(c);
114   String s4(lst1.begin(), lst1.end());
115   EXPECT_EQ(test, s4);
116
117   // Constructor from wchar_t pointers
118   wchar_t t[20];
119   t[0] = 'a';
120   t[1] = 'b';
121   String s5(t, t + 2);;
122   EXPECT_EQ("ab", s5);
123
124   test = s;
125 }
126 template <class String> void clause_21_3_1_d(String & test) {
127   // Assignment
128   auto size = random(0, 2000);
129   String s(size, '\0');
130   EXPECT_EQ(s.size(), size);
131   FOR_EACH_RANGE (i, 0, s.size()) {
132     s[i] = random('a', 'z');
133   }
134   test = s;
135 }
136 template <class String> void clause_21_3_1_e(String & test) {
137   // Assignment from char*
138   String s(random(0, 1000), '\0');
139   size_t i = 0;
140   for (; i != s.size(); ++i) {
141     s[i] = random('a', 'z');
142   }
143   test = s.c_str();
144 }
145 template <class String> void clause_21_3_1_f(String & test) {
146   // Aliased assign
147   const size_t pos = random(0, test.size());
148   if (avoidAliasing) {
149     test = String(test.c_str() + pos);
150   } else {
151     test = test.c_str() + pos;
152   }
153 }
154 template <class String> void clause_21_3_1_g(String & test) {
155   // Assignment from char
156   test = random('a', 'z');
157 }
158
159 template <class String> void clause_21_3_2(String & test) {
160   // Iterators. The code below should leave test unchanged
161   EXPECT_EQ(test.size(), test.end() - test.begin());
162   EXPECT_EQ(test.size(), test.rend() - test.rbegin());
163
164   auto s = test.size();
165   test.resize(test.end() - test.begin());
166   EXPECT_EQ(s, test.size());
167   test.resize(test.rend() - test.rbegin());
168   EXPECT_EQ(s, test.size());
169 }
170
171 template <class String> void clause_21_3_3(String & test) {
172   // exercise capacity, size, max_size
173   EXPECT_EQ(test.size(), test.length());
174   EXPECT_LE(test.size(), test.max_size());
175   EXPECT_LE(test.capacity(), test.max_size());
176   EXPECT_LE(test.size(), test.capacity());
177   // exercise empty
178   if (test.empty()) test = "empty";
179   else test = "not empty";
180 }
181
182 template <class String> void clause_21_3_4(String & test) {
183   // exercise element access 21.3.4
184   if (!test.empty()) {
185     auto const i = random(0, test.size() - 1);
186     EXPECT_EQ(test[i], test.at(i));
187     test = test[i];
188   }
189 }
190
191 template <class String> void clause_21_3_5_a(String & test) {
192   // 21.3.5 modifiers (+=)
193   String test1;
194   randomString(&test1);
195   assert(test1.size() == strlen(test1.c_str()));
196   auto len = test.size();
197   test += test1;
198   EXPECT_EQ(test.size(), test1.size() + len);
199   FOR_EACH_RANGE (i, 0, test1.size()) {
200     EXPECT_EQ(test[len + i], test1[i]);
201   }
202   // aliasing modifiers
203   String test2 = test;
204   auto dt = test2.data();
205   auto sz = test.c_str();
206   len = test.size();
207   EXPECT_EQ(memcmp(sz, dt, len), 0);
208   String copy(test.data(), test.size());
209   EXPECT_EQ(strlen(test.c_str()), len);
210   test += test;
211   //test.append(test);
212   EXPECT_EQ(test.size(), 2 * len);
213   EXPECT_EQ(strlen(test.c_str()), 2 * len);
214   FOR_EACH_RANGE (i, 0, len) {
215     EXPECT_EQ(test[i], copy[i]);
216     EXPECT_EQ(test[i], test[len + i]);
217   }
218   len = test.size();
219   EXPECT_EQ(strlen(test.c_str()), len);
220   // more aliasing
221   auto const pos = random(0, test.size());
222   EXPECT_EQ(strlen(test.c_str() + pos), len - pos);
223   if (avoidAliasing) {
224     String addMe(test.c_str() + pos);
225     EXPECT_EQ(addMe.size(), len - pos);
226     test += addMe;
227   } else {
228     test += test.c_str() + pos;
229   }
230   EXPECT_EQ(test.size(), 2 * len - pos);
231   // single char
232   len = test.size();
233   test += random('a', 'z');
234   EXPECT_EQ(test.size(), len + 1);
235 }
236
237 template <class String> void clause_21_3_5_b(String & test) {
238   // 21.3.5 modifiers (append, push_back)
239   String s;
240
241   // Test with a small string first
242   char c = random('a', 'z');
243   s.push_back(c);
244   EXPECT_EQ(s[s.size() - 1], c);
245   EXPECT_EQ(s.size(), 1);
246   s.resize(s.size() - 1);
247
248   randomString(&s, maxString);
249   test.append(s);
250   randomString(&s, maxString);
251   test.append(s, random(0, s.size()), random(0, maxString));
252   randomString(&s, maxString);
253   test.append(s.c_str(), random(0, s.size()));
254   randomString(&s, maxString);
255   test.append(s.c_str());
256   test.append(random(0, maxString), random('a', 'z'));
257   std::list<char> lst(RandomList(maxString));
258   test.append(lst.begin(), lst.end());
259   c = random('a', 'z');
260   test.push_back(c);
261   EXPECT_EQ(test[test.size() - 1], c);
262 }
263
264 template <class String> void clause_21_3_5_c(String & test) {
265   // assign
266   String s;
267   randomString(&s);
268   test.assign(s);
269 }
270
271 template <class String> void clause_21_3_5_d(String & test) {
272   // assign
273   String s;
274   randomString(&s, maxString);
275   test.assign(s, random(0, s.size()), random(0, maxString));
276 }
277
278 template <class String> void clause_21_3_5_e(String & test) {
279   // assign
280   String s;
281   randomString(&s, maxString);
282   test.assign(s.c_str(), random(0, s.size()));
283 }
284
285 template <class String> void clause_21_3_5_f(String & test) {
286   // assign
287   String s;
288   randomString(&s, maxString);
289   test.assign(s.c_str());
290 }
291
292 template <class String> void clause_21_3_5_g(String & test) {
293   // assign
294   String s;
295   randomString(&s, maxString);
296   test.assign(random(0, maxString), random('a', 'z'));
297 }
298
299 template <class String> void clause_21_3_5_h(String & test) {
300   // assign from bidirectional iterator
301   std::list<char> lst(RandomList(maxString));
302   test.assign(lst.begin(), lst.end());
303 }
304
305 template <class String> void clause_21_3_5_i(String & test) {
306   // assign from aliased source
307   test.assign(test);
308 }
309
310 template <class String> void clause_21_3_5_j(String & test) {
311   // assign from aliased source
312   test.assign(test, random(0, test.size()), random(0, maxString));
313 }
314
315 template <class String> void clause_21_3_5_k(String & test) {
316   // assign from aliased source
317   test.assign(test.c_str(), random(0, test.size()));
318 }
319
320 template <class String> void clause_21_3_5_l(String & test) {
321   // assign from aliased source
322   test.assign(test.c_str());
323 }
324
325 template <class String> void clause_21_3_5_m(String & test) {
326   // insert
327   String s;
328   randomString(&s, maxString);
329   test.insert(random(0, test.size()), s);
330   randomString(&s, maxString);
331   test.insert(random(0, test.size()),
332               s, random(0, s.size()),
333               random(0, maxString));
334   randomString(&s, maxString);
335   test.insert(random(0, test.size()),
336               s.c_str(), random(0, s.size()));
337   randomString(&s, maxString);
338   test.insert(random(0, test.size()), s.c_str());
339   test.insert(random(0, test.size()),
340               random(0, maxString), random('a', 'z'));
341   test.insert(test.begin() + random(0, test.size()),
342               random('a', 'z'));
343   std::list<char> lst(RandomList(maxString));
344   test.insert(test.begin() + random(0, test.size()),
345               lst.begin(), lst.end());
346 }
347
348 template <class String> void clause_21_3_5_n(String & test) {
349   // erase
350   if (!test.empty()) {
351     test.erase(random(0, test.size()), random(0, maxString));
352   }
353   if (!test.empty()) {
354     // TODO: is erase(end()) allowed?
355     test.erase(test.begin() + random(0, test.size() - 1));
356   }
357   if (!test.empty()) {
358     auto const i = test.begin() + random(0, test.size());
359     if (i != test.end()) {
360       test.erase(i, i + random(0, size_t(test.end() - i)));
361     }
362   }
363 }
364
365 template <class String> void clause_21_3_5_o(String & test) {
366   auto pos = random(0, test.size());
367   if (avoidAliasing) {
368     test.replace(pos, random(0, test.size() - pos),
369                  String(test));
370   } else {
371     test.replace(pos, random(0, test.size() - pos), test);
372   }
373   pos = random(0, test.size());
374   String s;
375   randomString(&s, maxString);
376   test.replace(pos, pos + random(0, test.size() - pos), s);
377   auto pos1 = random(0, test.size());
378   auto pos2 = random(0, test.size());
379   if (avoidAliasing) {
380     test.replace(pos1, pos1 + random(0, test.size() - pos1),
381                  String(test),
382                  pos2, pos2 + random(0, test.size() - pos2));
383   } else {
384     test.replace(pos1, pos1 + random(0, test.size() - pos1),
385                  test, pos2, pos2 + random(0, test.size() - pos2));
386   }
387   pos1 = random(0, test.size());
388   String str;
389   randomString(&str, maxString);
390   pos2 = random(0, str.size());
391   test.replace(pos1, pos1 + random(0, test.size() - pos1),
392                str, pos2, pos2 + random(0, str.size() - pos2));
393   pos = random(0, test.size());
394   if (avoidAliasing) {
395     test.replace(pos, random(0, test.size() - pos),
396                  String(test).c_str(), test.size());
397   } else {
398     test.replace(pos, random(0, test.size() - pos),
399                  test.c_str(), test.size());
400   }
401   pos = random(0, test.size());
402   randomString(&str, maxString);
403   test.replace(pos, pos + random(0, test.size() - pos),
404                str.c_str(), str.size());
405   pos = random(0, test.size());
406   randomString(&str, maxString);
407   test.replace(pos, pos + random(0, test.size() - pos),
408                str.c_str());
409   pos = random(0, test.size());
410   test.replace(pos, random(0, test.size() - pos),
411                random(0, maxString), random('a', 'z'));
412   pos = random(0, test.size());
413   if (avoidAliasing) {
414     test.replace(
415       test.begin() + pos,
416       test.begin() + pos + random(0, test.size() - pos),
417       String(test));
418   } else {
419     test.replace(
420       test.begin() + pos,
421       test.begin() + pos + random(0, test.size() - pos),
422       test);
423   }
424   pos = random(0, test.size());
425   if (avoidAliasing) {
426     test.replace(
427       test.begin() + pos,
428       test.begin() + pos + random(0, test.size() - pos),
429       String(test).c_str(),
430       test.size() - random(0, test.size()));
431   } else {
432     test.replace(
433       test.begin() + pos,
434       test.begin() + pos + random(0, test.size() - pos),
435       test.c_str(),
436       test.size() - random(0, test.size()));
437   }
438   pos = random(0, test.size());
439   auto const n = random(0, test.size() - pos);
440   typename String::iterator b = test.begin();
441   String str1;
442   randomString(&str1, maxString);
443   const String & str3 = str1;
444   const typename String::value_type* ss = str3.c_str();
445   test.replace(
446     b + pos,
447     b + pos + n,
448     ss);
449   pos = random(0, test.size());
450   test.replace(
451     test.begin() + pos,
452     test.begin() + pos + random(0, test.size() - pos),
453     random(0, maxString), random('a', 'z'));
454 }
455
456 template <class String> void clause_21_3_5_p(String & test) {
457   std::vector<typename String::value_type>
458     vec(random(0, maxString));
459   test.copy(
460     &vec[0],
461     vec.size(),
462     random(0, test.size()));
463 }
464
465 template <class String> void clause_21_3_5_q(String & test) {
466   String s;
467   randomString(&s, maxString);
468   s.swap(test);
469 }
470
471 template <class String> void clause_21_3_6_a(String & test) {
472   // 21.3.6 string operations
473   // exercise c_str() and data()
474   assert(test.c_str() == test.data());
475   // exercise get_allocator()
476   String s;
477   randomString(&s, maxString);
478   assert(test.get_allocator() == s.get_allocator());
479 }
480
481 template <class String> void clause_21_3_6_b(String & test) {
482   String str = test.substr(
483     random(0, test.size()),
484     random(0, test.size()));
485   Num2String(test, test.find(str, random(0, test.size())));
486 }
487
488 template <class String> void clause_21_3_6_c(String & test) {
489   auto from = random(0, test.size());
490   auto length = random(0, test.size() - from);
491   String str = test.substr(from, length);
492   Num2String(test, test.find(str.c_str(),
493                              random(0, test.size()),
494                              random(0, str.size())));
495 }
496
497 template <class String> void clause_21_3_6_d(String & test) {
498   String str = test.substr(
499     random(0, test.size()),
500     random(0, test.size()));
501   Num2String(test, test.find(str.c_str(),
502                              random(0, test.size())));
503 }
504
505 template <class String> void clause_21_3_6_e(String & test) {
506   Num2String(test, test.find(
507                random('a', 'z'),
508                random(0, test.size())));
509 }
510
511 template <class String> void clause_21_3_6_f(String & test) {
512   String str = test.substr(
513     random(0, test.size()),
514     random(0, test.size()));
515   Num2String(test, test.rfind(str, random(0, test.size())));
516 }
517
518 template <class String> void clause_21_3_6_g(String & test) {
519   String str = test.substr(
520     random(0, test.size()),
521     random(0, test.size()));
522   Num2String(test, test.rfind(str.c_str(),
523                               random(0, test.size()),
524                               random(0, str.size())));
525 }
526
527 template <class String> void clause_21_3_6_h(String & test) {
528   String str = test.substr(
529     random(0, test.size()),
530     random(0, test.size()));
531   Num2String(test, test.rfind(str.c_str(),
532                               random(0, test.size())));
533 }
534
535 template <class String> void clause_21_3_6_i(String & test) {
536   Num2String(test, test.rfind(
537                random('a', 'z'),
538                random(0, test.size())));
539 }
540
541 template <class String> void clause_21_3_6_j(String & test) {
542   String str;
543   randomString(&str, maxString);
544   Num2String(test, test.find_first_of(str,
545                                       random(0, test.size())));
546 }
547
548 template <class String> void clause_21_3_6_k(String & test) {
549   String str;
550   randomString(&str, maxString);
551   Num2String(test, test.find_first_of(str.c_str(),
552                                       random(0, test.size()),
553                                       random(0, str.size())));
554 }
555
556 template <class String> void clause_21_3_6_l(String & test) {
557   String str;
558   randomString(&str, maxString);
559   Num2String(test, test.find_first_of(str.c_str(),
560                                       random(0, test.size())));
561 }
562
563 template <class String> void clause_21_3_6_m(String & test) {
564   Num2String(test, test.find_first_of(
565                random('a', 'z'),
566                random(0, test.size())));
567 }
568
569 template <class String> void clause_21_3_6_n(String & test) {
570   String str;
571   randomString(&str, maxString);
572   Num2String(test, test.find_last_of(str,
573                                      random(0, test.size())));
574 }
575
576 template <class String> void clause_21_3_6_o(String & test) {
577   String str;
578   randomString(&str, maxString);
579   Num2String(test, test.find_last_of(str.c_str(),
580                                      random(0, test.size()),
581                                      random(0, str.size())));
582 }
583
584 template <class String> void clause_21_3_6_p(String & test) {
585   String str;
586   randomString(&str, maxString);
587   Num2String(test, test.find_last_of(str.c_str(),
588                                      random(0, test.size())));
589 }
590
591 template <class String> void clause_21_3_6_q(String & test) {
592   Num2String(test, test.find_last_of(
593                random('a', 'z'),
594                random(0, test.size())));
595 }
596
597 template <class String> void clause_21_3_6_r(String & test) {
598   String str;
599   randomString(&str, maxString);
600   Num2String(test, test.find_first_not_of(str,
601                                           random(0, test.size())));
602 }
603
604 template <class String> void clause_21_3_6_s(String & test) {
605   String str;
606   randomString(&str, maxString);
607   Num2String(test, test.find_first_not_of(str.c_str(),
608                                           random(0, test.size()),
609                                           random(0, str.size())));
610 }
611
612 template <class String> void clause_21_3_6_t(String & test) {
613   String str;
614   randomString(&str, maxString);
615   Num2String(test, test.find_first_not_of(str.c_str(),
616                                           random(0, test.size())));
617 }
618
619 template <class String> void clause_21_3_6_u(String & test) {
620   Num2String(test, test.find_first_not_of(
621                random('a', 'z'),
622                random(0, test.size())));
623 }
624
625 template <class String> void clause_21_3_6_v(String & test) {
626   String str;
627   randomString(&str, maxString);
628   Num2String(test, test.find_last_not_of(str,
629                                          random(0, test.size())));
630 }
631
632 template <class String> void clause_21_3_6_w(String & test) {
633   String str;
634   randomString(&str, maxString);
635   Num2String(test, test.find_last_not_of(str.c_str(),
636                                          random(0, test.size()),
637                                          random(0, str.size())));
638 }
639
640 template <class String> void clause_21_3_6_x(String & test) {
641   String str;
642   randomString(&str, maxString);
643   Num2String(test, test.find_last_not_of(str.c_str(),
644                                          random(0, test.size())));
645 }
646
647 template <class String> void clause_21_3_6_y(String & test) {
648   Num2String(test, test.find_last_not_of(
649                random('a', 'z'),
650                random(0, test.size())));
651 }
652
653 template <class String> void clause_21_3_6_z(String & test) {
654   test = test.substr(random(0, test.size()), random(0, test.size()));
655 }
656
657 template <class String> void clause_21_3_7_a(String & test) {
658   String s;
659   randomString(&s, maxString);
660   int tristate = test.compare(s);
661   if (tristate > 0) tristate = 1;
662   else if (tristate < 0) tristate = 2;
663   Num2String(test, tristate);
664 }
665
666 template <class String> void clause_21_3_7_b(String & test) {
667   String s;
668   randomString(&s, maxString);
669   int tristate = test.compare(
670     random(0, test.size()),
671     random(0, test.size()),
672     s);
673   if (tristate > 0) tristate = 1;
674   else if (tristate < 0) tristate = 2;
675   Num2String(test, tristate);
676 }
677
678 template <class String> void clause_21_3_7_c(String & test) {
679   String str;
680   randomString(&str, maxString);
681   int tristate = test.compare(
682     random(0, test.size()),
683     random(0, test.size()),
684     str,
685     random(0, str.size()),
686     random(0, str.size()));
687   if (tristate > 0) tristate = 1;
688   else if (tristate < 0) tristate = 2;
689   Num2String(test, tristate);
690 }
691
692 template <class String> void clause_21_3_7_d(String & test) {
693   String s;
694   randomString(&s, maxString);
695   int tristate = test.compare(s.c_str());
696   if (tristate > 0) tristate = 1;
697   else if (tristate < 0) tristate = 2;
698                 Num2String(test, tristate);
699 }
700
701 template <class String> void clause_21_3_7_e(String & test) {
702   String str;
703   randomString(&str, maxString);
704   int tristate = test.compare(
705     random(0, test.size()),
706     random(0, test.size()),
707     str.c_str(),
708     random(0, str.size()));
709   if (tristate > 0) tristate = 1;
710   else if (tristate < 0) tristate = 2;
711   Num2String(test, tristate);
712 }
713
714 template <class String> void clause_21_3_7_f(String & test) {
715   String s1;
716   randomString(&s1, maxString);
717   String s2;
718   randomString(&s2, maxString);
719   test = s1 + s2;
720 }
721
722 template <class String> void clause_21_3_7_g(String & test) {
723   String s;
724   randomString(&s, maxString);
725   String s1;
726   randomString(&s1, maxString);
727   test = s.c_str() + s1;
728 }
729
730 template <class String> void clause_21_3_7_h(String & test) {
731   String s;
732   randomString(&s, maxString);
733   test = typename String::value_type(random('a', 'z')) + s;
734 }
735
736 template <class String> void clause_21_3_7_i(String & test) {
737   String s;
738   randomString(&s, maxString);
739   String s1;
740   randomString(&s1, maxString);
741   test = s + s1.c_str();
742 }
743
744 template <class String> void clause_21_3_7_j(String & test) {
745   String s;
746   randomString(&s, maxString);
747   String s1;
748   randomString(&s1, maxString);
749   test = s + s1.c_str();
750 }
751
752 template <class String> void clause_21_3_7_k(String & test) {
753   String s;
754   randomString(&s, maxString);
755   test = s + typename String::value_type(random('a', 'z'));
756 }
757
758 // Numbering here is from C++11
759 template <class String> void clause_21_4_8_9_a(String & test) {
760   stringstream s("asd asdfjhuhdf    asdfasdf\tasdsdf");
761   String str;
762   while (s) {
763     s >> str;
764     test += str + test;
765   }
766 }
767
768 TEST(FBString, testAllClauses) {
769   EXPECT_TRUE(1) << "Starting with seed: " << seed;
770   std::string r;
771   folly::fbstring c;
772 #define TEST_CLAUSE(x)                                              \
773   do {                                                              \
774       if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x;     \
775       randomString(&r);                                             \
776       c = r;                                                        \
777       EXPECT_EQ(c, r);                                              \
778       auto localSeed = seed + count;                                \
779       rng = RandomT(localSeed);                                     \
780       clause_##x(r);                                                \
781       rng = RandomT(localSeed);                                     \
782       clause_##x(c);                                                \
783       EXPECT_EQ(r, c)                                               \
784         << "Lengths: " << r.size() << " vs. " << c.size()           \
785         << "\nReference: '" << r << "'"                             \
786         << "\nActual:    '" << c.data()[0] << "'";                  \
787     } while (++count % 100 != 0)
788
789   int count = 0;
790   TEST_CLAUSE(21_3_1_a);
791   TEST_CLAUSE(21_3_1_b);
792   TEST_CLAUSE(21_3_1_c);
793   TEST_CLAUSE(21_3_1_d);
794   TEST_CLAUSE(21_3_1_e);
795   TEST_CLAUSE(21_3_1_f);
796   TEST_CLAUSE(21_3_1_g);
797
798   TEST_CLAUSE(21_3_2);
799   TEST_CLAUSE(21_3_3);
800   TEST_CLAUSE(21_3_4);
801   TEST_CLAUSE(21_3_5_a);
802   TEST_CLAUSE(21_3_5_b);
803   TEST_CLAUSE(21_3_5_c);
804   TEST_CLAUSE(21_3_5_d);
805   TEST_CLAUSE(21_3_5_e);
806   TEST_CLAUSE(21_3_5_f);
807   TEST_CLAUSE(21_3_5_g);
808   TEST_CLAUSE(21_3_5_h);
809   TEST_CLAUSE(21_3_5_i);
810   TEST_CLAUSE(21_3_5_j);
811   TEST_CLAUSE(21_3_5_k);
812   TEST_CLAUSE(21_3_5_l);
813   TEST_CLAUSE(21_3_5_m);
814   TEST_CLAUSE(21_3_5_n);
815   TEST_CLAUSE(21_3_5_o);
816   TEST_CLAUSE(21_3_5_p);
817
818   TEST_CLAUSE(21_3_6_a);
819   TEST_CLAUSE(21_3_6_b);
820   TEST_CLAUSE(21_3_6_c);
821   TEST_CLAUSE(21_3_6_d);
822   TEST_CLAUSE(21_3_6_e);
823   TEST_CLAUSE(21_3_6_f);
824   TEST_CLAUSE(21_3_6_g);
825   TEST_CLAUSE(21_3_6_h);
826   TEST_CLAUSE(21_3_6_i);
827   TEST_CLAUSE(21_3_6_j);
828   TEST_CLAUSE(21_3_6_k);
829   TEST_CLAUSE(21_3_6_l);
830   TEST_CLAUSE(21_3_6_m);
831   TEST_CLAUSE(21_3_6_n);
832   TEST_CLAUSE(21_3_6_o);
833   TEST_CLAUSE(21_3_6_p);
834   TEST_CLAUSE(21_3_6_q);
835   TEST_CLAUSE(21_3_6_r);
836   TEST_CLAUSE(21_3_6_s);
837   TEST_CLAUSE(21_3_6_t);
838   TEST_CLAUSE(21_3_6_u);
839   TEST_CLAUSE(21_3_6_v);
840   TEST_CLAUSE(21_3_6_w);
841   TEST_CLAUSE(21_3_6_x);
842   TEST_CLAUSE(21_3_6_y);
843   TEST_CLAUSE(21_3_6_z);
844
845   TEST_CLAUSE(21_3_7_a);
846   TEST_CLAUSE(21_3_7_b);
847   TEST_CLAUSE(21_3_7_c);
848   TEST_CLAUSE(21_3_7_d);
849   TEST_CLAUSE(21_3_7_e);
850   TEST_CLAUSE(21_3_7_f);
851   TEST_CLAUSE(21_3_7_g);
852   TEST_CLAUSE(21_3_7_h);
853   TEST_CLAUSE(21_3_7_i);
854   TEST_CLAUSE(21_3_7_j);
855   TEST_CLAUSE(21_3_7_k);
856
857   TEST_CLAUSE(21_4_8_9_a);
858 }
859
860 TEST(FBString, testGetline) {
861   fbstring s1 = "\
862 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
863 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
864 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
865 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
866 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
867 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
868 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
869 tristique senectus et netus et malesuada fames ac turpis \n\
870 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
871 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
872 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
873 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
874 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
875 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
876 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
877 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
878 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
879   char f[] = "/tmp/fbstring_testing.XXXXXX";
880   int fd = mkstemp(f);
881   EXPECT_TRUE(fd > 0);
882   if (fd > 0) {
883     close(fd);  // Yeah
884     std::ofstream out(f);
885     if (!(out << s1)) {
886       EXPECT_TRUE(0) << "Couldn't write to temp file.";
887       return;
888     }
889   }
890   vector<fbstring> v;
891   boost::split(v, s1, boost::is_any_of("\n"));
892   {
893     ifstream input(f);
894     fbstring line;
895     FOR_EACH (i, v) {
896       EXPECT_TRUE(getline(input, line));
897       EXPECT_EQ(line, *i);
898     }
899   }
900   unlink(f);
901 }
902
903 TEST(FBString, testMoveCtor) {
904   // Move constructor. Make sure we allocate a large string, so the
905   // small string optimization doesn't kick in.
906   auto size = random(100, 2000);
907   fbstring s(size, 'a');
908   fbstring test = std::move(s);
909   EXPECT_TRUE(s.empty());
910   EXPECT_EQ(size, test.size());
911 }
912
913 TEST(FBString, testMoveAssign) {
914   // Move constructor. Make sure we allocate a large string, so the
915   // small string optimization doesn't kick in.
916   auto size = random(100, 2000);
917   fbstring s(size, 'a');
918   fbstring test;
919   test = std::move(s);
920   EXPECT_TRUE(s.empty());
921   EXPECT_EQ(size, test.size());
922 }
923
924 TEST(FBString, testMoveOperatorPlusLhs) {
925   // Make sure we allocate a large string, so the
926   // small string optimization doesn't kick in.
927   auto size1 = random(100, 2000);
928   auto size2 = random(100, 2000);
929   fbstring s1(size1, 'a');
930   fbstring s2(size2, 'b');
931   fbstring test;
932   test = std::move(s1) + s2;
933   EXPECT_TRUE(s1.empty());
934   EXPECT_EQ(size1 + size2, test.size());
935 }
936
937 TEST(FBString, testMoveOperatorPlusRhs) {
938   // Make sure we allocate a large string, so the
939   // small string optimization doesn't kick in.
940   auto size1 = random(100, 2000);
941   auto size2 = random(100, 2000);
942   fbstring s1(size1, 'a');
943   fbstring s2(size2, 'b');
944   fbstring test;
945   test = s1 + std::move(s2);
946   EXPECT_EQ(size1 + size2, test.size());
947 }
948
949 TEST(FBString, testConstructionFromLiteralZero) {
950   try {
951     std::string s(0);
952     EXPECT_TRUE(false);
953   } catch (const std::logic_error&) {
954   } catch (...) {
955     EXPECT_TRUE(false);
956   }
957
958   try {
959     fbstring s(0);
960     EXPECT_TRUE(false);
961   } catch (const std::logic_error& e) {
962   } catch (...) {
963     EXPECT_TRUE(false);
964   }
965 }
966
967 TEST(FBString, testFixedBugs) {
968   { // D479397
969     fbstring str(1337, 'f');
970     fbstring cp = str;
971     cp.clear();
972     cp.c_str();
973     EXPECT_EQ(str.front(), 'f');
974   }
975   { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
976     fbstring str(1337, 'f');
977     for (int i = 0; i < 2; ++i) {
978       fbstring cp = str;
979       cp[1] = 'b';
980       EXPECT_EQ(cp.c_str()[cp.size()], '\0');
981       cp.push_back('?');
982     }
983   }
984   { // D580267
985     {
986       fbstring str(1337, 'f');
987       fbstring cp = str;
988       cp.push_back('f');
989     }
990     {
991       fbstring str(1337, 'f');
992       fbstring cp = str;
993       cp += "bb";
994     }
995   }
996 }
997
998
999 TEST(FBString, testHash) {
1000   fbstring a;
1001   fbstring b;
1002   a.push_back(0);
1003   a.push_back(1);
1004   b.push_back(0);
1005   b.push_back(2);
1006   std::hash<fbstring> hashfunc;
1007   EXPECT_NE(hashfunc(a), hashfunc(b));
1008 }
1009
1010 int main(int argc, char** argv) {
1011   testing::InitGoogleTest(&argc, argv);
1012   google::ParseCommandLineFlags(&argc, &argv, true);
1013   return RUN_ALL_TESTS();
1014 }