2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 // Author: andrei.alexandrescu@fb.com
20 #include <folly/FBString.h>
27 #include <boost/algorithm/string.hpp>
28 #include <boost/random.hpp>
29 #include <gtest/gtest.h>
31 #include <gflags/gflags.h>
33 #include <folly/Foreach.h>
34 #include <folly/Portability.h>
35 #include <folly/Random.h>
36 #include <folly/Conv.h>
39 using namespace folly;
41 static const int seed = folly::randomNumberSeed();
42 typedef boost::mt19937 RandomT;
43 static RandomT rng(seed);
44 static const size_t maxString = 100;
45 static const bool avoidAliasing = true;
47 template <class Integral1, class Integral2>
48 Integral2 random(Integral1 low, Integral2 up) {
49 boost::uniform_int<> range(low, up);
53 template <class String>
54 void randomString(String* toFill, unsigned int maxSize = 1000) {
56 toFill->resize(random(0, maxSize));
57 FOR_EACH (i, *toFill) {
58 *i = random('a', 'z');
62 template <class String, class Integral>
63 void Num2String(String& str, Integral n) {
65 std::string tmp = folly::to<std::string>(n);
66 str = String(tmp.begin(), tmp.end());
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');
78 ////////////////////////////////////////////////////////////////////////////////
80 ////////////////////////////////////////////////////////////////////////////////
82 template <class String> void clause11_21_4_2_a(String & test) {
83 test.String::~String();
86 template <class String> void clause11_21_4_2_b(String & test) {
88 assert(test2 == test);
90 template <class String> void clause11_21_4_2_c(String & test) {
91 // Test move constructor. There is a more specialized test, see
92 // TEST(FBString, testMoveCtor)
94 String test2(std::move(donor));
95 EXPECT_EQ(test2, test);
96 // Technically not required, but all implementations that actually
97 // support move will move large strings. Make a guess for 128 as the
98 // maximum small string optimization that's reasonable.
99 EXPECT_LE(donor.size(), 128);
101 template <class String> void clause11_21_4_2_d(String & test) {
102 // Copy constructor with position and length
103 const size_t pos = random(0, test.size());
104 String s(test, pos, random(0, 9)
105 ? random(0, (size_t)(test.size() - pos))
106 : String::npos); // test for npos, too, in 10% of the cases
109 template <class String> void clause11_21_4_2_e(String & test) {
110 // Constructor from char*, size_t
112 pos = random(0, test.size()),
113 n = random(0, test.size() - pos);
114 String before(test.data(), test.size());
115 String s(test.c_str() + pos, n);
116 String after(test.data(), test.size());
117 EXPECT_EQ(before, after);
120 template <class String> void clause11_21_4_2_f(String & test) {
121 // Constructor from char*
122 const size_t pos = random(0, test.size());
123 String before(test.data(), test.size());
124 String s(test.c_str() + pos);
125 String after(test.data(), test.size());
126 EXPECT_EQ(before, after);
129 template <class String> void clause11_21_4_2_g(String & test) {
130 // Constructor from size_t, char
131 const size_t n = random(0, test.size());
132 const auto c = test.front();
135 template <class String> void clause11_21_4_2_h(String & test) {
136 // Constructors from various iterator pairs
137 // Constructor from char*, char*
138 String s1(test.begin(), test.end());
140 String s2(test.data(), test.data() + test.size());
142 // Constructor from other iterators
144 for (auto c : test) lst.push_back(c);
145 String s3(lst.begin(), lst.end());
147 // Constructor from wchar_t iterators
148 std::list<wchar_t> lst1;
149 for (auto c : test) lst1.push_back(c);
150 String s4(lst1.begin(), lst1.end());
152 // Constructor from wchar_t pointers
156 fbstring s5(t, t + 2);;
159 template <class String> void clause11_21_4_2_i(String & test) {
160 // From initializer_list<char>
161 std::initializer_list<typename String::value_type>
162 il = { 'h', 'e', 'l', 'l', 'o' };
166 template <class String> void clause11_21_4_2_j(String & test) {
167 // Assignment from const String&
168 auto size = random(0, 2000);
169 String s(size, '\0');
170 EXPECT_EQ(s.size(), size);
171 FOR_EACH_RANGE (i, 0, s.size()) {
172 s[i] = random('a', 'z');
176 template <class String> void clause11_21_4_2_k(String & test) {
177 // Assignment from String&&
178 auto size = random(0, 2000);
179 String s(size, '\0');
180 EXPECT_EQ(s.size(), size);
181 FOR_EACH_RANGE (i, 0, s.size()) {
182 s[i] = random('a', 'z');
185 if (typeid(String) == typeid(fbstring)) {
186 EXPECT_LE(s.size(), 128);
189 template <class String> void clause11_21_4_2_l(String & test) {
190 // Assignment from char*
191 String s(random(0, 1000), '\0');
193 for (; i != s.size(); ++i) {
194 s[i] = random('a', 'z');
198 template <class String> void clause11_21_4_2_lprime(String & test) {
200 const size_t pos = random(0, test.size());
202 test = String(test.c_str() + pos);
204 test = test.c_str() + pos;
207 template <class String> void clause11_21_4_2_m(String & test) {
208 // Assignment from char
209 test = random('a', 'z');
211 template <class String> void clause11_21_4_2_n(String & test) {
212 // Assignment from initializer_list<char>
213 initializer_list<typename String::value_type>
214 il = { 'h', 'e', 'l', 'l', 'o' };
218 template <class String> void clause11_21_4_3(String & test) {
219 // Iterators. The code below should leave test unchanged
220 EXPECT_EQ(test.size(), test.end() - test.begin());
221 EXPECT_EQ(test.size(), test.rend() - test.rbegin());
222 EXPECT_EQ(test.size(), test.cend() - test.cbegin());
223 EXPECT_EQ(test.size(), test.crend() - test.crbegin());
225 auto s = test.size();
226 test.resize(test.end() - test.begin());
227 EXPECT_EQ(s, test.size());
228 test.resize(test.rend() - test.rbegin());
229 EXPECT_EQ(s, test.size());
232 template <class String> void clause11_21_4_4(String & test) {
233 // exercise capacity, size, max_size
234 EXPECT_EQ(test.size(), test.length());
235 EXPECT_LE(test.size(), test.max_size());
236 EXPECT_LE(test.capacity(), test.max_size());
237 EXPECT_LE(test.size(), test.capacity());
239 // exercise shrink_to_fit. Nonbinding request so we can't really do
240 // much beyond calling it.
242 copy.reserve(copy.capacity() * 3);
243 copy.shrink_to_fit();
244 EXPECT_EQ(copy, test);
247 string empty("empty");
248 string notempty("not empty");
249 if (test.empty()) test = String(empty.begin(), empty.end());
250 else test = String(notempty.begin(), notempty.end());
253 template <class String> void clause11_21_4_5(String & test) {
254 // exercise element access
256 EXPECT_EQ(test[0], test.front());
257 EXPECT_EQ(test[test.size() - 1], test.back());
258 auto const i = random(0, test.size() - 1);
259 EXPECT_EQ(test[i], test.at(i));
264 template <class String> void clause11_21_4_6_1(String & test) {
265 // 21.3.5 modifiers (+=)
267 randomString(&test1);
268 assert(test1.size() == char_traits
269 <typename String::value_type>::length(test1.c_str()));
270 auto len = test.size();
272 EXPECT_EQ(test.size(), test1.size() + len);
273 FOR_EACH_RANGE (i, 0, test1.size()) {
274 EXPECT_EQ(test[len + i], test1[i]);
276 // aliasing modifiers
278 auto dt = test2.data();
279 auto sz = test.c_str();
281 EXPECT_EQ(memcmp(sz, dt, len), 0);
282 String copy(test.data(), test.size());
283 EXPECT_EQ(char_traits
284 <typename String::value_type>::length(test.c_str()), len);
287 EXPECT_EQ(test.size(), 2 * len);
288 EXPECT_EQ(char_traits
289 <typename String::value_type>::length(test.c_str()), 2 * len);
290 FOR_EACH_RANGE (i, 0, len) {
291 EXPECT_EQ(test[i], copy[i]);
292 EXPECT_EQ(test[i], test[len + i]);
295 EXPECT_EQ(char_traits
296 <typename String::value_type>::length(test.c_str()), len);
298 auto const pos = random(0, test.size());
299 EXPECT_EQ(char_traits
300 <typename String::value_type>::length(test.c_str() + pos), len - pos);
302 String addMe(test.c_str() + pos);
303 EXPECT_EQ(addMe.size(), len - pos);
306 test += test.c_str() + pos;
308 EXPECT_EQ(test.size(), 2 * len - pos);
311 test += random('a', 'z');
312 EXPECT_EQ(test.size(), len + 1);
314 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
318 template <class String> void clause11_21_4_6_2(String & test) {
319 // 21.3.5 modifiers (append, push_back)
322 // Test with a small string first
323 char c = random('a', 'z');
325 EXPECT_EQ(s[s.size() - 1], c);
326 EXPECT_EQ(s.size(), 1);
327 s.resize(s.size() - 1);
329 randomString(&s, maxString);
331 randomString(&s, maxString);
332 test.append(s, random(0, s.size()), random(0, maxString));
333 randomString(&s, maxString);
334 test.append(s.c_str(), random(0, s.size()));
335 randomString(&s, maxString);
336 test.append(s.c_str());
337 test.append(random(0, maxString), random('a', 'z'));
338 std::list<char> lst(RandomList(maxString));
339 test.append(lst.begin(), lst.end());
340 c = random('a', 'z');
342 EXPECT_EQ(test[test.size() - 1], c);
344 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
348 template <class String> void clause11_21_4_6_3_a(String & test) {
355 test.assign(std::move(s));
356 if (typeid(String) == typeid(fbstring)) {
357 EXPECT_LE(s.size(), 128);
361 template <class String> void clause11_21_4_6_3_b(String & test) {
364 randomString(&s, maxString);
365 test.assign(s, random(0, s.size()), random(0, maxString));
368 template <class String> void clause11_21_4_6_3_c(String & test) {
371 randomString(&s, maxString);
372 test.assign(s.c_str(), random(0, s.size()));
375 template <class String> void clause11_21_4_6_3_d(String & test) {
378 randomString(&s, maxString);
379 test.assign(s.c_str());
382 template <class String> void clause11_21_4_6_3_e(String & test) {
385 randomString(&s, maxString);
386 test.assign(random(0, maxString), random('a', 'z'));
389 template <class String> void clause11_21_4_6_3_f(String & test) {
390 // assign from bidirectional iterator
391 std::list<char> lst(RandomList(maxString));
392 test.assign(lst.begin(), lst.end());
395 template <class String> void clause11_21_4_6_3_g(String & test) {
396 // assign from aliased source
400 template <class String> void clause11_21_4_6_3_h(String & test) {
401 // assign from aliased source
402 test.assign(test, random(0, test.size()), random(0, maxString));
405 template <class String> void clause11_21_4_6_3_i(String & test) {
406 // assign from aliased source
407 test.assign(test.c_str(), random(0, test.size()));
410 template <class String> void clause11_21_4_6_3_j(String & test) {
411 // assign from aliased source
412 test.assign(test.c_str());
415 template <class String> void clause11_21_4_6_3_k(String & test) {
416 // assign from initializer_list
417 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
421 template <class String> void clause11_21_4_6_4(String & test) {
424 randomString(&s, maxString);
425 test.insert(random(0, test.size()), s);
426 randomString(&s, maxString);
427 test.insert(random(0, test.size()),
428 s, random(0, s.size()),
429 random(0, maxString));
430 randomString(&s, maxString);
431 test.insert(random(0, test.size()),
432 s.c_str(), random(0, s.size()));
433 randomString(&s, maxString);
434 test.insert(random(0, test.size()), s.c_str());
435 test.insert(random(0, test.size()),
436 random(0, maxString), random('a', 'z'));
437 typename String::size_type pos = random(0, test.size());
438 typename String::iterator res =
439 test.insert(test.begin() + pos, random('a', 'z'));
440 EXPECT_EQ(res - test.begin(), pos);
441 std::list<char> lst(RandomList(maxString));
442 pos = random(0, test.size());
443 // Uncomment below to see a bug in gcc
444 /*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
445 // insert from initializer_list
446 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
447 pos = random(0, test.size());
448 // Uncomment below to see a bug in gcc
449 /*res = */test.insert(test.begin() + pos, il);
451 // Test with actual input iterators
453 ss << "hello cruel world";
454 auto i = istream_iterator<char>(ss);
455 test.insert(test.begin(), i, istream_iterator<char>());
458 template <class String> void clause11_21_4_6_5(String & test) {
459 // erase and pop_back
461 test.erase(random(0, test.size()), random(0, maxString));
464 // TODO: is erase(end()) allowed?
465 test.erase(test.begin() + random(0, test.size() - 1));
468 auto const i = test.begin() + random(0, test.size());
469 if (i != test.end()) {
470 test.erase(i, i + random(0, size_t(test.end() - i)));
474 // Can't test pop_back with std::string, doesn't support it yet.
479 template <class String> void clause11_21_4_6_6(String & test) {
480 auto pos = random(0, test.size());
482 test.replace(pos, random(0, test.size() - pos),
485 test.replace(pos, random(0, test.size() - pos), test);
487 pos = random(0, test.size());
489 randomString(&s, maxString);
490 test.replace(pos, pos + random(0, test.size() - pos), s);
491 auto pos1 = random(0, test.size());
492 auto pos2 = random(0, test.size());
494 test.replace(pos1, pos1 + random(0, test.size() - pos1),
496 pos2, pos2 + random(0, test.size() - pos2));
498 test.replace(pos1, pos1 + random(0, test.size() - pos1),
499 test, pos2, pos2 + random(0, test.size() - pos2));
501 pos1 = random(0, test.size());
503 randomString(&str, maxString);
504 pos2 = random(0, str.size());
505 test.replace(pos1, pos1 + random(0, test.size() - pos1),
506 str, pos2, pos2 + random(0, str.size() - pos2));
507 pos = random(0, test.size());
509 test.replace(pos, random(0, test.size() - pos),
510 String(test).c_str(), test.size());
512 test.replace(pos, random(0, test.size() - pos),
513 test.c_str(), test.size());
515 pos = random(0, test.size());
516 randomString(&str, maxString);
517 test.replace(pos, pos + random(0, test.size() - pos),
518 str.c_str(), str.size());
519 pos = random(0, test.size());
520 randomString(&str, maxString);
521 test.replace(pos, pos + random(0, test.size() - pos),
523 pos = random(0, test.size());
524 test.replace(pos, random(0, test.size() - pos),
525 random(0, maxString), random('a', 'z'));
526 pos = random(0, test.size());
528 auto newString = String(test);
531 test.begin() + pos + random(0, test.size() - pos),
536 test.begin() + pos + random(0, test.size() - pos),
539 pos = random(0, test.size());
541 auto newString = String(test);
544 test.begin() + pos + random(0, test.size() - pos),
546 test.size() - random(0, test.size()));
550 test.begin() + pos + random(0, test.size() - pos),
552 test.size() - random(0, test.size()));
554 pos = random(0, test.size());
555 auto const n = random(0, test.size() - pos);
556 typename String::iterator b = test.begin();
558 randomString(&str1, maxString);
559 const String & str3 = str1;
560 const typename String::value_type* ss = str3.c_str();
565 pos = random(0, test.size());
568 test.begin() + pos + random(0, test.size() - pos),
569 random(0, maxString), random('a', 'z'));
572 template <class String> void clause11_21_4_6_7(String & test) {
573 std::vector<typename String::value_type>
574 vec(random(0, maxString));
578 random(0, test.size()));
581 template <class String> void clause11_21_4_6_8(String & test) {
583 randomString(&s, maxString);
587 template <class String> void clause11_21_4_7_1(String & test) {
588 // 21.3.6 string operations
589 // exercise c_str() and data()
590 assert(test.c_str() == test.data());
591 // exercise get_allocator()
593 randomString(&s, maxString);
594 assert(test.get_allocator() == s.get_allocator());
597 template <class String> void clause11_21_4_7_2_a(String & test) {
598 String str = test.substr(
599 random(0, test.size()),
600 random(0, test.size()));
601 Num2String(test, test.find(str, random(0, test.size())));
604 template <class String> void clause11_21_4_7_2_a1(String & test) {
605 String str = String(test).substr(
606 random(0, test.size()),
607 random(0, test.size()));
608 Num2String(test, test.find(str, random(0, test.size())));
611 template <class String> void clause11_21_4_7_2_a2(String & test) {
612 auto const& cTest = test;
613 String str = cTest.substr(
614 random(0, test.size()),
615 random(0, test.size()));
616 Num2String(test, test.find(str, random(0, test.size())));
619 template <class String> void clause11_21_4_7_2_b(String & test) {
620 auto from = random(0, test.size());
621 auto length = random(0, test.size() - from);
622 String str = test.substr(from, length);
623 Num2String(test, test.find(str.c_str(),
624 random(0, test.size()),
625 random(0, str.size())));
628 template <class String> void clause11_21_4_7_2_b1(String & test) {
629 auto from = random(0, test.size());
630 auto length = random(0, test.size() - from);
631 String str = String(test).substr(from, length);
632 Num2String(test, test.find(str.c_str(),
633 random(0, test.size()),
634 random(0, str.size())));
637 template <class String> void clause11_21_4_7_2_b2(String & test) {
638 auto from = random(0, test.size());
639 auto length = random(0, test.size() - from);
640 const auto& cTest = test;
641 String str = cTest.substr(from, length);
642 Num2String(test, test.find(str.c_str(),
643 random(0, test.size()),
644 random(0, str.size())));
647 template <class String> void clause11_21_4_7_2_c(String & test) {
648 String str = test.substr(
649 random(0, test.size()),
650 random(0, test.size()));
651 Num2String(test, test.find(str.c_str(),
652 random(0, test.size())));
655 template <class String> void clause11_21_4_7_2_c1(String & test) {
656 String str = String(test).substr(
657 random(0, test.size()),
658 random(0, test.size()));
659 Num2String(test, test.find(str.c_str(),
660 random(0, test.size())));
663 template <class String> void clause11_21_4_7_2_c2(String & test) {
664 const auto& cTest = test;
665 String str = cTest.substr(
666 random(0, test.size()),
667 random(0, test.size()));
668 Num2String(test, test.find(str.c_str(),
669 random(0, test.size())));
672 template <class String> void clause11_21_4_7_2_d(String & test) {
673 Num2String(test, test.find(
675 random(0, test.size())));
678 template <class String> void clause11_21_4_7_3_a(String & test) {
679 String str = test.substr(
680 random(0, test.size()),
681 random(0, test.size()));
682 Num2String(test, test.rfind(str, random(0, test.size())));
685 template <class String> void clause11_21_4_7_3_b(String & test) {
686 String str = test.substr(
687 random(0, test.size()),
688 random(0, test.size()));
689 Num2String(test, test.rfind(str.c_str(),
690 random(0, test.size()),
691 random(0, str.size())));
694 template <class String> void clause11_21_4_7_3_c(String & test) {
695 String str = test.substr(
696 random(0, test.size()),
697 random(0, test.size()));
698 Num2String(test, test.rfind(str.c_str(),
699 random(0, test.size())));
702 template <class String> void clause11_21_4_7_3_d(String & test) {
703 Num2String(test, test.rfind(
705 random(0, test.size())));
708 template <class String> void clause11_21_4_7_4_a(String & test) {
710 randomString(&str, maxString);
711 Num2String(test, test.find_first_of(str,
712 random(0, test.size())));
715 template <class String> void clause11_21_4_7_4_b(String & test) {
717 randomString(&str, maxString);
718 Num2String(test, test.find_first_of(str.c_str(),
719 random(0, test.size()),
720 random(0, str.size())));
723 template <class String> void clause11_21_4_7_4_c(String & test) {
725 randomString(&str, maxString);
726 Num2String(test, test.find_first_of(str.c_str(),
727 random(0, test.size())));
730 template <class String> void clause11_21_4_7_4_d(String & test) {
731 Num2String(test, test.find_first_of(
733 random(0, test.size())));
736 template <class String> void clause11_21_4_7_5_a(String & test) {
738 randomString(&str, maxString);
739 Num2String(test, test.find_last_of(str,
740 random(0, test.size())));
743 template <class String> void clause11_21_4_7_5_b(String & test) {
745 randomString(&str, maxString);
746 Num2String(test, test.find_last_of(str.c_str(),
747 random(0, test.size()),
748 random(0, str.size())));
751 template <class String> void clause11_21_4_7_5_c(String & test) {
753 randomString(&str, maxString);
754 Num2String(test, test.find_last_of(str.c_str(),
755 random(0, test.size())));
758 template <class String> void clause11_21_4_7_5_d(String & test) {
759 Num2String(test, test.find_last_of(
761 random(0, test.size())));
764 template <class String> void clause11_21_4_7_6_a(String & test) {
766 randomString(&str, maxString);
767 Num2String(test, test.find_first_not_of(str,
768 random(0, test.size())));
771 template <class String> void clause11_21_4_7_6_b(String & test) {
773 randomString(&str, maxString);
774 Num2String(test, test.find_first_not_of(str.c_str(),
775 random(0, test.size()),
776 random(0, str.size())));
779 template <class String> void clause11_21_4_7_6_c(String & test) {
781 randomString(&str, maxString);
782 Num2String(test, test.find_first_not_of(str.c_str(),
783 random(0, test.size())));
786 template <class String> void clause11_21_4_7_6_d(String & test) {
787 Num2String(test, test.find_first_not_of(
789 random(0, test.size())));
792 template <class String> void clause11_21_4_7_7_a(String & test) {
794 randomString(&str, maxString);
795 Num2String(test, test.find_last_not_of(str,
796 random(0, test.size())));
799 template <class String> void clause11_21_4_7_7_b(String & test) {
801 randomString(&str, maxString);
802 Num2String(test, test.find_last_not_of(str.c_str(),
803 random(0, test.size()),
804 random(0, str.size())));
807 template <class String> void clause11_21_4_7_7_c(String & test) {
809 randomString(&str, maxString);
810 Num2String(test, test.find_last_not_of(str.c_str(),
811 random(0, test.size())));
814 template <class String> void clause11_21_4_7_7_d(String & test) {
815 Num2String(test, test.find_last_not_of(
817 random(0, test.size())));
820 template <class String> void clause11_21_4_7_8(String & test) {
821 test = test.substr(random(0, test.size()), random(0, test.size()));
824 template <class String> void clause11_21_4_7_9_a(String & test) {
826 randomString(&s, maxString);
827 int tristate = test.compare(s);
828 if (tristate > 0) tristate = 1;
829 else if (tristate < 0) tristate = 2;
830 Num2String(test, tristate);
833 template <class String> void clause11_21_4_7_9_b(String & test) {
835 randomString(&s, maxString);
836 int tristate = test.compare(
837 random(0, test.size()),
838 random(0, test.size()),
840 if (tristate > 0) tristate = 1;
841 else if (tristate < 0) tristate = 2;
842 Num2String(test, tristate);
845 template <class String> void clause11_21_4_7_9_c(String & test) {
847 randomString(&str, maxString);
848 int tristate = test.compare(
849 random(0, test.size()),
850 random(0, test.size()),
852 random(0, str.size()),
853 random(0, str.size()));
854 if (tristate > 0) tristate = 1;
855 else if (tristate < 0) tristate = 2;
856 Num2String(test, tristate);
859 template <class String> void clause11_21_4_7_9_d(String & test) {
861 randomString(&s, maxString);
862 int tristate = test.compare(s.c_str());
863 if (tristate > 0) tristate = 1;
864 else if (tristate < 0) tristate = 2;
865 Num2String(test, tristate);
868 template <class String> void clause11_21_4_7_9_e(String & test) {
870 randomString(&str, maxString);
871 int tristate = test.compare(
872 random(0, test.size()),
873 random(0, test.size()),
875 random(0, str.size()));
876 if (tristate > 0) tristate = 1;
877 else if (tristate < 0) tristate = 2;
878 Num2String(test, tristate);
881 template <class String> void clause11_21_4_8_1_a(String & test) {
883 randomString(&s1, maxString);
885 randomString(&s2, maxString);
889 template <class String> void clause11_21_4_8_1_b(String & test) {
891 randomString(&s1, maxString);
893 randomString(&s2, maxString);
894 test = move(s1) + s2;
897 template <class String> void clause11_21_4_8_1_c(String & test) {
899 randomString(&s1, maxString);
901 randomString(&s2, maxString);
902 test = s1 + move(s2);
905 template <class String> void clause11_21_4_8_1_d(String & test) {
907 randomString(&s1, maxString);
909 randomString(&s2, maxString);
910 test = move(s1) + move(s2);
913 template <class String> void clause11_21_4_8_1_e(String & test) {
915 randomString(&s, maxString);
917 randomString(&s1, maxString);
918 test = s.c_str() + s1;
921 template <class String> void clause11_21_4_8_1_f(String & test) {
923 randomString(&s, maxString);
925 randomString(&s1, maxString);
926 test = s.c_str() + move(s1);
929 template <class String> void clause11_21_4_8_1_g(String & test) {
931 randomString(&s, maxString);
932 test = typename String::value_type(random('a', 'z')) + s;
935 template <class String> void clause11_21_4_8_1_h(String & test) {
937 randomString(&s, maxString);
938 test = typename String::value_type(random('a', 'z')) + move(s);
941 template <class String> void clause11_21_4_8_1_i(String & test) {
943 randomString(&s, maxString);
945 randomString(&s1, maxString);
946 test = s + s1.c_str();
949 template <class String> void clause11_21_4_8_1_j(String & test) {
951 randomString(&s, maxString);
953 randomString(&s1, maxString);
954 test = move(s) + s1.c_str();
957 template <class String> void clause11_21_4_8_1_k(String & test) {
959 randomString(&s, maxString);
960 test = s + typename String::value_type(random('a', 'z'));
963 template <class String> void clause11_21_4_8_1_l(String & test) {
965 randomString(&s, maxString);
967 randomString(&s1, maxString);
968 test = move(s) + s1.c_str();
971 // Numbering here is from C++11
972 template <class String> void clause11_21_4_8_9_a(String & test) {
973 basic_stringstream<typename String::value_type> stst(test.c_str());
981 TEST(FBString, testAllClauses) {
982 EXPECT_TRUE(1) << "Starting with seed: " << seed;
986 folly::basic_fbstring<wchar_t> wc;
989 auto l = [&](const char * const clause,
990 void(*f_string)(std::string&),
991 void(*f_fbstring)(folly::fbstring&),
992 void(*f_wfbstring)(folly::basic_fbstring<wchar_t>&)) {
994 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << clause;
998 wr = std::wstring(r.begin(), r.end());
999 wc = folly::basic_fbstring<wchar_t>(wr.c_str());
1000 auto localSeed = seed + count;
1001 rng = RandomT(localSeed);
1003 rng = RandomT(localSeed);
1006 << "Lengths: " << r.size() << " vs. " << c.size()
1007 << "\nReference: '" << r << "'"
1008 << "\nActual: '" << c.data()[0] << "'";
1009 rng = RandomT(localSeed);
1011 int wret = wcslen(wc.c_str());
1013 int ret = wcstombs(mb, wc.c_str(), sizeof(mb));
1014 if (ret == wret) mb[wret] = '\0';
1015 const char *mc = c.c_str();
1016 std::string one(mb);
1017 std::string two(mc);
1018 EXPECT_EQ(one, two);
1019 } while (++count % 100 != 0);
1022 #define TEST_CLAUSE(x) \
1024 clause11_##x<std::string>, \
1025 clause11_##x<folly::fbstring>, \
1026 clause11_##x<folly::basic_fbstring<wchar_t>>);
1028 TEST_CLAUSE(21_4_2_a);
1029 TEST_CLAUSE(21_4_2_b);
1030 TEST_CLAUSE(21_4_2_c);
1031 TEST_CLAUSE(21_4_2_d);
1032 TEST_CLAUSE(21_4_2_e);
1033 TEST_CLAUSE(21_4_2_f);
1034 TEST_CLAUSE(21_4_2_g);
1035 TEST_CLAUSE(21_4_2_h);
1036 TEST_CLAUSE(21_4_2_i);
1037 TEST_CLAUSE(21_4_2_j);
1038 TEST_CLAUSE(21_4_2_k);
1039 TEST_CLAUSE(21_4_2_l);
1040 TEST_CLAUSE(21_4_2_lprime);
1041 TEST_CLAUSE(21_4_2_m);
1042 TEST_CLAUSE(21_4_2_n);
1043 TEST_CLAUSE(21_4_3);
1044 TEST_CLAUSE(21_4_4);
1045 TEST_CLAUSE(21_4_5);
1046 TEST_CLAUSE(21_4_6_1);
1047 TEST_CLAUSE(21_4_6_2);
1048 TEST_CLAUSE(21_4_6_3_a);
1049 TEST_CLAUSE(21_4_6_3_b);
1050 TEST_CLAUSE(21_4_6_3_c);
1051 TEST_CLAUSE(21_4_6_3_d);
1052 TEST_CLAUSE(21_4_6_3_e);
1053 TEST_CLAUSE(21_4_6_3_f);
1054 TEST_CLAUSE(21_4_6_3_g);
1055 TEST_CLAUSE(21_4_6_3_h);
1056 TEST_CLAUSE(21_4_6_3_i);
1057 TEST_CLAUSE(21_4_6_3_j);
1058 TEST_CLAUSE(21_4_6_3_k);
1059 TEST_CLAUSE(21_4_6_4);
1060 TEST_CLAUSE(21_4_6_5);
1061 TEST_CLAUSE(21_4_6_6);
1062 TEST_CLAUSE(21_4_6_7);
1063 TEST_CLAUSE(21_4_6_8);
1064 TEST_CLAUSE(21_4_7_1);
1066 TEST_CLAUSE(21_4_7_2_a);
1067 TEST_CLAUSE(21_4_7_2_a1);
1068 TEST_CLAUSE(21_4_7_2_a2);
1069 TEST_CLAUSE(21_4_7_2_b);
1070 TEST_CLAUSE(21_4_7_2_b1);
1071 TEST_CLAUSE(21_4_7_2_b2);
1072 TEST_CLAUSE(21_4_7_2_c);
1073 TEST_CLAUSE(21_4_7_2_c1);
1074 TEST_CLAUSE(21_4_7_2_c2);
1075 TEST_CLAUSE(21_4_7_2_d);
1076 TEST_CLAUSE(21_4_7_3_a);
1077 TEST_CLAUSE(21_4_7_3_b);
1078 TEST_CLAUSE(21_4_7_3_c);
1079 TEST_CLAUSE(21_4_7_3_d);
1080 TEST_CLAUSE(21_4_7_4_a);
1081 TEST_CLAUSE(21_4_7_4_b);
1082 TEST_CLAUSE(21_4_7_4_c);
1083 TEST_CLAUSE(21_4_7_4_d);
1084 TEST_CLAUSE(21_4_7_5_a);
1085 TEST_CLAUSE(21_4_7_5_b);
1086 TEST_CLAUSE(21_4_7_5_c);
1087 TEST_CLAUSE(21_4_7_5_d);
1088 TEST_CLAUSE(21_4_7_6_a);
1089 TEST_CLAUSE(21_4_7_6_b);
1090 TEST_CLAUSE(21_4_7_6_c);
1091 TEST_CLAUSE(21_4_7_6_d);
1092 TEST_CLAUSE(21_4_7_7_a);
1093 TEST_CLAUSE(21_4_7_7_b);
1094 TEST_CLAUSE(21_4_7_7_c);
1095 TEST_CLAUSE(21_4_7_7_d);
1096 TEST_CLAUSE(21_4_7_8);
1097 TEST_CLAUSE(21_4_7_9_a);
1098 TEST_CLAUSE(21_4_7_9_b);
1099 TEST_CLAUSE(21_4_7_9_c);
1100 TEST_CLAUSE(21_4_7_9_d);
1101 TEST_CLAUSE(21_4_7_9_e);
1102 TEST_CLAUSE(21_4_8_1_a);
1103 TEST_CLAUSE(21_4_8_1_b);
1104 TEST_CLAUSE(21_4_8_1_c);
1105 TEST_CLAUSE(21_4_8_1_d);
1106 TEST_CLAUSE(21_4_8_1_e);
1107 TEST_CLAUSE(21_4_8_1_f);
1108 TEST_CLAUSE(21_4_8_1_g);
1109 TEST_CLAUSE(21_4_8_1_h);
1110 TEST_CLAUSE(21_4_8_1_i);
1111 TEST_CLAUSE(21_4_8_1_j);
1112 TEST_CLAUSE(21_4_8_1_k);
1113 TEST_CLAUSE(21_4_8_1_l);
1114 TEST_CLAUSE(21_4_8_9_a);
1117 TEST(FBString, testGetline) {
1119 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
1120 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1121 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1122 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1123 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1124 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1125 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1126 tristique senectus et netus et malesuada fames ac turpis \n\
1127 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1128 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1129 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1130 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1131 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1132 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1133 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1134 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1135 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1136 char f[] = "/tmp/fbstring_testing.XXXXXX";
1137 int fd = mkstemp(f);
1138 EXPECT_TRUE(fd > 0);
1141 std::ofstream out(f);
1143 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1148 boost::split(v, s1, boost::is_any_of("\n"));
1153 EXPECT_TRUE(!getline(input, line).fail());
1154 EXPECT_EQ(line, *i);
1160 TEST(FBString, testMoveCtor) {
1161 // Move constructor. Make sure we allocate a large string, so the
1162 // small string optimization doesn't kick in.
1163 auto size = random(100, 2000);
1164 fbstring s(size, 'a');
1165 fbstring test = std::move(s);
1166 EXPECT_TRUE(s.empty());
1167 EXPECT_EQ(size, test.size());
1170 TEST(FBString, testMoveAssign) {
1171 // Move constructor. Make sure we allocate a large string, so the
1172 // small string optimization doesn't kick in.
1173 auto size = random(100, 2000);
1174 fbstring s(size, 'a');
1176 test = std::move(s);
1177 EXPECT_TRUE(s.empty());
1178 EXPECT_EQ(size, test.size());
1181 TEST(FBString, testMoveOperatorPlusLhs) {
1182 // Make sure we allocate a large string, so the
1183 // small string optimization doesn't kick in.
1184 auto size1 = random(100, 2000);
1185 auto size2 = random(100, 2000);
1186 fbstring s1(size1, 'a');
1187 fbstring s2(size2, 'b');
1189 test = std::move(s1) + s2;
1190 EXPECT_TRUE(s1.empty());
1191 EXPECT_EQ(size1 + size2, test.size());
1194 TEST(FBString, testMoveOperatorPlusRhs) {
1195 // Make sure we allocate a large string, so the
1196 // small string optimization doesn't kick in.
1197 auto size1 = random(100, 2000);
1198 auto size2 = random(100, 2000);
1199 fbstring s1(size1, 'a');
1200 fbstring s2(size2, 'b');
1202 test = s1 + std::move(s2);
1203 EXPECT_EQ(size1 + size2, test.size());
1206 // The GNU C++ standard library throws an std::logic_error when an std::string
1207 // is constructed with a null pointer. Verify that we mirror this behavior.
1209 // N.B. We behave this way even if the C++ library being used is something
1210 // other than libstdc++. Someday if we deem it important to present
1211 // identical undefined behavior for other platforms, we can re-visit this.
1212 TEST(FBString, testConstructionFromLiteralZero) {
1213 EXPECT_THROW(fbstring s(0), std::logic_error);
1216 TEST(FBString, testFixedBugs) {
1218 fbstring str(1337, 'f');
1222 EXPECT_EQ(str.front(), 'f');
1225 fbstring str(1337, 'f');
1226 for (int i = 0; i < 2; ++i) {
1229 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1235 fbstring str(1337, 'f');
1240 fbstring str(1337, 'f');
1246 folly::basic_fbstring<wchar_t> s;
1247 EXPECT_EQ(0, s.size());
1250 fbstring str(1337, 'f');
1251 std::swap(str, str);
1252 EXPECT_EQ(1337, str.size());
1254 { // D1012196, --allocator=malloc
1255 fbstring str(128, 'f');
1256 str.clear(); // Empty medium string.
1257 fbstring copy(str); // Medium string of 0 capacity.
1258 copy.push_back('b');
1259 EXPECT_GE(copy.capacity(), 1);
1263 TEST(FBString, findWithNpos) {
1264 fbstring fbstr("localhost:80");
1265 EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1268 TEST(FBString, testHash) {
1275 std::hash<fbstring> hashfunc;
1276 EXPECT_NE(hashfunc(a), hashfunc(b));
1279 TEST(FBString, testFrontBack) {
1280 fbstring str("hello");
1281 EXPECT_EQ(str.front(), 'h');
1282 EXPECT_EQ(str.back(), 'o');
1284 EXPECT_EQ(str.front(), 'H');
1286 EXPECT_EQ(str.back(), 'O');
1287 EXPECT_EQ(str, "HellO");
1290 TEST(FBString, noexcept) {
1291 EXPECT_TRUE(noexcept(fbstring()));
1293 EXPECT_FALSE(noexcept(fbstring(x)));
1294 EXPECT_TRUE(noexcept(fbstring(std::move(x))));
1296 EXPECT_FALSE(noexcept(y = x));
1297 EXPECT_TRUE(noexcept(y = std::move(x)));
1300 TEST(FBString, iomanip) {
1302 fbstring fbstr("Hello");
1304 ss << setw(6) << fbstr;
1305 EXPECT_EQ(ss.str(), " Hello");
1308 ss << left << setw(6) << fbstr;
1309 EXPECT_EQ(ss.str(), "Hello ");
1312 ss << right << setw(6) << fbstr;
1313 EXPECT_EQ(ss.str(), " Hello");
1316 ss << setw(4) << fbstr;
1317 EXPECT_EQ(ss.str(), "Hello");
1320 ss << setfill('^') << setw(6) << fbstr;
1321 EXPECT_EQ(ss.str(), "^Hello");
1325 TEST(FBString, rvalueIterators) {
1326 // you cannot take &* of a move-iterator, so use that for testing
1327 fbstring s = "base";
1328 fbstring r = "hello";
1329 r.replace(r.begin(), r.end(),
1330 make_move_iterator(s.begin()), make_move_iterator(s.end()));
1331 EXPECT_EQ("base", r);
1333 // The following test is probably not required by the standard.
1334 // i.e. this could be in the realm of undefined behavior.
1335 fbstring b = "123abcXYZ";
1336 auto ait = b.begin() + 3;
1337 auto Xit = b.begin() + 6;
1338 b.replace(ait, b.end(), b.begin(), Xit);
1339 EXPECT_EQ("123123abc", b); // if things go wrong, you'd get "123123123"
1342 TEST(FBString, moveTerminator) {
1343 // The source of a move must remain in a valid state
1344 fbstring s(100, 'x'); // too big to be in-situ
1348 EXPECT_EQ(0, s.size());
1349 EXPECT_EQ('\0', *s.c_str());
1352 int main(int argc, char** argv) {
1353 testing::InitGoogleTest(&argc, argv);
1354 gflags::ParseCommandLineFlags(&argc, &argv, true);
1355 return RUN_ALL_TESTS();