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);
451 // Test with actual input iterators
453 ss << "hello cruel world";
454 auto i = istream_iterator<char>(ss);
455 test.insert(test.begin(), i, istream_iterator<char>());
458 template <class String> void clause11_21_4_6_5(String & test) {
459 // erase and pop_back
461 test.erase(random(0, test.size()), random(0, maxString));
464 // TODO: is erase(end()) allowed?
465 test.erase(test.begin() + random(0, test.size() - 1));
468 auto const i = test.begin() + random(0, test.size());
469 if (i != test.end()) {
470 test.erase(i, i + random(0, size_t(test.end() - i)));
474 // Can't test pop_back with std::string, doesn't support it yet.
479 template <class String> void clause11_21_4_6_6(String & test) {
480 auto pos = random(0, test.size());
482 test.replace(pos, random(0, test.size() - pos),
485 test.replace(pos, random(0, test.size() - pos), test);
487 pos = random(0, test.size());
489 randomString(&s, maxString);
490 test.replace(pos, pos + random(0, test.size() - pos), s);
491 auto pos1 = random(0, test.size());
492 auto pos2 = random(0, test.size());
494 test.replace(pos1, pos1 + random(0, test.size() - pos1),
496 pos2, pos2 + random(0, test.size() - pos2));
498 test.replace(pos1, pos1 + random(0, test.size() - pos1),
499 test, pos2, pos2 + random(0, test.size() - pos2));
501 pos1 = random(0, test.size());
503 randomString(&str, maxString);
504 pos2 = random(0, str.size());
505 test.replace(pos1, pos1 + random(0, test.size() - pos1),
506 str, pos2, pos2 + random(0, str.size() - pos2));
507 pos = random(0, test.size());
509 test.replace(pos, random(0, test.size() - pos),
510 String(test).c_str(), test.size());
512 test.replace(pos, random(0, test.size() - pos),
513 test.c_str(), test.size());
515 pos = random(0, test.size());
516 randomString(&str, maxString);
517 test.replace(pos, pos + random(0, test.size() - pos),
518 str.c_str(), str.size());
519 pos = random(0, test.size());
520 randomString(&str, maxString);
521 test.replace(pos, pos + random(0, test.size() - pos),
523 pos = random(0, test.size());
524 test.replace(pos, random(0, test.size() - pos),
525 random(0, maxString), random('a', 'z'));
526 pos = random(0, test.size());
530 test.begin() + pos + random(0, test.size() - pos),
535 test.begin() + pos + random(0, test.size() - pos),
538 pos = random(0, test.size());
542 test.begin() + pos + random(0, test.size() - pos),
543 String(test).c_str(),
544 test.size() - random(0, test.size()));
548 test.begin() + pos + random(0, test.size() - pos),
550 test.size() - random(0, test.size()));
552 pos = random(0, test.size());
553 auto const n = random(0, test.size() - pos);
554 typename String::iterator b = test.begin();
556 randomString(&str1, maxString);
557 const String & str3 = str1;
558 const typename String::value_type* ss = str3.c_str();
563 pos = random(0, test.size());
566 test.begin() + pos + random(0, test.size() - pos),
567 random(0, maxString), random('a', 'z'));
570 template <class String> void clause11_21_4_6_7(String & test) {
571 std::vector<typename String::value_type>
572 vec(random(0, maxString));
576 random(0, test.size()));
579 template <class String> void clause11_21_4_6_8(String & test) {
581 randomString(&s, maxString);
585 template <class String> void clause11_21_4_7_1(String & test) {
586 // 21.3.6 string operations
587 // exercise c_str() and data()
588 assert(test.c_str() == test.data());
589 // exercise get_allocator()
591 randomString(&s, maxString);
592 assert(test.get_allocator() == s.get_allocator());
595 template <class String> void clause11_21_4_7_2_a(String & test) {
596 String str = test.substr(
597 random(0, test.size()),
598 random(0, test.size()));
599 Num2String(test, test.find(str, random(0, test.size())));
602 template <class String> void clause11_21_4_7_2_b(String & test) {
603 auto from = random(0, test.size());
604 auto length = random(0, test.size() - from);
605 String str = test.substr(from, length);
606 Num2String(test, test.find(str.c_str(),
607 random(0, test.size()),
608 random(0, str.size())));
611 template <class String> void clause11_21_4_7_2_c(String & test) {
612 String str = test.substr(
613 random(0, test.size()),
614 random(0, test.size()));
615 Num2String(test, test.find(str.c_str(),
616 random(0, test.size())));
619 template <class String> void clause11_21_4_7_2_d(String & test) {
620 Num2String(test, test.find(
622 random(0, test.size())));
625 template <class String> void clause11_21_4_7_3_a(String & test) {
626 String str = test.substr(
627 random(0, test.size()),
628 random(0, test.size()));
629 Num2String(test, test.rfind(str, random(0, test.size())));
632 template <class String> void clause11_21_4_7_3_b(String & test) {
633 String str = test.substr(
634 random(0, test.size()),
635 random(0, test.size()));
636 Num2String(test, test.rfind(str.c_str(),
637 random(0, test.size()),
638 random(0, str.size())));
641 template <class String> void clause11_21_4_7_3_c(String & test) {
642 String str = test.substr(
643 random(0, test.size()),
644 random(0, test.size()));
645 Num2String(test, test.rfind(str.c_str(),
646 random(0, test.size())));
649 template <class String> void clause11_21_4_7_3_d(String & test) {
650 Num2String(test, test.rfind(
652 random(0, test.size())));
655 template <class String> void clause11_21_4_7_4_a(String & test) {
657 randomString(&str, maxString);
658 Num2String(test, test.find_first_of(str,
659 random(0, test.size())));
662 template <class String> void clause11_21_4_7_4_b(String & test) {
664 randomString(&str, maxString);
665 Num2String(test, test.find_first_of(str.c_str(),
666 random(0, test.size()),
667 random(0, str.size())));
670 template <class String> void clause11_21_4_7_4_c(String & test) {
672 randomString(&str, maxString);
673 Num2String(test, test.find_first_of(str.c_str(),
674 random(0, test.size())));
677 template <class String> void clause11_21_4_7_4_d(String & test) {
678 Num2String(test, test.find_first_of(
680 random(0, test.size())));
683 template <class String> void clause11_21_4_7_5_a(String & test) {
685 randomString(&str, maxString);
686 Num2String(test, test.find_last_of(str,
687 random(0, test.size())));
690 template <class String> void clause11_21_4_7_5_b(String & test) {
692 randomString(&str, maxString);
693 Num2String(test, test.find_last_of(str.c_str(),
694 random(0, test.size()),
695 random(0, str.size())));
698 template <class String> void clause11_21_4_7_5_c(String & test) {
700 randomString(&str, maxString);
701 Num2String(test, test.find_last_of(str.c_str(),
702 random(0, test.size())));
705 template <class String> void clause11_21_4_7_5_d(String & test) {
706 Num2String(test, test.find_last_of(
708 random(0, test.size())));
711 template <class String> void clause11_21_4_7_6_a(String & test) {
713 randomString(&str, maxString);
714 Num2String(test, test.find_first_not_of(str,
715 random(0, test.size())));
718 template <class String> void clause11_21_4_7_6_b(String & test) {
720 randomString(&str, maxString);
721 Num2String(test, test.find_first_not_of(str.c_str(),
722 random(0, test.size()),
723 random(0, str.size())));
726 template <class String> void clause11_21_4_7_6_c(String & test) {
728 randomString(&str, maxString);
729 Num2String(test, test.find_first_not_of(str.c_str(),
730 random(0, test.size())));
733 template <class String> void clause11_21_4_7_6_d(String & test) {
734 Num2String(test, test.find_first_not_of(
736 random(0, test.size())));
739 template <class String> void clause11_21_4_7_7_a(String & test) {
741 randomString(&str, maxString);
742 Num2String(test, test.find_last_not_of(str,
743 random(0, test.size())));
746 template <class String> void clause11_21_4_7_7_b(String & test) {
748 randomString(&str, maxString);
749 Num2String(test, test.find_last_not_of(str.c_str(),
750 random(0, test.size()),
751 random(0, str.size())));
754 template <class String> void clause11_21_4_7_7_c(String & test) {
756 randomString(&str, maxString);
757 Num2String(test, test.find_last_not_of(str.c_str(),
758 random(0, test.size())));
761 template <class String> void clause11_21_4_7_7_d(String & test) {
762 Num2String(test, test.find_last_not_of(
764 random(0, test.size())));
767 template <class String> void clause11_21_4_7_8(String & test) {
768 test = test.substr(random(0, test.size()), random(0, test.size()));
771 template <class String> void clause11_21_4_7_9_a(String & test) {
773 randomString(&s, maxString);
774 int tristate = test.compare(s);
775 if (tristate > 0) tristate = 1;
776 else if (tristate < 0) tristate = 2;
777 Num2String(test, tristate);
780 template <class String> void clause11_21_4_7_9_b(String & test) {
782 randomString(&s, maxString);
783 int tristate = test.compare(
784 random(0, test.size()),
785 random(0, test.size()),
787 if (tristate > 0) tristate = 1;
788 else if (tristate < 0) tristate = 2;
789 Num2String(test, tristate);
792 template <class String> void clause11_21_4_7_9_c(String & test) {
794 randomString(&str, maxString);
795 int tristate = test.compare(
796 random(0, test.size()),
797 random(0, test.size()),
799 random(0, str.size()),
800 random(0, str.size()));
801 if (tristate > 0) tristate = 1;
802 else if (tristate < 0) tristate = 2;
803 Num2String(test, tristate);
806 template <class String> void clause11_21_4_7_9_d(String & test) {
808 randomString(&s, maxString);
809 int tristate = test.compare(s.c_str());
810 if (tristate > 0) tristate = 1;
811 else if (tristate < 0) tristate = 2;
812 Num2String(test, tristate);
815 template <class String> void clause11_21_4_7_9_e(String & test) {
817 randomString(&str, maxString);
818 int tristate = test.compare(
819 random(0, test.size()),
820 random(0, test.size()),
822 random(0, str.size()));
823 if (tristate > 0) tristate = 1;
824 else if (tristate < 0) tristate = 2;
825 Num2String(test, tristate);
828 template <class String> void clause11_21_4_8_1_a(String & test) {
830 randomString(&s1, maxString);
832 randomString(&s2, maxString);
836 template <class String> void clause11_21_4_8_1_b(String & test) {
838 randomString(&s, maxString);
840 randomString(&s1, maxString);
841 test = s.c_str() + s1;
844 template <class String> void clause11_21_4_8_1_c(String & test) {
846 randomString(&s, maxString);
847 test = typename String::value_type(random('a', 'z')) + s;
850 template <class String> void clause11_21_4_8_1_d(String & test) {
852 randomString(&s, maxString);
854 randomString(&s1, maxString);
855 test = s + s1.c_str();
858 template <class String> void clause11_21_4_8_1_e(String & test) {
860 randomString(&s, maxString);
862 randomString(&s1, maxString);
863 test = s + s1.c_str();
866 template <class String> void clause11_21_4_8_1_f(String & test) {
868 randomString(&s, maxString);
869 test = s + typename String::value_type(random('a', 'z'));
872 // Numbering here is from C++11
873 template <class String> void clause11_21_4_8_9_a(String & test) {
874 basic_stringstream<typename String::value_type> stst(test.c_str());
882 TEST(FBString, testAllClauses) {
883 EXPECT_TRUE(1) << "Starting with seed: " << seed;
887 folly::basic_fbstring<wchar_t> wc;
888 #define TEST_CLAUSE(x) \
890 if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x; \
894 wr = std::wstring(r.begin(), r.end()); \
895 wc = folly::basic_fbstring<wchar_t>(wr.c_str()); \
896 auto localSeed = seed + count; \
897 rng = RandomT(localSeed); \
899 rng = RandomT(localSeed); \
902 << "Lengths: " << r.size() << " vs. " << c.size() \
903 << "\nReference: '" << r << "'" \
904 << "\nActual: '" << c.data()[0] << "'"; \
905 rng = RandomT(localSeed); \
907 int wret = wcslen(wc.c_str()); \
909 int ret = wcstombs(mb, wc.c_str(), sizeof(mb)); \
910 if (ret == wret) mb[wret] = '\0'; \
911 const char *mc = c.c_str(); \
912 std::string one(mb); \
913 std::string two(mc); \
914 EXPECT_EQ(one, two); \
915 } while (++count % 100 != 0)
918 TEST_CLAUSE(21_4_2_a);
919 TEST_CLAUSE(21_4_2_b);
920 TEST_CLAUSE(21_4_2_c);
921 TEST_CLAUSE(21_4_2_d);
922 TEST_CLAUSE(21_4_2_e);
923 TEST_CLAUSE(21_4_2_f);
924 TEST_CLAUSE(21_4_2_g);
925 TEST_CLAUSE(21_4_2_h);
926 TEST_CLAUSE(21_4_2_i);
927 TEST_CLAUSE(21_4_2_j);
928 TEST_CLAUSE(21_4_2_k);
929 TEST_CLAUSE(21_4_2_l);
930 TEST_CLAUSE(21_4_2_lprime);
931 TEST_CLAUSE(21_4_2_m);
932 TEST_CLAUSE(21_4_2_n);
936 TEST_CLAUSE(21_4_6_1);
937 TEST_CLAUSE(21_4_6_2);
938 TEST_CLAUSE(21_4_6_3_a);
939 TEST_CLAUSE(21_4_6_3_b);
940 TEST_CLAUSE(21_4_6_3_c);
941 TEST_CLAUSE(21_4_6_3_d);
942 TEST_CLAUSE(21_4_6_3_e);
943 TEST_CLAUSE(21_4_6_3_f);
944 TEST_CLAUSE(21_4_6_3_g);
945 TEST_CLAUSE(21_4_6_3_h);
946 TEST_CLAUSE(21_4_6_3_i);
947 TEST_CLAUSE(21_4_6_3_j);
948 TEST_CLAUSE(21_4_6_3_k);
949 TEST_CLAUSE(21_4_6_4);
950 TEST_CLAUSE(21_4_6_5);
951 TEST_CLAUSE(21_4_6_6);
952 TEST_CLAUSE(21_4_6_7);
953 TEST_CLAUSE(21_4_6_8);
954 TEST_CLAUSE(21_4_7_1);
956 TEST_CLAUSE(21_4_7_2_a);
957 TEST_CLAUSE(21_4_7_2_b);
958 TEST_CLAUSE(21_4_7_2_c);
959 TEST_CLAUSE(21_4_7_2_d);
960 TEST_CLAUSE(21_4_7_3_a);
961 TEST_CLAUSE(21_4_7_3_b);
962 TEST_CLAUSE(21_4_7_3_c);
963 TEST_CLAUSE(21_4_7_3_d);
964 TEST_CLAUSE(21_4_7_4_a);
965 TEST_CLAUSE(21_4_7_4_b);
966 TEST_CLAUSE(21_4_7_4_c);
967 TEST_CLAUSE(21_4_7_4_d);
968 TEST_CLAUSE(21_4_7_5_a);
969 TEST_CLAUSE(21_4_7_5_b);
970 TEST_CLAUSE(21_4_7_5_c);
971 TEST_CLAUSE(21_4_7_5_d);
972 TEST_CLAUSE(21_4_7_6_a);
973 TEST_CLAUSE(21_4_7_6_b);
974 TEST_CLAUSE(21_4_7_6_c);
975 TEST_CLAUSE(21_4_7_6_d);
976 TEST_CLAUSE(21_4_7_7_a);
977 TEST_CLAUSE(21_4_7_7_b);
978 TEST_CLAUSE(21_4_7_7_c);
979 TEST_CLAUSE(21_4_7_7_d);
980 TEST_CLAUSE(21_4_7_8);
981 TEST_CLAUSE(21_4_7_9_a);
982 TEST_CLAUSE(21_4_7_9_b);
983 TEST_CLAUSE(21_4_7_9_c);
984 TEST_CLAUSE(21_4_7_9_d);
985 TEST_CLAUSE(21_4_7_9_e);
986 TEST_CLAUSE(21_4_8_1_a);
987 TEST_CLAUSE(21_4_8_1_b);
988 TEST_CLAUSE(21_4_8_1_c);
989 TEST_CLAUSE(21_4_8_1_d);
990 TEST_CLAUSE(21_4_8_1_e);
991 TEST_CLAUSE(21_4_8_1_f);
992 TEST_CLAUSE(21_4_8_9_a);
995 TEST(FBString, testGetline) {
997 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras accumsan \n\
998 elit ut urna consectetur in sagittis mi auctor. Nulla facilisi. In nec \n\
999 dolor leo, vitae imperdiet neque. Donec ut erat mauris, a faucibus \n\
1000 elit. Integer consectetur gravida augue, sit amet mattis mauris auctor \n\
1001 sed. Morbi congue libero eu nunc sodales adipiscing. In lectus nunc, \n\
1002 vulputate a fringilla at, venenatis quis justo. Proin eu velit \n\
1003 nibh. Maecenas vitae tellus eros. Pellentesque habitant morbi \n\
1004 tristique senectus et netus et malesuada fames ac turpis \n\
1005 egestas. Vivamus faucibus feugiat consequat. Donec fermentum neque sit \n\
1006 amet ligula suscipit porta. Phasellus facilisis felis in purus luctus \n\
1007 quis posuere leo tempor. Nam nunc purus, luctus a pharetra ut, \n\
1008 placerat at dui. Donec imperdiet, diam quis convallis pulvinar, dui \n\
1009 est commodo lorem, ut tincidunt diam nibh et nibh. Maecenas nec velit \n\
1010 massa, ut accumsan magna. Donec imperdiet tempor nisi et \n\
1011 laoreet. Phasellus lectus quam, ultricies ut tincidunt in, dignissim \n\
1012 id eros. Mauris vulputate tortor nec neque pellentesque sagittis quis \n\
1013 sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam.";
1014 char f[] = "/tmp/fbstring_testing.XXXXXX";
1015 int fd = mkstemp(f);
1016 EXPECT_TRUE(fd > 0);
1019 std::ofstream out(f);
1021 EXPECT_TRUE(0) << "Couldn't write to temp file.";
1026 boost::split(v, s1, boost::is_any_of("\n"));
1031 EXPECT_TRUE(getline(input, line));
1032 EXPECT_EQ(line, *i);
1038 TEST(FBString, testMoveCtor) {
1039 // Move constructor. Make sure we allocate a large string, so the
1040 // small string optimization doesn't kick in.
1041 auto size = random(100, 2000);
1042 fbstring s(size, 'a');
1043 fbstring test = std::move(s);
1044 EXPECT_TRUE(s.empty());
1045 EXPECT_EQ(size, test.size());
1048 TEST(FBString, testMoveAssign) {
1049 // Move constructor. Make sure we allocate a large string, so the
1050 // small string optimization doesn't kick in.
1051 auto size = random(100, 2000);
1052 fbstring s(size, 'a');
1054 test = std::move(s);
1055 EXPECT_TRUE(s.empty());
1056 EXPECT_EQ(size, test.size());
1059 TEST(FBString, testMoveOperatorPlusLhs) {
1060 // Make sure we allocate a large string, so the
1061 // small string optimization doesn't kick in.
1062 auto size1 = random(100, 2000);
1063 auto size2 = random(100, 2000);
1064 fbstring s1(size1, 'a');
1065 fbstring s2(size2, 'b');
1067 test = std::move(s1) + s2;
1068 EXPECT_TRUE(s1.empty());
1069 EXPECT_EQ(size1 + size2, test.size());
1072 TEST(FBString, testMoveOperatorPlusRhs) {
1073 // Make sure we allocate a large string, so the
1074 // small string optimization doesn't kick in.
1075 auto size1 = random(100, 2000);
1076 auto size2 = random(100, 2000);
1077 fbstring s1(size1, 'a');
1078 fbstring s2(size2, 'b');
1080 test = s1 + std::move(s2);
1081 EXPECT_EQ(size1 + size2, test.size());
1084 TEST(FBString, testConstructionFromLiteralZero) {
1088 } catch (const std::logic_error&) {
1096 } catch (const std::logic_error& e) {
1102 TEST(FBString, testFixedBugs) {
1104 fbstring str(1337, 'f');
1108 EXPECT_EQ(str.front(), 'f');
1110 { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
1111 fbstring str(1337, 'f');
1112 for (int i = 0; i < 2; ++i) {
1115 EXPECT_EQ(cp.c_str()[cp.size()], '\0');
1121 fbstring str(1337, 'f');
1126 fbstring str(1337, 'f');
1132 folly::basic_fbstring<wchar_t> s;
1133 EXPECT_EQ(0, s.size());
1136 fbstring str(1337, 'f');
1137 std::swap(str, str);
1138 EXPECT_EQ(1337, str.size());
1143 TEST(FBString, testHash) {
1150 std::hash<fbstring> hashfunc;
1151 EXPECT_NE(hashfunc(a), hashfunc(b));
1154 TEST(FBString, testFrontBack) {
1155 fbstring str("hello");
1156 EXPECT_EQ(str.front(), 'h');
1157 EXPECT_EQ(str.back(), 'o');
1159 EXPECT_EQ(str.front(), 'H');
1161 EXPECT_EQ(str.back(), 'O');
1162 EXPECT_EQ(str, "HellO");
1165 int main(int argc, char** argv) {
1166 testing::InitGoogleTest(&argc, argv);
1167 google::ParseCommandLineFlags(&argc, &argv, true);
1168 return RUN_ALL_TESTS();