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());
531 test.begin() + pos + random(0, test.size() - pos),
536 test.begin() + pos + random(0, test.size() - pos),
539 pos = random(0, test.size());
543 test.begin() + pos + random(0, test.size() - pos),
544 String(test).c_str(),
545 test.size() - random(0, test.size()));
549 test.begin() + pos + random(0, test.size() - pos),
551 test.size() - random(0, test.size()));
553 pos = random(0, test.size());
554 auto const n = random(0, test.size() - pos);
555 typename String::iterator b = test.begin();
557 randomString(&str1, maxString);
558 const String & str3 = str1;
559 const typename String::value_type* ss = str3.c_str();
564 pos = random(0, test.size());
567 test.begin() + pos + random(0, test.size() - pos),
568 random(0, maxString), random('a', 'z'));
571 template <class String> void clause11_21_4_6_7(String & test) {
572 std::vector<typename String::value_type>
573 vec(random(0, maxString));
577 random(0, test.size()));
580 template <class String> void clause11_21_4_6_8(String & test) {
582 randomString(&s, maxString);
586 template <class String> void clause11_21_4_7_1(String & test) {
587 // 21.3.6 string operations
588 // exercise c_str() and data()
589 assert(test.c_str() == test.data());
590 // exercise get_allocator()
592 randomString(&s, maxString);
593 assert(test.get_allocator() == s.get_allocator());
596 template <class String> void clause11_21_4_7_2_a(String & test) {
597 String str = test.substr(
598 random(0, test.size()),
599 random(0, test.size()));
600 Num2String(test, test.find(str, random(0, test.size())));
603 template <class String> void clause11_21_4_7_2_b(String & test) {
604 auto from = random(0, test.size());
605 auto length = random(0, test.size() - from);
606 String str = test.substr(from, length);
607 Num2String(test, test.find(str.c_str(),
608 random(0, test.size()),
609 random(0, str.size())));
612 template <class String> void clause11_21_4_7_2_c(String & test) {
613 String str = test.substr(
614 random(0, test.size()),
615 random(0, test.size()));
616 Num2String(test, test.find(str.c_str(),
617 random(0, test.size())));
620 template <class String> void clause11_21_4_7_2_d(String & test) {
621 Num2String(test, test.find(
623 random(0, test.size())));
626 template <class String> void clause11_21_4_7_3_a(String & test) {
627 String str = test.substr(
628 random(0, test.size()),
629 random(0, test.size()));
630 Num2String(test, test.rfind(str, random(0, test.size())));
633 template <class String> void clause11_21_4_7_3_b(String & test) {
634 String str = test.substr(
635 random(0, test.size()),
636 random(0, test.size()));
637 Num2String(test, test.rfind(str.c_str(),
638 random(0, test.size()),
639 random(0, str.size())));
642 template <class String> void clause11_21_4_7_3_c(String & test) {
643 String str = test.substr(
644 random(0, test.size()),
645 random(0, test.size()));
646 Num2String(test, test.rfind(str.c_str(),
647 random(0, test.size())));
650 template <class String> void clause11_21_4_7_3_d(String & test) {
651 Num2String(test, test.rfind(
653 random(0, test.size())));
656 template <class String> void clause11_21_4_7_4_a(String & test) {
658 randomString(&str, maxString);
659 Num2String(test, test.find_first_of(str,
660 random(0, test.size())));
663 template <class String> void clause11_21_4_7_4_b(String & test) {
665 randomString(&str, maxString);
666 Num2String(test, test.find_first_of(str.c_str(),
667 random(0, test.size()),
668 random(0, str.size())));
671 template <class String> void clause11_21_4_7_4_c(String & test) {
673 randomString(&str, maxString);
674 Num2String(test, test.find_first_of(str.c_str(),
675 random(0, test.size())));
678 template <class String> void clause11_21_4_7_4_d(String & test) {
679 Num2String(test, test.find_first_of(
681 random(0, test.size())));
684 template <class String> void clause11_21_4_7_5_a(String & test) {
686 randomString(&str, maxString);
687 Num2String(test, test.find_last_of(str,
688 random(0, test.size())));
691 template <class String> void clause11_21_4_7_5_b(String & test) {
693 randomString(&str, maxString);
694 Num2String(test, test.find_last_of(str.c_str(),
695 random(0, test.size()),
696 random(0, str.size())));
699 template <class String> void clause11_21_4_7_5_c(String & test) {
701 randomString(&str, maxString);
702 Num2String(test, test.find_last_of(str.c_str(),
703 random(0, test.size())));
706 template <class String> void clause11_21_4_7_5_d(String & test) {
707 Num2String(test, test.find_last_of(
709 random(0, test.size())));
712 template <class String> void clause11_21_4_7_6_a(String & test) {
714 randomString(&str, maxString);
715 Num2String(test, test.find_first_not_of(str,
716 random(0, test.size())));
719 template <class String> void clause11_21_4_7_6_b(String & test) {
721 randomString(&str, maxString);
722 Num2String(test, test.find_first_not_of(str.c_str(),
723 random(0, test.size()),
724 random(0, str.size())));
727 template <class String> void clause11_21_4_7_6_c(String & test) {
729 randomString(&str, maxString);
730 Num2String(test, test.find_first_not_of(str.c_str(),
731 random(0, test.size())));
734 template <class String> void clause11_21_4_7_6_d(String & test) {
735 Num2String(test, test.find_first_not_of(
737 random(0, test.size())));
740 template <class String> void clause11_21_4_7_7_a(String & test) {
742 randomString(&str, maxString);
743 Num2String(test, test.find_last_not_of(str,
744 random(0, test.size())));
747 template <class String> void clause11_21_4_7_7_b(String & test) {
749 randomString(&str, maxString);
750 Num2String(test, test.find_last_not_of(str.c_str(),
751 random(0, test.size()),
752 random(0, str.size())));
755 template <class String> void clause11_21_4_7_7_c(String & test) {
757 randomString(&str, maxString);
758 Num2String(test, test.find_last_not_of(str.c_str(),
759 random(0, test.size())));
762 template <class String> void clause11_21_4_7_7_d(String & test) {
763 Num2String(test, test.find_last_not_of(
765 random(0, test.size())));
768 template <class String> void clause11_21_4_7_8(String & test) {
769 test = test.substr(random(0, test.size()), random(0, test.size()));
772 template <class String> void clause11_21_4_7_9_a(String & test) {
774 randomString(&s, maxString);
775 int tristate = test.compare(s);
776 if (tristate > 0) tristate = 1;
777 else if (tristate < 0) tristate = 2;
778 Num2String(test, tristate);
781 template <class String> void clause11_21_4_7_9_b(String & test) {
783 randomString(&s, maxString);
784 int tristate = test.compare(
785 random(0, test.size()),
786 random(0, test.size()),
788 if (tristate > 0) tristate = 1;
789 else if (tristate < 0) tristate = 2;
790 Num2String(test, tristate);
793 template <class String> void clause11_21_4_7_9_c(String & test) {
795 randomString(&str, maxString);
796 int tristate = test.compare(
797 random(0, test.size()),
798 random(0, test.size()),
800 random(0, str.size()),
801 random(0, str.size()));
802 if (tristate > 0) tristate = 1;
803 else if (tristate < 0) tristate = 2;
804 Num2String(test, tristate);
807 template <class String> void clause11_21_4_7_9_d(String & test) {
809 randomString(&s, maxString);
810 int tristate = test.compare(s.c_str());
811 if (tristate > 0) tristate = 1;
812 else if (tristate < 0) tristate = 2;
813 Num2String(test, tristate);
816 template <class String> void clause11_21_4_7_9_e(String & test) {
818 randomString(&str, maxString);
819 int tristate = test.compare(
820 random(0, test.size()),
821 random(0, test.size()),
823 random(0, str.size()));
824 if (tristate > 0) tristate = 1;
825 else if (tristate < 0) tristate = 2;
826 Num2String(test, tristate);
829 template <class String> void clause11_21_4_8_1_a(String & test) {
831 randomString(&s1, maxString);
833 randomString(&s2, maxString);
837 template <class String> void clause11_21_4_8_1_b(String & test) {
839 randomString(&s, maxString);
841 randomString(&s1, maxString);
842 test = s.c_str() + s1;
845 template <class String> void clause11_21_4_8_1_c(String & test) {
847 randomString(&s, maxString);
848 test = typename String::value_type(random('a', 'z')) + s;
851 template <class String> void clause11_21_4_8_1_d(String & test) {
853 randomString(&s, maxString);
855 randomString(&s1, maxString);
856 test = s + s1.c_str();
859 template <class String> void clause11_21_4_8_1_e(String & test) {
861 randomString(&s, maxString);
863 randomString(&s1, maxString);
864 test = s + s1.c_str();
867 template <class String> void clause11_21_4_8_1_f(String & test) {
869 randomString(&s, maxString);
870 test = s + typename String::value_type(random('a', 'z'));
873 // Numbering here is from C++11
874 template <class String> void clause11_21_4_8_9_a(String & test) {
875 basic_stringstream<typename String::value_type> stst(test.c_str());
883 TEST(FBString, testAllClauses) {
884 EXPECT_TRUE(1) << "Starting with seed: " << seed;
888 folly::basic_fbstring<wchar_t> wc;
889 #define TEST_CLAUSE(x) \
891 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x; \
895 wr = std::wstring(r.begin(), r.end()); \
896 wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \
897 auto localSeed = seed + count; \
898 rng = RandomT(localSeed); \
900 rng = RandomT(localSeed); \
903 << "Lengths: " << r.size() << " vs. " << c.size() \
904 << "\nReference: '" << r << "'" \
905 << "\nActual: '" << c.data()[0] << "'"; \
906 rng = RandomT(localSeed); \
908 int wret = wcslen(wc.c_str()); \
910 int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \
911 if (ret == wret) mb[wret] = '\0'; \
912 const char *mc = c.c_str(); \
913 std::string one(mb); \
914 std::string two(mc); \
915 EXPECT_EQ(one, two); \
916 } while (++count % 100 != 0)
919 TEST_CLAUSE(21_4_2_a);
920 TEST_CLAUSE(21_4_2_b);
921 TEST_CLAUSE(21_4_2_c);
922 TEST_CLAUSE(21_4_2_d);
923 TEST_CLAUSE(21_4_2_e);
924 TEST_CLAUSE(21_4_2_f);
925 TEST_CLAUSE(21_4_2_g);
926 TEST_CLAUSE(21_4_2_h);
927 TEST_CLAUSE(21_4_2_i);
928 TEST_CLAUSE(21_4_2_j);
929 TEST_CLAUSE(21_4_2_k);
930 TEST_CLAUSE(21_4_2_l);
931 TEST_CLAUSE(21_4_2_lprime);
932 TEST_CLAUSE(21_4_2_m);
933 TEST_CLAUSE(21_4_2_n);
937 TEST_CLAUSE(21_4_6_1);
938 TEST_CLAUSE(21_4_6_2);
939 TEST_CLAUSE(21_4_6_3_a);
940 TEST_CLAUSE(21_4_6_3_b);
941 TEST_CLAUSE(21_4_6_3_c);
942 TEST_CLAUSE(21_4_6_3_d);
943 TEST_CLAUSE(21_4_6_3_e);
944 TEST_CLAUSE(21_4_6_3_f);
945 TEST_CLAUSE(21_4_6_3_g);
946 TEST_CLAUSE(21_4_6_3_h);
947 TEST_CLAUSE(21_4_6_3_i);
948 TEST_CLAUSE(21_4_6_3_j);
949 TEST_CLAUSE(21_4_6_3_k);
950 TEST_CLAUSE(21_4_6_4);
951 TEST_CLAUSE(21_4_6_5);
952 TEST_CLAUSE(21_4_6_6);
953 TEST_CLAUSE(21_4_6_7);
954 TEST_CLAUSE(21_4_6_8);
955 TEST_CLAUSE(21_4_7_1);
957 TEST_CLAUSE(21_4_7_2_a);
958 TEST_CLAUSE(21_4_7_2_b);
959 TEST_CLAUSE(21_4_7_2_c);
960 TEST_CLAUSE(21_4_7_2_d);
961 TEST_CLAUSE(21_4_7_3_a);
962 TEST_CLAUSE(21_4_7_3_b);
963 TEST_CLAUSE(21_4_7_3_c);
964 TEST_CLAUSE(21_4_7_3_d);
965 TEST_CLAUSE(21_4_7_4_a);
966 TEST_CLAUSE(21_4_7_4_b);
967 TEST_CLAUSE(21_4_7_4_c);
968 TEST_CLAUSE(21_4_7_4_d);
969 TEST_CLAUSE(21_4_7_5_a);
970 TEST_CLAUSE(21_4_7_5_b);
971 TEST_CLAUSE(21_4_7_5_c);
972 TEST_CLAUSE(21_4_7_5_d);
973 TEST_CLAUSE(21_4_7_6_a);
974 TEST_CLAUSE(21_4_7_6_b);
975 TEST_CLAUSE(21_4_7_6_c);
976 TEST_CLAUSE(21_4_7_6_d);
977 TEST_CLAUSE(21_4_7_7_a);
978 TEST_CLAUSE(21_4_7_7_b);
979 TEST_CLAUSE(21_4_7_7_c);
980 TEST_CLAUSE(21_4_7_7_d);
981 TEST_CLAUSE(21_4_7_8);
982 TEST_CLAUSE(21_4_7_9_a);
983 TEST_CLAUSE(21_4_7_9_b);
984 TEST_CLAUSE(21_4_7_9_c);
985 TEST_CLAUSE(21_4_7_9_d);
986 TEST_CLAUSE(21_4_7_9_e);
987 TEST_CLAUSE(21_4_8_1_a);
988 TEST_CLAUSE(21_4_8_1_b);
989 TEST_CLAUSE(21_4_8_1_c);
990 TEST_CLAUSE(21_4_8_1_d);
991 TEST_CLAUSE(21_4_8_1_e);
992 TEST_CLAUSE(21_4_8_1_f);
993 TEST_CLAUSE(21_4_8_9_a);
996 TEST(FBString, testGetline) {
998 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
999 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
1000 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1001 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1002 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1003 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1004 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1005 tristique senectus et netus et malesuada fames ac turpis \n\
1006 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1007 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1008 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1009 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1010 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1011 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1012 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1013 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1014 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1015 char f[] = "/tmp/fbstring_testing.XXXXXX";
1016 int fd = mkstemp(f);
1017 EXPECT_TRUE(fd > 0);
1020 std::ofstream out(f);
1022 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1027 boost::split(v, s1, boost::is_any_of("\n"));
1032 EXPECT_TRUE(!getline(input, line).fail());
1033 EXPECT_EQ(line, *i);
1039 TEST(FBString, testMoveCtor) {
1040 // Move constructor. Make sure we allocate a large string, so the
1041 // small string optimization doesn't kick in.
1042 auto size = random(100, 2000);
1043 fbstring s(size, 'a');
1044 fbstring test = std::move(s);
1045 EXPECT_TRUE(s.empty());
1046 EXPECT_EQ(size, test.size());
1049 TEST(FBString, testMoveAssign) {
1050 // Move constructor. Make sure we allocate a large string, so the
1051 // small string optimization doesn't kick in.
1052 auto size = random(100, 2000);
1053 fbstring s(size, 'a');
1055 test = std::move(s);
1056 EXPECT_TRUE(s.empty());
1057 EXPECT_EQ(size, test.size());
1060 TEST(FBString, testMoveOperatorPlusLhs) {
1061 // Make sure we allocate a large string, so the
1062 // small string optimization doesn't kick in.
1063 auto size1 = random(100, 2000);
1064 auto size2 = random(100, 2000);
1065 fbstring s1(size1, 'a');
1066 fbstring s2(size2, 'b');
1068 test = std::move(s1) + s2;
1069 EXPECT_TRUE(s1.empty());
1070 EXPECT_EQ(size1 + size2, test.size());
1073 TEST(FBString, testMoveOperatorPlusRhs) {
1074 // Make sure we allocate a large string, so the
1075 // small string optimization doesn't kick in.
1076 auto size1 = random(100, 2000);
1077 auto size2 = random(100, 2000);
1078 fbstring s1(size1, 'a');
1079 fbstring s2(size2, 'b');
1081 test = s1 + std::move(s2);
1082 EXPECT_EQ(size1 + size2, test.size());
1085 // The GNU C++ standard library throws an std::logic_error when an std::string
1086 // is constructed with a null pointer. Verify that we mirror this behavior.
1088 // N.B. We behave this way even if the C++ library being used is something
1089 // other than libstdc++. Someday if we deem it important to present
1090 // identical undefined behavior for other platforms, we can re-visit this.
1091 TEST(FBString, testConstructionFromLiteralZero) {
1092 EXPECT_THROW(fbstring s(0), std::logic_error);
1095 TEST(FBString, testFixedBugs) {
1097 fbstring str(1337, 'f');
1101 EXPECT_EQ(str.front(), 'f');
1103 { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
1104 fbstring str(1337, 'f');
1105 for (int i = 0; i < 2; ++i) {
1108 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1114 fbstring str(1337, 'f');
1119 fbstring str(1337, 'f');
1125 folly::basic_fbstring<wchar_t> s;
1126 EXPECT_EQ(0, s.size());
1129 fbstring str(1337, 'f');
1130 std::swap(str, str);
1131 EXPECT_EQ(1337, str.size());
1133 { // D1012196, --allocator=malloc
1134 fbstring str(128, 'f');
1135 str.clear(); // Empty medium string.
1136 fbstring copy(str); // Medium string of 0 capacity.
1137 copy.push_back('b');
1138 EXPECT_GE(copy.capacity(), 1);
1142 TEST(FBString, findWithNpos) {
1143 fbstring fbstr("localhost:80");
1144 EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
1147 TEST(FBString, testHash) {
1154 std::hash<fbstring> hashfunc;
1155 EXPECT_NE(hashfunc(a), hashfunc(b));
1158 TEST(FBString, testFrontBack) {
1159 fbstring str("hello");
1160 EXPECT_EQ(str.front(), 'h');
1161 EXPECT_EQ(str.back(), 'o');
1163 EXPECT_EQ(str.front(), 'H');
1165 EXPECT_EQ(str.back(), 'O');
1166 EXPECT_EQ(str, "HellO");
1169 TEST(FBString, noexcept) {
1170 EXPECT_TRUE(noexcept(fbstring()));
1171 // std::move is not marked noexcept in gcc 4.6, sigh
1172 #if __GNUC_PREREQ(4, 7)
1174 EXPECT_FALSE(noexcept(fbstring(x)));
1175 EXPECT_TRUE(noexcept(fbstring(std::move(x))));
1177 EXPECT_FALSE(noexcept(y = x));
1178 EXPECT_TRUE(noexcept(y = std::move(x)));
1182 int main(int argc, char** argv) {
1183 testing::InitGoogleTest(&argc, argv);
1184 google::ParseCommandLineFlags(&argc, &argv, true);
1185 return RUN_ALL_TESTS();