Bring fbstring::operator+ to date with C++11
[folly.git] / folly / test / FBStringTest.cpp
index 8961363598e9a68208080e3f08c2cf05d67cf363..2e2a9617011bd7c2f96a70babbefb3313fab24c8 100644 (file)
@@ -17,7 +17,7 @@
 //
 // Author: andrei.alexandrescu@fb.com
 
-#include "folly/FBString.h"
+#include <folly/FBString.h>
 
 #include <cstdlib>
 
 
 #include <gflags/gflags.h>
 
-#include "folly/Foreach.h"
-#include "folly/Portability.h"
-#include "folly/Random.h"
-#include "folly/Conv.h"
+#include <folly/Foreach.h>
+#include <folly/Portability.h>
+#include <folly/Random.h>
+#include <folly/Conv.h>
 
 using namespace std;
 using namespace folly;
@@ -603,6 +603,21 @@ template <class String> void clause11_21_4_7_2_a(String & test) {
   Num2String(test, test.find(str, random(0, test.size())));
 }
 
+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);
@@ -612,6 +627,25 @@ template <class String> void clause11_21_4_7_2_b(String & test) {
                              random(0, str.size())));
 }
 
+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()),
@@ -620,6 +654,23 @@ template <class String> void clause11_21_4_7_2_c(String & test) {
                              random(0, test.size())));
 }
 
+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'),
@@ -838,6 +889,30 @@ template <class String> void clause11_21_4_8_1_a(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;
@@ -845,13 +920,27 @@ template <class String> void clause11_21_4_8_1_b(String & test) {
   test = s.c_str() + s1;
 }
 
-template <class String> void clause11_21_4_8_1_c(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 clause11_21_4_8_1_d(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;
@@ -859,20 +948,28 @@ template <class String> void clause11_21_4_8_1_d(String & test) {
   test = s + s1.c_str();
 }
 
-template <class String> void clause11_21_4_8_1_e(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 clause11_21_4_8_1_f(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 clause11_21_4_8_9_a(String & test) {
   basic_stringstream<typename String::value_type> stst(test.c_str());
@@ -889,36 +986,47 @@ TEST(FBString, testAllClauses) {
   std::wstring wr;
   folly::fbstring c;
   folly::basic_fbstring<wchar_t> wc;
-#define TEST_CLAUSE(x)                                              \
-  do {                                                              \
-      if (1) {} else EXPECT_TRUE(1) << "Testing clause " << #x;     \
-      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);                                     \
-      clause11_##x(r);                                                \
-      rng = RandomT(localSeed);                                     \
-      clause11_##x(c);                                                \
-      EXPECT_EQ(r, c)                                               \
-        << "Lengths: " << r.size() << " vs. " << c.size()           \
-        << "\nReference: '" << r << "'"                             \
-        << "\nActual:    '" << c.data()[0] << "'";                  \
-      rng = RandomT(localSeed);                                     \
-      clause11_##x(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)
-
   int count = 0;
+
+  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);
@@ -958,8 +1066,14 @@ TEST(FBString, testAllClauses) {
   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);
@@ -993,6 +1107,12 @@ TEST(FBString, testAllClauses) {
   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);
 }
 
@@ -1103,7 +1223,7 @@ 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;
@@ -1224,8 +1344,18 @@ TEST(FBString, rvalueIterators) {
   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();
 }