+
+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());
+}
+
+namespace {
+/*
+ * t8968589: Clang 3.7 refused to compile w/ certain constructors (specifically
+ * those that were "explicit" and had a defaulted parameter, if they were used
+ * in structs which were default-initialized). Exercise these just to ensure
+ * they compile.
+ *
+ * In diff D2632953 the old constructor:
+ * explicit basic_fbstring(const A& a = A()) noexcept;
+ *
+ * was split into these two, as a workaround:
+ * basic_fbstring() noexcept;
+ * explicit basic_fbstring(const A& a) noexcept;
+ */
+
+struct TestStructDefaultAllocator {
+ folly::basic_fbstring<char> stringMember;
+};
+
+template <class A>
+struct TestStructWithAllocator {
+ folly::basic_fbstring<char, std::char_traits<char>, A> stringMember;
+};
+
+std::atomic<size_t> allocatorConstructedCount(0);
+struct TestStructStringAllocator : std::allocator<char> {
+ TestStructStringAllocator() {
+ ++ allocatorConstructedCount;
+ }
+};
+
+} // namespace
+
+TEST(FBStringCtorTest, DefaultInitStructDefaultAlloc) {
+ TestStructDefaultAllocator t1 { };
+ EXPECT_TRUE(t1.stringMember.empty());
+}
+
+TEST(FBStringCtorTest, DefaultInitStructAlloc) {
+ EXPECT_EQ(allocatorConstructedCount.load(), 0);
+ TestStructWithAllocator<TestStructStringAllocator> t2;
+ EXPECT_TRUE(t2.stringMember.empty());
+ EXPECT_EQ(allocatorConstructedCount.load(), 1);
+}
+
+TEST(FBStringCtorTest, NullZeroConstruction) {
+ char* p = nullptr;
+ int n = 0;
+ folly::fbstring f(p, n);
+ EXPECT_EQ(f.size(), 0);
+}
+
+// Tests for the comparison operators. I use EXPECT_TRUE rather than EXPECT_LE
+// because what's under test is the operator rather than the relation between
+// the objects.
+
+TEST(FBString, compareToStdString) {
+ using folly::fbstring;
+ using namespace std::string_literals;
+ auto stdA = "a"s;
+ auto stdB = "b"s;
+ fbstring fbA("a");
+ fbstring fbB("b");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+TEST(U16FBString, compareToStdU16String) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = u"a"s;
+ auto stdB = u"b"s;
+ basic_fbstring<char16_t> fbA(u"a");
+ basic_fbstring<char16_t> fbB(u"b");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+TEST(U32FBString, compareToStdU32String) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = U"a"s;
+ auto stdB = U"b"s;
+ basic_fbstring<char32_t> fbA(U"a");
+ basic_fbstring<char32_t> fbB(U"b");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+TEST(WFBString, compareToStdWString) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = L"a"s;
+ auto stdB = L"b"s;
+ basic_fbstring<wchar_t> fbA(L"a");
+ basic_fbstring<wchar_t> fbB(L"b");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+// Same again, but with a more challenging input - a common prefix and different
+// lengths.
+
+TEST(FBString, compareToStdStringLong) {
+ using folly::fbstring;
+ using namespace std::string_literals;
+ auto stdA = "1234567890a"s;
+ auto stdB = "1234567890ab"s;
+ fbstring fbA("1234567890a");
+ fbstring fbB("1234567890ab");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+TEST(U16FBString, compareToStdU16StringLong) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = u"1234567890a"s;
+ auto stdB = u"1234567890ab"s;
+ basic_fbstring<char16_t> fbA(u"1234567890a");
+ basic_fbstring<char16_t> fbB(u"1234567890ab");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+#if FOLLY_HAVE_WCHAR_SUPPORT
+TEST(U32FBString, compareToStdU32StringLong) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = U"1234567890a"s;
+ auto stdB = U"1234567890ab"s;
+ basic_fbstring<char32_t> fbA(U"1234567890a");
+ basic_fbstring<char32_t> fbB(U"1234567890ab");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+
+TEST(WFBString, compareToStdWStringLong) {
+ using folly::basic_fbstring;
+ using namespace std::string_literals;
+ auto stdA = L"1234567890a"s;
+ auto stdB = L"1234567890ab"s;
+ basic_fbstring<wchar_t> fbA(L"1234567890a");
+ basic_fbstring<wchar_t> fbB(L"1234567890ab");
+ EXPECT_TRUE(stdA == fbA);
+ EXPECT_TRUE(fbB == stdB);
+ EXPECT_TRUE(stdA != fbB);
+ EXPECT_TRUE(fbA != stdB);
+ EXPECT_TRUE(stdA < fbB);
+ EXPECT_TRUE(fbA < stdB);
+ EXPECT_TRUE(stdB > fbA);
+ EXPECT_TRUE(fbB > stdA);
+ EXPECT_TRUE(stdA <= fbB);
+ EXPECT_TRUE(fbA <= stdB);
+ EXPECT_TRUE(stdA <= fbA);
+ EXPECT_TRUE(fbA <= stdA);
+ EXPECT_TRUE(stdB >= fbA);
+ EXPECT_TRUE(fbB >= stdA);
+ EXPECT_TRUE(stdB >= fbB);
+ EXPECT_TRUE(fbB >= stdB);
+}
+#endif