/*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
//
// Author: andrei.alexandrescu@fb.com
-#include "folly/FBString.h"
+#include <folly/FBString.h>
#include <cstdlib>
#include <list>
#include <fstream>
+#include <iomanip>
#include <boost/algorithm/string.hpp>
#include <boost/random.hpp>
#include <gtest/gtest.h>
#include <gflags/gflags.h>
-#include "folly/Foreach.h"
-#include "folly/Random.h"
+#include <folly/Foreach.h>
+#include <folly/Portability.h>
+#include <folly/Random.h>
+#include <folly/Conv.h>
using namespace std;
using namespace folly;
template <class String, class Integral>
void Num2String(String& str, Integral n) {
- str.resize(30, '\0');
- sprintf(&str[0], "%lu", static_cast<unsigned long>(n));
- str.resize(strlen(str.c_str()));
+
+ std::string tmp = folly::to<std::string>(n);
+ str = String(tmp.begin(), tmp.end());
}
std::list<char> RandomList(unsigned int maxSize) {
// Tests begin here
////////////////////////////////////////////////////////////////////////////////
-template <class String> void clause_21_3_1_a(String & test) {
+template <class String> void clause11_21_4_2_a(String & test) {
test.String::~String();
new(&test) String();
}
-template <class String> void clause_21_3_1_b(String & test) {
- // Copy constructor
+template <class String> void clause11_21_4_2_b(String & test) {
+ String test2(test);
+ assert(test2 == test);
+}
+template <class String> void clause11_21_4_2_c(String & test) {
+ // Test move constructor. There is a more specialized test, see
+ // TEST(FBString, testMoveCtor)
+ String donor(test);
+ String test2(std::move(donor));
+ EXPECT_EQ(test2, test);
+ // Technically not required, but all implementations that actually
+ // support move will move large strings. Make a guess for 128 as the
+ // maximum small string optimization that's reasonable.
+ EXPECT_LE(donor.size(), 128);
+}
+template <class String> void clause11_21_4_2_d(String & test) {
+ // Copy constructor with position and length
const size_t pos = random(0, test.size());
- String s(test, pos, random(0, (size_t)(test.size() - pos)));
+ String s(test, pos, random(0, 9)
+ ? random(0, (size_t)(test.size() - pos))
+ : String::npos); // test for npos, too, in 10% of the cases
test = s;
}
-template <class String> void clause_21_3_1_c(String & test) {
+template <class String> void clause11_21_4_2_e(String & test) {
// Constructor from char*, size_t
const size_t
pos = random(0, test.size()),
n = random(0, test.size() - pos);
- std::string before(test.data(), test.size());
+ String before(test.data(), test.size());
String s(test.c_str() + pos, n);
- std::string after(test.data(), test.size());
+ String after(test.data(), test.size());
EXPECT_EQ(before, after);
-
+ test.swap(s);
+}
+template <class String> void clause11_21_4_2_f(String & test) {
+ // Constructor from char*
+ const size_t pos = random(0, test.size());
+ String before(test.data(), test.size());
+ String s(test.c_str() + pos);
+ String after(test.data(), test.size());
+ EXPECT_EQ(before, after);
+ test.swap(s);
+}
+template <class String> void clause11_21_4_2_g(String & test) {
+ // Constructor from size_t, char
+ const size_t n = random(0, test.size());
+ const auto c = test.front();
+ test = String(n, c);
+}
+template <class String> void clause11_21_4_2_h(String & test) {
+ // Constructors from various iterator pairs
// Constructor from char*, char*
String s1(test.begin(), test.end());
EXPECT_EQ(test, s1);
String s2(test.data(), test.data() + test.size());
EXPECT_EQ(test, s2);
-
- // Constructor from iterators
+ // Constructor from other iterators
std::list<char> lst;
for (auto c : test) lst.push_back(c);
String s3(lst.begin(), lst.end());
EXPECT_EQ(test, s3);
-
// Constructor from wchar_t iterators
std::list<wchar_t> lst1;
for (auto c : test) lst1.push_back(c);
String s4(lst1.begin(), lst1.end());
EXPECT_EQ(test, s4);
-
// Constructor from wchar_t pointers
wchar_t t[20];
t[0] = 'a';
t[1] = 'b';
- String s5(t, t + 2);;
+ fbstring s5(t, t + 2);;
EXPECT_EQ("ab", s5);
-
- test = s;
}
-template <class String> void clause_21_3_1_d(String & test) {
- // Assignment
+template <class String> void clause11_21_4_2_i(String & test) {
+ // From initializer_list<char>
+ std::initializer_list<typename String::value_type>
+ il = { 'h', 'e', 'l', 'l', 'o' };
+ String s(il);
+ test.swap(s);
+}
+template <class String> void clause11_21_4_2_j(String & test) {
+ // Assignment from const String&
auto size = random(0, 2000);
String s(size, '\0');
EXPECT_EQ(s.size(), size);
}
test = s;
}
-template <class String> void clause_21_3_1_e(String & test) {
+template <class String> void clause11_21_4_2_k(String & test) {
+ // Assignment from String&&
+ auto size = random(0, 2000);
+ String s(size, '\0');
+ EXPECT_EQ(s.size(), size);
+ FOR_EACH_RANGE (i, 0, s.size()) {
+ s[i] = random('a', 'z');
+ }
+ test = std::move(s);
+ if (typeid(String) == typeid(fbstring)) {
+ EXPECT_LE(s.size(), 128);
+ }
+}
+template <class String> void clause11_21_4_2_l(String & test) {
// Assignment from char*
String s(random(0, 1000), '\0');
size_t i = 0;
}
test = s.c_str();
}
-template <class String> void clause_21_3_1_f(String & test) {
+template <class String> void clause11_21_4_2_lprime(String & test) {
// Aliased assign
const size_t pos = random(0, test.size());
if (avoidAliasing) {
test = test.c_str() + pos;
}
}
-template <class String> void clause_21_3_1_g(String & test) {
+template <class String> void clause11_21_4_2_m(String & test) {
// Assignment from char
test = random('a', 'z');
}
+template <class String> void clause11_21_4_2_n(String & test) {
+ // Assignment from initializer_list<char>
+ initializer_list<typename String::value_type>
+ il = { 'h', 'e', 'l', 'l', 'o' };
+ test = il;
+}
-template <class String> void clause_21_3_2(String & test) {
+template <class String> void clause11_21_4_3(String & test) {
// Iterators. The code below should leave test unchanged
EXPECT_EQ(test.size(), test.end() - test.begin());
EXPECT_EQ(test.size(), test.rend() - test.rbegin());
+ EXPECT_EQ(test.size(), test.cend() - test.cbegin());
+ EXPECT_EQ(test.size(), test.crend() - test.crbegin());
auto s = test.size();
test.resize(test.end() - test.begin());
EXPECT_EQ(s, test.size());
}
-template <class String> void clause_21_3_3(String & test) {
+template <class String> void clause11_21_4_4(String & test) {
// exercise capacity, size, max_size
EXPECT_EQ(test.size(), test.length());
EXPECT_LE(test.size(), test.max_size());
EXPECT_LE(test.capacity(), test.max_size());
EXPECT_LE(test.size(), test.capacity());
+
+ // exercise shrink_to_fit. Nonbinding request so we can't really do
+ // much beyond calling it.
+ auto copy = test;
+ copy.reserve(copy.capacity() * 3);
+ copy.shrink_to_fit();
+ EXPECT_EQ(copy, test);
+
// exercise empty
- if (test.empty()) test = "empty";
- else test = "not empty";
+ string empty("empty");
+ string notempty("not empty");
+ if (test.empty()) test = String(empty.begin(), empty.end());
+ else test = String(notempty.begin(), notempty.end());
}
-template <class String> void clause_21_3_4(String & test) {
- // exercise element access 21.3.4
+template <class String> void clause11_21_4_5(String & test) {
+ // exercise element access
if (!test.empty()) {
+ EXPECT_EQ(test[0], test.front());
+ EXPECT_EQ(test[test.size() - 1], test.back());
auto const i = random(0, test.size() - 1);
EXPECT_EQ(test[i], test.at(i));
test = test[i];
}
}
-template <class String> void clause_21_3_5_a(String & test) {
+template <class String> void clause11_21_4_6_1(String & test) {
// 21.3.5 modifiers (+=)
String test1;
randomString(&test1);
- assert(test1.size() == strlen(test1.c_str()));
+ assert(test1.size() == char_traits
+ <typename String::value_type>::length(test1.c_str()));
auto len = test.size();
test += test1;
EXPECT_EQ(test.size(), test1.size() + len);
len = test.size();
EXPECT_EQ(memcmp(sz, dt, len), 0);
String copy(test.data(), test.size());
- EXPECT_EQ(strlen(test.c_str()), len);
+ EXPECT_EQ(char_traits
+ <typename String::value_type>::length(test.c_str()), len);
test += test;
//test.append(test);
EXPECT_EQ(test.size(), 2 * len);
- EXPECT_EQ(strlen(test.c_str()), 2 * len);
+ EXPECT_EQ(char_traits
+ <typename String::value_type>::length(test.c_str()), 2 * len);
FOR_EACH_RANGE (i, 0, len) {
EXPECT_EQ(test[i], copy[i]);
EXPECT_EQ(test[i], test[len + i]);
}
len = test.size();
- EXPECT_EQ(strlen(test.c_str()), len);
+ EXPECT_EQ(char_traits
+ <typename String::value_type>::length(test.c_str()), len);
// more aliasing
auto const pos = random(0, test.size());
- EXPECT_EQ(strlen(test.c_str() + pos), len - pos);
+ EXPECT_EQ(char_traits
+ <typename String::value_type>::length(test.c_str() + pos), len - pos);
if (avoidAliasing) {
String addMe(test.c_str() + pos);
EXPECT_EQ(addMe.size(), len - pos);
len = test.size();
test += random('a', 'z');
EXPECT_EQ(test.size(), len + 1);
+ // initializer_list
+ initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
+ test += il;
}
-template <class String> void clause_21_3_5_b(String & test) {
+template <class String> void clause11_21_4_6_2(String & test) {
// 21.3.5 modifiers (append, push_back)
String s;
c = random('a', 'z');
test.push_back(c);
EXPECT_EQ(test[test.size() - 1], c);
+ // initializer_list
+ initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
+ test.append(il);
}
-template <class String> void clause_21_3_5_c(String & test) {
+template <class String> void clause11_21_4_6_3_a(String & test) {
// assign
String s;
randomString(&s);
test.assign(s);
+ EXPECT_EQ(test, s);
+ // move assign
+ test.assign(std::move(s));
+ if (typeid(String) == typeid(fbstring)) {
+ EXPECT_LE(s.size(), 128);
+ }
}
-template <class String> void clause_21_3_5_d(String & test) {
+template <class String> void clause11_21_4_6_3_b(String & test) {
// assign
String s;
randomString(&s, maxString);
test.assign(s, random(0, s.size()), random(0, maxString));
}
-template <class String> void clause_21_3_5_e(String & test) {
+template <class String> void clause11_21_4_6_3_c(String & test) {
// assign
String s;
randomString(&s, maxString);
test.assign(s.c_str(), random(0, s.size()));
}
-template <class String> void clause_21_3_5_f(String & test) {
+template <class String> void clause11_21_4_6_3_d(String & test) {
// assign
String s;
randomString(&s, maxString);
test.assign(s.c_str());
}
-template <class String> void clause_21_3_5_g(String & test) {
+template <class String> void clause11_21_4_6_3_e(String & test) {
// assign
String s;
randomString(&s, maxString);
test.assign(random(0, maxString), random('a', 'z'));
}
-template <class String> void clause_21_3_5_h(String & test) {
+template <class String> void clause11_21_4_6_3_f(String & test) {
// assign from bidirectional iterator
std::list<char> lst(RandomList(maxString));
test.assign(lst.begin(), lst.end());
}
-template <class String> void clause_21_3_5_i(String & test) {
+template <class String> void clause11_21_4_6_3_g(String & test) {
// assign from aliased source
test.assign(test);
}
-template <class String> void clause_21_3_5_j(String & test) {
+template <class String> void clause11_21_4_6_3_h(String & test) {
// assign from aliased source
test.assign(test, random(0, test.size()), random(0, maxString));
}
-template <class String> void clause_21_3_5_k(String & test) {
+template <class String> void clause11_21_4_6_3_i(String & test) {
// assign from aliased source
test.assign(test.c_str(), random(0, test.size()));
}
-template <class String> void clause_21_3_5_l(String & test) {
+template <class String> void clause11_21_4_6_3_j(String & test) {
// assign from aliased source
test.assign(test.c_str());
}
-template <class String> void clause_21_3_5_m(String & test) {
+template <class String> void clause11_21_4_6_3_k(String & test) {
+ // assign from initializer_list
+ initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
+ test.assign(il);
+}
+
+template <class String> void clause11_21_4_6_4(String & test) {
// insert
String s;
randomString(&s, maxString);
test.insert(random(0, test.size()), s.c_str());
test.insert(random(0, test.size()),
random(0, maxString), random('a', 'z'));
- test.insert(test.begin() + random(0, test.size()),
- random('a', 'z'));
+ typename String::size_type pos = random(0, test.size());
+ typename String::iterator res =
+ test.insert(test.begin() + pos, random('a', 'z'));
+ EXPECT_EQ(res - test.begin(), pos);
std::list<char> lst(RandomList(maxString));
- test.insert(test.begin() + random(0, test.size()),
- lst.begin(), lst.end());
+ pos = random(0, test.size());
+ // Uncomment below to see a bug in gcc
+ /*res = */test.insert(test.begin() + pos, lst.begin(), lst.end());
+ // insert from initializer_list
+ initializer_list<typename String::value_type> il { 'a', 'b', 'c' };
+ pos = random(0, test.size());
+ // Uncomment below to see a bug in gcc
+ /*res = */test.insert(test.begin() + pos, il);
+
+ // Test with actual input iterators
+ stringstream ss;
+ ss << "hello cruel world";
+ auto i = istream_iterator<char>(ss);
+ test.insert(test.begin(), i, istream_iterator<char>());
}
-template <class String> void clause_21_3_5_n(String & test) {
- // erase
+template <class String> void clause11_21_4_6_5(String & test) {
+ // erase and pop_back
if (!test.empty()) {
test.erase(random(0, test.size()), random(0, maxString));
}
test.erase(i, i + random(0, size_t(test.end() - i)));
}
}
+ if (!test.empty()) {
+ // Can't test pop_back with std::string, doesn't support it yet.
+ //test.pop_back();
+ }
}
-template <class String> void clause_21_3_5_o(String & test) {
+template <class String> void clause11_21_4_6_6(String & test) {
auto pos = random(0, test.size());
if (avoidAliasing) {
test.replace(pos, random(0, test.size() - pos),
random(0, maxString), random('a', 'z'));
pos = random(0, test.size());
if (avoidAliasing) {
+ auto newString = String(test);
test.replace(
test.begin() + pos,
test.begin() + pos + random(0, test.size() - pos),
- String(test));
+ newString);
} else {
test.replace(
test.begin() + pos,
}
pos = random(0, test.size());
if (avoidAliasing) {
+ auto newString = String(test);
test.replace(
test.begin() + pos,
test.begin() + pos + random(0, test.size() - pos),
- String(test).c_str(),
+ newString.c_str(),
test.size() - random(0, test.size()));
} else {
test.replace(
random(0, maxString), random('a', 'z'));
}
-template <class String> void clause_21_3_5_p(String & test) {
+template <class String> void clause11_21_4_6_7(String & test) {
std::vector<typename String::value_type>
vec(random(0, maxString));
test.copy(
random(0, test.size()));
}
-template <class String> void clause_21_3_5_q(String & test) {
+template <class String> void clause11_21_4_6_8(String & test) {
String s;
randomString(&s, maxString);
s.swap(test);
}
-template <class String> void clause_21_3_6_a(String & test) {
+template <class String> void clause11_21_4_7_1(String & test) {
// 21.3.6 string operations
// exercise c_str() and data()
assert(test.c_str() == test.data());
assert(test.get_allocator() == s.get_allocator());
}
-template <class String> void clause_21_3_6_b(String & test) {
+template <class String> void clause11_21_4_7_2_a(String & test) {
String str = test.substr(
random(0, test.size()),
random(0, test.size()));
Num2String(test, test.find(str, random(0, test.size())));
}
-template <class String> void clause_21_3_6_c(String & test) {
+template <class String> void clause11_21_4_7_2_a1(String & test) {
+ String str = String(test).substr(
+ random(0, test.size()),
+ random(0, test.size()));
+ Num2String(test, test.find(str, random(0, test.size())));
+}
+
+template <class String> void clause11_21_4_7_2_a2(String & test) {
+ auto const& cTest = test;
+ String str = cTest.substr(
+ random(0, test.size()),
+ random(0, test.size()));
+ Num2String(test, test.find(str, random(0, test.size())));
+}
+
+template <class String> void clause11_21_4_7_2_b(String & test) {
auto from = random(0, test.size());
auto length = random(0, test.size() - from);
String str = test.substr(from, length);
random(0, str.size())));
}
-template <class String> void clause_21_3_6_d(String & test) {
+template <class String> void clause11_21_4_7_2_b1(String & test) {
+ auto from = random(0, test.size());
+ auto length = random(0, test.size() - from);
+ String str = String(test).substr(from, length);
+ Num2String(test, test.find(str.c_str(),
+ random(0, test.size()),
+ random(0, str.size())));
+}
+
+template <class String> void clause11_21_4_7_2_b2(String & test) {
+ auto from = random(0, test.size());
+ auto length = random(0, test.size() - from);
+ const auto& cTest = test;
+ String str = cTest.substr(from, length);
+ Num2String(test, test.find(str.c_str(),
+ random(0, test.size()),
+ random(0, str.size())));
+}
+
+template <class String> void clause11_21_4_7_2_c(String & test) {
String str = test.substr(
random(0, test.size()),
random(0, test.size()));
random(0, test.size())));
}
-template <class String> void clause_21_3_6_e(String & test) {
+template <class String> void clause11_21_4_7_2_c1(String & test) {
+ String str = String(test).substr(
+ random(0, test.size()),
+ random(0, test.size()));
+ Num2String(test, test.find(str.c_str(),
+ random(0, test.size())));
+}
+
+template <class String> void clause11_21_4_7_2_c2(String & test) {
+ const auto& cTest = test;
+ String str = cTest.substr(
+ random(0, test.size()),
+ random(0, test.size()));
+ Num2String(test, test.find(str.c_str(),
+ random(0, test.size())));
+}
+
+template <class String> void clause11_21_4_7_2_d(String & test) {
Num2String(test, test.find(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_f(String & test) {
+template <class String> void clause11_21_4_7_3_a(String & test) {
String str = test.substr(
random(0, test.size()),
random(0, test.size()));
Num2String(test, test.rfind(str, random(0, test.size())));
}
-template <class String> void clause_21_3_6_g(String & test) {
+template <class String> void clause11_21_4_7_3_b(String & test) {
String str = test.substr(
random(0, test.size()),
random(0, test.size()));
random(0, str.size())));
}
-template <class String> void clause_21_3_6_h(String & test) {
+template <class String> void clause11_21_4_7_3_c(String & test) {
String str = test.substr(
random(0, test.size()),
random(0, test.size()));
random(0, test.size())));
}
-template <class String> void clause_21_3_6_i(String & test) {
+template <class String> void clause11_21_4_7_3_d(String & test) {
Num2String(test, test.rfind(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_j(String & test) {
+template <class String> void clause11_21_4_7_4_a(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_of(str,
random(0, test.size())));
}
-template <class String> void clause_21_3_6_k(String & test) {
+template <class String> void clause11_21_4_7_4_b(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_of(str.c_str(),
random(0, str.size())));
}
-template <class String> void clause_21_3_6_l(String & test) {
+template <class String> void clause11_21_4_7_4_c(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_of(str.c_str(),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_m(String & test) {
+template <class String> void clause11_21_4_7_4_d(String & test) {
Num2String(test, test.find_first_of(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_n(String & test) {
+template <class String> void clause11_21_4_7_5_a(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_of(str,
random(0, test.size())));
}
-template <class String> void clause_21_3_6_o(String & test) {
+template <class String> void clause11_21_4_7_5_b(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_of(str.c_str(),
random(0, str.size())));
}
-template <class String> void clause_21_3_6_p(String & test) {
+template <class String> void clause11_21_4_7_5_c(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_of(str.c_str(),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_q(String & test) {
+template <class String> void clause11_21_4_7_5_d(String & test) {
Num2String(test, test.find_last_of(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_r(String & test) {
+template <class String> void clause11_21_4_7_6_a(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str,
random(0, test.size())));
}
-template <class String> void clause_21_3_6_s(String & test) {
+template <class String> void clause11_21_4_7_6_b(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str.c_str(),
random(0, str.size())));
}
-template <class String> void clause_21_3_6_t(String & test) {
+template <class String> void clause11_21_4_7_6_c(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_first_not_of(str.c_str(),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_u(String & test) {
+template <class String> void clause11_21_4_7_6_d(String & test) {
Num2String(test, test.find_first_not_of(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_v(String & test) {
+template <class String> void clause11_21_4_7_7_a(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str,
random(0, test.size())));
}
-template <class String> void clause_21_3_6_w(String & test) {
+template <class String> void clause11_21_4_7_7_b(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str.c_str(),
random(0, str.size())));
}
-template <class String> void clause_21_3_6_x(String & test) {
+template <class String> void clause11_21_4_7_7_c(String & test) {
String str;
randomString(&str, maxString);
Num2String(test, test.find_last_not_of(str.c_str(),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_y(String & test) {
+template <class String> void clause11_21_4_7_7_d(String & test) {
Num2String(test, test.find_last_not_of(
random('a', 'z'),
random(0, test.size())));
}
-template <class String> void clause_21_3_6_z(String & test) {
+template <class String> void clause11_21_4_7_8(String & test) {
test = test.substr(random(0, test.size()), random(0, test.size()));
}
-template <class String> void clause_21_3_7_a(String & test) {
+template <class String> void clause11_21_4_7_9_a(String & test) {
String s;
randomString(&s, maxString);
int tristate = test.compare(s);
Num2String(test, tristate);
}
-template <class String> void clause_21_3_7_b(String & test) {
+template <class String> void clause11_21_4_7_9_b(String & test) {
String s;
randomString(&s, maxString);
int tristate = test.compare(
Num2String(test, tristate);
}
-template <class String> void clause_21_3_7_c(String & test) {
+template <class String> void clause11_21_4_7_9_c(String & test) {
String str;
randomString(&str, maxString);
int tristate = test.compare(
Num2String(test, tristate);
}
-template <class String> void clause_21_3_7_d(String & test) {
+template <class String> void clause11_21_4_7_9_d(String & test) {
String s;
randomString(&s, maxString);
int tristate = test.compare(s.c_str());
Num2String(test, tristate);
}
-template <class String> void clause_21_3_7_e(String & test) {
+template <class String> void clause11_21_4_7_9_e(String & test) {
String str;
randomString(&str, maxString);
int tristate = test.compare(
Num2String(test, tristate);
}
-template <class String> void clause_21_3_7_f(String & test) {
+template <class String> void clause11_21_4_8_1_a(String & test) {
String s1;
randomString(&s1, maxString);
String s2;
test = s1 + s2;
}
-template <class String> void clause_21_3_7_g(String & test) {
+template <class String> void clause11_21_4_8_1_b(String & test) {
+ String s1;
+ randomString(&s1, maxString);
+ String s2;
+ randomString(&s2, maxString);
+ test = move(s1) + s2;
+}
+
+template <class String> void clause11_21_4_8_1_c(String & test) {
+ String s1;
+ randomString(&s1, maxString);
+ String s2;
+ randomString(&s2, maxString);
+ test = s1 + move(s2);
+}
+
+template <class String> void clause11_21_4_8_1_d(String & test) {
+ String s1;
+ randomString(&s1, maxString);
+ String s2;
+ randomString(&s2, maxString);
+ test = move(s1) + move(s2);
+}
+
+template <class String> void clause11_21_4_8_1_e(String & test) {
String s;
randomString(&s, maxString);
String s1;
test = s.c_str() + s1;
}
-template <class String> void clause_21_3_7_h(String & test) {
+template <class String> void clause11_21_4_8_1_f(String & test) {
+ String s;
+ randomString(&s, maxString);
+ String s1;
+ randomString(&s1, maxString);
+ test = s.c_str() + move(s1);
+}
+
+template <class String> void clause11_21_4_8_1_g(String & test) {
String s;
randomString(&s, maxString);
test = typename String::value_type(random('a', 'z')) + s;
}
-template <class String> void clause_21_3_7_i(String & test) {
+template <class String> void clause11_21_4_8_1_h(String & test) {
+ String s;
+ randomString(&s, maxString);
+ test = typename String::value_type(random('a', 'z')) + move(s);
+}
+
+template <class String> void clause11_21_4_8_1_i(String & test) {
String s;
randomString(&s, maxString);
String s1;
test = s + s1.c_str();
}
-template <class String> void clause_21_3_7_j(String & test) {
+template <class String> void clause11_21_4_8_1_j(String & test) {
String s;
randomString(&s, maxString);
String s1;
randomString(&s1, maxString);
- test = s + s1.c_str();
+ test = move(s) + s1.c_str();
}
-template <class String> void clause_21_3_7_k(String & test) {
+template <class String> void clause11_21_4_8_1_k(String & test) {
String s;
randomString(&s, maxString);
test = s + typename String::value_type(random('a', 'z'));
}
+template <class String> void clause11_21_4_8_1_l(String & test) {
+ String s;
+ randomString(&s, maxString);
+ String s1;
+ randomString(&s1, maxString);
+ test = move(s) + s1.c_str();
+}
+
// Numbering here is from C++11
-template <class String> void clause_21_4_8_9_a(String & test) {
- stringstream s("asd asdfjhuhdf asdfasdf\tasdsdf");
+template <class String> void clause11_21_4_8_9_a(String & test) {
+ basic_stringstream<typename String::value_type> stst(test.c_str());
String str;
- while (s) {
- s >> str;
+ while (stst) {
+ stst >> str;
test += str + test;
}
}
TEST(FBString, testAllClauses) {
EXPECT_TRUE(1) << "Starting with seed: " << seed;
std::string r;
+ std::wstring wr;
folly::fbstring c;
-#define TEST_CLAUSE(x) \
- do { \
- if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x; \
- randomString(&r); \
- c = r; \
- EXPECT_EQ(c, r); \
- auto localSeed = seed + count; \
- rng = RandomT(localSeed); \
- clause_##x(r); \
- rng = RandomT(localSeed); \
- clause_##x(c); \
- EXPECT_EQ(r, c) \
- << "Lengths: " << r.size() << " vs. " << c.size() \
- << "\nReference: '" << r << "'" \
- << "\nActual: '" << c.data()[0] << "'"; \
- } while (++count % 100 != 0)
-
+ folly::basic_fbstring<wchar_t> wc;
int count = 0;
- TEST_CLAUSE(21_3_1_a);
- TEST_CLAUSE(21_3_1_b);
- TEST_CLAUSE(21_3_1_c);
- TEST_CLAUSE(21_3_1_d);
- TEST_CLAUSE(21_3_1_e);
- TEST_CLAUSE(21_3_1_f);
- TEST_CLAUSE(21_3_1_g);
-
- TEST_CLAUSE(21_3_2);
- TEST_CLAUSE(21_3_3);
- TEST_CLAUSE(21_3_4);
- TEST_CLAUSE(21_3_5_a);
- TEST_CLAUSE(21_3_5_b);
- TEST_CLAUSE(21_3_5_c);
- TEST_CLAUSE(21_3_5_d);
- TEST_CLAUSE(21_3_5_e);
- TEST_CLAUSE(21_3_5_f);
- TEST_CLAUSE(21_3_5_g);
- TEST_CLAUSE(21_3_5_h);
- TEST_CLAUSE(21_3_5_i);
- TEST_CLAUSE(21_3_5_j);
- TEST_CLAUSE(21_3_5_k);
- TEST_CLAUSE(21_3_5_l);
- TEST_CLAUSE(21_3_5_m);
- TEST_CLAUSE(21_3_5_n);
- TEST_CLAUSE(21_3_5_o);
- TEST_CLAUSE(21_3_5_p);
-
- TEST_CLAUSE(21_3_6_a);
- TEST_CLAUSE(21_3_6_b);
- TEST_CLAUSE(21_3_6_c);
- TEST_CLAUSE(21_3_6_d);
- TEST_CLAUSE(21_3_6_e);
- TEST_CLAUSE(21_3_6_f);
- TEST_CLAUSE(21_3_6_g);
- TEST_CLAUSE(21_3_6_h);
- TEST_CLAUSE(21_3_6_i);
- TEST_CLAUSE(21_3_6_j);
- TEST_CLAUSE(21_3_6_k);
- TEST_CLAUSE(21_3_6_l);
- TEST_CLAUSE(21_3_6_m);
- TEST_CLAUSE(21_3_6_n);
- TEST_CLAUSE(21_3_6_o);
- TEST_CLAUSE(21_3_6_p);
- TEST_CLAUSE(21_3_6_q);
- TEST_CLAUSE(21_3_6_r);
- TEST_CLAUSE(21_3_6_s);
- TEST_CLAUSE(21_3_6_t);
- TEST_CLAUSE(21_3_6_u);
- TEST_CLAUSE(21_3_6_v);
- TEST_CLAUSE(21_3_6_w);
- TEST_CLAUSE(21_3_6_x);
- TEST_CLAUSE(21_3_6_y);
- TEST_CLAUSE(21_3_6_z);
-
- TEST_CLAUSE(21_3_7_a);
- TEST_CLAUSE(21_3_7_b);
- TEST_CLAUSE(21_3_7_c);
- TEST_CLAUSE(21_3_7_d);
- TEST_CLAUSE(21_3_7_e);
- TEST_CLAUSE(21_3_7_f);
- TEST_CLAUSE(21_3_7_g);
- TEST_CLAUSE(21_3_7_h);
- TEST_CLAUSE(21_3_7_i);
- TEST_CLAUSE(21_3_7_j);
- TEST_CLAUSE(21_3_7_k);
+ auto l = [&](const char * const clause,
+ void(*f_string)(std::string&),
+ void(*f_fbstring)(folly::fbstring&),
+ void(*f_wfbstring)(folly::basic_fbstring<wchar_t>&)) {
+ do {
+ if (1) {} else EXPECT_TRUE(1) << "Testing clause " << clause;
+ randomString(&r);
+ c = r;
+ EXPECT_EQ(c, r);
+ wr = std::wstring(r.begin(), r.end());
+ wc = folly::basic_fbstring<wchar_t>(wr.c_str());
+ auto localSeed = seed + count;
+ rng = RandomT(localSeed);
+ f_string(r);
+ rng = RandomT(localSeed);
+ f_fbstring(c);
+ EXPECT_EQ(r, c)
+ << "Lengths: " << r.size() << " vs. " << c.size()
+ << "\nReference: '" << r << "'"
+ << "\nActual: '" << c.data()[0] << "'";
+ rng = RandomT(localSeed);
+ f_wfbstring(wc);
+ int wret = wcslen(wc.c_str());
+ char mb[wret+1];
+ int ret = wcstombs(mb, wc.c_str(), sizeof(mb));
+ if (ret == wret) mb[wret] = '\0';
+ const char *mc = c.c_str();
+ std::string one(mb);
+ std::string two(mc);
+ EXPECT_EQ(one, two);
+ } while (++count % 100 != 0);
+ };
+
+#define TEST_CLAUSE(x) \
+ l(#x, \
+ clause11_##x<std::string>, \
+ clause11_##x<folly::fbstring>, \
+ clause11_##x<folly::basic_fbstring<wchar_t>>);
+
+ TEST_CLAUSE(21_4_2_a);
+ TEST_CLAUSE(21_4_2_b);
+ TEST_CLAUSE(21_4_2_c);
+ TEST_CLAUSE(21_4_2_d);
+ TEST_CLAUSE(21_4_2_e);
+ TEST_CLAUSE(21_4_2_f);
+ TEST_CLAUSE(21_4_2_g);
+ TEST_CLAUSE(21_4_2_h);
+ TEST_CLAUSE(21_4_2_i);
+ TEST_CLAUSE(21_4_2_j);
+ TEST_CLAUSE(21_4_2_k);
+ TEST_CLAUSE(21_4_2_l);
+ TEST_CLAUSE(21_4_2_lprime);
+ TEST_CLAUSE(21_4_2_m);
+ TEST_CLAUSE(21_4_2_n);
+ TEST_CLAUSE(21_4_3);
+ TEST_CLAUSE(21_4_4);
+ TEST_CLAUSE(21_4_5);
+ TEST_CLAUSE(21_4_6_1);
+ TEST_CLAUSE(21_4_6_2);
+ TEST_CLAUSE(21_4_6_3_a);
+ TEST_CLAUSE(21_4_6_3_b);
+ TEST_CLAUSE(21_4_6_3_c);
+ TEST_CLAUSE(21_4_6_3_d);
+ TEST_CLAUSE(21_4_6_3_e);
+ TEST_CLAUSE(21_4_6_3_f);
+ TEST_CLAUSE(21_4_6_3_g);
+ TEST_CLAUSE(21_4_6_3_h);
+ TEST_CLAUSE(21_4_6_3_i);
+ TEST_CLAUSE(21_4_6_3_j);
+ TEST_CLAUSE(21_4_6_3_k);
+ TEST_CLAUSE(21_4_6_4);
+ TEST_CLAUSE(21_4_6_5);
+ TEST_CLAUSE(21_4_6_6);
+ TEST_CLAUSE(21_4_6_7);
+ TEST_CLAUSE(21_4_6_8);
+ TEST_CLAUSE(21_4_7_1);
+
+ TEST_CLAUSE(21_4_7_2_a);
+ TEST_CLAUSE(21_4_7_2_a1);
+ TEST_CLAUSE(21_4_7_2_a2);
+ TEST_CLAUSE(21_4_7_2_b);
+ TEST_CLAUSE(21_4_7_2_b1);
+ TEST_CLAUSE(21_4_7_2_b2);
+ TEST_CLAUSE(21_4_7_2_c);
+ TEST_CLAUSE(21_4_7_2_c1);
+ TEST_CLAUSE(21_4_7_2_c2);
+ TEST_CLAUSE(21_4_7_2_d);
+ TEST_CLAUSE(21_4_7_3_a);
+ TEST_CLAUSE(21_4_7_3_b);
+ TEST_CLAUSE(21_4_7_3_c);
+ TEST_CLAUSE(21_4_7_3_d);
+ TEST_CLAUSE(21_4_7_4_a);
+ TEST_CLAUSE(21_4_7_4_b);
+ TEST_CLAUSE(21_4_7_4_c);
+ TEST_CLAUSE(21_4_7_4_d);
+ TEST_CLAUSE(21_4_7_5_a);
+ TEST_CLAUSE(21_4_7_5_b);
+ TEST_CLAUSE(21_4_7_5_c);
+ TEST_CLAUSE(21_4_7_5_d);
+ TEST_CLAUSE(21_4_7_6_a);
+ TEST_CLAUSE(21_4_7_6_b);
+ TEST_CLAUSE(21_4_7_6_c);
+ TEST_CLAUSE(21_4_7_6_d);
+ TEST_CLAUSE(21_4_7_7_a);
+ TEST_CLAUSE(21_4_7_7_b);
+ TEST_CLAUSE(21_4_7_7_c);
+ TEST_CLAUSE(21_4_7_7_d);
+ TEST_CLAUSE(21_4_7_8);
+ TEST_CLAUSE(21_4_7_9_a);
+ TEST_CLAUSE(21_4_7_9_b);
+ TEST_CLAUSE(21_4_7_9_c);
+ TEST_CLAUSE(21_4_7_9_d);
+ TEST_CLAUSE(21_4_7_9_e);
+ TEST_CLAUSE(21_4_8_1_a);
+ TEST_CLAUSE(21_4_8_1_b);
+ TEST_CLAUSE(21_4_8_1_c);
+ TEST_CLAUSE(21_4_8_1_d);
+ TEST_CLAUSE(21_4_8_1_e);
+ TEST_CLAUSE(21_4_8_1_f);
+ TEST_CLAUSE(21_4_8_1_g);
+ TEST_CLAUSE(21_4_8_1_h);
+ TEST_CLAUSE(21_4_8_1_i);
+ TEST_CLAUSE(21_4_8_1_j);
+ TEST_CLAUSE(21_4_8_1_k);
+ TEST_CLAUSE(21_4_8_1_l);
TEST_CLAUSE(21_4_8_9_a);
}
ifstream input(f);
fbstring line;
FOR_EACH (i, v) {
- EXPECT_TRUE(getline(input, line));
+ EXPECT_TRUE(!getline(input, line).fail());
EXPECT_EQ(line, *i);
}
}
EXPECT_EQ(size1 + size2, test.size());
}
+// The GNU C++ standard library throws an std::logic_error when an std::string
+// is constructed with a null pointer. Verify that we mirror this behavior.
+//
+// N.B. We behave this way even if the C++ library being used is something
+// other than libstdc++. Someday if we deem it important to present
+// identical undefined behavior for other platforms, we can re-visit this.
TEST(FBString, testConstructionFromLiteralZero) {
- try {
- std::string s(0);
- EXPECT_TRUE(false);
- } catch (const std::logic_error&) {
- } catch (...) {
- EXPECT_TRUE(false);
- }
-
- try {
- fbstring s(0);
- EXPECT_TRUE(false);
- } catch (const std::logic_error& e) {
- } catch (...) {
- EXPECT_TRUE(false);
- }
+ EXPECT_THROW(fbstring s(0), std::logic_error);
}
TEST(FBString, testFixedBugs) {
cp.c_str();
EXPECT_EQ(str.front(), 'f');
}
- { // D481173, --extra-cxxflags=-DFBSTRING_CONSERVATIVE
+ { // D481173
fbstring str(1337, 'f');
for (int i = 0; i < 2; ++i) {
fbstring cp = str;
cp += "bb";
}
}
- {
- // D661622
- basic_fbstring<wchar_t> s;
+ { // D661622
+ folly::basic_fbstring<wchar_t> s;
EXPECT_EQ(0, s.size());
}
+ { // D785057
+ fbstring str(1337, 'f');
+ std::swap(str, str);
+ EXPECT_EQ(1337, str.size());
+ }
+ { // D1012196, --allocator=malloc
+ fbstring str(128, 'f');
+ str.clear(); // Empty medium string.
+ fbstring copy(str); // Medium string of 0 capacity.
+ copy.push_back('b');
+ EXPECT_GE(copy.capacity(), 1);
+ }
}
+TEST(FBString, findWithNpos) {
+ fbstring fbstr("localhost:80");
+ EXPECT_EQ(fbstring::npos, fbstr.find(":", fbstring::npos));
+}
TEST(FBString, testHash) {
fbstring a;
EXPECT_EQ(str, "HellO");
}
+TEST(FBString, noexcept) {
+ EXPECT_TRUE(noexcept(fbstring()));
+ fbstring x;
+ EXPECT_FALSE(noexcept(fbstring(x)));
+ EXPECT_TRUE(noexcept(fbstring(std::move(x))));
+ fbstring y;
+ EXPECT_FALSE(noexcept(y = x));
+ EXPECT_TRUE(noexcept(y = std::move(x)));
+}
+
+TEST(FBString, iomanip) {
+ stringstream ss;
+ fbstring fbstr("Hello");
+
+ ss << setw(6) << fbstr;
+ EXPECT_EQ(ss.str(), " Hello");
+ ss.str("");
+
+ ss << left << setw(6) << fbstr;
+ EXPECT_EQ(ss.str(), "Hello ");
+ ss.str("");
+
+ ss << right << setw(6) << fbstr;
+ EXPECT_EQ(ss.str(), " Hello");
+ ss.str("");
+
+ ss << setw(4) << fbstr;
+ EXPECT_EQ(ss.str(), "Hello");
+ ss.str("");
+
+ ss << setfill('^') << setw(6) << fbstr;
+ EXPECT_EQ(ss.str(), "^Hello");
+ ss.str("");
+}
+
+TEST(FBString, rvalueIterators) {
+ // you cannot take &* of a move-iterator, so use that for testing
+ fbstring s = "base";
+ fbstring r = "hello";
+ r.replace(r.begin(), r.end(),
+ make_move_iterator(s.begin()), make_move_iterator(s.end()));
+ EXPECT_EQ("base", r);
+
+ // The following test is probably not required by the standard.
+ // i.e. this could be in the realm of undefined behavior.
+ fbstring b = "123abcXYZ";
+ auto ait = b.begin() + 3;
+ auto Xit = b.begin() + 6;
+ b.replace(ait, b.end(), b.begin(), Xit);
+ EXPECT_EQ("123123abc", b); // if things go wrong, you'd get "123123123"
+}
+
+TEST(FBString, moveTerminator) {
+ // The source of a move must remain in a valid state
+ fbstring s(100, 'x'); // too big to be in-situ
+ fbstring k;
+ k = std::move(s);
+
+ EXPECT_EQ(0, s.size());
+ EXPECT_EQ('\0', *s.c_str());
+}
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
- google::ParseCommandLineFlags(&argc, &argv, true);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
return RUN_ALL_TESTS();
}