2 * Copyright 2013 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"
26 #include <boost/algorithm/string.hpp>
27 #include <boost/random.hpp>
28 #include <gtest/gtest.h>
30 #include <gflags/gflags.h>
32 #include "folly/Foreach.h"
33 #include "folly/Portability.h"
34 #include "folly/Random.h"
35 #include "folly/Conv.h"
38 using namespace folly;
40 static const int seed = folly::randomNumberSeed();
41 typedef boost::mt19937 RandomT;
42 static RandomT rng(seed);
43 static const size_t maxString = 100;
44 static const bool avoidAliasing = true;
46 template <class Integral1, class Integral2>
47 Integral2 random(Integral1 low, Integral2 up) {
48 boost::uniform_int<> range(low, up);
52 template <class String>
53 void randomString(String* toFill, unsigned int maxSize = 1000) {
55 toFill->resize(random(0, maxSize));
56 FOR_EACH (i, *toFill) {
57 *i = random('a', 'z');
61 template <class String, class Integral>
62 void Num2String(String& str, Integral n) {
64 std::string tmp = folly::to<std::string>(n);
65 str = String(tmp.begin(), tmp.end());
68 std::list<char> RandomList(unsigned int maxSize) {
69 std::list<char> lst(random(0u, maxSize));
70 std::list<char>::iterator i = lst.begin();
71 for (; i != lst.end(); ++i) {
72 *i = random('a', 'z');
77 ////////////////////////////////////////////////////////////////////////////////
79 ////////////////////////////////////////////////////////////////////////////////
81 template <class String> void clause11_21_4_2_a(String & test) {
82 test.String::~String();
85 template <class String> void clause11_21_4_2_b(String & test) {
87 assert(test2 == test);
89 template <class String> void clause11_21_4_2_c(String & test) {
90 // Test move constructor. There is a more specialized test, see
91 // TEST(FBString, testMoveCtor)
93 String test2(std::move(donor));
94 EXPECT_EQ(test2, test);
95 // Technically not required, but all implementations that actually
96 // support move will move large strings. Make a guess for 128 as the
97 // maximum small string optimization that's reasonable.
98 EXPECT_LE(donor.size(), 128);
100 template <class String> void clause11_21_4_2_d(String & test) {
101 // Copy constructor with position and length
102 const size_t pos = random(0, test.size());
103 String s(test, pos, random(0, 9)
104 ? random(0, (size_t)(test.size() - pos))
105 : String::npos); // test for npos, too, in 10% of the cases
108 template <class String> void clause11_21_4_2_e(String & test) {
109 // Constructor from char*, size_t
111 pos = random(0, test.size()),
112 n = random(0, test.size() - pos);
113 String before(test.data(), test.size());
114 String s(test.c_str() + pos, n);
115 String after(test.data(), test.size());
116 EXPECT_EQ(before, after);
119 template <class String> void clause11_21_4_2_f(String & test) {
120 // Constructor from char*
122 pos = random(0, test.size()),
123 n = random(0, test.size() - pos);
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_b(String & test) {
606 auto from = random(0, test.size());
607 auto length = random(0, test.size() - from);
608 String str = test.substr(from, length);
609 Num2String(test, test.find(str.c_str(),
610 random(0, test.size()),
611 random(0, str.size())));
614 template <class String> void clause11_21_4_7_2_c(String & test) {
615 String str = test.substr(
616 random(0, test.size()),
617 random(0, test.size()));
618 Num2String(test, test.find(str.c_str(),
619 random(0, test.size())));
622 template <class String> void clause11_21_4_7_2_d(String & test) {
623 Num2String(test, test.find(
625 random(0, test.size())));
628 template <class String> void clause11_21_4_7_3_a(String & test) {
629 String str = test.substr(
630 random(0, test.size()),
631 random(0, test.size()));
632 Num2String(test, test.rfind(str, random(0, test.size())));
635 template <class String> void clause11_21_4_7_3_b(String & test) {
636 String str = test.substr(
637 random(0, test.size()),
638 random(0, test.size()));
639 Num2String(test, test.rfind(str.c_str(),
640 random(0, test.size()),
641 random(0, str.size())));
644 template <class String> void clause11_21_4_7_3_c(String & test) {
645 String str = test.substr(
646 random(0, test.size()),
647 random(0, test.size()));
648 Num2String(test, test.rfind(str.c_str(),
649 random(0, test.size())));
652 template <class String> void clause11_21_4_7_3_d(String & test) {
653 Num2String(test, test.rfind(
655 random(0, test.size())));
658 template <class String> void clause11_21_4_7_4_a(String & test) {
660 randomString(&str, maxString);
661 Num2String(test, test.find_first_of(str,
662 random(0, test.size())));
665 template <class String> void clause11_21_4_7_4_b(String & test) {
667 randomString(&str, maxString);
668 Num2String(test, test.find_first_of(str.c_str(),
669 random(0, test.size()),
670 random(0, str.size())));
673 template <class String> void clause11_21_4_7_4_c(String & test) {
675 randomString(&str, maxString);
676 Num2String(test, test.find_first_of(str.c_str(),
677 random(0, test.size())));
680 template <class String> void clause11_21_4_7_4_d(String & test) {
681 Num2String(test, test.find_first_of(
683 random(0, test.size())));
686 template <class String> void clause11_21_4_7_5_a(String & test) {
688 randomString(&str, maxString);
689 Num2String(test, test.find_last_of(str,
690 random(0, test.size())));
693 template <class String> void clause11_21_4_7_5_b(String & test) {
695 randomString(&str, maxString);
696 Num2String(test, test.find_last_of(str.c_str(),
697 random(0, test.size()),
698 random(0, str.size())));
701 template <class String> void clause11_21_4_7_5_c(String & test) {
703 randomString(&str, maxString);
704 Num2String(test, test.find_last_of(str.c_str(),
705 random(0, test.size())));
708 template <class String> void clause11_21_4_7_5_d(String & test) {
709 Num2String(test, test.find_last_of(
711 random(0, test.size())));
714 template <class String> void clause11_21_4_7_6_a(String & test) {
716 randomString(&str, maxString);
717 Num2String(test, test.find_first_not_of(str,
718 random(0, test.size())));
721 template <class String> void clause11_21_4_7_6_b(String & test) {
723 randomString(&str, maxString);
724 Num2String(test, test.find_first_not_of(str.c_str(),
725 random(0, test.size()),
726 random(0, str.size())));
729 template <class String> void clause11_21_4_7_6_c(String & test) {
731 randomString(&str, maxString);
732 Num2String(test, test.find_first_not_of(str.c_str(),
733 random(0, test.size())));
736 template <class String> void clause11_21_4_7_6_d(String & test) {
737 Num2String(test, test.find_first_not_of(
739 random(0, test.size())));
742 template <class String> void clause11_21_4_7_7_a(String & test) {
744 randomString(&str, maxString);
745 Num2String(test, test.find_last_not_of(str,
746 random(0, test.size())));
749 template <class String> void clause11_21_4_7_7_b(String & test) {
751 randomString(&str, maxString);
752 Num2String(test, test.find_last_not_of(str.c_str(),
753 random(0, test.size()),
754 random(0, str.size())));
757 template <class String> void clause11_21_4_7_7_c(String & test) {
759 randomString(&str, maxString);
760 Num2String(test, test.find_last_not_of(str.c_str(),
761 random(0, test.size())));
764 template <class String> void clause11_21_4_7_7_d(String & test) {
765 Num2String(test, test.find_last_not_of(
767 random(0, test.size())));
770 template <class String> void clause11_21_4_7_8(String & test) {
771 test = test.substr(random(0, test.size()), random(0, test.size()));
774 template <class String> void clause11_21_4_7_9_a(String & test) {
776 randomString(&s, maxString);
777 int tristate = test.compare(s);
778 if (tristate > 0) tristate = 1;
779 else if (tristate < 0) tristate = 2;
780 Num2String(test, tristate);
783 template <class String> void clause11_21_4_7_9_b(String & test) {
785 randomString(&s, maxString);
786 int tristate = test.compare(
787 random(0, test.size()),
788 random(0, test.size()),
790 if (tristate > 0) tristate = 1;
791 else if (tristate < 0) tristate = 2;
792 Num2String(test, tristate);
795 template <class String> void clause11_21_4_7_9_c(String & test) {
797 randomString(&str, maxString);
798 int tristate = test.compare(
799 random(0, test.size()),
800 random(0, test.size()),
802 random(0, str.size()),
803 random(0, str.size()));
804 if (tristate > 0) tristate = 1;
805 else if (tristate < 0) tristate = 2;
806 Num2String(test, tristate);
809 template <class String> void clause11_21_4_7_9_d(String & test) {
811 randomString(&s, maxString);
812 int tristate = test.compare(s.c_str());
813 if (tristate > 0) tristate = 1;
814 else if (tristate < 0) tristate = 2;
815 Num2String(test, tristate);
818 template <class String> void clause11_21_4_7_9_e(String & test) {
820 randomString(&str, maxString);
821 int tristate = test.compare(
822 random(0, test.size()),
823 random(0, test.size()),
825 random(0, str.size()));
826 if (tristate > 0) tristate = 1;
827 else if (tristate < 0) tristate = 2;
828 Num2String(test, tristate);
831 template <class String> void clause11_21_4_8_1_a(String & test) {
833 randomString(&s1, maxString);
835 randomString(&s2, maxString);
839 template <class String> void clause11_21_4_8_1_b(String & test) {
841 randomString(&s, maxString);
843 randomString(&s1, maxString);
844 test = s.c_str() + s1;
847 template <class String> void clause11_21_4_8_1_c(String & test) {
849 randomString(&s, maxString);
850 test = typename String::value_type(random('a', 'z')) + s;
853 template <class String> void clause11_21_4_8_1_d(String & test) {
855 randomString(&s, maxString);
857 randomString(&s1, maxString);
858 test = s + s1.c_str();
861 template <class String> void clause11_21_4_8_1_e(String & test) {
863 randomString(&s, maxString);
865 randomString(&s1, maxString);
866 test = s + s1.c_str();
869 template <class String> void clause11_21_4_8_1_f(String & test) {
871 randomString(&s, maxString);
872 test = s + typename String::value_type(random('a', 'z'));
875 // Numbering here is from C++11
876 template <class String> void clause11_21_4_8_9_a(String & test) {
877 basic_stringstream<typename String::value_type> stst(test.c_str());
885 TEST(FBString, testAllClauses) {
886 EXPECT_TRUE(1) << "Starting with seed: " << seed;
890 folly::basic_fbstring<wchar_t> wc;
891 #define TEST_CLAUSE(x) \
893 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x; \
897 wr = std::wstring(r.begin(), r.end()); \
898 wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \
899 auto localSeed = seed + count; \
900 rng = RandomT(localSeed); \
902 rng = RandomT(localSeed); \
905 << "Lengths: " << r.size() << " vs. " << c.size() \
906 << "\nReference: '" << r << "'" \
907 << "\nActual: '" << c.data()[0] << "'"; \
908 rng = RandomT(localSeed); \
910 int wret = wcslen(wc.c_str()); \
912 int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \
913 if (ret == wret) mb[wret] = '\0'; \
914 const char *mc = c.c_str(); \
915 std::string one(mb); \
916 std::string two(mc); \
917 EXPECT_EQ(one, two); \
918 } while (++count % 100 != 0)
921 TEST_CLAUSE(21_4_2_a);
922 TEST_CLAUSE(21_4_2_b);
923 TEST_CLAUSE(21_4_2_c);
924 TEST_CLAUSE(21_4_2_d);
925 TEST_CLAUSE(21_4_2_e);
926 TEST_CLAUSE(21_4_2_f);
927 TEST_CLAUSE(21_4_2_g);
928 TEST_CLAUSE(21_4_2_h);
929 TEST_CLAUSE(21_4_2_i);
930 TEST_CLAUSE(21_4_2_j);
931 TEST_CLAUSE(21_4_2_k);
932 TEST_CLAUSE(21_4_2_l);
933 TEST_CLAUSE(21_4_2_lprime);
934 TEST_CLAUSE(21_4_2_m);
935 TEST_CLAUSE(21_4_2_n);
939 TEST_CLAUSE(21_4_6_1);
940 TEST_CLAUSE(21_4_6_2);
941 TEST_CLAUSE(21_4_6_3_a);
942 TEST_CLAUSE(21_4_6_3_b);
943 TEST_CLAUSE(21_4_6_3_c);
944 TEST_CLAUSE(21_4_6_3_d);
945 TEST_CLAUSE(21_4_6_3_e);
946 TEST_CLAUSE(21_4_6_3_f);
947 TEST_CLAUSE(21_4_6_3_g);
948 TEST_CLAUSE(21_4_6_3_h);
949 TEST_CLAUSE(21_4_6_3_i);
950 TEST_CLAUSE(21_4_6_3_j);
951 TEST_CLAUSE(21_4_6_3_k);
952 TEST_CLAUSE(21_4_6_4);
953 TEST_CLAUSE(21_4_6_5);
954 TEST_CLAUSE(21_4_6_6);
955 TEST_CLAUSE(21_4_6_7);
956 TEST_CLAUSE(21_4_6_8);
957 TEST_CLAUSE(21_4_7_1);
959 TEST_CLAUSE(21_4_7_2_a);
960 TEST_CLAUSE(21_4_7_2_b);
961 TEST_CLAUSE(21_4_7_2_c);
962 TEST_CLAUSE(21_4_7_2_d);
963 TEST_CLAUSE(21_4_7_3_a);
964 TEST_CLAUSE(21_4_7_3_b);
965 TEST_CLAUSE(21_4_7_3_c);
966 TEST_CLAUSE(21_4_7_3_d);
967 TEST_CLAUSE(21_4_7_4_a);
968 TEST_CLAUSE(21_4_7_4_b);
969 TEST_CLAUSE(21_4_7_4_c);
970 TEST_CLAUSE(21_4_7_4_d);
971 TEST_CLAUSE(21_4_7_5_a);
972 TEST_CLAUSE(21_4_7_5_b);
973 TEST_CLAUSE(21_4_7_5_c);
974 TEST_CLAUSE(21_4_7_5_d);
975 TEST_CLAUSE(21_4_7_6_a);
976 TEST_CLAUSE(21_4_7_6_b);
977 TEST_CLAUSE(21_4_7_6_c);
978 TEST_CLAUSE(21_4_7_6_d);
979 TEST_CLAUSE(21_4_7_7_a);
980 TEST_CLAUSE(21_4_7_7_b);
981 TEST_CLAUSE(21_4_7_7_c);
982 TEST_CLAUSE(21_4_7_7_d);
983 TEST_CLAUSE(21_4_7_8);
984 TEST_CLAUSE(21_4_7_9_a);
985 TEST_CLAUSE(21_4_7_9_b);
986 TEST_CLAUSE(21_4_7_9_c);
987 TEST_CLAUSE(21_4_7_9_d);
988 TEST_CLAUSE(21_4_7_9_e);
989 TEST_CLAUSE(21_4_8_1_a);
990 TEST_CLAUSE(21_4_8_1_b);
991 TEST_CLAUSE(21_4_8_1_c);
992 TEST_CLAUSE(21_4_8_1_d);
993 TEST_CLAUSE(21_4_8_1_e);
994 TEST_CLAUSE(21_4_8_1_f);
995 TEST_CLAUSE(21_4_8_9_a);
998 TEST(FBString, testGetline) {
1000 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
1001 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1002 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1003 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1004 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1005 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1006 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1007 tristique senectus et netus et malesuada fames ac turpis \n\
1008 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1009 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1010 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1011 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1012 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1013 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1014 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1015 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1016 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1017 char f[] = "/tmp/fbstring_testing.XXXXXX";
1018 int fd = mkstemp(f);
1019 EXPECT_TRUE(fd > 0);
1022 std::ofstream out(f);
1024 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1029 boost::split(v, s1, boost::is_any_of("\n"));
1034 EXPECT_TRUE(!getline(input, line).fail());
1035 EXPECT_EQ(line, *i);
1041 TEST(FBString, testMoveCtor) {
1042 // Move constructor. Make sure we allocate a large string, so the
1043 // small string optimization doesn't kick in.
1044 auto size = random(100, 2000);
1045 fbstring s(size, 'a');
1046 fbstring test = std::move(s);
1047 EXPECT_TRUE(s.empty());
1048 EXPECT_EQ(size, test.size());
1051 TEST(FBString, testMoveAssign) {
1052 // Move constructor. Make sure we allocate a large string, so the
1053 // small string optimization doesn't kick in.
1054 auto size = random(100, 2000);
1055 fbstring s(size, 'a');
1057 test = std::move(s);
1058 EXPECT_TRUE(s.empty());
1059 EXPECT_EQ(size, test.size());
1062 TEST(FBString, testMoveOperatorPlusLhs) {
1063 // Make sure we allocate a large string, so the
1064 // small string optimization doesn't kick in.
1065 auto size1 = random(100, 2000);
1066 auto size2 = random(100, 2000);
1067 fbstring s1(size1, 'a');
1068 fbstring s2(size2, 'b');
1070 test = std::move(s1) + s2;
1071 EXPECT_TRUE(s1.empty());
1072 EXPECT_EQ(size1 + size2, test.size());
1075 TEST(FBString, testMoveOperatorPlusRhs) {
1076 // Make sure we allocate a large string, so the
1077 // small string optimization doesn't kick in.
1078 auto size1 = random(100, 2000);
1079 auto size2 = random(100, 2000);
1080 fbstring s1(size1, 'a');
1081 fbstring s2(size2, 'b');
1083 test = s1 + std::move(s2);
1084 EXPECT_EQ(size1 + size2, test.size());
1087 // The GNU C++ standard library throws an std::logic_error when an std::string
1088 // is constructed with a null pointer. Verify that we mirror this behavior.
1090 // N.B. We behave this way even if the C++ library being used is something
1091 // other than libstdc++. Someday if we deem it important to present
1092 // identical undefined behavior for other platforms, we can re-visit this.
1093 TEST(FBString, testConstructionFromLiteralZero) {
1094 EXPECT_THROW(fbstring s(0), std::logic_error);
1097 TEST(FBString, testFixedBugs) {
1099 fbstring str(1337, 'f');
1103 EXPECT_EQ(str.front(), 'f');
1105 { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
1106 fbstring str(1337, 'f');
1107 for (int i = 0; i < 2; ++i) {
1110 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1116 fbstring str(1337, 'f');
1121 fbstring str(1337, 'f');
1127 folly::basic_fbstring<wchar_t> s;
1128 EXPECT_EQ(0, s.size());
1131 fbstring str(1337, 'f');
1132 std::swap(str, str);
1133 EXPECT_EQ(1337, str.size());
1135 { // D1012196, --allocator=malloc
1136 fbstring str(128, 'f');
1137 str.clear(); // Empty medium string.
1138 fbstring copy(str); // Medium string of 0 capacity.
1139 copy.push_back('b');
1140 EXPECT_GE(copy.capacity(), 1);
1144 TEST(FBString, findWithNpos) {
1145 fbstring fbstr("localhost:80");
1146 EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1149 TEST(FBString, testHash) {
1156 std::hash<fbstring> hashfunc;
1157 EXPECT_NE(hashfunc(a), hashfunc(b));
1160 TEST(FBString, testFrontBack) {
1161 fbstring str("hello");
1162 EXPECT_EQ(str.front(), 'h');
1163 EXPECT_EQ(str.back(), 'o');
1165 EXPECT_EQ(str.front(), 'H');
1167 EXPECT_EQ(str.back(), 'O');
1168 EXPECT_EQ(str, "HellO");
1171 TEST(FBString, noexcept) {
1172 EXPECT_TRUE(noexcept(fbstring()));
1173 // std::move is not marked noexcept in gcc 4.6, sigh
1174 #if __GNUC_PREREQ(4, 7)
1176 EXPECT_FALSE(noexcept(fbstring(x)));
1177 EXPECT_TRUE(noexcept(fbstring(std::move(x))));
1179 EXPECT_FALSE(noexcept(y = x));
1180 EXPECT_TRUE(noexcept(y = std::move(x)));
1184 int main(int argc, char** argv) {
1185 testing::InitGoogleTest(&argc, argv);
1186 google::ParseCommandLineFlags(&argc, &argv, true);
1187 return RUN_ALL_TESTS();