2 * Copyright 2014 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*
123 pos = random(0, test.size()),
124 n = random(0, test.size() - pos);
125 String before(test.data(), test.size());
126 String s(test.c_str() + pos);
127 String after(test.data(), test.size());
128 EXPECT_EQ(before, after);
131 template <class String> void clause11_21_4_2_g(String & test) {
132 // Constructor from size_t, char
133 const size_t n = random(0, test.size());
134 const auto c = test.front();
137 template <class String> void clause11_21_4_2_h(String & test) {
138 // Constructors from various iterator pairs
139 // Constructor from char*, char*
140 String s1(test.begin(), test.end());
142 String s2(test.data(), test.data() + test.size());
144 // Constructor from other iterators
146 for (auto c : test) lst.push_back(c);
147 String s3(lst.begin(), lst.end());
149 // Constructor from wchar_t iterators
150 std::list<wchar_t> lst1;
151 for (auto c : test) lst1.push_back(c);
152 String s4(lst1.begin(), lst1.end());
154 // Constructor from wchar_t pointers
158 fbstring s5(t, t + 2);;
161 template <class String> void clause11_21_4_2_i(String & test) {
162 // From initializer_list<char>
163 std::initializer_list<typename String::value_type>
164 il = { 'h', 'e', 'l', 'l', 'o' };
168 template <class String> void clause11_21_4_2_j(String & test) {
169 // Assignment from const String&
170 auto size = random(0, 2000);
171 String s(size, '\0');
172 EXPECT_EQ(s.size(), size);
173 FOR_EACH_RANGE (i, 0, s.size()) {
174 s[i] = random('a', 'z');
178 template <class String> void clause11_21_4_2_k(String & test) {
179 // Assignment from String&&
180 auto size = random(0, 2000);
181 String s(size, '\0');
182 EXPECT_EQ(s.size(), size);
183 FOR_EACH_RANGE (i, 0, s.size()) {
184 s[i] = random('a', 'z');
187 if (typeid(String) == typeid(fbstring)) {
188 EXPECT_LE(s.size(), 128);
191 template <class String> void clause11_21_4_2_l(String & test) {
192 // Assignment from char*
193 String s(random(0, 1000), '\0');
195 for (; i != s.size(); ++i) {
196 s[i] = random('a', 'z');
200 template <class String> void clause11_21_4_2_lprime(String & test) {
202 const size_t pos = random(0, test.size());
204 test = String(test.c_str() + pos);
206 test = test.c_str() + pos;
209 template <class String> void clause11_21_4_2_m(String & test) {
210 // Assignment from char
211 test = random('a', 'z');
213 template <class String> void clause11_21_4_2_n(String & test) {
214 // Assignment from initializer_list<char>
215 initializer_list<typename String::value_type>
216 il = { 'h', 'e', 'l', 'l', 'o' };
220 template <class String> void clause11_21_4_3(String & test) {
221 // Iterators. The code below should leave test unchanged
222 EXPECT_EQ(test.size(), test.end() - test.begin());
223 EXPECT_EQ(test.size(), test.rend() - test.rbegin());
224 EXPECT_EQ(test.size(), test.cend() - test.cbegin());
225 EXPECT_EQ(test.size(), test.crend() - test.crbegin());
227 auto s = test.size();
228 test.resize(test.end() - test.begin());
229 EXPECT_EQ(s, test.size());
230 test.resize(test.rend() - test.rbegin());
231 EXPECT_EQ(s, test.size());
234 template <class String> void clause11_21_4_4(String & test) {
235 // exercise capacity, size, max_size
236 EXPECT_EQ(test.size(), test.length());
237 EXPECT_LE(test.size(), test.max_size());
238 EXPECT_LE(test.capacity(), test.max_size());
239 EXPECT_LE(test.size(), test.capacity());
241 // exercise shrink_to_fit. Nonbinding request so we can't really do
242 // much beyond calling it.
244 copy.reserve(copy.capacity() * 3);
245 copy.shrink_to_fit();
246 EXPECT_EQ(copy, test);
249 string empty("empty");
250 string notempty("not empty");
251 if (test.empty()) test = String(empty.begin(), empty.end());
252 else test = String(notempty.begin(), notempty.end());
255 template <class String> void clause11_21_4_5(String & test) {
256 // exercise element access
258 EXPECT_EQ(test[0], test.front());
259 EXPECT_EQ(test[test.size() - 1], test.back());
260 auto const i = random(0, test.size() - 1);
261 EXPECT_EQ(test[i], test.at(i));
266 template <class String> void clause11_21_4_6_1(String & test) {
267 // 21.3.5 modifiers (+=)
269 randomString(&test1);
270 assert(test1.size() == char_traits
271 <typename String::value_type>::length(test1.c_str()));
272 auto len = test.size();
274 EXPECT_EQ(test.size(), test1.size() + len);
275 FOR_EACH_RANGE (i, 0, test1.size()) {
276 EXPECT_EQ(test[len + i], test1[i]);
278 // aliasing modifiers
280 auto dt = test2.data();
281 auto sz = test.c_str();
283 EXPECT_EQ(memcmp(sz, dt, len), 0);
284 String copy(test.data(), test.size());
285 EXPECT_EQ(char_traits
286 <typename String::value_type>::length(test.c_str()), len);
289 EXPECT_EQ(test.size(), 2 * len);
290 EXPECT_EQ(char_traits
291 <typename String::value_type>::length(test.c_str()), 2 * len);
292 FOR_EACH_RANGE (i, 0, len) {
293 EXPECT_EQ(test[i], copy[i]);
294 EXPECT_EQ(test[i], test[len + i]);
297 EXPECT_EQ(char_traits
298 <typename String::value_type>::length(test.c_str()), len);
300 auto const pos = random(0, test.size());
301 EXPECT_EQ(char_traits
302 <typename String::value_type>::length(test.c_str() + pos), len - pos);
304 String addMe(test.c_str() + pos);
305 EXPECT_EQ(addMe.size(), len - pos);
308 test += test.c_str() + pos;
310 EXPECT_EQ(test.size(), 2 * len - pos);
313 test += random('a', 'z');
314 EXPECT_EQ(test.size(), len + 1);
316 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
320 template <class String> void clause11_21_4_6_2(String & test) {
321 // 21.3.5 modifiers (append, push_back)
324 // Test with a small string first
325 char c = random('a', 'z');
327 EXPECT_EQ(s[s.size() - 1], c);
328 EXPECT_EQ(s.size(), 1);
329 s.resize(s.size() - 1);
331 randomString(&s, maxString);
333 randomString(&s, maxString);
334 test.append(s, random(0, s.size()), random(0, maxString));
335 randomString(&s, maxString);
336 test.append(s.c_str(), random(0, s.size()));
337 randomString(&s, maxString);
338 test.append(s.c_str());
339 test.append(random(0, maxString), random('a', 'z'));
340 std::list<char> lst(RandomList(maxString));
341 test.append(lst.begin(), lst.end());
342 c = random('a', 'z');
344 EXPECT_EQ(test[test.size() - 1], c);
346 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
350 template <class String> void clause11_21_4_6_3_a(String & test) {
357 test.assign(std::move(s));
358 if (typeid(String) == typeid(fbstring)) {
359 EXPECT_LE(s.size(), 128);
363 template <class String> void clause11_21_4_6_3_b(String & test) {
366 randomString(&s, maxString);
367 test.assign(s, random(0, s.size()), random(0, maxString));
370 template <class String> void clause11_21_4_6_3_c(String & test) {
373 randomString(&s, maxString);
374 test.assign(s.c_str(), random(0, s.size()));
377 template <class String> void clause11_21_4_6_3_d(String & test) {
380 randomString(&s, maxString);
381 test.assign(s.c_str());
384 template <class String> void clause11_21_4_6_3_e(String & test) {
387 randomString(&s, maxString);
388 test.assign(random(0, maxString), random('a', 'z'));
391 template <class String> void clause11_21_4_6_3_f(String & test) {
392 // assign from bidirectional iterator
393 std::list<char> lst(RandomList(maxString));
394 test.assign(lst.begin(), lst.end());
397 template <class String> void clause11_21_4_6_3_g(String & test) {
398 // assign from aliased source
402 template <class String> void clause11_21_4_6_3_h(String & test) {
403 // assign from aliased source
404 test.assign(test, random(0, test.size()), random(0, maxString));
407 template <class String> void clause11_21_4_6_3_i(String & test) {
408 // assign from aliased source
409 test.assign(test.c_str(), random(0, test.size()));
412 template <class String> void clause11_21_4_6_3_j(String & test) {
413 // assign from aliased source
414 test.assign(test.c_str());
417 template <class String> void clause11_21_4_6_3_k(String & test) {
418 // assign from initializer_list
419 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
423 template <class String> void clause11_21_4_6_4(String & test) {
426 randomString(&s, maxString);
427 test.insert(random(0, test.size()), s);
428 randomString(&s, maxString);
429 test.insert(random(0, test.size()),
430 s, random(0, s.size()),
431 random(0, maxString));
432 randomString(&s, maxString);
433 test.insert(random(0, test.size()),
434 s.c_str(), random(0, s.size()));
435 randomString(&s, maxString);
436 test.insert(random(0, test.size()), s.c_str());
437 test.insert(random(0, test.size()),
438 random(0, maxString), random('a', 'z'));
439 typename String::size_type pos = random(0, test.size());
440 typename String::iterator res =
441 test.insert(test.begin() + pos, random('a', 'z'));
442 EXPECT_EQ(res - test.begin(), pos);
443 std::list<char> lst(RandomList(maxString));
444 pos = random(0, test.size());
445 // Uncomment below to see a bug in gcc
446 /*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
447 // insert from initializer_list
448 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
449 pos = random(0, test.size());
450 // Uncomment below to see a bug in gcc
451 /*res = */test.insert(test.begin() + pos, il);
453 // Test with actual input iterators
455 ss << "hello cruel world";
456 auto i = istream_iterator<char>(ss);
457 test.insert(test.begin(), i, istream_iterator<char>());
460 template <class String> void clause11_21_4_6_5(String & test) {
461 // erase and pop_back
463 test.erase(random(0, test.size()), random(0, maxString));
466 // TODO: is erase(end()) allowed?
467 test.erase(test.begin() + random(0, test.size() - 1));
470 auto const i = test.begin() + random(0, test.size());
471 if (i != test.end()) {
472 test.erase(i, i + random(0, size_t(test.end() - i)));
476 // Can't test pop_back with std::string, doesn't support it yet.
481 template <class String> void clause11_21_4_6_6(String & test) {
482 auto pos = random(0, test.size());
484 test.replace(pos, random(0, test.size() - pos),
487 test.replace(pos, random(0, test.size() - pos), test);
489 pos = random(0, test.size());
491 randomString(&s, maxString);
492 test.replace(pos, pos + random(0, test.size() - pos), s);
493 auto pos1 = random(0, test.size());
494 auto pos2 = random(0, test.size());
496 test.replace(pos1, pos1 + random(0, test.size() - pos1),
498 pos2, pos2 + random(0, test.size() - pos2));
500 test.replace(pos1, pos1 + random(0, test.size() - pos1),
501 test, pos2, pos2 + random(0, test.size() - pos2));
503 pos1 = random(0, test.size());
505 randomString(&str, maxString);
506 pos2 = random(0, str.size());
507 test.replace(pos1, pos1 + random(0, test.size() - pos1),
508 str, pos2, pos2 + random(0, str.size() - pos2));
509 pos = random(0, test.size());
511 test.replace(pos, random(0, test.size() - pos),
512 String(test).c_str(), test.size());
514 test.replace(pos, random(0, test.size() - pos),
515 test.c_str(), test.size());
517 pos = random(0, test.size());
518 randomString(&str, maxString);
519 test.replace(pos, pos + random(0, test.size() - pos),
520 str.c_str(), str.size());
521 pos = random(0, test.size());
522 randomString(&str, maxString);
523 test.replace(pos, pos + random(0, test.size() - pos),
525 pos = random(0, test.size());
526 test.replace(pos, random(0, test.size() - pos),
527 random(0, maxString), random('a', 'z'));
528 pos = random(0, test.size());
530 auto newString = String(test);
533 test.begin() + pos + random(0, test.size() - pos),
538 test.begin() + pos + random(0, test.size() - pos),
541 pos = random(0, test.size());
543 auto newString = String(test);
546 test.begin() + pos + random(0, test.size() - pos),
548 test.size() - random(0, test.size()));
552 test.begin() + pos + random(0, test.size() - pos),
554 test.size() - random(0, test.size()));
556 pos = random(0, test.size());
557 auto const n = random(0, test.size() - pos);
558 typename String::iterator b = test.begin();
560 randomString(&str1, maxString);
561 const String & str3 = str1;
562 const typename String::value_type* ss = str3.c_str();
567 pos = random(0, test.size());
570 test.begin() + pos + random(0, test.size() - pos),
571 random(0, maxString), random('a', 'z'));
574 template <class String> void clause11_21_4_6_7(String & test) {
575 std::vector<typename String::value_type>
576 vec(random(0, maxString));
580 random(0, test.size()));
583 template <class String> void clause11_21_4_6_8(String & test) {
585 randomString(&s, maxString);
589 template <class String> void clause11_21_4_7_1(String & test) {
590 // 21.3.6 string operations
591 // exercise c_str() and data()
592 assert(test.c_str() == test.data());
593 // exercise get_allocator()
595 randomString(&s, maxString);
596 assert(test.get_allocator() == s.get_allocator());
599 template <class String> void clause11_21_4_7_2_a(String & test) {
600 String str = test.substr(
601 random(0, test.size()),
602 random(0, test.size()));
603 Num2String(test, test.find(str, random(0, test.size())));
606 template <class String> void clause11_21_4_7_2_b(String & test) {
607 auto from = random(0, test.size());
608 auto length = random(0, test.size() - from);
609 String str = test.substr(from, length);
610 Num2String(test, test.find(str.c_str(),
611 random(0, test.size()),
612 random(0, str.size())));
615 template <class String> void clause11_21_4_7_2_c(String & test) {
616 String str = test.substr(
617 random(0, test.size()),
618 random(0, test.size()));
619 Num2String(test, test.find(str.c_str(),
620 random(0, test.size())));
623 template <class String> void clause11_21_4_7_2_d(String & test) {
624 Num2String(test, test.find(
626 random(0, test.size())));
629 template <class String> void clause11_21_4_7_3_a(String & test) {
630 String str = test.substr(
631 random(0, test.size()),
632 random(0, test.size()));
633 Num2String(test, test.rfind(str, random(0, test.size())));
636 template <class String> void clause11_21_4_7_3_b(String & test) {
637 String str = test.substr(
638 random(0, test.size()),
639 random(0, test.size()));
640 Num2String(test, test.rfind(str.c_str(),
641 random(0, test.size()),
642 random(0, str.size())));
645 template <class String> void clause11_21_4_7_3_c(String & test) {
646 String str = test.substr(
647 random(0, test.size()),
648 random(0, test.size()));
649 Num2String(test, test.rfind(str.c_str(),
650 random(0, test.size())));
653 template <class String> void clause11_21_4_7_3_d(String & test) {
654 Num2String(test, test.rfind(
656 random(0, test.size())));
659 template <class String> void clause11_21_4_7_4_a(String & test) {
661 randomString(&str, maxString);
662 Num2String(test, test.find_first_of(str,
663 random(0, test.size())));
666 template <class String> void clause11_21_4_7_4_b(String & test) {
668 randomString(&str, maxString);
669 Num2String(test, test.find_first_of(str.c_str(),
670 random(0, test.size()),
671 random(0, str.size())));
674 template <class String> void clause11_21_4_7_4_c(String & test) {
676 randomString(&str, maxString);
677 Num2String(test, test.find_first_of(str.c_str(),
678 random(0, test.size())));
681 template <class String> void clause11_21_4_7_4_d(String & test) {
682 Num2String(test, test.find_first_of(
684 random(0, test.size())));
687 template <class String> void clause11_21_4_7_5_a(String & test) {
689 randomString(&str, maxString);
690 Num2String(test, test.find_last_of(str,
691 random(0, test.size())));
694 template <class String> void clause11_21_4_7_5_b(String & test) {
696 randomString(&str, maxString);
697 Num2String(test, test.find_last_of(str.c_str(),
698 random(0, test.size()),
699 random(0, str.size())));
702 template <class String> void clause11_21_4_7_5_c(String & test) {
704 randomString(&str, maxString);
705 Num2String(test, test.find_last_of(str.c_str(),
706 random(0, test.size())));
709 template <class String> void clause11_21_4_7_5_d(String & test) {
710 Num2String(test, test.find_last_of(
712 random(0, test.size())));
715 template <class String> void clause11_21_4_7_6_a(String & test) {
717 randomString(&str, maxString);
718 Num2String(test, test.find_first_not_of(str,
719 random(0, test.size())));
722 template <class String> void clause11_21_4_7_6_b(String & test) {
724 randomString(&str, maxString);
725 Num2String(test, test.find_first_not_of(str.c_str(),
726 random(0, test.size()),
727 random(0, str.size())));
730 template <class String> void clause11_21_4_7_6_c(String & test) {
732 randomString(&str, maxString);
733 Num2String(test, test.find_first_not_of(str.c_str(),
734 random(0, test.size())));
737 template <class String> void clause11_21_4_7_6_d(String & test) {
738 Num2String(test, test.find_first_not_of(
740 random(0, test.size())));
743 template <class String> void clause11_21_4_7_7_a(String & test) {
745 randomString(&str, maxString);
746 Num2String(test, test.find_last_not_of(str,
747 random(0, test.size())));
750 template <class String> void clause11_21_4_7_7_b(String & test) {
752 randomString(&str, maxString);
753 Num2String(test, test.find_last_not_of(str.c_str(),
754 random(0, test.size()),
755 random(0, str.size())));
758 template <class String> void clause11_21_4_7_7_c(String & test) {
760 randomString(&str, maxString);
761 Num2String(test, test.find_last_not_of(str.c_str(),
762 random(0, test.size())));
765 template <class String> void clause11_21_4_7_7_d(String & test) {
766 Num2String(test, test.find_last_not_of(
768 random(0, test.size())));
771 template <class String> void clause11_21_4_7_8(String & test) {
772 test = test.substr(random(0, test.size()), random(0, test.size()));
775 template <class String> void clause11_21_4_7_9_a(String & test) {
777 randomString(&s, maxString);
778 int tristate = test.compare(s);
779 if (tristate > 0) tristate = 1;
780 else if (tristate < 0) tristate = 2;
781 Num2String(test, tristate);
784 template <class String> void clause11_21_4_7_9_b(String & test) {
786 randomString(&s, maxString);
787 int tristate = test.compare(
788 random(0, test.size()),
789 random(0, test.size()),
791 if (tristate > 0) tristate = 1;
792 else if (tristate < 0) tristate = 2;
793 Num2String(test, tristate);
796 template <class String> void clause11_21_4_7_9_c(String & test) {
798 randomString(&str, maxString);
799 int tristate = test.compare(
800 random(0, test.size()),
801 random(0, test.size()),
803 random(0, str.size()),
804 random(0, str.size()));
805 if (tristate > 0) tristate = 1;
806 else if (tristate < 0) tristate = 2;
807 Num2String(test, tristate);
810 template <class String> void clause11_21_4_7_9_d(String & test) {
812 randomString(&s, maxString);
813 int tristate = test.compare(s.c_str());
814 if (tristate > 0) tristate = 1;
815 else if (tristate < 0) tristate = 2;
816 Num2String(test, tristate);
819 template <class String> void clause11_21_4_7_9_e(String & test) {
821 randomString(&str, maxString);
822 int tristate = test.compare(
823 random(0, test.size()),
824 random(0, test.size()),
826 random(0, str.size()));
827 if (tristate > 0) tristate = 1;
828 else if (tristate < 0) tristate = 2;
829 Num2String(test, tristate);
832 template <class String> void clause11_21_4_8_1_a(String & test) {
834 randomString(&s1, maxString);
836 randomString(&s2, maxString);
840 template <class String> void clause11_21_4_8_1_b(String & test) {
842 randomString(&s, maxString);
844 randomString(&s1, maxString);
845 test = s.c_str() + s1;
848 template <class String> void clause11_21_4_8_1_c(String & test) {
850 randomString(&s, maxString);
851 test = typename String::value_type(random('a', 'z')) + s;
854 template <class String> void clause11_21_4_8_1_d(String & test) {
856 randomString(&s, maxString);
858 randomString(&s1, maxString);
859 test = s + s1.c_str();
862 template <class String> void clause11_21_4_8_1_e(String & test) {
864 randomString(&s, maxString);
866 randomString(&s1, maxString);
867 test = s + s1.c_str();
870 template <class String> void clause11_21_4_8_1_f(String & test) {
872 randomString(&s, maxString);
873 test = s + typename String::value_type(random('a', 'z'));
876 // Numbering here is from C++11
877 template <class String> void clause11_21_4_8_9_a(String & test) {
878 basic_stringstream<typename String::value_type> stst(test.c_str());
886 TEST(FBString, testAllClauses) {
887 EXPECT_TRUE(1) << "Starting with seed: " << seed;
891 folly::basic_fbstring<wchar_t> wc;
894 auto l = [&](const char * const clause,
895 void(*f_string)(std::string&),
896 void(*f_fbstring)(folly::fbstring&),
897 void(*f_wfbstring)(folly::basic_fbstring<wchar_t>&)) {
899 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << clause;
903 wr = std::wstring(r.begin(), r.end());
904 wc = folly::basic_fbstring<wchar_t>(wr.c_str());
905 auto localSeed = seed + count;
906 rng = RandomT(localSeed);
908 rng = RandomT(localSeed);
911 << "Lengths: " << r.size() << " vs. " << c.size()
912 << "\nReference: '" << r << "'"
913 << "\nActual: '" << c.data()[0] << "'";
914 rng = RandomT(localSeed);
916 int wret = wcslen(wc.c_str());
918 int ret = wcstombs(mb, wc.c_str(), sizeof(mb));
919 if (ret == wret) mb[wret] = '\0';
920 const char *mc = c.c_str();
924 } while (++count % 100 != 0);
927 #define TEST_CLAUSE(x) \
929 clause11_##x<std::string>, \
930 clause11_##x<folly::fbstring>, \
931 clause11_##x<folly::basic_fbstring<wchar_t>>);
933 TEST_CLAUSE(21_4_2_a);
934 TEST_CLAUSE(21_4_2_b);
935 TEST_CLAUSE(21_4_2_c);
936 TEST_CLAUSE(21_4_2_d);
937 TEST_CLAUSE(21_4_2_e);
938 TEST_CLAUSE(21_4_2_f);
939 TEST_CLAUSE(21_4_2_g);
940 TEST_CLAUSE(21_4_2_h);
941 TEST_CLAUSE(21_4_2_i);
942 TEST_CLAUSE(21_4_2_j);
943 TEST_CLAUSE(21_4_2_k);
944 TEST_CLAUSE(21_4_2_l);
945 TEST_CLAUSE(21_4_2_lprime);
946 TEST_CLAUSE(21_4_2_m);
947 TEST_CLAUSE(21_4_2_n);
951 TEST_CLAUSE(21_4_6_1);
952 TEST_CLAUSE(21_4_6_2);
953 TEST_CLAUSE(21_4_6_3_a);
954 TEST_CLAUSE(21_4_6_3_b);
955 TEST_CLAUSE(21_4_6_3_c);
956 TEST_CLAUSE(21_4_6_3_d);
957 TEST_CLAUSE(21_4_6_3_e);
958 TEST_CLAUSE(21_4_6_3_f);
959 TEST_CLAUSE(21_4_6_3_g);
960 TEST_CLAUSE(21_4_6_3_h);
961 TEST_CLAUSE(21_4_6_3_i);
962 TEST_CLAUSE(21_4_6_3_j);
963 TEST_CLAUSE(21_4_6_3_k);
964 TEST_CLAUSE(21_4_6_4);
965 TEST_CLAUSE(21_4_6_5);
966 TEST_CLAUSE(21_4_6_6);
967 TEST_CLAUSE(21_4_6_7);
968 TEST_CLAUSE(21_4_6_8);
969 TEST_CLAUSE(21_4_7_1);
971 TEST_CLAUSE(21_4_7_2_a);
972 TEST_CLAUSE(21_4_7_2_b);
973 TEST_CLAUSE(21_4_7_2_c);
974 TEST_CLAUSE(21_4_7_2_d);
975 TEST_CLAUSE(21_4_7_3_a);
976 TEST_CLAUSE(21_4_7_3_b);
977 TEST_CLAUSE(21_4_7_3_c);
978 TEST_CLAUSE(21_4_7_3_d);
979 TEST_CLAUSE(21_4_7_4_a);
980 TEST_CLAUSE(21_4_7_4_b);
981 TEST_CLAUSE(21_4_7_4_c);
982 TEST_CLAUSE(21_4_7_4_d);
983 TEST_CLAUSE(21_4_7_5_a);
984 TEST_CLAUSE(21_4_7_5_b);
985 TEST_CLAUSE(21_4_7_5_c);
986 TEST_CLAUSE(21_4_7_5_d);
987 TEST_CLAUSE(21_4_7_6_a);
988 TEST_CLAUSE(21_4_7_6_b);
989 TEST_CLAUSE(21_4_7_6_c);
990 TEST_CLAUSE(21_4_7_6_d);
991 TEST_CLAUSE(21_4_7_7_a);
992 TEST_CLAUSE(21_4_7_7_b);
993 TEST_CLAUSE(21_4_7_7_c);
994 TEST_CLAUSE(21_4_7_7_d);
995 TEST_CLAUSE(21_4_7_8);
996 TEST_CLAUSE(21_4_7_9_a);
997 TEST_CLAUSE(21_4_7_9_b);
998 TEST_CLAUSE(21_4_7_9_c);
999 TEST_CLAUSE(21_4_7_9_d);
1000 TEST_CLAUSE(21_4_7_9_e);
1001 TEST_CLAUSE(21_4_8_1_a);
1002 TEST_CLAUSE(21_4_8_1_b);
1003 TEST_CLAUSE(21_4_8_1_c);
1004 TEST_CLAUSE(21_4_8_1_d);
1005 TEST_CLAUSE(21_4_8_1_e);
1006 TEST_CLAUSE(21_4_8_1_f);
1007 TEST_CLAUSE(21_4_8_9_a);
1010 TEST(FBString, testGetline) {
1012 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
1013 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1014 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1015 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1016 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1017 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1018 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1019 tristique senectus et netus et malesuada fames ac turpis \n\
1020 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1021 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1022 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1023 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1024 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1025 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1026 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1027 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1028 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1029 char f[] = "/tmp/fbstring_testing.XXXXXX";
1030 int fd = mkstemp(f);
1031 EXPECT_TRUE(fd > 0);
1034 std::ofstream out(f);
1036 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1041 boost::split(v, s1, boost::is_any_of("\n"));
1046 EXPECT_TRUE(!getline(input, line).fail());
1047 EXPECT_EQ(line, *i);
1053 TEST(FBString, testMoveCtor) {
1054 // Move constructor. Make sure we allocate a large string, so the
1055 // small string optimization doesn't kick in.
1056 auto size = random(100, 2000);
1057 fbstring s(size, 'a');
1058 fbstring test = std::move(s);
1059 EXPECT_TRUE(s.empty());
1060 EXPECT_EQ(size, test.size());
1063 TEST(FBString, testMoveAssign) {
1064 // Move constructor. Make sure we allocate a large string, so the
1065 // small string optimization doesn't kick in.
1066 auto size = random(100, 2000);
1067 fbstring s(size, 'a');
1069 test = std::move(s);
1070 EXPECT_TRUE(s.empty());
1071 EXPECT_EQ(size, test.size());
1074 TEST(FBString, testMoveOperatorPlusLhs) {
1075 // Make sure we allocate a large string, so the
1076 // small string optimization doesn't kick in.
1077 auto size1 = random(100, 2000);
1078 auto size2 = random(100, 2000);
1079 fbstring s1(size1, 'a');
1080 fbstring s2(size2, 'b');
1082 test = std::move(s1) + s2;
1083 EXPECT_TRUE(s1.empty());
1084 EXPECT_EQ(size1 + size2, test.size());
1087 TEST(FBString, testMoveOperatorPlusRhs) {
1088 // Make sure we allocate a large string, so the
1089 // small string optimization doesn't kick in.
1090 auto size1 = random(100, 2000);
1091 auto size2 = random(100, 2000);
1092 fbstring s1(size1, 'a');
1093 fbstring s2(size2, 'b');
1095 test = s1 + std::move(s2);
1096 EXPECT_EQ(size1 + size2, test.size());
1099 // The GNU C++ standard library throws an std::logic_error when an std::string
1100 // is constructed with a null pointer. Verify that we mirror this behavior.
1102 // N.B. We behave this way even if the C++ library being used is something
1103 // other than libstdc++. Someday if we deem it important to present
1104 // identical undefined behavior for other platforms, we can re-visit this.
1105 TEST(FBString, testConstructionFromLiteralZero) {
1106 EXPECT_THROW(fbstring s(0), std::logic_error);
1109 TEST(FBString, testFixedBugs) {
1111 fbstring str(1337, 'f');
1115 EXPECT_EQ(str.front(), 'f');
1117 { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
1118 fbstring str(1337, 'f');
1119 for (int i = 0; i < 2; ++i) {
1122 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1128 fbstring str(1337, 'f');
1133 fbstring str(1337, 'f');
1139 folly::basic_fbstring<wchar_t> s;
1140 EXPECT_EQ(0, s.size());
1143 fbstring str(1337, 'f');
1144 std::swap(str, str);
1145 EXPECT_EQ(1337, str.size());
1147 { // D1012196, --allocator=malloc
1148 fbstring str(128, 'f');
1149 str.clear(); // Empty medium string.
1150 fbstring copy(str); // Medium string of 0 capacity.
1151 copy.push_back('b');
1152 EXPECT_GE(copy.capacity(), 1);
1156 TEST(FBString, findWithNpos) {
1157 fbstring fbstr("localhost:80");
1158 EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1161 TEST(FBString, testHash) {
1168 std::hash<fbstring> hashfunc;
1169 EXPECT_NE(hashfunc(a), hashfunc(b));
1172 TEST(FBString, testFrontBack) {
1173 fbstring str("hello");
1174 EXPECT_EQ(str.front(), 'h');
1175 EXPECT_EQ(str.back(), 'o');
1177 EXPECT_EQ(str.front(), 'H');
1179 EXPECT_EQ(str.back(), 'O');
1180 EXPECT_EQ(str, "HellO");
1183 TEST(FBString, noexcept) {
1184 EXPECT_TRUE(noexcept(fbstring()));
1185 // std::move is not marked noexcept in gcc 4.6, sigh
1186 #if __GNUC_PREREQ(4, 7)
1188 EXPECT_FALSE(noexcept(fbstring(x)));
1189 EXPECT_TRUE(noexcept(fbstring(std::move(x))));
1191 EXPECT_FALSE(noexcept(y = x));
1192 EXPECT_TRUE(noexcept(y = std::move(x)));
1196 TEST(FBString, iomanip) {
1198 fbstring fbstr("Hello");
1200 ss << setw(6) << fbstr;
1201 EXPECT_EQ(ss.str(), " Hello");
1204 ss << left << setw(6) << fbstr;
1205 EXPECT_EQ(ss.str(), "Hello ");
1208 ss << right << setw(6) << fbstr;
1209 EXPECT_EQ(ss.str(), " Hello");
1212 ss << setw(4) << fbstr;
1213 EXPECT_EQ(ss.str(), "Hello");
1216 ss << setfill('^') << setw(6) << fbstr;
1217 EXPECT_EQ(ss.str(), "^Hello");
1221 TEST(FBString, rvalueIterators) {
1222 // you cannot take &* of a move-iterator, so use that for testing
1223 fbstring s = "base";
1224 fbstring r = "hello";
1225 r.replace(r.begin(), r.end(),
1226 make_move_iterator(s.begin()), make_move_iterator(s.end()));
1227 EXPECT_EQ("base", r);
1229 // The following test is probably not required by the standard.
1230 // i.e. this could be in the realm of undefined behavior.
1231 fbstring b = "123abcXYZ";
1232 auto ait = b.begin() + 3;
1233 auto Xit = b.begin() + 6;
1234 b.replace(ait, b.end(), b.begin(), Xit);
1235 EXPECT_EQ("123123abc", b); // if things go wrong, you'd get "123123123"
1238 int main(int argc, char** argv) {
1239 testing::InitGoogleTest(&argc, argv);
1240 google::ParseCommandLineFlags(&argc, &argv, true);
1241 return RUN_ALL_TESTS();