Googletest export

Change string matchers, like HasSubstr, to accept `string_view` input if available.

PiperOrigin-RevId: 315726484
This commit is contained in:
Abseil Team 2020-06-10 14:07:42 -04:00 committed by vslashg
parent 9f287b46d1
commit 13a433a94d
3 changed files with 82 additions and 40 deletions

View File

@ -903,9 +903,10 @@ bool CaseInsensitiveStringEquals(const StringType& s1,
template <typename StringType> template <typename StringType>
class StrEqualityMatcher { class StrEqualityMatcher {
public: public:
StrEqualityMatcher(const StringType& str, bool expect_eq, StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive)
bool case_sensitive) : string_(std::move(str)),
: string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} expect_eq_(expect_eq),
case_sensitive_(case_sensitive) {}
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
bool MatchAndExplain(const internal::StringView& s, bool MatchAndExplain(const internal::StringView& s,
@ -3990,52 +3991,60 @@ internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
// String matchers. // String matchers.
// Matches a string equal to str. // Matches a string equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq( template <typename T = std::string>
const std::string& str) { PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq(
const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(str, true, true)); internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
} }
// Matches a string not equal to str. // Matches a string not equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe( template <typename T = std::string>
const std::string& str) { PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe(
const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(str, false, true)); internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
} }
// Matches a string equal to str, ignoring case. // Matches a string equal to str, ignoring case.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq( template <typename T = std::string>
const std::string& str) { PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq(
const internal::StringLike<T>& str) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StrEqualityMatcher<std::string>(str, true, false)); internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
} }
// Matches a string not equal to str, ignoring case. // Matches a string not equal to str, ignoring case.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe( template <typename T = std::string>
const std::string& str) { PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe(
return MakePolymorphicMatcher( const internal::StringLike<T>& str) {
internal::StrEqualityMatcher<std::string>(str, false, false)); return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>(
std::string(str), false, false));
} }
// Creates a matcher that matches any string, std::string, or C string // Creates a matcher that matches any string, std::string, or C string
// that contains the given substring. // that contains the given substring.
inline PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr( template <typename T = std::string>
const std::string& substring) { PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr(
const internal::StringLike<T>& substring) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::HasSubstrMatcher<std::string>(substring)); internal::HasSubstrMatcher<std::string>(std::string(substring)));
} }
// Matches a string that starts with 'prefix' (case-sensitive). // Matches a string that starts with 'prefix' (case-sensitive).
inline PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith( template <typename T = std::string>
const std::string& prefix) { PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith(
const internal::StringLike<T>& prefix) {
return MakePolymorphicMatcher( return MakePolymorphicMatcher(
internal::StartsWithMatcher<std::string>(prefix)); internal::StartsWithMatcher<std::string>(std::string(prefix)));
} }
// Matches a string that ends with 'suffix' (case-sensitive). // Matches a string that ends with 'suffix' (case-sensitive).
inline PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith( template <typename T = std::string>
const std::string& suffix) { PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith(
return MakePolymorphicMatcher(internal::EndsWithMatcher<std::string>(suffix)); const internal::StringLike<T>& suffix) {
return MakePolymorphicMatcher(
internal::EndsWithMatcher<std::string>(std::string(suffix)));
} }
#if GTEST_HAS_STD_WSTRING #if GTEST_HAS_STD_WSTRING

View File

