X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Ftest%2FFBStringTest.cpp;h=8133b0167b9db8138e4d9666e1cba74554caa53d;hb=ce64f0f685111ac24c7a321ea56d0c3524621df1;hp=ede69e6a26393a65b09321b48b80796536849daa;hpb=2302d45ad8d8ddff953711d209139e10b5c40881;p=folly.git diff --git a/folly/test/FBStringTest.cpp b/folly/test/FBStringTest.cpp index ede69e6a..8133b016 100644 --- a/folly/test/FBStringTest.cpp +++ b/folly/test/FBStringTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,21 +17,23 @@ // // Author: andrei.alexandrescu@fb.com -#include "folly/FBString.h" +#include #include #include #include +#include #include #include #include #include -#include "folly/Foreach.h" -#include "folly/Random.h" -#include "folly/Conv.h" +#include +#include +#include +#include using namespace std; using namespace folly; @@ -525,10 +527,11 @@ template void clause11_21_4_6_6(String & test) { 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, @@ -537,10 +540,11 @@ template void clause11_21_4_6_6(String & test) { } 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( @@ -885,36 +889,47 @@ TEST(FBString, testAllClauses) { std::wstring wr; folly::fbstring c; folly::basic_fbstring 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(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&)) { + 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(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, \ + clause11_##x, \ + clause11_##x>); + TEST_CLAUSE(21_4_2_a); TEST_CLAUSE(21_4_2_b); TEST_CLAUSE(21_4_2_c); @@ -1028,7 +1043,7 @@ sed nisl. In diam lacus, lobortis ut posuere nec, ornare id quam."; ifstream input(f); fbstring line; FOR_EACH (i, v) { - EXPECT_TRUE(getline(input, line)); + EXPECT_TRUE(!getline(input, line).fail()); EXPECT_EQ(line, *i); } } @@ -1081,22 +1096,14 @@ TEST(FBString, testMoveOperatorPlusRhs) { 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) { @@ -1107,7 +1114,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; @@ -1137,8 +1144,19 @@ TEST(FBString, testFixedBugs) { 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; @@ -1162,6 +1180,71 @@ TEST(FBString, testFrontBack) { EXPECT_EQ(str, "HellO"); } +TEST(FBString, noexcept) { + EXPECT_TRUE(noexcept(fbstring())); + // std::move is not marked noexcept in gcc 4.6, sigh +#if __GNUC_PREREQ(4, 7) + 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))); +#endif +} + +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);