diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 08fd6d14ff..0bc9b3649f 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -903,9 +903,10 @@ bool CaseInsensitiveStringEquals(const StringType& s1, template class StrEqualityMatcher { public: - StrEqualityMatcher(const StringType& str, bool expect_eq, - bool case_sensitive) - : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} + StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive) + : string_(std::move(str)), + expect_eq_(expect_eq), + case_sensitive_(case_sensitive) {} #if GTEST_INTERNAL_HAS_STRING_VIEW bool MatchAndExplain(const internal::StringView& s, @@ -3990,52 +3991,60 @@ internal::ResultOfMatcher ResultOf( // String matchers. // Matches a string equal to str. -inline PolymorphicMatcher > StrEq( - const std::string& str) { +template +PolymorphicMatcher > StrEq( + const internal::StringLike& str) { return MakePolymorphicMatcher( - internal::StrEqualityMatcher(str, true, true)); + internal::StrEqualityMatcher(std::string(str), true, true)); } // Matches a string not equal to str. -inline PolymorphicMatcher > StrNe( - const std::string& str) { +template +PolymorphicMatcher > StrNe( + const internal::StringLike& str) { return MakePolymorphicMatcher( - internal::StrEqualityMatcher(str, false, true)); + internal::StrEqualityMatcher(std::string(str), false, true)); } // Matches a string equal to str, ignoring case. -inline PolymorphicMatcher > StrCaseEq( - const std::string& str) { +template +PolymorphicMatcher > StrCaseEq( + const internal::StringLike& str) { return MakePolymorphicMatcher( - internal::StrEqualityMatcher(str, true, false)); + internal::StrEqualityMatcher(std::string(str), true, false)); } // Matches a string not equal to str, ignoring case. -inline PolymorphicMatcher > StrCaseNe( - const std::string& str) { - return MakePolymorphicMatcher( - internal::StrEqualityMatcher(str, false, false)); +template +PolymorphicMatcher > StrCaseNe( + const internal::StringLike& str) { + return MakePolymorphicMatcher(internal::StrEqualityMatcher( + std::string(str), false, false)); } // Creates a matcher that matches any string, std::string, or C string // that contains the given substring. -inline PolymorphicMatcher > HasSubstr( - const std::string& substring) { +template +PolymorphicMatcher > HasSubstr( + const internal::StringLike& substring) { return MakePolymorphicMatcher( - internal::HasSubstrMatcher(substring)); + internal::HasSubstrMatcher(std::string(substring))); } // Matches a string that starts with 'prefix' (case-sensitive). -inline PolymorphicMatcher > StartsWith( - const std::string& prefix) { +template +PolymorphicMatcher > StartsWith( + const internal::StringLike& prefix) { return MakePolymorphicMatcher( - internal::StartsWithMatcher(prefix)); + internal::StartsWithMatcher(std::string(prefix))); } // Matches a string that ends with 'suffix' (case-sensitive). -inline PolymorphicMatcher > EndsWith( - const std::string& suffix) { - return MakePolymorphicMatcher(internal::EndsWithMatcher(suffix)); +template +PolymorphicMatcher > EndsWith( + const internal::StringLike& suffix) { + return MakePolymorphicMatcher( + internal::EndsWithMatcher(std::string(suffix))); } #if GTEST_HAS_STD_WSTRING diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 5db0a7ae10..a22ff34b57 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -1226,6 +1226,25 @@ TEST(RefTest, ExplainsResult) { // Tests string comparison matchers. +template +std::string FromStringLike(internal::StringLike 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) { Matcher m = StrEq(std::string("Hello")); EXPECT_TRUE(m.Matches("Hello")); @@ -1237,7 +1256,8 @@ TEST(StrEqTest, MatchesEqualString) { EXPECT_FALSE(m2.Matches("Hi")); #if GTEST_INTERNAL_HAS_STRING_VIEW - Matcher m3 = StrEq("Hello"); + Matcher m3 = + StrEq(internal::StringView("Hello")); EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); EXPECT_FALSE(m3.Matches(internal::StringView("hello"))); EXPECT_FALSE(m3.Matches(internal::StringView())); @@ -1274,7 +1294,7 @@ TEST(StrNeTest, MatchesUnequalString) { EXPECT_FALSE(m2.Matches("Hello")); #if GTEST_INTERNAL_HAS_STRING_VIEW - Matcher m3 = StrNe("Hello"); + Matcher m3 = StrNe(internal::StringView("Hello")); EXPECT_TRUE(m3.Matches(internal::StringView(""))); EXPECT_TRUE(m3.Matches(internal::StringView())); EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); @@ -1298,7 +1318,8 @@ TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) { EXPECT_FALSE(m2.Matches("Hi")); #if GTEST_INTERNAL_HAS_STRING_VIEW - Matcher m3 = StrCaseEq(std::string("Hello")); + Matcher m3 = + StrCaseEq(internal::StringView("Hello")); EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); EXPECT_TRUE(m3.Matches(internal::StringView("hello"))); EXPECT_FALSE(m3.Matches(internal::StringView("Hi"))); @@ -1348,7 +1369,8 @@ TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) { EXPECT_FALSE(m2.Matches("Hello")); #if GTEST_INTERNAL_HAS_STRING_VIEW - Matcher m3 = StrCaseNe("Hello"); + Matcher m3 = + StrCaseNe(internal::StringView("Hello")); EXPECT_TRUE(m3.Matches(internal::StringView("Hi"))); EXPECT_TRUE(m3.Matches(internal::StringView())); EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); @@ -1397,7 +1419,8 @@ TEST(HasSubstrTest, WorksForCStrings) { #if GTEST_INTERNAL_HAS_STRING_VIEW // Tests that HasSubstr() works for matching StringView-typed values. TEST(HasSubstrTest, WorksForStringViewClasses) { - const Matcher m1 = HasSubstr("foo"); + const Matcher m1 = + HasSubstr(internal::StringView("foo")); EXPECT_TRUE(m1.Matches(internal::StringView("I love food."))); EXPECT_FALSE(m1.Matches(internal::StringView("tofo"))); EXPECT_FALSE(m1.Matches(internal::StringView())); @@ -1650,7 +1673,8 @@ TEST(StartsWithTest, MatchesStringWithGivenPrefix) { EXPECT_FALSE(m2.Matches(" Hi")); #if GTEST_INTERNAL_HAS_STRING_VIEW - const Matcher m_empty = StartsWith(""); + const Matcher 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("not empty"))); @@ -1678,7 +1702,8 @@ TEST(EndsWithTest, MatchesStringWithGivenSuffix) { EXPECT_FALSE(m2.Matches("Hi ")); #if GTEST_INTERNAL_HAS_STRING_VIEW - const Matcher m4 = EndsWith(""); + const Matcher m4 = + EndsWith(internal::StringView("")); EXPECT_TRUE(m4.Matches("Hi")); EXPECT_TRUE(m4.Matches("")); EXPECT_TRUE(m4.Matches(internal::StringView())); @@ -1710,7 +1735,8 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) { EXPECT_TRUE(m3.Matches(internal::StringView("abcz"))); EXPECT_FALSE(m3.Matches(internal::StringView("1az"))); EXPECT_FALSE(m3.Matches(internal::StringView())); - const Matcher m4 = MatchesRegex(""); + const Matcher m4 = + MatchesRegex(internal::StringView("")); EXPECT_TRUE(m4.Matches(internal::StringView(""))); EXPECT_TRUE(m4.Matches(internal::StringView())); #endif // GTEST_INTERNAL_HAS_STRING_VIEW @@ -1749,7 +1775,8 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) { EXPECT_TRUE(m3.Matches(internal::StringView("az1"))); EXPECT_FALSE(m3.Matches(internal::StringView("1a"))); EXPECT_FALSE(m3.Matches(internal::StringView())); - const Matcher m4 = ContainsRegex(""); + const Matcher m4 = + ContainsRegex(internal::StringView("")); EXPECT_TRUE(m4.Matches(internal::StringView(""))); EXPECT_TRUE(m4.Matches(internal::StringView())); #endif // GTEST_INTERNAL_HAS_STRING_VIEW diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h index a61cef4093..04cc63de23 100644 --- a/googletest/include/gtest/gtest-matchers.h +++ b/googletest/include/gtest/gtest-matchers.h @@ -612,6 +612,10 @@ class GeMatcher : public ComparisonBase, Rhs, AnyGe> { static const char* NegatedDesc() { return "isn't >="; } }; +template ::value>::type> +using StringLike = T; + // Implements polymorphic matchers MatchesRegex(regex) and // ContainsRegex(regex), which can be used as a Matcher as long as // T can be converted to a string. @@ -672,9 +676,10 @@ inline PolymorphicMatcher MatchesRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); } -inline PolymorphicMatcher MatchesRegex( - const std::string& regex) { - return MatchesRegex(new internal::RE(regex)); +template +PolymorphicMatcher MatchesRegex( + const internal::StringLike& regex) { + return MatchesRegex(new internal::RE(std::string(regex))); } // Matches a string that contains regular expression 'regex'. @@ -683,9 +688,10 @@ inline PolymorphicMatcher ContainsRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); } -inline PolymorphicMatcher ContainsRegex( - const std::string& regex) { - return ContainsRegex(new internal::RE(regex)); +template +PolymorphicMatcher ContainsRegex( + const internal::StringLike& regex) { + return ContainsRegex(new internal::RE(std::string(regex))); } // Creates a polymorphic matcher that matches anything equal to x.