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>
28 #include <boost/algorithm/string.hpp>
29 #include <boost/random.hpp>
30 #include <gtest/gtest.h>
32 #include <gflags/gflags.h>
34 #include <folly/Foreach.h>
35 #include <folly/Portability.h>
36 #include <folly/Random.h>
37 #include <folly/Conv.h>
40 using namespace folly;
42 static const int seed = folly::randomNumberSeed();
43 typedef boost::mt19937 RandomT;
44 static RandomT rng(seed);
45 static const size_t maxString = 100;
46 static const bool avoidAliasing = true;
48 template <class Integral1, class Integral2>
49 Integral2 random(Integral1 low, Integral2 up) {
50 boost::uniform_int<> range(low, up);
54 template <class String>
55 void randomString(String* toFill, unsigned int maxSize = 1000) {
57 toFill->resize(random(0, maxSize));
58 FOR_EACH (i, *toFill) {
59 *i = random('a', 'z');
63 template <class String, class Integral>
64 void Num2String(String& str, Integral n) {
66 std::string tmp = folly::to<std::string>(n);
67 str = String(tmp.begin(), tmp.end());
70 std::list<char> RandomList(unsigned int maxSize) {
71 std::list<char> lst(random(0u, maxSize));
72 std::list<char>::iterator i = lst.begin();
73 for (; i != lst.end(); ++i) {
74 *i = random('a', 'z');
79 ////////////////////////////////////////////////////////////////////////////////
81 ////////////////////////////////////////////////////////////////////////////////
83 template <class String> void clause11_21_4_2_a(String & test) {
84 test.String::~String();
87 template <class String> void clause11_21_4_2_b(String & test) {
89 assert(test2 == test);
91 template <class String> void clause11_21_4_2_c(String & test) {
92 // Test move constructor. There is a more specialized test, see
93 // TEST(FBString, testMoveCtor)
95 String test2(std::move(donor));
96 EXPECT_EQ(test2, test);
97 // Technically not required, but all implementations that actually
98 // support move will move large strings. Make a guess for 128 as the
99 // maximum small string optimization that's reasonable.
100 EXPECT_LE(donor.size(), 128);
102 template <class String> void clause11_21_4_2_d(String & test) {
103 // Copy constructor with position and length
104 const size_t pos = random(0, test.size());
105 String s(test, pos, random(0, 9)
106 ? random(0, (size_t)(test.size() - pos))
107 : String::npos); // test for npos, too, in 10% of the cases
110 template <class String> void clause11_21_4_2_e(String & test) {
111 // Constructor from char*, size_t
113 pos = random(0, test.size()),
114 n = random(0, test.size() - pos);
115 String before(test.data(), test.size());
116 String s(test.c_str() + pos, n);
117 String after(test.data(), test.size());
118 EXPECT_EQ(before, after);
121 template <class String> void clause11_21_4_2_f(String & test) {
122 // Constructor from char*
123 const size_t pos = random(0, test.size());
124 String before(test.data(), test.size());
125 String s(test.c_str() + pos);
126 String after(test.data(), test.size());
127 EXPECT_EQ(before, after);
130 template <class String> void clause11_21_4_2_g(String & test) {
131 // Constructor from size_t, char
132 const size_t n = random(0, test.size());
133 const auto c = test.front();
136 template <class String> void clause11_21_4_2_h(String & test) {
137 // Constructors from various iterator pairs
138 // Constructor from char*, char*
139 String s1(test.begin(), test.end());
141 String s2(test.data(), test.data() + test.size());
143 // Constructor from other iterators
145 for (auto c : test) lst.push_back(c);
146 String s3(lst.begin(), lst.end());
148 // Constructor from wchar_t iterators
149 std::list<wchar_t> lst1;
150 for (auto c : test) lst1.push_back(c);
151 String s4(lst1.begin(), lst1.end());
153 // Constructor from wchar_t pointers
157 fbstring s5(t, t + 2);;
160 template <class String> void clause11_21_4_2_i(String & test) {
161 // From initializer_list<char>
162 std::initializer_list<typename String::value_type>
163 il = { 'h', 'e', 'l', 'l', 'o' };
167 template <class String> void clause11_21_4_2_j(String & test) {
168 // Assignment from const String&
169 auto size = random(0, 2000);
170 String s(size, '\0');
171 EXPECT_EQ(s.size(), size);
172 FOR_EACH_RANGE (i, 0, s.size()) {
173 s[i] = random('a', 'z');
177 template <class String> void clause11_21_4_2_k(String & test) {
178 // Assignment from String&&
179 auto size = random(0, 2000);
180 String s(size, '\0');
181 EXPECT_EQ(s.size(), size);
182 FOR_EACH_RANGE (i, 0, s.size()) {
183 s[i] = random('a', 'z');
186 if (typeid(String) == typeid(fbstring)) {
187 EXPECT_LE(s.size(), 128);
190 template <class String> void clause11_21_4_2_l(String & test) {
191 // Assignment from char*
192 String s(random(0, 1000), '\0');
194 for (; i != s.size(); ++i) {
195 s[i] = random('a', 'z');
199 template <class String> void clause11_21_4_2_lprime(String & test) {
201 const size_t pos = random(0, test.size());
203 test = String(test.c_str() + pos);
205 test = test.c_str() + pos;
208 template <class String> void clause11_21_4_2_m(String & test) {
209 // Assignment from char
210 test = random('a', 'z');
212 template <class String> void clause11_21_4_2_n(String & test) {
213 // Assignment from initializer_list<char>
214 initializer_list<typename String::value_type>
215 il = { 'h', 'e', 'l', 'l', 'o' };
219 template <class String> void clause11_21_4_3(String & test) {
220 // Iterators. The code below should leave test unchanged
221 EXPECT_EQ(test.size(), test.end() - test.begin());
222 EXPECT_EQ(test.size(), test.rend() - test.rbegin());
223 EXPECT_EQ(test.size(), test.cend() - test.cbegin());
224 EXPECT_EQ(test.size(), test.crend() - test.crbegin());
226 auto s = test.size();
227 test.resize(test.end() - test.begin());
228 EXPECT_EQ(s, test.size());
229 test.resize(test.rend() - test.rbegin());
230 EXPECT_EQ(s, test.size());
233 template <class String> void clause11_21_4_4(String & test) {
234 // exercise capacity, size, max_size
235 EXPECT_EQ(test.size(), test.length());
236 EXPECT_LE(test.size(), test.max_size());
237 EXPECT_LE(test.capacity(), test.max_size());
238 EXPECT_LE(test.size(), test.capacity());
240 // exercise shrink_to_fit. Nonbinding request so we can't really do
241 // much beyond calling it.
243 copy.reserve(copy.capacity() * 3);
244 copy.shrink_to_fit();
245 EXPECT_EQ(copy, test);
248 string empty("empty");
249 string notempty("not empty");
250 if (test.empty()) test = String(empty.begin(), empty.end());
251 else test = String(notempty.begin(), notempty.end());
254 template <class String> void clause11_21_4_5(String & test) {
255 // exercise element access
257 EXPECT_EQ(test[0], test.front());
258 EXPECT_EQ(test[test.size() - 1], test.back());
259 auto const i = random(0, test.size() - 1);
260 EXPECT_EQ(test[i], test.at(i));
265 template <class String> void clause11_21_4_6_1(String & test) {
266 // 21.3.5 modifiers (+=)
268 randomString(&test1);
269 assert(test1.size() == char_traits
270 <typename String::value_type>::length(test1.c_str()));
271 auto len = test.size();
273 EXPECT_EQ(test.size(), test1.size() + len);
274 FOR_EACH_RANGE (i, 0, test1.size()) {
275 EXPECT_EQ(test[len + i], test1[i]);
277 // aliasing modifiers
279 auto dt = test2.data();
280 auto sz = test.c_str();
282 EXPECT_EQ(memcmp(sz, dt, len), 0);
283 String copy(test.data(), test.size());
284 EXPECT_EQ(char_traits
285 <typename String::value_type>::length(test.c_str()), len);
288 EXPECT_EQ(test.size(), 2 * len);
289 EXPECT_EQ(char_traits
290 <typename String::value_type>::length(test.c_str()), 2 * len);
291 FOR_EACH_RANGE (i, 0, len) {
292 EXPECT_EQ(test[i], copy[i]);
293 EXPECT_EQ(test[i], test[len + i]);
296 EXPECT_EQ(char_traits
297 <typename String::value_type>::length(test.c_str()), len);
299 auto const pos = random(0, test.size());
300 EXPECT_EQ(char_traits
301 <typename String::value_type>::length(test.c_str() + pos), len - pos);
303 String addMe(test.c_str() + pos);
304 EXPECT_EQ(addMe.size(), len - pos);
307 test += test.c_str() + pos;
309 EXPECT_EQ(test.size(), 2 * len - pos);
312 test += random('a', 'z');
313 EXPECT_EQ(test.size(), len + 1);
315 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
319 template <class String> void clause11_21_4_6_2(String & test) {
320 // 21.3.5 modifiers (append, push_back)
323 // Test with a small string first
324 char c = random('a', 'z');
326 EXPECT_EQ(s[s.size() - 1], c);
327 EXPECT_EQ(s.size(), 1);
328 s.resize(s.size() - 1);
330 randomString(&s, maxString);
332 randomString(&s, maxString);
333 test.append(s, random(0, s.size()), random(0, maxString));
334 randomString(&s, maxString);
335 test.append(s.c_str(), random(0, s.size()));
336 randomString(&s, maxString);
337 test.append(s.c_str());
338 test.append(random(0, maxString), random('a', 'z'));
339 std::list<char> lst(RandomList(maxString));
340 test.append(lst.begin(), lst.end());
341 c = random('a', 'z');
343 EXPECT_EQ(test[test.size() - 1], c);
345 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
349 template <class String> void clause11_21_4_6_3_a(String & test) {
356 test.assign(std::move(s));
357 if (typeid(String) == typeid(fbstring)) {
358 EXPECT_LE(s.size(), 128);
362 template <class String> void clause11_21_4_6_3_b(String & test) {
365 randomString(&s, maxString);
366 test.assign(s, random(0, s.size()), random(0, maxString));
369 template <class String> void clause11_21_4_6_3_c(String & test) {
372 randomString(&s, maxString);
373 test.assign(s.c_str(), random(0, s.size()));
376 template <class String> void clause11_21_4_6_3_d(String & test) {
379 randomString(&s, maxString);
380 test.assign(s.c_str());
383 template <class String> void clause11_21_4_6_3_e(String & test) {
386 randomString(&s, maxString);
387 test.assign(random(0, maxString), random('a', 'z'));
390 template <class String> void clause11_21_4_6_3_f(String & test) {
391 // assign from bidirectional iterator
392 std::list<char> lst(RandomList(maxString));
393 test.assign(lst.begin(), lst.end());
396 template <class String> void clause11_21_4_6_3_g(String & test) {
397 // assign from aliased source
401 template <class String> void clause11_21_4_6_3_h(String & test) {
402 // assign from aliased source
403 test.assign(test, random(0, test.size()), random(0, maxString));
406 template <class String> void clause11_21_4_6_3_i(String & test) {
407 // assign from aliased source
408 test.assign(test.c_str(), random(0, test.size()));
411 template <class String> void clause11_21_4_6_3_j(String & test) {
412 // assign from aliased source
413 test.assign(test.c_str());
416 template <class String> void clause11_21_4_6_3_k(String & test) {
417 // assign from initializer_list
418 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
422 template <class String> void clause11_21_4_6_4(String & test) {
425 randomString(&s, maxString);
426 test.insert(random(0, test.size()), s);
427 randomString(&s, maxString);
428 test.insert(random(0, test.size()),
429 s, random(0, s.size()),
430 random(0, maxString));
431 randomString(&s, maxString);
432 test.insert(random(0, test.size()),
433 s.c_str(), random(0, s.size()));
434 randomString(&s, maxString);
435 test.insert(random(0, test.size()), s.c_str());
436 test.insert(random(0, test.size()),
437 random(0, maxString), random('a', 'z'));
438 typename String::size_type pos = random(0, test.size());
439 typename String::iterator res =
440 test.insert(test.begin() + pos, random('a', 'z'));
441 EXPECT_EQ(res - test.begin(), pos);
442 std::list<char> lst(RandomList(maxString));
443 pos = random(0, test.size());
444 // Uncomment below to see a bug in gcc
445 /*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
446 // insert from initializer_list
447 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
448 pos = random(0, test.size());
449 // Uncomment below to see a bug in gcc
450 /*res = */test.insert(test.begin() + pos, il);
452 // Test with actual input iterators
454 ss << "hello cruel world";
455 auto i = istream_iterator<char>(ss);
456 test.insert(test.begin(), i, istream_iterator<char>());
459 template <class String> void clause11_21_4_6_5(String & test) {
460 // erase and pop_back
462 test.erase(random(0, test.size()), random(0, maxString));
465 // TODO: is erase(end()) allowed?
466 test.erase(test.begin() + random(0, test.size() - 1));
469 auto const i = test.begin() + random(0, test.size());
470 if (i != test.end()) {
471 test.erase(i, i + random(0, size_t(test.end() - i)));
475 // Can't test pop_back with std::string, doesn't support it yet.
480 template <class String> void clause11_21_4_6_6(String & test) {
481 auto pos = random(0, test.size());
483 test.replace(pos, random(0, test.size() - pos),
486 test.replace(pos, random(0, test.size() - pos), test);
488 pos = random(0, test.size());
490 randomString(&s, maxString);
491 test.replace(pos, pos + random(0, test.size() - pos), s);
492 auto pos1 = random(0, test.size());
493 auto pos2 = random(0, test.size());
495 test.replace(pos1, pos1 + random(0, test.size() - pos1),
497 pos2, pos2 + random(0, test.size() - pos2));
499 test.replace(pos1, pos1 + random(0, test.size() - pos1),
500 test, pos2, pos2 + random(0, test.size() - pos2));
502 pos1 = random(0, test.size());
504 randomString(&str, maxString);
505 pos2 = random(0, str.size());
506 test.replace(pos1, pos1 + random(0, test.size() - pos1),
507 str, pos2, pos2 + random(0, str.size() - pos2));
508 pos = random(0, test.size());
510 test.replace(pos, random(0, test.size() - pos),
511 String(test).c_str(), test.size());
513 test.replace(pos, random(0, test.size() - pos),
514 test.c_str(), test.size());
516 pos = random(0, test.size());
517 randomString(&str, maxString);
518 test.replace(pos, pos + random(0, test.size() - pos),
519 str.c_str(), str.size());
520 pos = random(0, test.size());
521 randomString(&str, maxString);
522 test.replace(pos, pos + random(0, test.size() - pos),
524 pos = random(0, test.size());
525 test.replace(pos, random(0, test.size() - pos),
526 random(0, maxString), random('a', 'z'));
527 pos = random(0, test.size());
529 auto newString = String(test);
532 test.begin() + pos + random(0, test.size() - pos),
537 test.begin() + pos + random(0, test.size() - pos),
540 pos = random(0, test.size());
542 auto newString = String(test);
545 test.begin() + pos + random(0, test.size() - pos),
547 test.size() - random(0, test.size()));
551 test.begin() + pos + random(0, test.size() - pos),
553 test.size() - random(0, test.size()));
555 pos = random(0, test.size());
556 auto const n = random(0, test.size() - pos);
557 typename String::iterator b = test.begin();
559 randomString(&str1, maxString);
560 const String & str3 = str1;
561 const typename String::value_type* ss = str3.c_str();
566 pos = random(0, test.size());
569 test.begin() + pos + random(0, test.size() - pos),
570 random(0, maxString), random('a', 'z'));
573 template <class String> void clause11_21_4_6_7(String & test) {
574 std::vector<typename String::value_type>
575 vec(random(0, maxString));
579 random(0, test.size()));
582 template <class String> void clause11_21_4_6_8(String & test) {
584 randomString(&s, maxString);
588 template <class String> void clause11_21_4_7_1(String & test) {
589 // 21.3.6 string operations
590 // exercise c_str() and data()
591 assert(test.c_str() == test.data());
592 // exercise get_allocator()
594 randomString(&s, maxString);
595 assert(test.get_allocator() == s.get_allocator());
598 template <class String> void clause11_21_4_7_2_a(String & test) {
599 String str = test.substr(
600 random(0, test.size()),
601 random(0, test.size()));
602 Num2String(test, test.find(str, random(0, test.size())));
605 template <class String> void clause11_21_4_7_2_a1(String & test) {
606 String str = String(test).substr(
607 random(0, test.size()),
608 random(0, test.size()));
609 Num2String(test, test.find(str, random(0, test.size())));
612 template <class String> void clause11_21_4_7_2_a2(String & test) {
613 auto const& cTest = test;
614 String str = cTest.substr(
615 random(0, test.size()),
616 random(0, test.size()));
617 Num2String(test, test.find(str, random(0, test.size())));
620 template <class String> void clause11_21_4_7_2_b(String & test) {
621 auto from = random(0, test.size());
622 auto length = random(0, test.size() - from);
623 String str = test.substr(from, length);
624 Num2String(test, test.find(str.c_str(),
625 random(0, test.size()),
626 random(0, str.size())));
629 template <class String> void clause11_21_4_7_2_b1(String & test) {
630 auto from = random(0, test.size());
631 auto length = random(0, test.size() - from);
632 String str = String(test).substr(from, length);
633 Num2String(test, test.find(str.c_str(),
634 random(0, test.size()),
635 random(0, str.size())));
638 template <class String> void clause11_21_4_7_2_b2(String & test) {
639 auto from = random(0, test.size());
640 auto length = random(0, test.size() - from);
641 const auto& cTest = test;
642 String str = cTest.substr(from, length);
643 Num2String(test, test.find(str.c_str(),
644 random(0, test.size()),
645 random(0, str.size())));
648 template <class String> void clause11_21_4_7_2_c(String & test) {
649 String str = test.substr(
650 random(0, test.size()),
651 random(0, test.size()));
652 Num2String(test, test.find(str.c_str(),
653 random(0, test.size())));
656 template <class String> void clause11_21_4_7_2_c1(String & test) {
657 String str = String(test).substr(
658 random(0, test.size()),
659 random(0, test.size()));
660 Num2String(test, test.find(str.c_str(),
661 random(0, test.size())));
664 template <class String> void clause11_21_4_7_2_c2(String & test) {
665 const auto& cTest = test;
666 String str = cTest.substr(
667 random(0, test.size()),
668 random(0, test.size()));
669 Num2String(test, test.find(str.c_str(),
670 random(0, test.size())));
673 template <class String> void clause11_21_4_7_2_d(String & test) {
674 Num2String(test, test.find(
676 random(0, test.size())));
679 template <class String> void clause11_21_4_7_3_a(String & test) {
680 String str = test.substr(
681 random(0, test.size()),
682 random(0, test.size()));
683 Num2String(test, test.rfind(str, random(0, test.size())));
686 template <class String> void clause11_21_4_7_3_b(String & test) {
687 String str = test.substr(
688 random(0, test.size()),
689 random(0, test.size()));
690 Num2String(test, test.rfind(str.c_str(),
691 random(0, test.size()),
692 random(0, str.size())));
695 template <class String> void clause11_21_4_7_3_c(String & test) {
696 String str = test.substr(
697 random(0, test.size()),
698 random(0, test.size()));
699 Num2String(test, test.rfind(str.c_str(),
700 random(0, test.size())));
703 template <class String> void clause11_21_4_7_3_d(String & test) {
704 Num2String(test, test.rfind(
706 random(0, test.size())));
709 template <class String> void clause11_21_4_7_4_a(String & test) {
711 randomString(&str, maxString);
712 Num2String(test, test.find_first_of(str,
713 random(0, test.size())));
716 template <class String> void clause11_21_4_7_4_b(String & test) {
718 randomString(&str, maxString);
719 Num2String(test, test.find_first_of(str.c_str(),
720 random(0, test.size()),
721 random(0, str.size())));
724 template <class String> void clause11_21_4_7_4_c(String & test) {
726 randomString(&str, maxString);
727 Num2String(test, test.find_first_of(str.c_str(),
728 random(0, test.size())));
731 template <class String> void clause11_21_4_7_4_d(String & test) {
732 Num2String(test, test.find_first_of(
734 random(0, test.size())));
737 template <class String> void clause11_21_4_7_5_a(String & test) {
739 randomString(&str, maxString);
740 Num2String(test, test.find_last_of(str,
741 random(0, test.size())));
744 template <class String> void clause11_21_4_7_5_b(String & test) {
746 randomString(&str, maxString);
747 Num2String(test, test.find_last_of(str.c_str(),
748 random(0, test.size()),
749 random(0, str.size())));
752 template <class String> void clause11_21_4_7_5_c(String & test) {
754 randomString(&str, maxString);
755 Num2String(test, test.find_last_of(str.c_str(),
756 random(0, test.size())));
759 template <class String> void clause11_21_4_7_5_d(String & test) {
760 Num2String(test, test.find_last_of(
762 random(0, test.size())));
765 template <class String> void clause11_21_4_7_6_a(String & test) {
767 randomString(&str, maxString);
768 Num2String(test, test.find_first_not_of(str,
769 random(0, test.size())));
772 template <class String> void clause11_21_4_7_6_b(String & test) {
774 randomString(&str, maxString);
775 Num2String(test, test.find_first_not_of(str.c_str(),
776 random(0, test.size()),
777 random(0, str.size())));
780 template <class String> void clause11_21_4_7_6_c(String & test) {
782 randomString(&str, maxString);
783 Num2String(test, test.find_first_not_of(str.c_str(),
784 random(0, test.size())));
787 template <class String> void clause11_21_4_7_6_d(String & test) {
788 Num2String(test, test.find_first_not_of(
790 random(0, test.size())));
793 template <class String> void clause11_21_4_7_7_a(String & test) {
795 randomString(&str, maxString);
796 Num2String(test, test.find_last_not_of(str,
797 random(0, test.size())));
800 template <class String> void clause11_21_4_7_7_b(String & test) {
802 randomString(&str, maxString);
803 Num2String(test, test.find_last_not_of(str.c_str(),
804 random(0, test.size()),
805 random(0, str.size())));
808 template <class String> void clause11_21_4_7_7_c(String & test) {
810 randomString(&str, maxString);
811 Num2String(test, test.find_last_not_of(str.c_str(),
812 random(0, test.size())));
815 template <class String> void clause11_21_4_7_7_d(String & test) {
816 Num2String(test, test.find_last_not_of(
818 random(0, test.size())));
821 template <class String> void clause11_21_4_7_8(String & test) {
822 test = test.substr(random(0, test.size()), random(0, test.size()));
825 template <class String> void clause11_21_4_7_9_a(String & test) {
827 randomString(&s, maxString);
828 int tristate = test.compare(s);
829 if (tristate > 0) tristate = 1;
830 else if (tristate < 0) tristate = 2;
831 Num2String(test, tristate);
834 template <class String> void clause11_21_4_7_9_b(String & test) {
836 randomString(&s, maxString);
837 int tristate = test.compare(
838 random(0, test.size()),
839 random(0, test.size()),
841 if (tristate > 0) tristate = 1;
842 else if (tristate < 0) tristate = 2;
843 Num2String(test, tristate);
846 template <class String> void clause11_21_4_7_9_c(String & test) {
848 randomString(&str, maxString);
849 int tristate = test.compare(
850 random(0, test.size()),
851 random(0, test.size()),
853 random(0, str.size()),
854 random(0, str.size()));
855 if (tristate > 0) tristate = 1;
856 else if (tristate < 0) tristate = 2;
857 Num2String(test, tristate);
860 template <class String> void clause11_21_4_7_9_d(String & test) {
862 randomString(&s, maxString);
863 int tristate = test.compare(s.c_str());
864 if (tristate > 0) tristate = 1;
865 else if (tristate < 0) tristate = 2;
866 Num2String(test, tristate);
869 template <class String> void clause11_21_4_7_9_e(String & test) {
871 randomString(&str, maxString);
872 int tristate = test.compare(
873 random(0, test.size()),
874 random(0, test.size()),
876 random(0, str.size()));
877 if (tristate > 0) tristate = 1;
878 else if (tristate < 0) tristate = 2;
879 Num2String(test, tristate);
882 template <class String> void clause11_21_4_8_1_a(String & test) {
884 randomString(&s1, maxString);
886 randomString(&s2, maxString);
890 template <class String> void clause11_21_4_8_1_b(String & test) {
892 randomString(&s1, maxString);
894 randomString(&s2, maxString);
895 test = move(s1) + s2;
898 template <class String> void clause11_21_4_8_1_c(String & test) {
900 randomString(&s1, maxString);
902 randomString(&s2, maxString);
903 test = s1 + move(s2);
906 template <class String> void clause11_21_4_8_1_d(String & test) {
908 randomString(&s1, maxString);
910 randomString(&s2, maxString);
911 test = move(s1) + move(s2);
914 template <class String> void clause11_21_4_8_1_e(String & test) {
916 randomString(&s, maxString);
918 randomString(&s1, maxString);
919 test = s.c_str() + s1;
922 template <class String> void clause11_21_4_8_1_f(String & test) {
924 randomString(&s, maxString);
926 randomString(&s1, maxString);
927 test = s.c_str() + move(s1);
930 template <class String> void clause11_21_4_8_1_g(String & test) {
932 randomString(&s, maxString);
933 test = typename String::value_type(random('a', 'z')) + s;
936 template <class String> void clause11_21_4_8_1_h(String & test) {
938 randomString(&s, maxString);
939 test = typename String::value_type(random('a', 'z')) + move(s);
942 template <class String> void clause11_21_4_8_1_i(String & test) {
944 randomString(&s, maxString);
946 randomString(&s1, maxString);
947 test = s + s1.c_str();
950 template <class String> void clause11_21_4_8_1_j(String & test) {
952 randomString(&s, maxString);
954 randomString(&s1, maxString);
955 test = move(s) + s1.c_str();
958 template <class String> void clause11_21_4_8_1_k(String & test) {
960 randomString(&s, maxString);
961 test = s + typename String::value_type(random('a', 'z'));
964 template <class String> void clause11_21_4_8_1_l(String & test) {
966 randomString(&s, maxString);
968 randomString(&s1, maxString);
969 test = move(s) + s1.c_str();
972 // Numbering here is from C++11
973 template <class String> void clause11_21_4_8_9_a(String & test) {
974 basic_stringstream<typename String::value_type> stst(test.c_str());
982 TEST(FBString, testAllClauses) {
983 EXPECT_TRUE(1) << "Starting with seed: " << seed;
987 folly::basic_fbstring<wchar_t> wc;
990 auto l = [&](const char * const clause,
991 void(*f_string)(std::string&),
992 void(*f_fbstring)(folly::fbstring&),
993 void(*f_wfbstring)(folly::basic_fbstring<wchar_t>&)) {
995 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << clause;
999 wr = std::wstring(r.begin(), r.end());
1000 wc = folly::basic_fbstring<wchar_t>(wr.c_str());
1001 auto localSeed = seed + count;
1002 rng = RandomT(localSeed);
1004 rng = RandomT(localSeed);
1007 << "Lengths: " << r.size() << " vs. " << c.size()
1008 << "\nReference: '" << r << "'"
1009 << "\nActual: '" << c.data()[0] << "'";
1010 rng = RandomT(localSeed);
1012 int wret = wcslen(wc.c_str());
1014 int ret = wcstombs(mb, wc.c_str(), sizeof(mb));
1015 if (ret == wret) mb[wret] = '\0';
1016 const char *mc = c.c_str();
1017 std::string one(mb);
1018 std::string two(mc);
1019 EXPECT_EQ(one, two);
1020 } while (++count % 100 != 0);
1023 #define TEST_CLAUSE(x) \
1025 clause11_##x<std::string>, \
1026 clause11_##x<folly::fbstring>, \
1027 clause11_##x<folly::basic_fbstring<wchar_t>>);
1029 TEST_CLAUSE(21_4_2_a);
1030 TEST_CLAUSE(21_4_2_b);
1031 TEST_CLAUSE(21_4_2_c);
1032 TEST_CLAUSE(21_4_2_d);
1033 TEST_CLAUSE(21_4_2_e);
1034 TEST_CLAUSE(21_4_2_f);
1035 TEST_CLAUSE(21_4_2_g);
1036 TEST_CLAUSE(21_4_2_h);
1037 TEST_CLAUSE(21_4_2_i);
1038 TEST_CLAUSE(21_4_2_j);
1039 TEST_CLAUSE(21_4_2_k);
1040 TEST_CLAUSE(21_4_2_l);
1041 TEST_CLAUSE(21_4_2_lprime);
1042 TEST_CLAUSE(21_4_2_m);
1043 TEST_CLAUSE(21_4_2_n);
1044 TEST_CLAUSE(21_4_3);
1045 TEST_CLAUSE(21_4_4);
1046 TEST_CLAUSE(21_4_5);
1047 TEST_CLAUSE(21_4_6_1);
1048 TEST_CLAUSE(21_4_6_2);
1049 TEST_CLAUSE(21_4_6_3_a);
1050 TEST_CLAUSE(21_4_6_3_b);
1051 TEST_CLAUSE(21_4_6_3_c);
1052 TEST_CLAUSE(21_4_6_3_d);
1053 TEST_CLAUSE(21_4_6_3_e);
1054 TEST_CLAUSE(21_4_6_3_f);
1055 TEST_CLAUSE(21_4_6_3_g);
1056 TEST_CLAUSE(21_4_6_3_h);
1057 TEST_CLAUSE(21_4_6_3_i);
1058 TEST_CLAUSE(21_4_6_3_j);
1059 TEST_CLAUSE(21_4_6_3_k);
1060 TEST_CLAUSE(21_4_6_4);
1061 TEST_CLAUSE(21_4_6_5);
1062 TEST_CLAUSE(21_4_6_6);
1063 TEST_CLAUSE(21_4_6_7);
1064 TEST_CLAUSE(21_4_6_8);
1065 TEST_CLAUSE(21_4_7_1);
1067 TEST_CLAUSE(21_4_7_2_a);
1068 TEST_CLAUSE(21_4_7_2_a1);
1069 TEST_CLAUSE(21_4_7_2_a2);
1070 TEST_CLAUSE(21_4_7_2_b);
1071 TEST_CLAUSE(21_4_7_2_b1);
1072 TEST_CLAUSE(21_4_7_2_b2);
1073 TEST_CLAUSE(21_4_7_2_c);
1074 TEST_CLAUSE(21_4_7_2_c1);
1075 TEST_CLAUSE(21_4_7_2_c2);
1076 TEST_CLAUSE(21_4_7_2_d);
1077 TEST_CLAUSE(21_4_7_3_a);
1078 TEST_CLAUSE(21_4_7_3_b);
1079 TEST_CLAUSE(21_4_7_3_c);
1080 TEST_CLAUSE(21_4_7_3_d);
1081 TEST_CLAUSE(21_4_7_4_a);
1082 TEST_CLAUSE(21_4_7_4_b);
1083 TEST_CLAUSE(21_4_7_4_c);
1084 TEST_CLAUSE(21_4_7_4_d);
1085 TEST_CLAUSE(21_4_7_5_a);
1086 TEST_CLAUSE(21_4_7_5_b);
1087 TEST_CLAUSE(21_4_7_5_c);
1088 TEST_CLAUSE(21_4_7_5_d);
1089 TEST_CLAUSE(21_4_7_6_a);
1090 TEST_CLAUSE(21_4_7_6_b);
1091 TEST_CLAUSE(21_4_7_6_c);
1092 TEST_CLAUSE(21_4_7_6_d);
1093 TEST_CLAUSE(21_4_7_7_a);
1094 TEST_CLAUSE(21_4_7_7_b);
1095 TEST_CLAUSE(21_4_7_7_c);
1096 TEST_CLAUSE(21_4_7_7_d);
1097 TEST_CLAUSE(21_4_7_8);
1098 TEST_CLAUSE(21_4_7_9_a);
1099 TEST_CLAUSE(21_4_7_9_b);
1100 TEST_CLAUSE(21_4_7_9_c);
1101 TEST_CLAUSE(21_4_7_9_d);
1102 TEST_CLAUSE(21_4_7_9_e);
1103 TEST_CLAUSE(21_4_8_1_a);
1104 TEST_CLAUSE(21_4_8_1_b);
1105 TEST_CLAUSE(21_4_8_1_c);
1106 TEST_CLAUSE(21_4_8_1_d);
1107 TEST_CLAUSE(21_4_8_1_e);
1108 TEST_CLAUSE(21_4_8_1_f);
1109 TEST_CLAUSE(21_4_8_1_g);
1110 TEST_CLAUSE(21_4_8_1_h);
1111 TEST_CLAUSE(21_4_8_1_i);
1112 TEST_CLAUSE(21_4_8_1_j);
1113 TEST_CLAUSE(21_4_8_1_k);
1114 TEST_CLAUSE(21_4_8_1_l);
1115 TEST_CLAUSE(21_4_8_9_a);
1118 TEST(FBString, testGetline) {
1120 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
1121 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1122 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1123 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1124 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1125 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1126 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1127 tristique senectus et netus et malesuada fames ac turpis \n\
1128 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1129 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1130 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1131 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1132 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1133 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1134 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1135 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1136 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1137 char f[] = "/tmp/fbstring_testing.XXXXXX";
1138 int fd = mkstemp(f);
1139 EXPECT_TRUE(fd > 0);
1142 std::ofstream out(f);
1144 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1149 boost::split(v, s1, boost::is_any_of("\n"));
1154 EXPECT_TRUE(!getline(input, line).fail());
1155 EXPECT_EQ(line, *i);
1161 TEST(FBString, testMoveCtor) {
1162 // Move constructor. Make sure we allocate a large string, so the
1163 // small string optimization doesn't kick in.
1164 auto size = random(100, 2000);
1165 fbstring s(size, 'a');
1166 fbstring test = std::move(s);
1167 EXPECT_TRUE(s.empty());
1168 EXPECT_EQ(size, test.size());
1171 TEST(FBString, testMoveAssign) {
1172 // Move constructor. Make sure we allocate a large string, so the
1173 // small string optimization doesn't kick in.
1174 auto size = random(100, 2000);
1175 fbstring s(size, 'a');
1177 test = std::move(s);
1178 EXPECT_TRUE(s.empty());
1179 EXPECT_EQ(size, test.size());
1182 TEST(FBString, testMoveOperatorPlusLhs) {
1183 // Make sure we allocate a large string, so the
1184 // small string optimization doesn't kick in.
1185 auto size1 = random(100, 2000);
1186 auto size2 = random(100, 2000);
1187 fbstring s1(size1, 'a');
1188 fbstring s2(size2, 'b');
1190 test = std::move(s1) + s2;
1191 EXPECT_TRUE(s1.empty());
1192 EXPECT_EQ(size1 + size2, test.size());
1195 TEST(FBString, testMoveOperatorPlusRhs) {
1196 // Make sure we allocate a large string, so the
1197 // small string optimization doesn't kick in.
1198 auto size1 = random(100, 2000);
1199 auto size2 = random(100, 2000);
1200 fbstring s1(size1, 'a');
1201 fbstring s2(size2, 'b');
1203 test = s1 + std::move(s2);
1204 EXPECT_EQ(size1 + size2, test.size());
1207 // The GNU C++ standard library throws an std::logic_error when an std::string
1208 // is constructed with a null pointer. Verify that we mirror this behavior.
1210 // N.B. We behave this way even if the C++ library being used is something
1211 // other than libstdc++. Someday if we deem it important to present
1212 // identical undefined behavior for other platforms, we can re-visit this.
1213 TEST(FBString, testConstructionFromLiteralZero) {
1214 EXPECT_THROW(fbstring s(0), std::logic_error);
1217 TEST(FBString, testFixedBugs) {
1219 fbstring str(1337, 'f');
1223 EXPECT_EQ(str.front(), 'f');
1226 fbstring str(1337, 'f');
1227 for (int i = 0; i < 2; ++i) {
1230 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1236 fbstring str(1337, 'f');
1241 fbstring str(1337, 'f');
1247 folly::basic_fbstring<wchar_t> s;
1248 EXPECT_EQ(0, s.size());
1251 fbstring str(1337, 'f');
1252 std::swap(str, str);
1253 EXPECT_EQ(1337, str.size());
1255 { // D1012196, --allocator=malloc
1256 fbstring str(128, 'f');
1257 str.clear(); // Empty medium string.
1258 fbstring copy(str); // Medium string of 0 capacity.
1259 copy.push_back('b');
1260 EXPECT_GE(copy.capacity(), 1);
1264 TEST(FBString, findWithNpos) {
1265 fbstring fbstr("localhost:80");
1266 EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1269 TEST(FBString, testHash) {
1276 std::hash<fbstring> hashfunc;
1277 EXPECT_NE(hashfunc(a), hashfunc(b));
1280 TEST(FBString, testFrontBack) {
1281 fbstring str("hello");
1282 EXPECT_EQ(str.front(), 'h');
1283 EXPECT_EQ(str.back(), 'o');
1285 EXPECT_EQ(str.front(), 'H');
1287 EXPECT_EQ(str.back(), 'O');
1288 EXPECT_EQ(str, "HellO");
1291 TEST(FBString, noexcept) {
1292 EXPECT_TRUE(noexcept(fbstring()));
1294 EXPECT_FALSE(noexcept(fbstring(x)));
1295 EXPECT_TRUE(noexcept(fbstring(std::move(x))));
1297 EXPECT_FALSE(noexcept(y = x));
1298 EXPECT_TRUE(noexcept(y = std::move(x)));
1301 TEST(FBString, iomanip) {
1303 fbstring fbstr("Hello");
1305 ss << setw(6) << fbstr;
1306 EXPECT_EQ(ss.str(), " Hello");
1309 ss << left << setw(6) << fbstr;
1310 EXPECT_EQ(ss.str(), "Hello ");
1313 ss << right << setw(6) << fbstr;
1314 EXPECT_EQ(ss.str(), " Hello");
1317 ss << setw(4) << fbstr;
1318 EXPECT_EQ(ss.str(), "Hello");
1321 ss << setfill('^') << setw(6) << fbstr;
1322 EXPECT_EQ(ss.str(), "^Hello");
1326 TEST(FBString, rvalueIterators) {
1327 // you cannot take &* of a move-iterator, so use that for testing
1328 fbstring s = "base";
1329 fbstring r = "hello";
1330 r.replace(r.begin(), r.end(),
1331 make_move_iterator(s.begin()), make_move_iterator(s.end()));
1332 EXPECT_EQ("base", r);
1334 // The following test is probably not required by the standard.
1335 // i.e. this could be in the realm of undefined behavior.
1336 fbstring b = "123abcXYZ";
1337 auto ait = b.begin() + 3;
1338 auto Xit = b.begin() + 6;
1339 b.replace(ait, b.end(), b.begin(), Xit);
1340 EXPECT_EQ("123123abc", b); // if things go wrong, you'd get "123123123"
1343 TEST(FBString, moveTerminator) {
1344 // The source of a move must remain in a valid state
1345 fbstring s(100, 'x'); // too big to be in-situ
1349 EXPECT_EQ(0, s.size());
1350 EXPECT_EQ('\0', *s.c_str());
1355 * t8968589: Clang 3.7 refused to compile w/ certain constructors (specifically
1356 * those that were "explicit" and had a defaulted parameter, if they were used
1357 * in structs which were default-initialized). Exercise these just to ensure
1360 * In diff D2632953 the old constructor:
1361 * explicit basic_fbstring(const A& a = A()) noexcept;
1363 * was split into these two, as a workaround:
1364 * basic_fbstring() noexcept;
1365 * explicit basic_fbstring(const A& a) noexcept;
1368 struct TestStructDefaultAllocator {
1369 folly::basic_fbstring<char> stringMember;
1373 struct TestStructWithAllocator {
1374 folly::basic_fbstring<char, std::char_traits<char>, A> stringMember;
1377 std::atomic<size_t> allocatorConstructedCount(0);
1378 struct TestStructStringAllocator : std::allocator<char> {
1379 TestStructStringAllocator() {
1380 ++ allocatorConstructedCount;
1386 TEST(FBStringCtorTest, DefaultInitStructDefaultAlloc) {
1387 TestStructDefaultAllocator t1 { };
1388 EXPECT_TRUE(t1.stringMember.empty());
1391 TEST(FBStringCtorTest, DefaultInitStructAlloc) {
1392 EXPECT_EQ(allocatorConstructedCount.load(), 0);
1393 TestStructWithAllocator<TestStructStringAllocator> t2;
1394 EXPECT_TRUE(t2.stringMember.empty());
1395 EXPECT_EQ(allocatorConstructedCount.load(), 1);
1398 int main(int argc, char** argv) {
1399 testing::InitGoogleTest(&argc, argv);
1400 gflags::ParseCommandLineFlags(&argc, &argv, true);
1401 return RUN_ALL_TESTS();