@ -1226,6 +1226,25 @@ TEST(RefTest, ExplainsResult) {
// Tests string comparison matchers. // Tests string comparison matchers.
template <typename T = std::string>
std::string FromStringLike(internal::StringLike<T> str) {
return std::string(str);
}
TEST(StringLike, TestConversions) {
EXPECT_EQ("foo", FromStringLike("foo"));
EXPECT_EQ("foo", FromStringLike(std::string("foo")));
#if GTEST_INTERNAL_HAS_STRING_VIEW
EXPECT_EQ("foo", FromStringLike(internal::StringView("foo")));
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
// Non deducible types.
EXPECT_EQ("", FromStringLike({}));
EXPECT_EQ("foo", FromStringLike({'f', 'o', 'o'}));
const char buf[] = "foo";
EXPECT_EQ("foo", FromStringLike({buf, buf + 3}));
}
TEST(StrEqTest, MatchesEqualString) { TEST(StrEqTest, MatchesEqualString) {
Matcher<const char*> m = StrEq(std::string("Hello")); Matcher<const char*> m = StrEq(std::string("Hello"));
EXPECT_TRUE(m.Matches("Hello")); EXPECT_TRUE(m.Matches("Hello"));
@ -1237,7 +1256,8 @@ TEST(StrEqTest, MatchesEqualString) {
EXPECT_FALSE(m2.Matches("Hi")); EXPECT_FALSE(m2.Matches("Hi"));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
Matcher<const internal::StringView&> m3 = StrEq("Hello"); Matcher<const internal::StringView&> m3 =
StrEq(internal::StringView("Hello"));
EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
EXPECT_FALSE(m3.Matches(internal::StringView("hello"))); EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
EXPECT_FALSE(m3.Matches(internal::StringView())); EXPECT_FALSE(m3.Matches(internal::StringView()));
@ -1274,7 +1294,7 @@ TEST(StrNeTest, MatchesUnequalString) {
EXPECT_FALSE(m2.Matches("Hello")); EXPECT_FALSE(m2.Matches("Hello"));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
Matcher<const internal::StringView> m3 = StrNe("Hello"); Matcher<const internal::StringView> m3 = StrNe(internal::StringView("Hello"));
EXPECT_TRUE(m3.Matches(internal::StringView(""))); EXPECT_TRUE(m3.Matches(internal::StringView("")));
EXPECT_TRUE(m3.Matches(internal::StringView())); EXPECT_TRUE(m3.Matches(internal::StringView()));
EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
@ -1298,7 +1318,8 @@ TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) {
EXPECT_FALSE(m2.Matches("Hi")); EXPECT_FALSE(m2.Matches("Hi"));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
Matcher<const internal::StringView&> m3 = StrCaseEq(std::string("Hello")); Matcher<const internal::StringView&> m3 =
StrCaseEq(internal::StringView("Hello"));
EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
EXPECT_TRUE(m3.Matches(internal::StringView("hello"))); EXPECT_TRUE(m3.Matches(internal::StringView("hello")));
EXPECT_FALSE(m3.Matches(internal::StringView("Hi"))); EXPECT_FALSE(m3.Matches(internal::StringView("Hi")));
@ -1348,7 +1369,8 @@ TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) {
EXPECT_FALSE(m2.Matches("Hello")); EXPECT_FALSE(m2.Matches("Hello"));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
Matcher<const internal::StringView> m3 = StrCaseNe("Hello"); Matcher<const internal::StringView> m3 =
StrCaseNe(internal::StringView("Hello"));
EXPECT_TRUE(m3.Matches(internal::StringView("Hi"))); EXPECT_TRUE(m3.Matches(internal::StringView("Hi")));
EXPECT_TRUE(m3.Matches(internal::StringView())); EXPECT_TRUE(m3.Matches(internal::StringView()));
EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
@ -1397,7 +1419,8 @@ TEST(HasSubstrTest, WorksForCStrings) {
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
// Tests that HasSubstr() works for matching StringView-typed values. // Tests that HasSubstr() works for matching StringView-typed values.
TEST(HasSubstrTest, WorksForStringViewClasses) { TEST(HasSubstrTest, WorksForStringViewClasses) {
const Matcher<internal::StringView> m1 = HasSubstr("foo"); const Matcher<internal::StringView> m1 =
HasSubstr(internal::StringView("foo"));
EXPECT_TRUE(m1.Matches(internal::StringView("I love food."))); EXPECT_TRUE(m1.Matches(internal::StringView("I love food.")));
EXPECT_FALSE(m1.Matches(internal::StringView("tofo"))); EXPECT_FALSE(m1.Matches(internal::StringView("tofo")));
EXPECT_FALSE(m1.Matches(internal::StringView())); EXPECT_FALSE(m1.Matches(internal::StringView()));
@ -1650,7 +1673,8 @@ TEST(StartsWithTest, MatchesStringWithGivenPrefix) {
EXPECT_FALSE(m2.Matches(" Hi")); EXPECT_FALSE(m2.Matches(" Hi"));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
const Matcher<internal::StringView> m_empty = StartsWith(""); const Matcher<internal::StringView> m_empty =
StartsWith(internal::StringView(""));
EXPECT_TRUE(m_empty.Matches(internal::StringView())); EXPECT_TRUE(m_empty.Matches(internal::StringView()));
EXPECT_TRUE(m_empty.Matches(internal::StringView(""))); EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty"))); EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty")));
@ -1678,7 +1702,8 @@ TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
EXPECT_FALSE(m2.Matches("Hi ")); EXPECT_FALSE(m2.Matches("Hi "));
#if GTEST_INTERNAL_HAS_STRING_VIEW #if GTEST_INTERNAL_HAS_STRING_VIEW
const Matcher<const internal::StringView&> m4 = EndsWith(""); const Matcher<const internal::StringView&> m4 =
EndsWith(internal::StringView(""));
EXPECT_TRUE(m4.Matches("Hi")); EXPECT_TRUE(m4.Matches("Hi"));
EXPECT_TRUE(m4.Matches("")); EXPECT_TRUE(m4.Matches(""));
EXPECT_TRUE(m4.Matches(internal::StringView())); EXPECT_TRUE(m4.Matches(internal::StringView()));
@ -1710,7 +1735,8 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
EXPECT_TRUE(m3.Matches(internal::StringView("abcz"))); EXPECT_TRUE(m3.Matches(internal::StringView("abcz")));
EXPECT_FALSE(m3.Matches(internal::StringView("1az"))); EXPECT_FALSE(m3.Matches(internal::StringView("1az")));
EXPECT_FALSE(m3.Matches(internal::StringView())); EXPECT_FALSE(m3.Matches(internal::StringView()));
const Matcher<const internal::StringView&> m4 = MatchesRegex(""); const Matcher<const internal::StringView&> m4 =
MatchesRegex(internal::StringView(""));
EXPECT_TRUE(m4.Matches(internal::StringView(""))); EXPECT_TRUE(m4.Matches(internal::StringView("")));
EXPECT_TRUE(m4.Matches(internal::StringView())); EXPECT_TRUE(m4.Matches(internal::StringView()));
#endif // GTEST_INTERNAL_HAS_STRING_VIEW #endif // GTEST_INTERNAL_HAS_STRING_VIEW
@ -1749,7 +1775,8 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
EXPECT_TRUE(m3.Matches(internal::StringView("az1"))); EXPECT_TRUE(m3.Matches(internal::StringView("az1")));
EXPECT_FALSE(m3.Matches(internal::StringView("1a"))); EXPECT_FALSE(m3.Matches(internal::StringView("1a")));
EXPECT_FALSE(m3.Matches(internal::StringView())); EXPECT_FALSE(m3.Matches(internal::StringView()));
const Matcher<const internal::StringView&> m4 = ContainsRegex(""); const Matcher<const internal::StringView&> m4 =
ContainsRegex(internal::StringView(""));
EXPECT_TRUE(m4.Matches(internal::StringView(""))); EXPECT_TRUE(m4.Matches(internal::StringView("")));
EXPECT_TRUE(m4.Matches(internal::StringView())); EXPECT_TRUE(m4.Matches(internal::StringView()));
#endif // GTEST_INTERNAL_HAS_STRING_VIEW #endif // GTEST_INTERNAL_HAS_STRING_VIEW

View File

@ -612,6 +612,10 @@ class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
static const char* NegatedDesc() { return "isn't >="; } static const char* NegatedDesc() { return "isn't >="; }
}; };
template <typename T, typename = typename std::enable_if<
std::is_constructible<std::string, T>::value>::type>
using StringLike = T;
// Implements polymorphic matchers MatchesRegex(regex) and // Implements polymorphic matchers MatchesRegex(regex) and
// ContainsRegex(regex), which can be used as a Matcher<T> as long as // ContainsRegex(regex), which can be used as a Matcher<T> as long as
// T can be converted to a string. // T can be converted to a string.
@ -672,9 +676,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const internal::RE* regex) { const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
} }
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex( template <typename T = std::string>
const std::string& regex) { PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
return MatchesRegex(new internal::RE(regex)); const internal::StringLike<T>& regex) {
return MatchesRegex(new internal::RE(std::string(regex)));
} }
// Matches a string that contains regular expression 'regex'. // Matches a string that contains regular expression 'regex'.
@ -683,9 +688,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const internal::RE* regex) { const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
} }
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex( template <typename T = std::string>
const std::string& regex) { PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
return ContainsRegex(new internal::RE(regex)); const internal::StringLike<T>& regex) {
return ContainsRegex(new internal::RE(std::string(regex)));
} }
// Creates a polymorphic matcher that matches anything equal to x. // Creates a polymorphic matcher that matches anything equal to x.