proxygen
FBStringTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present 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 <atomic>
23 #include <cstdlib>
24 #include <iomanip>
25 #include <list>
26 #include <sstream>
27 
28 #include <boost/algorithm/string.hpp>
29 #include <boost/random.hpp>
30 
31 #include <folly/Conv.h>
32 #include <folly/Portability.h>
33 #include <folly/Random.h>
34 #include <folly/Utility.h>
37 #include <folly/test/TestUtils.h>
38 
39 using namespace std;
40 using namespace folly;
41 
42 namespace {
43 
44 static const int seed = folly::randomNumberSeed();
45 typedef boost::mt19937 RandomT;
46 static RandomT rng(seed);
47 static const size_t maxString = 100;
48 static const bool avoidAliasing = true;
49 
50 template <class Integral1, class Integral2>
51 Integral2 random(Integral1 low, Integral2 up) {
52  boost::uniform_int<> range(low, up);
53  return range(rng);
54 }
55 
56 template <class String>
57 void randomString(String* toFill, unsigned int maxSize = 1000) {
58  assert(toFill);
59  toFill->resize(random(0, maxSize));
60  FOR_EACH (i, *toFill) { *i = random('a', 'z'); }
61 }
62 
63 template <class String, class Integral>
64 void Num2String(String& str, Integral n) {
65  std::string tmp = folly::to<std::string>(n);
66  str = String(tmp.begin(), tmp.end());
67 }
68 
69 std::list<char> RandomList(unsigned int maxSize) {
70  std::list<char> lst(random(0u, maxSize));
71  std::list<char>::iterator i = lst.begin();
72  for (; i != lst.end(); ++i) {
73  *i = random('a', 'z');
74  }
75  return lst;
76 }
77 } // namespace
78 
80 // Tests begin here
82 
83 template <class String>
84 void clause11_21_4_2_a(String& test) {
85  test.String::~String();
86  new (&test) String();
87 }
88 template <class String>
89 void clause11_21_4_2_b(String& test) {
90  String test2(test);
91  assert(test2 == test);
92 }
93 template <class String>
94 void clause11_21_4_2_c(String& test) {
95  // Test move constructor. There is a more specialized test, see
96  // TEST(FBString, testMoveCtor)
97  String donor(test);
98  String test2(std::move(donor));
99  EXPECT_EQ(test2, test);
100  // Technically not required, but all implementations that actually
101  // support move will move large strings. Make a guess for 128 as the
102  // maximum small string optimization that's reasonable.
103  EXPECT_LE(donor.size(), 128);
104 }
105 template <class String>
106 void clause11_21_4_2_d(String& test) {
107  // Copy constructor with position and length
108  const size_t pos = random(0, test.size());
109  String s(
110  test,
111  pos,
112  random(0, 9) ? random(0, (size_t)(test.size() - pos))
113  : String::npos); // test for npos, too, in 10% of the cases
114  test = s;
115 }
116 template <class String>
117 void clause11_21_4_2_e(String& test) {
118  // Constructor from char*, size_t
119  const size_t pos = random(0, test.size()), n = random(0, test.size() - pos);
120  String before(test.data(), test.size());
121  String s(test.c_str() + pos, n);
122  String after(test.data(), test.size());
123  EXPECT_EQ(before, after);
124  test.swap(s);
125 }
126 template <class String>
127 void clause11_21_4_2_f(String& test) {
128  // Constructor from char*
129  const size_t pos = random(0, test.size());
130  String before(test.data(), test.size());
131  String s(test.c_str() + pos);
132  String after(test.data(), test.size());
133  EXPECT_EQ(before, after);
134  test.swap(s);
135 }
136 template <class String>
137 void clause11_21_4_2_g(String& test) {
138  // Constructor from size_t, char
139  const size_t n = random(0, test.size());
140  const auto c = test.front();
141  test = String(n, c);
142 }
143 template <class String>
144 void clause11_21_4_2_h(String& test) {
145  // Constructors from various iterator pairs
146  // Constructor from char*, char*
147  String s1(test.begin(), test.end());
148  EXPECT_EQ(test, s1);
149  String s2(test.data(), test.data() + test.size());
150  EXPECT_EQ(test, s2);
151  // Constructor from other iterators
152  std::list<char> lst;
153  for (auto c : test) {
154  lst.push_back(c);
155  }
156  String s3(lst.begin(), lst.end());
157  EXPECT_EQ(test, s3);
158  // Constructor from wchar_t iterators
159  std::list<wchar_t> lst1;
160  for (auto c : test) {
161  lst1.push_back(c);
162  }
163  String s4(lst1.begin(), lst1.end());
164  EXPECT_EQ(test, s4);
165  // Constructor from wchar_t pointers
166  wchar_t t[20];
167  t[0] = 'a';
168  t[1] = 'b';
169  fbstring s5(t, t + 2);
170  EXPECT_EQ("ab", s5);
171 }
172 template <class String>
173 void clause11_21_4_2_i(String& test) {
174  // From initializer_list<char>
175  std::initializer_list<typename String::value_type> il = {
176  'h', 'e', 'l', 'l', 'o'};
177  String s(il);
178  test.swap(s);
179 }
180 template <class String>
181 void clause11_21_4_2_j(String& test) {
182  // Assignment from const String&
183  auto size = random(0, 2000);
184  String s(size, '\0');
185  EXPECT_EQ(s.size(), size);
186  FOR_EACH_RANGE (i, 0, s.size()) { s[i] = random('a', 'z'); }
187  test = s;
188 }
189 template <class String>
190 void clause11_21_4_2_k(String& test) {
191  // Assignment from String&&
192  auto size = random(0, 2000);
193  String s(size, '\0');
194  EXPECT_EQ(s.size(), size);
195  FOR_EACH_RANGE (i, 0, s.size()) { s[i] = random('a', 'z'); }
196  test = std::move(s);
197  if (typeid(String) == typeid(fbstring)) {
198  EXPECT_LE(s.size(), 128);
199  }
200 }
201 template <class String>
202 void clause11_21_4_2_l(String& test) {
203  // Assignment from char*
204  String s(random(0, 1000), '\0');
205  size_t i = 0;
206  for (; i != s.size(); ++i) {
207  s[i] = random('a', 'z');
208  }
209  test = s.c_str();
210 }
211 template <class String>
213  // Aliased assign
214  const size_t pos = random(0, test.size());
215  if (avoidAliasing) {
216  test = String(test.c_str() + pos);
217  } else {
218  test = test.c_str() + pos;
219  }
220 }
221 template <class String>
222 void clause11_21_4_2_m(String& test) {
223  // Assignment from char
224  using value_type = typename String::value_type;
225  test = random(static_cast<value_type>('a'), static_cast<value_type>('z'));
226 }
227 template <class String>
228 void clause11_21_4_2_n(String& test) {
229  // Assignment from initializer_list<char>
230  initializer_list<typename String::value_type> il = {'h', 'e', 'l', 'l', 'o'};
231  test = il;
232 }
233 
234 template <class String>
235 void clause11_21_4_3(String& test) {
236  // Iterators. The code below should leave test unchanged
237  EXPECT_EQ(test.size(), test.end() - test.begin());
238  EXPECT_EQ(test.size(), test.rend() - test.rbegin());
239  EXPECT_EQ(test.size(), test.cend() - test.cbegin());
240  EXPECT_EQ(test.size(), test.crend() - test.crbegin());
241 
242  auto s = test.size();
243  test.resize(test.end() - test.begin());
244  EXPECT_EQ(s, test.size());
245  test.resize(test.rend() - test.rbegin());
246  EXPECT_EQ(s, test.size());
247 }
248 
249 template <class String>
250 void clause11_21_4_4(String& test) {
251  // exercise capacity, size, max_size
252  EXPECT_EQ(test.size(), test.length());
253  EXPECT_LE(test.size(), test.max_size());
254  EXPECT_LE(test.capacity(), test.max_size());
255  EXPECT_LE(test.size(), test.capacity());
256 
257  // exercise shrink_to_fit. Nonbinding request so we can't really do
258  // much beyond calling it.
259  auto copy = test;
260  copy.reserve(copy.capacity() * 3);
261  copy.shrink_to_fit();
262  EXPECT_EQ(copy, test);
263 
264  // exercise empty
265  string empty("empty");
266  string notempty("not empty");
267  if (test.empty()) {
268  test = String(empty.begin(), empty.end());
269  } else {
270  test = String(notempty.begin(), notempty.end());
271  }
272 }
273 
274 template <class String>
275 void clause11_21_4_5(String& test) {
276  // exercise element access
277  if (!test.empty()) {
278  EXPECT_EQ(test[0], test.front());
279  EXPECT_EQ(test[test.size() - 1], test.back());
280  auto const i = random(0, test.size() - 1);
281  EXPECT_EQ(test[i], test.at(i));
282  test = test[i];
283  }
284 
285  EXPECT_THROW(test.at(test.size()), std::out_of_range);
286  EXPECT_THROW(as_const(test).at(test.size()), std::out_of_range);
287 }
288 
289 template <class String>
290 void clause11_21_4_6_1(String& test) {
291  // 21.3.5 modifiers (+=)
292  String test1;
293  randomString(&test1);
294  assert(
295  test1.size() ==
296  char_traits<typename String::value_type>::length(test1.c_str()));
297  auto len = test.size();
298  test += test1;
299  EXPECT_EQ(test.size(), test1.size() + len);
300  FOR_EACH_RANGE (i, 0, test1.size()) { EXPECT_EQ(test[len + i], test1[i]); }
301  // aliasing modifiers
302  String test2 = test;
303  auto dt = test2.data();
304  auto sz = test.c_str();
305  len = test.size();
306  EXPECT_EQ(memcmp(sz, dt, len), 0);
307  String copy(test.data(), test.size());
308  EXPECT_EQ(
309  char_traits<typename String::value_type>::length(test.c_str()), len);
310  test += test;
311  // test.append(test);
312  EXPECT_EQ(test.size(), 2 * len);
313  EXPECT_EQ(
314  char_traits<typename String::value_type>::length(test.c_str()), 2 * len);
315  FOR_EACH_RANGE (i, 0, len) {
316  EXPECT_EQ(test[i], copy[i]);
317  EXPECT_EQ(test[i], test[len + i]);
318  }
319  len = test.size();
320  EXPECT_EQ(
321  char_traits<typename String::value_type>::length(test.c_str()), len);
322  // more aliasing
323  auto const pos = random(0, test.size());
324  EXPECT_EQ(
325  char_traits<typename String::value_type>::length(test.c_str() + pos),
326  len - pos);
327  if (avoidAliasing) {
328  String addMe(test.c_str() + pos);
329  EXPECT_EQ(addMe.size(), len - pos);
330  test += addMe;
331  } else {
332  test += test.c_str() + pos;
333  }
334  EXPECT_EQ(test.size(), 2 * len - pos);
335  // single char
336  len = test.size();
337  test += random('a', 'z');
338  EXPECT_EQ(test.size(), len + 1);
339  // initializer_list
340  initializer_list<typename String::value_type> il{'a', 'b', 'c'};
341  test += il;
342 }
343 
344 template <class String>
345 void clause11_21_4_6_2(String& test) {
346  // 21.3.5 modifiers (append, push_back)
347  String s;
348 
349  // Test with a small string first
350  char c = random('a', 'z');
351  s.push_back(c);
352  EXPECT_EQ(s[s.size() - 1], c);
353  EXPECT_EQ(s.size(), 1);
354  s.resize(s.size() - 1);
355 
356  randomString(&s, maxString);
357  test.append(s);
358  randomString(&s, maxString);
359  test.append(s, random(0, s.size()), random(0, maxString));
360  randomString(&s, maxString);
361  test.append(s.c_str(), random(0, s.size()));
362  randomString(&s, maxString);
363  test.append(s.c_str());
364  test.append(random(0, maxString), random('a', 'z'));
365  std::list<char> lst(RandomList(maxString));
366  test.append(lst.begin(), lst.end());
367  c = random('a', 'z');
368  test.push_back(c);
369  EXPECT_EQ(test[test.size() - 1], c);
370  // initializer_list
371  initializer_list<typename String::value_type> il{'a', 'b', 'c'};
372  test.append(il);
373 }
374 
375 template <class String>
376 void clause11_21_4_6_3_a(String& test) {
377  // assign
378  String s;
379  randomString(&s);
380  test.assign(s);
381  EXPECT_EQ(test, s);
382  // move assign
383  test.assign(std::move(s));
384  if (typeid(String) == typeid(fbstring)) {
385  EXPECT_LE(s.size(), 128);
386  }
387 }
388 
389 template <class String>
390 void clause11_21_4_6_3_b(String& test) {
391  // assign
392  String s;
393  randomString(&s, maxString);
394  test.assign(s, random(0, s.size()), random(0, maxString));
395 }
396 
397 template <class String>
398 void clause11_21_4_6_3_c(String& test) {
399  // assign
400  String s;
401  randomString(&s, maxString);
402  test.assign(s.c_str(), random(0, s.size()));
403 }
404 
405 template <class String>
406 void clause11_21_4_6_3_d(String& test) {
407  // assign
408  String s;
409  randomString(&s, maxString);
410  test.assign(s.c_str());
411 }
412 
413 template <class String>
414 void clause11_21_4_6_3_e(String& test) {
415  // assign
416  String s;
417  randomString(&s, maxString);
418  test.assign(random(0, maxString), random('a', 'z'));
419 }
420 
421 template <class String>
422 void clause11_21_4_6_3_f(String& test) {
423  // assign from bidirectional iterator
424  std::list<char> lst(RandomList(maxString));
425  test.assign(lst.begin(), lst.end());
426 }
427 
428 template <class String>
429 void clause11_21_4_6_3_g(String& test) {
430  // assign from aliased source
431  test.assign(test);
432 }
433 
434 template <class String>
435 void clause11_21_4_6_3_h(String& test) {
436  // assign from aliased source
437  test.assign(test, random(0, test.size()), random(0, maxString));
438 }
439 
440 template <class String>
441 void clause11_21_4_6_3_i(String& test) {
442  // assign from aliased source
443  test.assign(test.c_str(), random(0, test.size()));
444 }
445 
446 template <class String>
447 void clause11_21_4_6_3_j(String& test) {
448  // assign from aliased source
449  test.assign(test.c_str());
450 }
451 
452 template <class String>
453 void clause11_21_4_6_3_k(String& test) {
454  // assign from initializer_list
455  initializer_list<typename String::value_type> il{'a', 'b', 'c'};
456  test.assign(il);
457 }
458 
459 template <class String>
460 void clause11_21_4_6_4(String& test) {
461  // insert
462  String s;
463  randomString(&s, maxString);
464  test.insert(random(0, test.size()), s);
465  randomString(&s, maxString);
466  test.insert(
467  random(0, test.size()), s, random(0, s.size()), random(0, maxString));
468  randomString(&s, maxString);
469  test.insert(random(0, test.size()), s.c_str(), random(0, s.size()));
470  randomString(&s, maxString);
471  test.insert(random(0, test.size()), s.c_str());
472  test.insert(random(0, test.size()), random(0, maxString), random('a', 'z'));
473  typename String::size_type pos = random(0, test.size());
474  typename String::iterator res =
475  test.insert(test.begin() + pos, random('a', 'z'));
476  EXPECT_EQ(res - test.begin(), pos);
477  std::list<char> lst(RandomList(maxString));
478  pos = random(0, test.size());
479  // Uncomment below to see a bug in gcc
480  /*res = */ test.insert(test.begin() + pos, lst.begin(), lst.end());
481  // insert from initializer_list
482  initializer_list<typename String::value_type> il{'a', 'b', 'c'};
483  pos = random(0, test.size());
484  // Uncomment below to see a bug in gcc
485  /*res = */ test.insert(test.begin() + pos, il);
486 
487  // Test with actual input iterators
488  stringstream ss;
489  ss << "hello cruel world";
490  auto i = istream_iterator<char>(ss);
491  test.insert(test.begin(), i, istream_iterator<char>());
492 }
493 
494 template <class String>
495 void clause11_21_4_6_5(String& test) {
496  // erase and pop_back
497  if (!test.empty()) {
498  test.erase(random(0, test.size()), random(0, maxString));
499  }
500  if (!test.empty()) {
501  // TODO: is erase(end()) allowed?
502  test.erase(test.begin() + random(0, test.size() - 1));
503  }
504  if (!test.empty()) {
505  auto const i = test.begin() + random(0, test.size());
506  if (i != test.end()) {
507  test.erase(i, i + random(0, size_t(test.end() - i)));
508  }
509  }
510  if (!test.empty()) {
511  // Can't test pop_back with std::string, doesn't support it yet.
512  // test.pop_back();
513  }
514 }
515 
516 template <class String>
517 void clause11_21_4_6_6(String& test) {
518  auto pos = random(0, test.size());
519  if (avoidAliasing) {
520  test.replace(pos, random(0, test.size() - pos), String(test));
521  } else {
522  test.replace(pos, random(0, test.size() - pos), test);
523  }
524  pos = random(0, test.size());
525  String s;
526  randomString(&s, maxString);
527  test.replace(pos, pos + random(0, test.size() - pos), s);
528  auto pos1 = random(0, test.size());
529  auto pos2 = random(0, test.size());
530  if (avoidAliasing) {
531  test.replace(
532  pos1,
533  pos1 + random(0, test.size() - pos1),
534  String(test),
535  pos2,
536  pos2 + random(0, test.size() - pos2));
537  } else {
538  test.replace(
539  pos1,
540  pos1 + random(0, test.size() - pos1),
541  test,
542  pos2,
543  pos2 + random(0, test.size() - pos2));
544  }
545  pos1 = random(0, test.size());
546  String str;
547  randomString(&str, maxString);
548  pos2 = random(0, str.size());
549  test.replace(
550  pos1,
551  pos1 + random(0, test.size() - pos1),
552  str,
553  pos2,
554  pos2 + random(0, str.size() - pos2));
555  pos = random(0, test.size());
556  if (avoidAliasing) {
557  test.replace(
558  pos, random(0, test.size() - pos), String(test).c_str(), test.size());
559  } else {
560  test.replace(pos, random(0, test.size() - pos), test.c_str(), test.size());
561  }
562  pos = random(0, test.size());
563  randomString(&str, maxString);
564  test.replace(
565  pos, pos + random(0, test.size() - pos), str.c_str(), str.size());
566  pos = random(0, test.size());
567  randomString(&str, maxString);
568  test.replace(pos, pos + random(0, test.size() - pos), str.c_str());
569  pos = random(0, test.size());
570  test.replace(
571  pos,
572  random(0, test.size() - pos),
573  random(0, maxString),
574  random('a', 'z'));
575  pos = random(0, test.size());
576  if (avoidAliasing) {
577  auto newString = String(test);
578  test.replace(
579  test.begin() + pos,
580  test.begin() + pos + random(0, test.size() - pos),
581  newString);
582  } else {
583  test.replace(
584  test.begin() + pos,
585  test.begin() + pos + random(0, test.size() - pos),
586  test);
587  }
588  pos = random(0, test.size());
589  if (avoidAliasing) {
590  auto newString = String(test);
591  test.replace(
592  test.begin() + pos,
593  test.begin() + pos + random(0, test.size() - pos),
594  newString.c_str(),
595  test.size() - random(0, test.size()));
596  } else {
597  test.replace(
598  test.begin() + pos,
599  test.begin() + pos + random(0, test.size() - pos),
600  test.c_str(),
601  test.size() - random(0, test.size()));
602  }
603  pos = random(0, test.size());
604  auto const n = random(0, test.size() - pos);
605  typename String::iterator b = test.begin();
606  String str1;
607  randomString(&str1, maxString);
608  const String& str3 = str1;
609  const typename String::value_type* ss = str3.c_str();
610  test.replace(b + pos, b + pos + n, ss);
611  pos = random(0, test.size());
612  test.replace(
613  test.begin() + pos,
614  test.begin() + pos + random(0, test.size() - pos),
615  random(0, maxString),
616  random('a', 'z'));
617 }
618 
619 template <class String>
620 void clause11_21_4_6_7(String& test) {
621  std::vector<typename String::value_type> vec(random(0, maxString));
622  if (vec.empty()) {
623  return;
624  }
625  test.copy(vec.data(), vec.size(), random(0, test.size()));
626 }
627 
628 template <class String>
629 void clause11_21_4_6_8(String& test) {
630  String s;
631  randomString(&s, maxString);
632  s.swap(test);
633 }
634 
635 template <class String>
636 void clause11_21_4_7_1(String& test) {
637  // 21.3.6 string operations
638  // exercise c_str() and data()
639  assert(test.c_str() == test.data());
640  // exercise get_allocator()
641  String s;
642  randomString(&s, maxString);
643  DCHECK(test.get_allocator() == s.get_allocator());
644 }
645 
646 template <class String>
647 void clause11_21_4_7_2_a(String& test) {
648  String str = test.substr(random(0, test.size()), random(0, test.size()));
649  Num2String(test, test.find(str, random(0, test.size())));
650 }
651 
652 template <class String>
653 void clause11_21_4_7_2_a1(String& test) {
654  String str =
655  String(test).substr(random(0, test.size()), random(0, test.size()));
656  Num2String(test, test.find(str, random(0, test.size())));
657 }
658 
659 template <class String>
660 void clause11_21_4_7_2_a2(String& test) {
661  auto const& cTest = test;
662  String str = cTest.substr(random(0, test.size()), random(0, test.size()));
663  Num2String(test, test.find(str, random(0, test.size())));
664 }
665 
666 template <class String>
667 void clause11_21_4_7_2_b(String& test) {
668  auto from = random(0, test.size());
669  auto length = random(0, test.size() - from);
670  String str = test.substr(from, length);
671  Num2String(
672  test,
673  test.find(str.c_str(), random(0, test.size()), random(0, str.size())));
674 }
675 
676 template <class String>
677 void clause11_21_4_7_2_b1(String& test) {
678  auto from = random(0, test.size());
679  auto length = random(0, test.size() - from);
680  String str = String(test).substr(from, length);
681  Num2String(
682  test,
683  test.find(str.c_str(), random(0, test.size()), random(0, str.size())));
684 }
685 
686 template <class String>
687 void clause11_21_4_7_2_b2(String& test) {
688  auto from = random(0, test.size());
689  auto length = random(0, test.size() - from);
690  const auto& cTest = test;
691  String str = cTest.substr(from, length);
692  Num2String(
693  test,
694  test.find(str.c_str(), random(0, test.size()), random(0, str.size())));
695 }
696 
697 template <class String>
698 void clause11_21_4_7_2_c(String& test) {
699  String str = test.substr(random(0, test.size()), random(0, test.size()));
700  Num2String(test, test.find(str.c_str(), random(0, test.size())));
701 }
702 
703 template <class String>
704 void clause11_21_4_7_2_c1(String& test) {
705  String str =
706  String(test).substr(random(0, test.size()), random(0, test.size()));
707  Num2String(test, test.find(str.c_str(), random(0, test.size())));
708 }
709 
710 template <class String>
711 void clause11_21_4_7_2_c2(String& test) {
712  const auto& cTest = test;
713  String str = cTest.substr(random(0, test.size()), random(0, test.size()));
714  Num2String(test, test.find(str.c_str(), random(0, test.size())));
715 }
716 
717 template <class String>
718 void clause11_21_4_7_2_d(String& test) {
719  Num2String(test, test.find(random('a', 'z'), random(0, test.size())));
720 }
721 
722 template <class String>
723 void clause11_21_4_7_3_a(String& test) {
724  String str = test.substr(random(0, test.size()), random(0, test.size()));
725  Num2String(test, test.rfind(str, random(0, test.size())));
726 }
727 
728 template <class String>
729 void clause11_21_4_7_3_b(String& test) {
730  String str = test.substr(random(0, test.size()), random(0, test.size()));
731  Num2String(
732  test,
733  test.rfind(str.c_str(), random(0, test.size()), random(0, str.size())));
734 }
735 
736 template <class String>
737 void clause11_21_4_7_3_c(String& test) {
738  String str = test.substr(random(0, test.size()), random(0, test.size()));
739  Num2String(test, test.rfind(str.c_str(), random(0, test.size())));
740 }
741 
742 template <class String>
743 void clause11_21_4_7_3_d(String& test) {
744  Num2String(test, test.rfind(random('a', 'z'), random(0, test.size())));
745 }
746 
747 template <class String>
748 void clause11_21_4_7_4_a(String& test) {
749  String str;
750  randomString(&str, maxString);
751  Num2String(test, test.find_first_of(str, random(0, test.size())));
752 }
753 
754 template <class String>
755 void clause11_21_4_7_4_b(String& test) {
756  String str;
757  randomString(&str, maxString);
758  Num2String(
759  test,
760  test.find_first_of(
761  str.c_str(), random(0, test.size()), random(0, str.size())));
762 }
763 
764 template <class String>
765 void clause11_21_4_7_4_c(String& test) {
766  String str;
767  randomString(&str, maxString);
768  Num2String(test, test.find_first_of(str.c_str(), random(0, test.size())));
769 }
770 
771 template <class String>
772 void clause11_21_4_7_4_d(String& test) {
773  Num2String(
774  test, test.find_first_of(random('a', 'z'), random(0, test.size())));
775 }
776 
777 template <class String>
778 void clause11_21_4_7_5_a(String& test) {
779  String str;
780  randomString(&str, maxString);
781  Num2String(test, test.find_last_of(str, random(0, test.size())));
782 }
783 
784 template <class String>
785 void clause11_21_4_7_5_b(String& test) {
786  String str;
787  randomString(&str, maxString);
788  Num2String(
789  test,
790  test.find_last_of(
791  str.c_str(), random(0, test.size()), random(0, str.size())));
792 }
793 
794 template <class String>
795 void clause11_21_4_7_5_c(String& test) {
796  String str;
797  randomString(&str, maxString);
798  Num2String(test, test.find_last_of(str.c_str(), random(0, test.size())));
799 }
800 
801 template <class String>
802 void clause11_21_4_7_5_d(String& test) {
803  Num2String(test, test.find_last_of(random('a', 'z'), random(0, test.size())));
804 }
805 
806 template <class String>
807 void clause11_21_4_7_6_a(String& test) {
808  String str;
809  randomString(&str, maxString);
810  Num2String(test, test.find_first_not_of(str, random(0, test.size())));
811 }
812 
813 template <class String>
814 void clause11_21_4_7_6_b(String& test) {
815  String str;
816  randomString(&str, maxString);
817  Num2String(
818  test,
819  test.find_first_not_of(
820  str.c_str(), random(0, test.size()), random(0, str.size())));
821 }
822 
823 template <class String>
824 void clause11_21_4_7_6_c(String& test) {
825  String str;
826  randomString(&str, maxString);
827  Num2String(test, test.find_first_not_of(str.c_str(), random(0, test.size())));
828 }
829 
830 template <class String>
831 void clause11_21_4_7_6_d(String& test) {
832  Num2String(
833  test, test.find_first_not_of(random('a', 'z'), random(0, test.size())));
834 }
835 
836 template <class String>
837 void clause11_21_4_7_7_a(String& test) {
838  String str;
839  randomString(&str, maxString);
840  Num2String(test, test.find_last_not_of(str, random(0, test.size())));
841 }
842 
843 template <class String>
844 void clause11_21_4_7_7_b(String& test) {
845  String str;
846  randomString(&str, maxString);
847  Num2String(
848  test,
849  test.find_last_not_of(
850  str.c_str(), random(0, test.size()), random(0, str.size())));
851 }
852 
853 template <class String>
854 void clause11_21_4_7_7_c(String& test) {
855  String str;
856  randomString(&str, maxString);
857  Num2String(test, test.find_last_not_of(str.c_str(), random(0, test.size())));
858 }
859 
860 template <class String>
861 void clause11_21_4_7_7_d(String& test) {
862  Num2String(
863  test, test.find_last_not_of(random('a', 'z'), random(0, test.size())));
864 }
865 
866 template <class String>
867 void clause11_21_4_7_8(String& test) {
868  test = test.substr(random(0, test.size()), random(0, test.size()));
869 }
870 
871 template <class String>
872 void clause11_21_4_7_9_a(String& test) {
873  String s;
874  randomString(&s, maxString);
875  int tristate = test.compare(s);
876  if (tristate > 0) {
877  tristate = 1;
878  } else if (tristate < 0) {
879  tristate = 2;
880  }
881  Num2String(test, tristate);
882 }
883 
884 template <class String>
885 void clause11_21_4_7_9_b(String& test) {
886  String s;
887  randomString(&s, maxString);
888  int tristate =
889  test.compare(random(0, test.size()), random(0, test.size()), s);
890  if (tristate > 0) {
891  tristate = 1;
892  } else if (tristate < 0) {
893  tristate = 2;
894  }
895  Num2String(test, tristate);
896 }
897 
898 template <class String>
899 void clause11_21_4_7_9_c(String& test) {
900  String str;
901  randomString(&str, maxString);
902  int tristate = test.compare(
903  random(0, test.size()),
904  random(0, test.size()),
905  str,
906  random(0, str.size()),
907  random(0, str.size()));
908  if (tristate > 0) {
909  tristate = 1;
910  } else if (tristate < 0) {
911  tristate = 2;
912  }
913  Num2String(test, tristate);
914 }
915 
916 template <class String>
917 void clause11_21_4_7_9_d(String& test) {
918  String s;
919  randomString(&s, maxString);
920  int tristate = test.compare(s.c_str());
921  if (tristate > 0) {
922  tristate = 1;
923  } else if (tristate < 0) {
924  tristate = 2;
925  }
926  Num2String(test, tristate);
927 }
928 
929 template <class String>
930 void clause11_21_4_7_9_e(String& test) {
931  String str;
932  randomString(&str, maxString);
933  int tristate = test.compare(
934  random(0, test.size()),
935  random(0, test.size()),
936  str.c_str(),
937  random(0, str.size()));
938  if (tristate > 0) {
939  tristate = 1;
940  } else if (tristate < 0) {
941  tristate = 2;
942  }
943  Num2String(test, tristate);
944 }
945 
946 template <class String>
947 void clause11_21_4_8_1_a(String& test) {
948  String s1;
949  randomString(&s1, maxString);
950  String s2;
951  randomString(&s2, maxString);
952  test = s1 + s2;
953 }
954 
955 template <class String>
956 void clause11_21_4_8_1_b(String& test) {
957  String s1;
958  randomString(&s1, maxString);
959  String s2;
960  randomString(&s2, maxString);
961  test = move(s1) + s2;
962 }
963 
964 template <class String>
965 void clause11_21_4_8_1_c(String& test) {
966  String s1;
967  randomString(&s1, maxString);
968  String s2;
969  randomString(&s2, maxString);
970  test = s1 + move(s2);
971 }
972 
973 template <class String>
974 void clause11_21_4_8_1_d(String& test) {
975  String s1;
976  randomString(&s1, maxString);
977  String s2;
978  randomString(&s2, maxString);
979  test = move(s1) + move(s2);
980 }
981 
982 template <class String>
983 void clause11_21_4_8_1_e(String& test) {
984  String s;
985  randomString(&s, maxString);
986  String s1;
987  randomString(&s1, maxString);
988  test = s.c_str() + s1;
989 }
990 
991 template <class String>
992 void clause11_21_4_8_1_f(String& test) {
993  String s;
994  randomString(&s, maxString);
995  String s1;
996  randomString(&s1, maxString);
997  test = s.c_str() + move(s1);
998 }
999 
1000 template <class String>
1001 void clause11_21_4_8_1_g(String& test) {
1002  String s;
1003  randomString(&s, maxString);
1004  test = typename String::value_type(random('a', 'z')) + s;
1005 }
1006 
1007 template <class String>
1008 void clause11_21_4_8_1_h(String& test) {
1009  String s;
1010  randomString(&s, maxString);
1011  test = typename String::value_type(random('a', 'z')) + move(s);
1012 }
1013 
1014 template <class String>
1015 void clause11_21_4_8_1_i(String& test) {
1016  String s;
1017  randomString(&s, maxString);
1018  String s1;
1019  randomString(&s1, maxString);
1020  test = s + s1.c_str();
1021 }
1022 
1023 template <class String>
1024 void clause11_21_4_8_1_j(String& test) {
1025  String s;
1026  randomString(&s, maxString);
1027  String s1;
1028  randomString(&s1, maxString);
1029  test = move(s) + s1.c_str();
1030 }
1031 
1032 template <class String>
1033 void clause11_21_4_8_1_k(String& test) {
1034  String s;
1035  randomString(&s, maxString);
1036  test = s + typename String::value_type(random('a', 'z'));
1037 }
1038 
1039 template <class String>
1040 void clause11_21_4_8_1_l(String& test) {
1041  String s;
1042  randomString(&s, maxString);
1043  String s1;
1044  randomString(&s1, maxString);
1045  test = move(s) + s1.c_str();
1046 }
1047 
1048 // Numbering here is from C++11
1049 template <class String>
1050 void clause11_21_4_8_9_a(String& test) {
1051  basic_stringstream<typename String::value_type> stst(test.c_str());
1052  String str;
1053  while (stst) {
1054  stst >> str;
1055  test += str + test;
1056  }
1057 }
1058 
1059 TEST(FBString, testAllClauses) {
1060  EXPECT_TRUE(1) << "Starting with seed: " << seed;
1061  std::string r;
1063 #if FOLLY_HAVE_WCHAR_SUPPORT
1064  std::wstring wr;
1066 #endif
1067  int count = 0;
1068 
1069  auto l = [&](const char* const clause,
1070  void (*f_string)(std::string&),
1071  void (*f_fbstring)(folly::fbstring&),
1072  void (*f_wfbstring)(folly::basic_fbstring<wchar_t>&)) {
1073  do {
1074  if (true) {
1075  } else {
1076  EXPECT_TRUE(1) << "Testing clause " << clause;
1077  }
1078  randomString(&r);
1079  c = r;
1080  EXPECT_EQ(c, r);
1081 #if FOLLY_HAVE_WCHAR_SUPPORT
1082  wr = std::wstring(r.begin(), r.end());
1083  wc = folly::basic_fbstring<wchar_t>(wr.c_str());
1084 #endif
1085  auto localSeed = seed + count;
1086  rng = RandomT(localSeed);
1087  f_string(r);
1088  rng = RandomT(localSeed);
1089  f_fbstring(c);
1090  EXPECT_EQ(r, c) << "Lengths: " << r.size() << " vs. " << c.size()
1091  << "\nReference: '" << r << "'"
1092  << "\nActual: '" << c.data()[0] << "'";
1093 #if FOLLY_HAVE_WCHAR_SUPPORT
1094  rng = RandomT(localSeed);
1095  f_wfbstring(wc);
1096  int wret = wcslen(wc.c_str());
1097  auto mbv = std::vector<char>(wret + 1);
1098  auto mb = mbv.data();
1099  int ret = wcstombs(mb, wc.c_str(), wret + 1);
1100  if (ret == wret) {
1101  mb[wret] = '\0';
1102  }
1103  const char* mc = c.c_str();
1104  std::string one(mb);
1105  std::string two(mc);
1106  EXPECT_EQ(one, two);
1107 #endif
1108  } while (++count % 100 != 0);
1109  };
1110 
1111 #define TEST_CLAUSE(x) \
1112  l(#x, \
1113  clause11_##x<std::string>, \
1114  clause11_##x<folly::fbstring>, \
1115  clause11_##x<folly::basic_fbstring<wchar_t>>);
1116 
1117  TEST_CLAUSE(21_4_2_a);
1118  TEST_CLAUSE(21_4_2_b);
1119  TEST_CLAUSE(21_4_2_c);
1120  TEST_CLAUSE(21_4_2_d);
1121  TEST_CLAUSE(21_4_2_e);
1122  TEST_CLAUSE(21_4_2_f);
1123  TEST_CLAUSE(21_4_2_g);
1124  TEST_CLAUSE(21_4_2_h);
1125  TEST_CLAUSE(21_4_2_i);
1126  TEST_CLAUSE(21_4_2_j);
1127  TEST_CLAUSE(21_4_2_k);
1128  TEST_CLAUSE(21_4_2_l);
1129  TEST_CLAUSE(21_4_2_lprime);
1130  TEST_CLAUSE(21_4_2_m);
1131  TEST_CLAUSE(21_4_2_n);
1132  TEST_CLAUSE(21_4_3);
1133  TEST_CLAUSE(21_4_4);
1134  TEST_CLAUSE(21_4_5);
1135  TEST_CLAUSE(21_4_6_1);
1136  TEST_CLAUSE(21_4_6_2);
1137  TEST_CLAUSE(21_4_6_3_a);
1138  TEST_CLAUSE(21_4_6_3_b);
1139  TEST_CLAUSE(21_4_6_3_c);
1140  TEST_CLAUSE(21_4_6_3_d);
1141  TEST_CLAUSE(21_4_6_3_e);
1142  TEST_CLAUSE(21_4_6_3_f);
1143  TEST_CLAUSE(21_4_6_3_g);
1144  TEST_CLAUSE(21_4_6_3_h);
1145  TEST_CLAUSE(21_4_6_3_i);
1146  TEST_CLAUSE(21_4_6_3_j);
1147  TEST_CLAUSE(21_4_6_3_k);
1148  TEST_CLAUSE(21_4_6_4);
1149  TEST_CLAUSE(21_4_6_5);
1150  TEST_CLAUSE(21_4_6_6);
1151  TEST_CLAUSE(21_4_6_7);
1152  TEST_CLAUSE(21_4_6_8);
1153  TEST_CLAUSE(21_4_7_1);
1154 
1155  TEST_CLAUSE(21_4_7_2_a);
1156  TEST_CLAUSE(21_4_7_2_a1);
1157  TEST_CLAUSE(21_4_7_2_a2);
1158  TEST_CLAUSE(21_4_7_2_b);
1159  TEST_CLAUSE(21_4_7_2_b1);
1160  TEST_CLAUSE(21_4_7_2_b2);
1161  TEST_CLAUSE(21_4_7_2_c);
1162  TEST_CLAUSE(21_4_7_2_c1);
1163  TEST_CLAUSE(21_4_7_2_c2);
1164  TEST_CLAUSE(21_4_7_2_d);
1165  TEST_CLAUSE(21_4_7_3_a);
1166  TEST_CLAUSE(21_4_7_3_b);
1167  TEST_CLAUSE(21_4_7_3_c);
1168  TEST_CLAUSE(21_4_7_3_d);
1169  TEST_CLAUSE(21_4_7_4_a);
1170  TEST_CLAUSE(21_4_7_4_b);
1171  TEST_CLAUSE(21_4_7_4_c);
1172  TEST_CLAUSE(21_4_7_4_d);
1173  TEST_CLAUSE(21_4_7_5_a);
1174  TEST_CLAUSE(21_4_7_5_b);
1175  TEST_CLAUSE(21_4_7_5_c);
1176  TEST_CLAUSE(21_4_7_5_d);
1177  TEST_CLAUSE(21_4_7_6_a);
1178  TEST_CLAUSE(21_4_7_6_b);
1179  TEST_CLAUSE(21_4_7_6_c);
1180  TEST_CLAUSE(21_4_7_6_d);
1181  TEST_CLAUSE(21_4_7_7_a);
1182  TEST_CLAUSE(21_4_7_7_b);
1183  TEST_CLAUSE(21_4_7_7_c);
1184  TEST_CLAUSE(21_4_7_7_d);
1185  TEST_CLAUSE(21_4_7_8);
1186  TEST_CLAUSE(21_4_7_9_a);
1187  TEST_CLAUSE(21_4_7_9_b);
1188  TEST_CLAUSE(21_4_7_9_c);
1189  TEST_CLAUSE(21_4_7_9_d);
1190  TEST_CLAUSE(21_4_7_9_e);
1191  TEST_CLAUSE(21_4_8_1_a);
1192  TEST_CLAUSE(21_4_8_1_b);
1193  TEST_CLAUSE(21_4_8_1_c);
1194  TEST_CLAUSE(21_4_8_1_d);
1195  TEST_CLAUSE(21_4_8_1_e);
1196  TEST_CLAUSE(21_4_8_1_f);
1197  TEST_CLAUSE(21_4_8_1_g);
1198  TEST_CLAUSE(21_4_8_1_h);
1199  TEST_CLAUSE(21_4_8_1_i);
1200  TEST_CLAUSE(21_4_8_1_j);
1201  TEST_CLAUSE(21_4_8_1_k);
1202  TEST_CLAUSE(21_4_8_1_l);
1203  TEST_CLAUSE(21_4_8_9_a);
1204 }
1205 
1206 TEST(FBString, testGetline) {
1207  string s1 =
1208  "\
1209 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
1210 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1211 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1212 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1213 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1214 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1215 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1216 tristique senectus et netus et malesuada fames ac turpis \n\
1217 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1218 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1219 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1220 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1221 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1222 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1223 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1224 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1225 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1226 
1227  vector<fbstring> v;
1228  boost::split(v, s1, boost::is_any_of("\n"));
1229  {
1230  istringstream input(s1);
1231  fbstring line;
1232  FOR_EACH (i, v) {
1233  EXPECT_TRUE(!getline(input, line).fail());
1234  EXPECT_EQ(line, *i);
1235  }
1236  }
1237 }
1238 
1239 TEST(FBString, testMoveCtor) {
1240  // Move constructor. Make sure we allocate a large string, so the
1241  // small string optimization doesn't kick in.
1242  auto size = random(100, 2000);
1243  fbstring s(size, 'a');
1244  fbstring test = std::move(s);
1245  EXPECT_TRUE(s.empty());
1246  EXPECT_EQ(size, test.size());
1247 }
1248 
1249 TEST(FBString, testMoveAssign) {
1250  // Move constructor. Make sure we allocate a large string, so the
1251  // small string optimization doesn't kick in.
1252  auto size = random(100, 2000);
1253  fbstring s(size, 'a');
1254  fbstring test;
1255  test = std::move(s);
1256  EXPECT_TRUE(s.empty());
1257  EXPECT_EQ(size, test.size());
1258 }
1259 
1260 TEST(FBString, testMoveOperatorPlusLhs) {
1261  // Make sure we allocate a large string, so the
1262  // small string optimization doesn't kick in.
1263  auto size1 = random(100, 2000);
1264  auto size2 = random(100, 2000);
1265  fbstring s1(size1, 'a');
1266  fbstring s2(size2, 'b');
1267  fbstring test;
1268  test = std::move(s1) + s2;
1269  EXPECT_TRUE(s1.empty());
1270  EXPECT_EQ(size1 + size2, test.size());
1271 }
1272 
1273 TEST(FBString, testMoveOperatorPlusRhs) {
1274  // Make sure we allocate a large string, so the
1275  // small string optimization doesn't kick in.
1276  auto size1 = random(100, 2000);
1277  auto size2 = random(100, 2000);
1278  fbstring s1(size1, 'a');
1279  fbstring s2(size2, 'b');
1280  fbstring test;
1281  test = s1 + std::move(s2);
1282  EXPECT_EQ(size1 + size2, test.size());
1283 }
1284 
1285 // The GNU C++ standard library throws an std::logic_error when an std::string
1286 // is constructed with a null pointer. Verify that we mirror this behavior.
1287 //
1288 // N.B. We behave this way even if the C++ library being used is something
1289 // other than libstdc++. Someday if we deem it important to present
1290 // identical undefined behavior for other platforms, we can re-visit this.
1291 TEST(FBString, testConstructionFromLiteralZero) {
1292  EXPECT_THROW(fbstring s(nullptr), std::logic_error);
1293 }
1294 
1295 TEST(FBString, testFixedBugs_D479397) {
1296  fbstring str(1337, 'f');
1297  fbstring cp = str;
1298  cp.clear();
1299  cp.c_str();
1300  EXPECT_EQ(str.front(), 'f');
1301 }
1302 
1303 TEST(FBString, testFixedBugs_D481173) {
1304  fbstring str(1337, 'f');
1305  for (int i = 0; i < 2; ++i) {
1306  fbstring cp = str;
1307  cp[1] = 'b';
1308  EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1309  cp.push_back('?');
1310  }
1311 }
1312 
1313 TEST(FBString, testFixedBugs_D580267_push_back) {
1314  fbstring str(1337, 'f');
1315  fbstring cp = str;
1316  cp.push_back('f');
1317 }
1318 
1319 TEST(FBString, testFixedBugs_D580267_operator_add_assign) {
1320  fbstring str(1337, 'f');
1321  fbstring cp = str;
1322  cp += "bb";
1323 }
1324 
1325 TEST(FBString, testFixedBugs_D661622) {
1327  EXPECT_EQ(0, s.size());
1328 }
1329 
1330 TEST(FBString, testFixedBugs_D785057) {
1331  fbstring str(1337, 'f');
1332  std::swap(str, str);
1333  EXPECT_EQ(1337, str.size());
1334 }
1335 
1336 TEST(FBString, testFixedBugs_D1012196_allocator_malloc) {
1337  fbstring str(128, 'f');
1338  str.clear(); // Empty medium string.
1339  fbstring copy(str); // Medium string of 0 capacity.
1340  copy.push_back('b');
1341  EXPECT_GE(copy.capacity(), 1);
1342 }
1343 
1344 TEST(FBString, testFixedBugs_D2813713) {
1345  fbstring s1("a");
1346  s1.reserve(8); // Trigger the optimized code path.
1347  auto test1 = '\0' + std::move(s1);
1348  EXPECT_EQ(2, test1.size());
1349 
1350  fbstring s2(1, '\0');
1351  s2.reserve(8);
1352  auto test2 = "a" + std::move(s2);
1353  EXPECT_EQ(2, test2.size());
1354 }
1355 
1356 TEST(FBString, testFixedBugs_D3698862) {
1357  EXPECT_EQ(fbstring().find(fbstring(), 4), fbstring::npos);
1358 }
1359 
1360 TEST(FBString, testFixedBugs_D4355440) {
1361  SKIP_IF(!usingJEMalloc());
1362 
1363  fbstring str(1337, 'f');
1364  str.reserve(3840);
1365  EXPECT_NE(str.capacity(), 3840);
1366 
1367  struct DummyRefCounted {
1368  std::atomic<size_t> refCount_;
1369  };
1370  EXPECT_EQ(
1371  str.capacity(),
1372  goodMallocSize(3840) - sizeof(DummyRefCounted) - sizeof(char));
1373 }
1374 
1375 TEST(FBString, findWithNpos) {
1376  fbstring fbstr("localhost:80");
1377  EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1378 }
1379 
1380 TEST(FBString, testHash) {
1381  fbstring a;
1382  fbstring b;
1383  a.push_back(0);
1384  a.push_back(1);
1385  b.push_back(0);
1386  b.push_back(2);
1387  std::hash<fbstring> hashfunc;
1388  EXPECT_NE(hashfunc(a), hashfunc(b));
1389 }
1390 
1391 #if FOLLY_HAVE_WCHAR_SUPPORT
1392 TEST(FBString, testHashChar16) {
1393  using u16fbstring = folly::basic_fbstring<char16_t>;
1394  u16fbstring a;
1395  u16fbstring b;
1396  a.push_back(0);
1397  a.push_back(1);
1398  b.push_back(0);
1399  b.push_back(2);
1400  std::hash<u16fbstring> hashfunc;
1401  EXPECT_NE(hashfunc(a), hashfunc(b));
1402 }
1403 #endif
1404 
1405 TEST(FBString, testFrontBack) {
1406  fbstring str("hello");
1407  EXPECT_EQ(str.front(), 'h');
1408  EXPECT_EQ(str.back(), 'o');
1409  str.front() = 'H';
1410  EXPECT_EQ(str.front(), 'H');
1411  str.back() = 'O';
1412  EXPECT_EQ(str.back(), 'O');
1413  EXPECT_EQ(str, "HellO");
1414 }
1415 
1416 TEST(FBString, noexcept) {
1418  fbstring x;
1421  fbstring y;
1422  EXPECT_FALSE(noexcept(y = x));
1423  EXPECT_TRUE(noexcept(y = std::move(x)));
1424 }
1425 
1426 TEST(FBString, iomanip) {
1427  stringstream ss;
1428  fbstring fbstr("Hello");
1429 
1430  ss << setw(6) << fbstr;
1431  EXPECT_EQ(ss.str(), " Hello");
1432  ss.str("");
1433 
1434  ss << left << setw(6) << fbstr;
1435  EXPECT_EQ(ss.str(), "Hello ");
1436  ss.str("");
1437 
1438  ss << right << setw(6) << fbstr;
1439  EXPECT_EQ(ss.str(), " Hello");
1440  ss.str("");
1441 
1442  ss << setw(4) << fbstr;
1443  EXPECT_EQ(ss.str(), "Hello");
1444  ss.str("");
1445 
1446  ss << setfill('^') << setw(6) << fbstr;
1447  EXPECT_EQ(ss.str(), "^Hello");
1448  ss.str("");
1449 }
1450 
1451 TEST(FBString, rvalueIterators) {
1452  // you cannot take &* of a move-iterator, so use that for testing
1453  fbstring s = "base";
1454  fbstring r = "hello";
1455  r.replace(
1456  r.begin(),
1457  r.end(),
1458  make_move_iterator(s.begin()),
1459  make_move_iterator(s.end()));
1460  EXPECT_EQ("base", r);
1461 
1462  // The following test is probably not required by the standard.
1463  // i.e. this could be in the realm of undefined behavior.
1464  fbstring b = "123abcXYZ";
1465  auto ait = b.begin() + 3;
1466  auto Xit = b.begin() + 6;
1467  b.replace(ait, b.end(), b.begin(), Xit);
1468  EXPECT_EQ("123123abc", b); // if things go wrong, you'd get "123123123"
1469 }
1470 
1471 TEST(FBString, moveTerminator) {
1472  // The source of a move must remain in a valid state
1473  fbstring s(100, 'x'); // too big to be in-situ
1474  fbstring k;
1475  k = std::move(s);
1476 
1477  EXPECT_EQ(0, s.size());
1478  EXPECT_EQ('\0', *s.c_str());
1479 }
1480 
1481 namespace {
1482 /*
1483  * t8968589: Clang 3.7 refused to compile w/ certain constructors (specifically
1484  * those that were "explicit" and had a defaulted parameter, if they were used
1485  * in structs which were default-initialized). Exercise these just to ensure
1486  * they compile.
1487  *
1488  * In diff D2632953 the old constructor:
1489  * explicit basic_fbstring(const A& a = A()) noexcept;
1490  *
1491  * was split into these two, as a workaround:
1492  * basic_fbstring() noexcept;
1493  * explicit basic_fbstring(const A& a) noexcept;
1494  */
1495 
1496 struct TestStructDefaultAllocator {
1497  folly::basic_fbstring<char> stringMember;
1498 };
1499 
1500 template <class A>
1501 struct TestStructWithAllocator {
1503 };
1504 
1505 std::atomic<size_t> allocatorConstructedCount(0);
1506 struct TestStructStringAllocator : std::allocator<char> {
1507  TestStructStringAllocator() {
1508  ++allocatorConstructedCount;
1509  }
1510 };
1511 
1512 } // namespace
1513 
1514 TEST(FBStringCtorTest, DefaultInitStructDefaultAlloc) {
1515  TestStructDefaultAllocator t1{};
1516  EXPECT_TRUE(t1.stringMember.empty());
1517 }
1518 
1519 TEST(FBStringCtorTest, DefaultInitStructAlloc) {
1520  EXPECT_EQ(allocatorConstructedCount.load(), 0);
1521  TestStructWithAllocator<TestStructStringAllocator> t2;
1522  EXPECT_TRUE(t2.stringMember.empty());
1523  EXPECT_EQ(allocatorConstructedCount.load(), 1);
1524 }
1525 
1526 TEST(FBStringCtorTest, NullZeroConstruction) {
1527  char* p = nullptr;
1528  int n = 0;
1529  folly::fbstring f(p, n);
1530  EXPECT_EQ(f.size(), 0);
1531 }
1532 
1533 // Tests for the comparison operators. I use EXPECT_TRUE rather than EXPECT_LE
1534 // because what's under test is the operator rather than the relation between
1535 // the objects.
1536 
1537 TEST(FBString, compareToStdString) {
1538  using folly::fbstring;
1539  using namespace std::string_literals;
1540  auto stdA = "a"s;
1541  auto stdB = "b"s;
1542  fbstring fbA("a");
1543  fbstring fbB("b");
1544  EXPECT_TRUE(stdA == fbA);
1545  EXPECT_TRUE(fbB == stdB);
1546  EXPECT_TRUE(stdA != fbB);
1547  EXPECT_TRUE(fbA != stdB);
1548  EXPECT_TRUE(stdA < fbB);
1549  EXPECT_TRUE(fbA < stdB);
1550  EXPECT_TRUE(stdB > fbA);
1551  EXPECT_TRUE(fbB > stdA);
1552  EXPECT_TRUE(stdA <= fbB);
1553  EXPECT_TRUE(fbA <= stdB);
1554  EXPECT_TRUE(stdA <= fbA);
1555  EXPECT_TRUE(fbA <= stdA);
1556  EXPECT_TRUE(stdB >= fbA);
1557  EXPECT_TRUE(fbB >= stdA);
1558  EXPECT_TRUE(stdB >= fbB);
1559  EXPECT_TRUE(fbB >= stdB);
1560 }
1561 
1562 TEST(U16FBString, compareToStdU16String) {
1563  using folly::basic_fbstring;
1564  using namespace std::string_literals;
1565  auto stdA = u"a"s;
1566  auto stdB = u"b"s;
1567  basic_fbstring<char16_t> fbA(u"a");
1568  basic_fbstring<char16_t> fbB(u"b");
1569  EXPECT_TRUE(stdA == fbA);
1570  EXPECT_TRUE(fbB == stdB);
1571  EXPECT_TRUE(stdA != fbB);
1572  EXPECT_TRUE(fbA != stdB);
1573  EXPECT_TRUE(stdA < fbB);
1574  EXPECT_TRUE(fbA < stdB);
1575  EXPECT_TRUE(stdB > fbA);
1576  EXPECT_TRUE(fbB > stdA);
1577  EXPECT_TRUE(stdA <= fbB);
1578  EXPECT_TRUE(fbA <= stdB);
1579  EXPECT_TRUE(stdA <= fbA);
1580  EXPECT_TRUE(fbA <= stdA);
1581  EXPECT_TRUE(stdB >= fbA);
1582  EXPECT_TRUE(fbB >= stdA);
1583  EXPECT_TRUE(stdB >= fbB);
1584  EXPECT_TRUE(fbB >= stdB);
1585 }
1586 
1587 TEST(U32FBString, compareToStdU32String) {
1588  using folly::basic_fbstring;
1589  using namespace std::string_literals;
1590  auto stdA = U"a"s;
1591  auto stdB = U"b"s;
1592  basic_fbstring<char32_t> fbA(U"a");
1593  basic_fbstring<char32_t> fbB(U"b");
1594  EXPECT_TRUE(stdA == fbA);
1595  EXPECT_TRUE(fbB == stdB);
1596  EXPECT_TRUE(stdA != fbB);
1597  EXPECT_TRUE(fbA != stdB);
1598  EXPECT_TRUE(stdA < fbB);
1599  EXPECT_TRUE(fbA < stdB);
1600  EXPECT_TRUE(stdB > fbA);
1601  EXPECT_TRUE(fbB > stdA);
1602  EXPECT_TRUE(stdA <= fbB);
1603  EXPECT_TRUE(fbA <= stdB);
1604  EXPECT_TRUE(stdA <= fbA);
1605  EXPECT_TRUE(fbA <= stdA);
1606  EXPECT_TRUE(stdB >= fbA);
1607  EXPECT_TRUE(fbB >= stdA);
1608  EXPECT_TRUE(stdB >= fbB);
1609  EXPECT_TRUE(fbB >= stdB);
1610 }
1611 
1612 TEST(WFBString, compareToStdWString) {
1613  using folly::basic_fbstring;
1614  using namespace std::string_literals;
1615  auto stdA = L"a"s;
1616  auto stdB = L"b"s;
1617  basic_fbstring<wchar_t> fbA(L"a");
1618  basic_fbstring<wchar_t> fbB(L"b");
1619  EXPECT_TRUE(stdA == fbA);
1620  EXPECT_TRUE(fbB == stdB);
1621  EXPECT_TRUE(stdA != fbB);
1622  EXPECT_TRUE(fbA != stdB);
1623  EXPECT_TRUE(stdA < fbB);
1624  EXPECT_TRUE(fbA < stdB);
1625  EXPECT_TRUE(stdB > fbA);
1626  EXPECT_TRUE(fbB > stdA);
1627  EXPECT_TRUE(stdA <= fbB);
1628  EXPECT_TRUE(fbA <= stdB);
1629  EXPECT_TRUE(stdA <= fbA);
1630  EXPECT_TRUE(fbA <= stdA);
1631  EXPECT_TRUE(stdB >= fbA);
1632  EXPECT_TRUE(fbB >= stdA);
1633  EXPECT_TRUE(stdB >= fbB);
1634  EXPECT_TRUE(fbB >= stdB);
1635 }
1636 
1637 // Same again, but with a more challenging input - a common prefix and different
1638 // lengths.
1639 
1640 TEST(FBString, compareToStdStringLong) {
1641  using folly::fbstring;
1642  using namespace std::string_literals;
1643  auto stdA = "1234567890a"s;
1644  auto stdB = "1234567890ab"s;
1645  fbstring fbA("1234567890a");
1646  fbstring fbB("1234567890ab");
1647  EXPECT_TRUE(stdA == fbA);
1648  EXPECT_TRUE(fbB == stdB);
1649  EXPECT_TRUE(stdA != fbB);
1650  EXPECT_TRUE(fbA != stdB);
1651  EXPECT_TRUE(stdA < fbB);
1652  EXPECT_TRUE(fbA < stdB);
1653  EXPECT_TRUE(stdB > fbA);
1654  EXPECT_TRUE(fbB > stdA);
1655  EXPECT_TRUE(stdA <= fbB);
1656  EXPECT_TRUE(fbA <= stdB);
1657  EXPECT_TRUE(stdA <= fbA);
1658  EXPECT_TRUE(fbA <= stdA);
1659  EXPECT_TRUE(stdB >= fbA);
1660  EXPECT_TRUE(fbB >= stdA);
1661  EXPECT_TRUE(stdB >= fbB);
1662  EXPECT_TRUE(fbB >= stdB);
1663 }
1664 
1665 TEST(U16FBString, compareToStdU16StringLong) {
1666  using folly::basic_fbstring;
1667  using namespace std::string_literals;
1668  auto stdA = u"1234567890a"s;
1669  auto stdB = u"1234567890ab"s;
1670  basic_fbstring<char16_t> fbA(u"1234567890a");
1671  basic_fbstring<char16_t> fbB(u"1234567890ab");
1672  EXPECT_TRUE(stdA == fbA);
1673  EXPECT_TRUE(fbB == stdB);
1674  EXPECT_TRUE(stdA != fbB);
1675  EXPECT_TRUE(fbA != stdB);
1676  EXPECT_TRUE(stdA < fbB);
1677  EXPECT_TRUE(fbA < stdB);
1678  EXPECT_TRUE(stdB > fbA);
1679  EXPECT_TRUE(fbB > stdA);
1680  EXPECT_TRUE(stdA <= fbB);
1681  EXPECT_TRUE(fbA <= stdB);
1682  EXPECT_TRUE(stdA <= fbA);
1683  EXPECT_TRUE(fbA <= stdA);
1684  EXPECT_TRUE(stdB >= fbA);
1685  EXPECT_TRUE(fbB >= stdA);
1686  EXPECT_TRUE(stdB >= fbB);
1687  EXPECT_TRUE(fbB >= stdB);
1688 }
1689 
1690 #if FOLLY_HAVE_WCHAR_SUPPORT
1691 TEST(U32FBString, compareToStdU32StringLong) {
1692  using folly::basic_fbstring;
1693  using namespace std::string_literals;
1694  auto stdA = U"1234567890a"s;
1695  auto stdB = U"1234567890ab"s;
1696  basic_fbstring<char32_t> fbA(U"1234567890a");
1697  basic_fbstring<char32_t> fbB(U"1234567890ab");
1698  EXPECT_TRUE(stdA == fbA);
1699  EXPECT_TRUE(fbB == stdB);
1700  EXPECT_TRUE(stdA != fbB);
1701  EXPECT_TRUE(fbA != stdB);
1702  EXPECT_TRUE(stdA < fbB);
1703  EXPECT_TRUE(fbA < stdB);
1704  EXPECT_TRUE(stdB > fbA);
1705  EXPECT_TRUE(fbB > stdA);
1706  EXPECT_TRUE(stdA <= fbB);
1707  EXPECT_TRUE(fbA <= stdB);
1708  EXPECT_TRUE(stdA <= fbA);
1709  EXPECT_TRUE(fbA <= stdA);
1710  EXPECT_TRUE(stdB >= fbA);
1711  EXPECT_TRUE(fbB >= stdA);
1712  EXPECT_TRUE(stdB >= fbB);
1713  EXPECT_TRUE(fbB >= stdB);
1714 }
1715 
1716 TEST(WFBString, compareToStdWStringLong) {
1717  using folly::basic_fbstring;
1718  using namespace std::string_literals;
1719  auto stdA = L"1234567890a"s;
1720  auto stdB = L"1234567890ab"s;
1721  basic_fbstring<wchar_t> fbA(L"1234567890a");
1722  basic_fbstring<wchar_t> fbB(L"1234567890ab");
1723  EXPECT_TRUE(stdA == fbA);
1724  EXPECT_TRUE(fbB == stdB);
1725  EXPECT_TRUE(stdA != fbB);
1726  EXPECT_TRUE(fbA != stdB);
1727  EXPECT_TRUE(stdA < fbB);
1728  EXPECT_TRUE(fbA < stdB);
1729  EXPECT_TRUE(stdB > fbA);
1730  EXPECT_TRUE(fbB > stdA);
1731  EXPECT_TRUE(stdA <= fbB);
1732  EXPECT_TRUE(fbA <= stdB);
1733  EXPECT_TRUE(stdA <= fbA);
1734  EXPECT_TRUE(fbA <= stdA);
1735  EXPECT_TRUE(stdB >= fbA);
1736  EXPECT_TRUE(fbB >= stdA);
1737  EXPECT_TRUE(stdB >= fbB);
1738  EXPECT_TRUE(fbB >= stdB);
1739 }
1740 #endif
#define EXPECT_LE(val1, val2)
Definition: gtest.h:1928
const value_type * c_str() const
Definition: FBString.h:1712
size_type size() const
Definition: FBString.h:1337
void clause11_21_4_6_8(String &test)
void clause11_21_4_8_1_d(String &test)
void clause11_21_4_7_4_b(String &test)
void Num2String(String &str, Integral n)
Integral2 random(Integral1 low, Integral2 up)
void clause11_21_4_2_e(String &test)
void clause11_21_4_7_9_c(String &test)
void clause11_21_4_2_d(String &test)
#define TEST_CLAUSE(x)
void clause11_21_4_6_4(String &test)
auto f
void clause11_21_4_7_9_a(String &test)
bool empty() const
Definition: FBString.h:1372
void clause11_21_4_8_1_c(String &test)
auto v
std::unique_ptr< int > A
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
void clause11_21_4_7_2_b1(String &test)
char b
void clause11_21_4_7_2_c1(String &test)
void clause11_21_4_7_2_b(String &test)
void clause11_21_4_2_h(String &test)
bool usingJEMalloc() noexcept
Definition: Malloc.h:147
void clause11_21_4_6_1(String &test)
static const int seed
void clause11_21_4_7_6_b(String &test)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void clause11_21_4_2_i(String &test)
void clause11_21_4_7_9_b(String &test)
void clause11_21_4_8_1_i(String &test)
static uint64_t test(std::string name, bool fc_, bool dedicated_, bool tc_, bool syncops_, uint64_t base)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const int x
const value_type & back() const
Definition: FBString.h:1318
void clause11_21_4_7_5_a(String &test)
void clause11_21_4_2_b(String &test)
void clause11_21_4_2_m(String &test)
void clause11_21_4_6_7(String &test)
void clause11_21_4_7_7_a(String &test)
STL namespace.
void clause11_21_4_8_1_k(String &test)
void BENCHFUN() getline(size_t iters, size_t arg)
void clause11_21_4_7_4_a(String &test)
void clause11_21_4_8_9_a(String &test)
void clause11_21_4_7_6_d(String &test)
void clause11_21_4_7_3_b(String &test)
void clause11_21_4_8_1_e(String &test)
void clause11_21_4_7_4_d(String &test)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
boost::mt19937 RandomT
void clause11_21_4_6_3_f(String &test)
void clause11_21_4_2_g(String &test)
requires E e noexcept(noexcept(s.error(std::move(e))))
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
void clause11_21_4_6_3_d(String &test)
void clause11_21_4_7_3_c(String &test)
void clause11_21_4_7_5_b(String &test)
void clause11_21_4_7_2_c2(String &test)
void clause11_21_4_7_9_e(String &test)
void clause11_21_4_6_3_h(String &test)
std::list< char > RandomList(unsigned int maxSize)
void reserve(size_type res_arg=0)
Definition: FBString.h:1355
const value_type & front() const
Definition: FBString.h:1315
void clause11_21_4_8_1_l(String &test)
void clause11_21_4_8_1_g(String &test)
auto rng
Definition: CollectTest.cpp:31
void clause11_21_4_6_3_c(String &test)
void clause11_21_4_6_3_i(String &test)
#define FOR_EACH_RANGE(i, begin, end)
Definition: Foreach.h:313
Gen range(Value begin, Value end)
Definition: Base.h:467
void clause11_21_4_6_2(String &test)
void clause11_21_4_7_7_d(String &test)
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
void clause11_21_4_7_2_a1(String &test)
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void clause11_21_4_7_2_b2(String &test)
const value_type * data() const
Definition: FBString.h:1716
::std::wstring wstring
Definition: gtest-port.h:1103
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
void clause11_21_4_7_7_c(String &test)
void clause11_21_4_8_1_a(String &test)
void clause11_21_4_6_3_e(String &test)
void fail()
void clause11_21_4_4(String &test)
void clause11_21_4_2_lprime(String &test)
void clause11_21_4_2_l(String &test)
void clause11_21_4_7_1(String &test)
void clause11_21_4_8_1_f(String &test)
void clause11_21_4_2_c(String &test)
void clause11_21_4_6_3_g(String &test)
void clause11_21_4_8_1_b(String &test)
void clause11_21_4_6_6(String &test)
S split(const StringPiece source, char delimiter)
Definition: String.h:61
void clause11_21_4_2_f(String &test)
void clause11_21_4_7_3_a(String &test)
size_type capacity() const
Definition: FBString.h:1351
char a
void clause11_21_4_6_5(String &test)
void clause11_21_4_7_9_d(String &test)
void clause11_21_4_3(String &test)
size_type find(const basic_fbstring &str, size_type pos=0) const
Definition: FBString.h:1724
void push_back(const value_type c)
Definition: FBString.h:1437
void clause11_21_4_8_1_h(String &test)
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::operators::from_fn from
void clause11_21_4_7_2_a(String &test)
void clause11_21_4_5(String &test)
void clause11_21_4_7_6_a(String &test)
int * count
void clause11_21_4_2_k(String &test)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void clause11_21_4_6_3_k(String &test)
void clause11_21_4_2_n(String &test)
static constexpr int mb(int megs)
#define FOR_EACH(i, c)
Definition: Foreach.h:143
const char * string
Definition: Conv.cpp:212
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::detail::as_const_fn as_const
void clause11_21_4_7_8(String &test)
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
void clause11_21_4_7_5_c(String &test)
Definition: InvokeTest.cpp:65
void clause11_21_4_7_2_d(String &test)
#define SKIP_IF(expr)
Definition: TestUtils.h:59
vector< string > vec
Definition: StringTest.cpp:35
basic_fbstring & replace(size_type pos1, size_type n1, const basic_fbstring &str)
Definition: FBString.h:1581
void clause11_21_4_7_2_a2(String &test)
void clause11_21_4_7_4_c(String &test)
void clause11_21_4_2_a(String &test)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
void clause11_21_4_7_2_c(String &test)
basic_fbstring< char > fbstring
Definition: FBString.h:2904
char c
TEST(FBString, testAllClauses)
KeyT k
void clause11_21_4_7_3_d(String &test)
uint32_t randomNumberSeed()
Definition: Random.h:367
void clause11_21_4_7_5_d(String &test)
void clause11_21_4_8_1_j(String &test)
void clause11_21_4_2_j(String &test)
void clause11_21_4_6_3_j(String &test)
void randomString(String *toFill, size_t size=1000)
void clause11_21_4_6_3_a(String &test)
void clause11_21_4_7_7_b(String &test)
void clause11_21_4_7_6_c(String &test)
size_t goodMallocSize(size_t minSize) noexcept
Definition: Malloc.h:201
void clause11_21_4_6_3_b(String &test)