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/Random.h"
34 #include "folly/Conv.h"
37 using namespace folly;
39 static const int seed = folly::randomNumberSeed();
40 typedef boost::mt19937 RandomT;
41 static RandomT rng(seed);
42 static const size_t maxString = 100;
43 static const bool avoidAliasing = true;
45 template <class Integral1, class Integral2>
46 Integral2 random(Integral1 low, Integral2 up) {
47 boost::uniform_int<> range(low, up);
51 template <class String>
52 void randomString(String* toFill, unsigned int maxSize = 1000) {
54 toFill->resize(random(0, maxSize));
55 FOR_EACH (i, *toFill) {
56 *i = random('a', 'z');
60 template <class String, class Integral>
61 void Num2String(String& str, Integral n) {
63 std::string tmp = folly::to<std::string>(n);
64 str = String(tmp.begin(), tmp.end());
67 std::list<char> RandomList(unsigned int maxSize) {
68 std::list<char> lst(random(0u, maxSize));
69 std::list<char>::iterator i = lst.begin();
70 for (; i != lst.end(); ++i) {
71 *i = random('a', 'z');
76 ////////////////////////////////////////////////////////////////////////////////
78 ////////////////////////////////////////////////////////////////////////////////
80 template <class String> void clause11_21_4_2_a(String & test) {
81 test.String::~String();
84 template <class String> void clause11_21_4_2_b(String & test) {
86 assert(test2 == test);
88 template <class String> void clause11_21_4_2_c(String & test) {
89 // Test move constructor. There is a more specialized test, see
90 // TEST(FBString, testMoveCtor)
92 String test2(std::move(donor));
93 EXPECT_EQ(test2, test);
94 // Technically not required, but all implementations that actually
95 // support move will move large strings. Make a guess for 128 as the
96 // maximum small string optimization that's reasonable.
97 EXPECT_LE(donor.size(), 128);
99 template <class String> void clause11_21_4_2_d(String & test) {
100 // Copy constructor with position and length
101 const size_t pos = random(0, test.size());
102 String s(test, pos, random(0, 9)
103 ? random(0, (size_t)(test.size() - pos))
104 : String::npos); // test for npos, too, in 10% of the cases
107 template <class String> void clause11_21_4_2_e(String & test) {
108 // Constructor from char*, size_t
110 pos = random(0, test.size()),
111 n = random(0, test.size() - pos);
112 String before(test.data(), test.size());
113 String s(test.c_str() + pos, n);
114 String after(test.data(), test.size());
115 EXPECT_EQ(before, after);
118 template <class String> void clause11_21_4_2_f(String & test) {
119 // Constructor from char*
121 pos = random(0, test.size()),
122 n = random(0, test.size() - pos);
123 String before(test.data(), test.size());
124 String s(test.c_str() + pos);
125 String after(test.data(), test.size());
126 EXPECT_EQ(before, after);
129 template <class String> void clause11_21_4_2_g(String & test) {
130 // Constructor from size_t, char
131 const size_t n = random(0, test.size());
132 const auto c = test.front();
135 template <class String> void clause11_21_4_2_h(String & test) {
136 // Constructors from various iterator pairs
137 // Constructor from char*, char*
138 String s1(test.begin(), test.end());
140 String s2(test.data(), test.data() + test.size());
142 // Constructor from other iterators
144 for (auto c : test) lst.push_back(c);
145 String s3(lst.begin(), lst.end());
147 // Constructor from wchar_t iterators
148 std::list<wchar_t> lst1;
149 for (auto c : test) lst1.push_back(c);
150 String s4(lst1.begin(), lst1.end());
152 // Constructor from wchar_t pointers
156 fbstring s5(t, t + 2);;
159 template <class String> void clause11_21_4_2_i(String & test) {
160 // From initializer_list<char>
161 std::initializer_list<typename String::value_type>
162 il = { 'h', 'e', 'l', 'l', 'o' };
166 template <class String> void clause11_21_4_2_j(String & test) {
167 // Assignment from const String&
168 auto size = random(0, 2000);
169 String s(size, '\0');
170 EXPECT_EQ(s.size(), size);
171 FOR_EACH_RANGE (i, 0, s.size()) {
172 s[i] = random('a', 'z');
176 template <class String> void clause11_21_4_2_k(String & test) {
177 // Assignment from String&&
178 auto size = random(0, 2000);
179 String s(size, '\0');
180 EXPECT_EQ(s.size(), size);
181 FOR_EACH_RANGE (i, 0, s.size()) {
182 s[i] = random('a', 'z');
185 if (typeid(String) == typeid(fbstring)) {
186 EXPECT_LE(s.size(), 128);
189 template <class String> void clause11_21_4_2_l(String & test) {
190 // Assignment from char*
191 String s(random(0, 1000), '\0');
193 for (; i != s.size(); ++i) {
194 s[i] = random('a', 'z');
198 template <class String> void clause11_21_4_2_lprime(String & test) {
200 const size_t pos = random(0, test.size());
202 test = String(test.c_str() + pos);
204 test = test.c_str() + pos;
207 template <class String> void clause11_21_4_2_m(String & test) {
208 // Assignment from char
209 test = random('a', 'z');
211 template <class String> void clause11_21_4_2_n(String & test) {
212 // Assignment from initializer_list<char>
213 initializer_list<typename String::value_type>
214 il = { 'h', 'e', 'l', 'l', 'o' };
218 template <class String> void clause11_21_4_3(String & test) {
219 // Iterators. The code below should leave test unchanged
220 EXPECT_EQ(test.size(), test.end() - test.begin());
221 EXPECT_EQ(test.size(), test.rend() - test.rbegin());
222 EXPECT_EQ(test.size(), test.cend() - test.cbegin());
223 EXPECT_EQ(test.size(), test.crend() - test.crbegin());
225 auto s = test.size();
226 test.resize(test.end() - test.begin());
227 EXPECT_EQ(s, test.size());
228 test.resize(test.rend() - test.rbegin());
229 EXPECT_EQ(s, test.size());
232 template <class String> void clause11_21_4_4(String & test) {
233 // exercise capacity, size, max_size
234 EXPECT_EQ(test.size(), test.length());
235 EXPECT_LE(test.size(), test.max_size());
236 EXPECT_LE(test.capacity(), test.max_size());
237 EXPECT_LE(test.size(), test.capacity());
239 // exercise shrink_to_fit. Nonbinding request so we can't really do
240 // much beyond calling it.
242 copy.reserve(copy.capacity() * 3);
243 copy.shrink_to_fit();
244 EXPECT_EQ(copy, test);
247 string empty("empty");
248 string notempty("not empty");
249 if (test.empty()) test = String(empty.begin(), empty.end());
250 else test = String(notempty.begin(), notempty.end());
253 template <class String> void clause11_21_4_5(String & test) {
254 // exercise element access
256 EXPECT_EQ(test[0], test.front());
257 EXPECT_EQ(test[test.size() - 1], test.back());
258 auto const i = random(0, test.size() - 1);
259 EXPECT_EQ(test[i], test.at(i));
264 template <class String> void clause11_21_4_6_1(String & test) {
265 // 21.3.5 modifiers (+=)
267 randomString(&test1);
268 assert(test1.size() == char_traits
269 <typename String::value_type>::length(test1.c_str()));
270 auto len = test.size();
272 EXPECT_EQ(test.size(), test1.size() + len);
273 FOR_EACH_RANGE (i, 0, test1.size()) {
274 EXPECT_EQ(test[len + i], test1[i]);
276 // aliasing modifiers
278 auto dt = test2.data();
279 auto sz = test.c_str();
281 EXPECT_EQ(memcmp(sz, dt, len), 0);
282 String copy(test.data(), test.size());
283 EXPECT_EQ(char_traits
284 <typename String::value_type>::length(test.c_str()), len);
287 EXPECT_EQ(test.size(), 2 * len);
288 EXPECT_EQ(char_traits
289 <typename String::value_type>::length(test.c_str()), 2 * len);
290 FOR_EACH_RANGE (i, 0, len) {
291 EXPECT_EQ(test[i], copy[i]);
292 EXPECT_EQ(test[i], test[len + i]);
295 EXPECT_EQ(char_traits
296 <typename String::value_type>::length(test.c_str()), len);
298 auto const pos = random(0, test.size());
299 EXPECT_EQ(char_traits
300 <typename String::value_type>::length(test.c_str() + pos), len - pos);
302 String addMe(test.c_str() + pos);
303 EXPECT_EQ(addMe.size(), len - pos);
306 test += test.c_str() + pos;
308 EXPECT_EQ(test.size(), 2 * len - pos);
311 test += random('a', 'z');
312 EXPECT_EQ(test.size(), len + 1);
314 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
318 template <class String> void clause11_21_4_6_2(String & test) {
319 // 21.3.5 modifiers (append, push_back)
322 // Test with a small string first
323 char c = random('a', 'z');
325 EXPECT_EQ(s[s.size() - 1], c);
326 EXPECT_EQ(s.size(), 1);
327 s.resize(s.size() - 1);
329 randomString(&s, maxString);
331 randomString(&s, maxString);
332 test.append(s, random(0, s.size()), random(0, maxString));
333 randomString(&s, maxString);
334 test.append(s.c_str(), random(0, s.size()));
335 randomString(&s, maxString);
336 test.append(s.c_str());
337 test.append(random(0, maxString), random('a', 'z'));
338 std::list<char> lst(RandomList(maxString));
339 test.append(lst.begin(), lst.end());
340 c = random('a', 'z');
342 EXPECT_EQ(test[test.size() - 1], c);
344 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
348 template <class String> void clause11_21_4_6_3_a(String & test) {
355 test.assign(std::move(s));
356 if (typeid(String) == typeid(fbstring)) {
357 EXPECT_LE(s.size(), 128);
361 template <class String> void clause11_21_4_6_3_b(String & test) {
364 randomString(&s, maxString);
365 test.assign(s, random(0, s.size()), random(0, maxString));
368 template <class String> void clause11_21_4_6_3_c(String & test) {
371 randomString(&s, maxString);
372 test.assign(s.c_str(), random(0, s.size()));
375 template <class String> void clause11_21_4_6_3_d(String & test) {
378 randomString(&s, maxString);
379 test.assign(s.c_str());
382 template <class String> void clause11_21_4_6_3_e(String & test) {
385 randomString(&s, maxString);
386 test.assign(random(0, maxString), random('a', 'z'));
389 template <class String> void clause11_21_4_6_3_f(String & test) {
390 // assign from bidirectional iterator
391 std::list<char> lst(RandomList(maxString));
392 test.assign(lst.begin(), lst.end());
395 template <class String> void clause11_21_4_6_3_g(String & test) {
396 // assign from aliased source
400 template <class String> void clause11_21_4_6_3_h(String & test) {
401 // assign from aliased source
402 test.assign(test, random(0, test.size()), random(0, maxString));
405 template <class String> void clause11_21_4_6_3_i(String & test) {
406 // assign from aliased source
407 test.assign(test.c_str(), random(0, test.size()));
410 template <class String> void clause11_21_4_6_3_j(String & test) {
411 // assign from aliased source
412 test.assign(test.c_str());
415 template <class String> void clause11_21_4_6_3_k(String & test) {
416 // assign from initializer_list
417 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
421 template <class String> void clause11_21_4_6_4(String & test) {
424 randomString(&s, maxString);
425 test.insert(random(0, test.size()), s);
426 randomString(&s, maxString);
427 test.insert(random(0, test.size()),
428 s, random(0, s.size()),
429 random(0, maxString));
430 randomString(&s, maxString);
431 test.insert(random(0, test.size()),
432 s.c_str(), random(0, s.size()));
433 randomString(&s, maxString);
434 test.insert(random(0, test.size()), s.c_str());
435 test.insert(random(0, test.size()),
436 random(0, maxString), random('a', 'z'));
437 typename String::size_type pos = random(0, test.size());
438 typename String::iterator res =
439 test.insert(test.begin() + pos, random('a', 'z'));
440 EXPECT_EQ(res - test.begin(), pos);
441 std::list<char> lst(RandomList(maxString));
442 pos = random(0, test.size());
443 // Uncomment below to see a bug in gcc
444 /*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
445 // insert from initializer_list
446 initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
447 pos = random(0, test.size());
448 // Uncomment below to see a bug in gcc
449 /*res = */test.insert(test.begin() + pos, il);
452 template <class String> void clause11_21_4_6_5(String & test) {
453 // erase and pop_back
455 test.erase(random(0, test.size()), random(0, maxString));
458 // TODO: is erase(end()) allowed?
459 test.erase(test.begin() + random(0, test.size() - 1));
462 auto const i = test.begin() + random(0, test.size());
463 if (i != test.end()) {
464 test.erase(i, i + random(0, size_t(test.end() - i)));
468 // Can't test pop_back with std::string, doesn't support it yet.
473 template <class String> void clause11_21_4_6_6(String & test) {
474 auto pos = random(0, test.size());
476 test.replace(pos, random(0, test.size() - pos),
479 test.replace(pos, random(0, test.size() - pos), test);
481 pos = random(0, test.size());
483 randomString(&s, maxString);
484 test.replace(pos, pos + random(0, test.size() - pos), s);
485 auto pos1 = random(0, test.size());
486 auto pos2 = random(0, test.size());
488 test.replace(pos1, pos1 + random(0, test.size() - pos1),
490 pos2, pos2 + random(0, test.size() - pos2));
492 test.replace(pos1, pos1 + random(0, test.size() - pos1),
493 test, pos2, pos2 + random(0, test.size() - pos2));
495 pos1 = random(0, test.size());
497 randomString(&str, maxString);
498 pos2 = random(0, str.size());
499 test.replace(pos1, pos1 + random(0, test.size() - pos1),
500 str, pos2, pos2 + random(0, str.size() - pos2));
501 pos = random(0, test.size());
503 test.replace(pos, random(0, test.size() - pos),
504 String(test).c_str(), test.size());
506 test.replace(pos, random(0, test.size() - pos),
507 test.c_str(), test.size());
509 pos = random(0, test.size());
510 randomString(&str, maxString);
511 test.replace(pos, pos + random(0, test.size() - pos),
512 str.c_str(), str.size());
513 pos = random(0, test.size());
514 randomString(&str, maxString);
515 test.replace(pos, pos + random(0, test.size() - pos),
517 pos = random(0, test.size());
518 test.replace(pos, random(0, test.size() - pos),
519 random(0, maxString), random('a', 'z'));
520 pos = random(0, test.size());
524 test.begin() + pos + random(0, test.size() - pos),
529 test.begin() + pos + random(0, test.size() - pos),
532 pos = random(0, test.size());
536 test.begin() + pos + random(0, test.size() - pos),
537 String(test).c_str(),
538 test.size() - random(0, test.size()));
542 test.begin() + pos + random(0, test.size() - pos),
544 test.size() - random(0, test.size()));
546 pos = random(0, test.size());
547 auto const n = random(0, test.size() - pos);
548 typename String::iterator b = test.begin();
550 randomString(&str1, maxString);
551 const String & str3 = str1;
552 const typename String::value_type* ss = str3.c_str();
557 pos = random(0, test.size());
560 test.begin() + pos + random(0, test.size() - pos),
561 random(0, maxString), random('a', 'z'));
564 template <class String> void clause11_21_4_6_7(String & test) {
565 std::vector<typename String::value_type>
566 vec(random(0, maxString));
570 random(0, test.size()));
573 template <class String> void clause11_21_4_6_8(String & test) {
575 randomString(&s, maxString);
579 template <class String> void clause11_21_4_7_1(String & test) {
580 // 21.3.6 string operations
581 // exercise c_str() and data()
582 assert(test.c_str() == test.data());
583 // exercise get_allocator()
585 randomString(&s, maxString);
586 assert(test.get_allocator() == s.get_allocator());
589 template <class String> void clause11_21_4_7_2_a(String & test) {
590 String str = test.substr(
591 random(0, test.size()),
592 random(0, test.size()));
593 Num2String(test, test.find(str, random(0, test.size())));
596 template <class String> void clause11_21_4_7_2_b(String & test) {
597 auto from = random(0, test.size());
598 auto length = random(0, test.size() - from);
599 String str = test.substr(from, length);
600 Num2String(test, test.find(str.c_str(),
601 random(0, test.size()),
602 random(0, str.size())));
605 template <class String> void clause11_21_4_7_2_c(String & test) {
606 String str = test.substr(
607 random(0, test.size()),
608 random(0, test.size()));
609 Num2String(test, test.find(str.c_str(),
610 random(0, test.size())));
613 template <class String> void clause11_21_4_7_2_d(String & test) {
614 Num2String(test, test.find(
616 random(0, test.size())));
619 template <class String> void clause11_21_4_7_3_a(String & test) {
620 String str = test.substr(
621 random(0, test.size()),
622 random(0, test.size()));
623 Num2String(test, test.rfind(str, random(0, test.size())));
626 template <class String> void clause11_21_4_7_3_b(String & test) {
627 String str = test.substr(
628 random(0, test.size()),
629 random(0, test.size()));
630 Num2String(test, test.rfind(str.c_str(),
631 random(0, test.size()),
632 random(0, str.size())));
635 template <class String> void clause11_21_4_7_3_c(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())));
643 template <class String> void clause11_21_4_7_3_d(String & test) {
644 Num2String(test, test.rfind(
646 random(0, test.size())));
649 template <class String> void clause11_21_4_7_4_a(String & test) {
651 randomString(&str, maxString);
652 Num2String(test, test.find_first_of(str,
653 random(0, test.size())));
656 template <class String> void clause11_21_4_7_4_b(String & test) {
658 randomString(&str, maxString);
659 Num2String(test, test.find_first_of(str.c_str(),
660 random(0, test.size()),
661 random(0, str.size())));
664 template <class String> void clause11_21_4_7_4_c(String & test) {
666 randomString(&str, maxString);
667 Num2String(test, test.find_first_of(str.c_str(),
668 random(0, test.size())));
671 template <class String> void clause11_21_4_7_4_d(String & test) {
672 Num2String(test, test.find_first_of(
674 random(0, test.size())));
677 template <class String> void clause11_21_4_7_5_a(String & test) {
679 randomString(&str, maxString);
680 Num2String(test, test.find_last_of(str,
681 random(0, test.size())));
684 template <class String> void clause11_21_4_7_5_b(String & test) {
686 randomString(&str, maxString);
687 Num2String(test, test.find_last_of(str.c_str(),
688 random(0, test.size()),
689 random(0, str.size())));
692 template <class String> void clause11_21_4_7_5_c(String & test) {
694 randomString(&str, maxString);
695 Num2String(test, test.find_last_of(str.c_str(),
696 random(0, test.size())));
699 template <class String> void clause11_21_4_7_5_d(String & test) {
700 Num2String(test, test.find_last_of(
702 random(0, test.size())));
705 template <class String> void clause11_21_4_7_6_a(String & test) {
707 randomString(&str, maxString);
708 Num2String(test, test.find_first_not_of(str,
709 random(0, test.size())));
712 template <class String> void clause11_21_4_7_6_b(String & test) {
714 randomString(&str, maxString);
715 Num2String(test, test.find_first_not_of(str.c_str(),
716 random(0, test.size()),
717 random(0, str.size())));
720 template <class String> void clause11_21_4_7_6_c(String & test) {
722 randomString(&str, maxString);
723 Num2String(test, test.find_first_not_of(str.c_str(),
724 random(0, test.size())));
727 template <class String> void clause11_21_4_7_6_d(String & test) {
728 Num2String(test, test.find_first_not_of(
730 random(0, test.size())));
733 template <class String> void clause11_21_4_7_7_a(String & test) {
735 randomString(&str, maxString);
736 Num2String(test, test.find_last_not_of(str,
737 random(0, test.size())));
740 template <class String> void clause11_21_4_7_7_b(String & test) {
742 randomString(&str, maxString);
743 Num2String(test, test.find_last_not_of(str.c_str(),
744 random(0, test.size()),
745 random(0, str.size())));
748 template <class String> void clause11_21_4_7_7_c(String & test) {
750 randomString(&str, maxString);
751 Num2String(test, test.find_last_not_of(str.c_str(),
752 random(0, test.size())));
755 template <class String> void clause11_21_4_7_7_d(String & test) {
756 Num2String(test, test.find_last_not_of(
758 random(0, test.size())));
761 template <class String> void clause11_21_4_7_8(String & test) {
762 test = test.substr(random(0, test.size()), random(0, test.size()));
765 template <class String> void clause11_21_4_7_9_a(String & test) {
767 randomString(&s, maxString);
768 int tristate = test.compare(s);
769 if (tristate > 0) tristate = 1;
770 else if (tristate < 0) tristate = 2;
771 Num2String(test, tristate);
774 template <class String> void clause11_21_4_7_9_b(String & test) {
776 randomString(&s, maxString);
777 int tristate = test.compare(
778 random(0, test.size()),
779 random(0, test.size()),
781 if (tristate > 0) tristate = 1;
782 else if (tristate < 0) tristate = 2;
783 Num2String(test, tristate);
786 template <class String> void clause11_21_4_7_9_c(String & test) {
788 randomString(&str, maxString);
789 int tristate = test.compare(
790 random(0, test.size()),
791 random(0, test.size()),
793 random(0, str.size()),
794 random(0, str.size()));
795 if (tristate > 0) tristate = 1;
796 else if (tristate < 0) tristate = 2;
797 Num2String(test, tristate);
800 template <class String> void clause11_21_4_7_9_d(String & test) {
802 randomString(&s, maxString);
803 int tristate = test.compare(s.c_str());
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_e(String & test) {
811 randomString(&str, maxString);
812 int tristate = test.compare(
813 random(0, test.size()),
814 random(0, test.size()),
816 random(0, str.size()));
817 if (tristate > 0) tristate = 1;
818 else if (tristate < 0) tristate = 2;
819 Num2String(test, tristate);
822 template <class String> void clause11_21_4_8_1_a(String & test) {
824 randomString(&s1, maxString);
826 randomString(&s2, maxString);
830 template <class String> void clause11_21_4_8_1_b(String & test) {
832 randomString(&s, maxString);
834 randomString(&s1, maxString);
835 test = s.c_str() + s1;
838 template <class String> void clause11_21_4_8_1_c(String & test) {
840 randomString(&s, maxString);
841 test = typename String::value_type(random('a', 'z')) + s;
844 template <class String> void clause11_21_4_8_1_d(String & test) {
846 randomString(&s, maxString);
848 randomString(&s1, maxString);
849 test = s + s1.c_str();
852 template <class String> void clause11_21_4_8_1_e(String & test) {
854 randomString(&s, maxString);
856 randomString(&s1, maxString);
857 test = s + s1.c_str();
860 template <class String> void clause11_21_4_8_1_f(String & test) {
862 randomString(&s, maxString);
863 test = s + typename String::value_type(random('a', 'z'));
866 // Numbering here is from C++11
867 template <class String> void clause11_21_4_8_9_a(String & test) {
868 basic_stringstream<typename String::value_type> stst(test.c_str());
876 TEST(FBString, testAllClauses) {
877 EXPECT_TRUE(1) << "Starting with seed: " << seed;
881 folly::basic_fbstring<wchar_t> wc;
882 #define TEST_CLAUSE(x) \
884 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x; \
888 wr = std::wstring(r.begin(), r.end()); \
889 wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \
890 auto localSeed = seed + count; \
891 rng = RandomT(localSeed); \
893 rng = RandomT(localSeed); \
896 << "Lengths: " << r.size() << " vs. " << c.size() \
897 << "\nReference: '" << r << "'" \
898 << "\nActual: '" << c.data()[0] << "'"; \
899 rng = RandomT(localSeed); \
901 int wret = wcslen(wc.c_str()); \
903 int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \
904 if (ret == wret) mb[wret] = '\0'; \
905 const char *mc = c.c_str(); \
906 std::string one(mb); \
907 std::string two(mc); \
908 EXPECT_EQ(one, two); \
909 } while (++count % 100 != 0)
912 TEST_CLAUSE(21_4_2_a);
913 TEST_CLAUSE(21_4_2_b);
914 TEST_CLAUSE(21_4_2_c);
915 TEST_CLAUSE(21_4_2_d);
916 TEST_CLAUSE(21_4_2_e);
917 TEST_CLAUSE(21_4_2_f);
918 TEST_CLAUSE(21_4_2_g);
919 TEST_CLAUSE(21_4_2_h);
920 TEST_CLAUSE(21_4_2_i);
921 TEST_CLAUSE(21_4_2_j);
922 TEST_CLAUSE(21_4_2_k);
923 TEST_CLAUSE(21_4_2_l);
924 TEST_CLAUSE(21_4_2_lprime);
925 TEST_CLAUSE(21_4_2_m);
926 TEST_CLAUSE(21_4_2_n);
930 TEST_CLAUSE(21_4_6_1);
931 TEST_CLAUSE(21_4_6_2);
932 TEST_CLAUSE(21_4_6_3_a);
933 TEST_CLAUSE(21_4_6_3_b);
934 TEST_CLAUSE(21_4_6_3_c);
935 TEST_CLAUSE(21_4_6_3_d);
936 TEST_CLAUSE(21_4_6_3_e);
937 TEST_CLAUSE(21_4_6_3_f);
938 TEST_CLAUSE(21_4_6_3_g);
939 TEST_CLAUSE(21_4_6_3_h);
940 TEST_CLAUSE(21_4_6_3_i);
941 TEST_CLAUSE(21_4_6_3_j);
942 TEST_CLAUSE(21_4_6_3_k);
943 TEST_CLAUSE(21_4_6_4);
944 TEST_CLAUSE(21_4_6_5);
945 TEST_CLAUSE(21_4_6_6);
946 TEST_CLAUSE(21_4_6_7);
947 TEST_CLAUSE(21_4_6_8);
948 TEST_CLAUSE(21_4_7_1);
950 TEST_CLAUSE(21_4_7_2_a);
951 TEST_CLAUSE(21_4_7_2_b);
952 TEST_CLAUSE(21_4_7_2_c);
953 TEST_CLAUSE(21_4_7_2_d);
954 TEST_CLAUSE(21_4_7_3_a);
955 TEST_CLAUSE(21_4_7_3_b);
956 TEST_CLAUSE(21_4_7_3_c);
957 TEST_CLAUSE(21_4_7_3_d);
958 TEST_CLAUSE(21_4_7_4_a);
959 TEST_CLAUSE(21_4_7_4_b);
960 TEST_CLAUSE(21_4_7_4_c);
961 TEST_CLAUSE(21_4_7_4_d);
962 TEST_CLAUSE(21_4_7_5_a);
963 TEST_CLAUSE(21_4_7_5_b);
964 TEST_CLAUSE(21_4_7_5_c);
965 TEST_CLAUSE(21_4_7_5_d);
966 TEST_CLAUSE(21_4_7_6_a);
967 TEST_CLAUSE(21_4_7_6_b);
968 TEST_CLAUSE(21_4_7_6_c);
969 TEST_CLAUSE(21_4_7_6_d);
970 TEST_CLAUSE(21_4_7_7_a);
971 TEST_CLAUSE(21_4_7_7_b);
972 TEST_CLAUSE(21_4_7_7_c);
973 TEST_CLAUSE(21_4_7_7_d);
974 TEST_CLAUSE(21_4_7_8);
975 TEST_CLAUSE(21_4_7_9_a);
976 TEST_CLAUSE(21_4_7_9_b);
977 TEST_CLAUSE(21_4_7_9_c);
978 TEST_CLAUSE(21_4_7_9_d);
979 TEST_CLAUSE(21_4_7_9_e);
980 TEST_CLAUSE(21_4_8_1_a);
981 TEST_CLAUSE(21_4_8_1_b);
982 TEST_CLAUSE(21_4_8_1_c);
983 TEST_CLAUSE(21_4_8_1_d);
984 TEST_CLAUSE(21_4_8_1_e);
985 TEST_CLAUSE(21_4_8_1_f);
986 TEST_CLAUSE(21_4_8_9_a);
989 TEST(FBString, testGetline) {
991 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
992 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
993 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
994 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
995 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
996 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
997 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
998 tristique senectus et netus et malesuada fames ac turpis \n\
999 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1000 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1001 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1002 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1003 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1004 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1005 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1006 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1007 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1008 char f[] = "/tmp/fbstring_testing.XXXXXX";
1009 int fd = mkstemp(f);
1010 EXPECT_TRUE(fd > 0);
1013 std::ofstream out(f);
1015 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1020 boost::split(v, s1, boost::is_any_of("\n"));
1025 EXPECT_TRUE(getline(input, line));
1026 EXPECT_EQ(line, *i);
1032 TEST(FBString, testMoveCtor) {
1033 // Move constructor. Make sure we allocate a large string, so the
1034 // small string optimization doesn't kick in.
1035 auto size = random(100, 2000);
1036 fbstring s(size, 'a');
1037 fbstring test = std::move(s);
1038 EXPECT_TRUE(s.empty());
1039 EXPECT_EQ(size, test.size());
1042 TEST(FBString, testMoveAssign) {
1043 // Move constructor. Make sure we allocate a large string, so the
1044 // small string optimization doesn't kick in.
1045 auto size = random(100, 2000);
1046 fbstring s(size, 'a');
1048 test = std::move(s);
1049 EXPECT_TRUE(s.empty());
1050 EXPECT_EQ(size, test.size());
1053 TEST(FBString, testMoveOperatorPlusLhs) {
1054 // Make sure we allocate a large string, so the
1055 // small string optimization doesn't kick in.
1056 auto size1 = random(100, 2000);
1057 auto size2 = random(100, 2000);
1058 fbstring s1(size1, 'a');
1059 fbstring s2(size2, 'b');
1061 test = std::move(s1) + s2;
1062 EXPECT_TRUE(s1.empty());
1063 EXPECT_EQ(size1 + size2, test.size());
1066 TEST(FBString, testMoveOperatorPlusRhs) {
1067 // Make sure we allocate a large string, so the
1068 // small string optimization doesn't kick in.
1069 auto size1 = random(100, 2000);
1070 auto size2 = random(100, 2000);
1071 fbstring s1(size1, 'a');
1072 fbstring s2(size2, 'b');
1074 test = s1 + std::move(s2);
1075 EXPECT_EQ(size1 + size2, test.size());
1078 TEST(FBString, testConstructionFromLiteralZero) {
1082 } catch (const std::logic_error&) {
1090 } catch (const std::logic_error& e) {
1096 TEST(FBString, testFixedBugs) {
1098 fbstring str(1337, 'f');
1102 EXPECT_EQ(str.front(), 'f');
1104 { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
1105 fbstring str(1337, 'f');
1106 for (int i = 0; i < 2; ++i) {
1109 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1115 fbstring str(1337, 'f');
1120 fbstring str(1337, 'f');
1126 folly::basic_fbstring<wchar_t> s;
1127 EXPECT_EQ(0, s.size());
1130 fbstring str(1337, 'f');
1131 std::swap(str, str);
1132 EXPECT_EQ(1337, str.size());
1137 TEST(FBString, testHash) {
1144 std::hash<fbstring> hashfunc;
1145 EXPECT_NE(hashfunc(a), hashfunc(b));
1148 TEST(FBString, testFrontBack) {
1149 fbstring str("hello");
1150 EXPECT_EQ(str.front(), 'h');
1151 EXPECT_EQ(str.back(), 'o');
1153 EXPECT_EQ(str.front(), 'H');
1155 EXPECT_EQ(str.back(), 'O');
1156 EXPECT_EQ(str, "HellO");
1159 int main(int argc, char** argv) {
1160 testing::InitGoogleTest(&argc, argv);
1161 google::ParseCommandLineFlags(&argc, &argv, true);
1162 return RUN_ALL_TESTS();