0
0
mirror of https://github.com/google/googletest.git synced 2025-03-20 10:53:47 +00:00

Unfortunately, the svn repo is a bit out of date. This commit contains 8

changes that haven't made it to svn. The descriptions of each change are listed
below.

- Fixes some python shebang lines.

- Add ElementsAreArray overloads to gmock. ElementsAreArray now makes a copy of
  its input elements before the conversion to a Matcher. ElementsAreArray can
  now take a vector as input. ElementsAreArray can now take an iterator pair as
  input.

- Templatize MatchAndExplain to allow independent string types for the matcher
  and matchee. I also templatized the ConstCharPointer version of
  MatchAndExplain to avoid calls with "char*" from using the new templated
  MatchAndExplain.

- Fixes the bug where the constructor of the return type of ElementsAre() saves
  a reference instead of a copy of the arguments.

- Extends ElementsAre() to accept arrays whose sizes aren't known.

- Switches gTest's internal FilePath class from testing::internal::String to
  std::string. testing::internal::String was introduced when gTest couldn't
  depend on std::string.  It's now deprecated.

- Switches gTest & gMock from using testing::internal::String objects to
  std::string. Some static methods of String are still in use.  We may be able
  to remove some but not all of them.  In particular, String::Format() should
  eventually be removed as it truncates the result at 4096 characters, often
  causing problems.
This commit is contained in:
jgm 2012-11-15 15:50:36 +00:00
parent ada23475e2
commit 38513a8bb1
11 changed files with 392 additions and 191 deletions

View File

@ -38,6 +38,7 @@
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#include <iterator>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@ -305,7 +306,9 @@ class ArgsMatcher {
GTEST_DISALLOW_ASSIGN_(ArgsMatcher); GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
}; };
// Implements ElementsAre() of 1-10 arguments. // Implements ElementsAre() of 1-10 arguments. The use of DecayArray in
// the implementation allows ElementsAre() to accept string literals, whose
// inferred type is const char[N] while we want to treat them as const char*.
template <typename T1> template <typename T1>
class ElementsAreMatcher1 { class ElementsAreMatcher1 {
@ -326,11 +329,12 @@ class ElementsAreMatcher1 {
// a local array. // a local array.
const Matcher<const Element&> matcher = const Matcher<const Element&> matcher =
MatcherCast<const Element&>(e1_); MatcherCast<const Element&>(e1_);
return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher,
&matcher + 1));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher1); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher1);
}; };
@ -351,12 +355,13 @@ class ElementsAreMatcher2 {
MatcherCast<const Element&>(e2_), MatcherCast<const Element&>(e2_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 2)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 2));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher2); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher2);
}; };
@ -379,13 +384,14 @@ class ElementsAreMatcher3 {
MatcherCast<const Element&>(e3_), MatcherCast<const Element&>(e3_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 3)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 3));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher3); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher3);
}; };
@ -409,14 +415,15 @@ class ElementsAreMatcher4 {
MatcherCast<const Element&>(e4_), MatcherCast<const Element&>(e4_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 4)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 4));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher4); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher4);
}; };
@ -441,15 +448,16 @@ class ElementsAreMatcher5 {
MatcherCast<const Element&>(e5_), MatcherCast<const Element&>(e5_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 5)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 5));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher5); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher5);
}; };
@ -477,16 +485,17 @@ class ElementsAreMatcher6 {
MatcherCast<const Element&>(e6_), MatcherCast<const Element&>(e6_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 6)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 6));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
const T6& e6_; const typename DecayArray<T6>::type e6_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher6); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher6);
}; };
@ -515,17 +524,18 @@ class ElementsAreMatcher7 {
MatcherCast<const Element&>(e7_), MatcherCast<const Element&>(e7_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 7)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 7));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
const T6& e6_; const typename DecayArray<T6>::type e6_;
const T7& e7_; const typename DecayArray<T7>::type e7_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher7); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher7);
}; };
@ -555,18 +565,19 @@ class ElementsAreMatcher8 {
MatcherCast<const Element&>(e8_), MatcherCast<const Element&>(e8_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 8)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 8));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
const T6& e6_; const typename DecayArray<T6>::type e6_;
const T7& e7_; const typename DecayArray<T7>::type e7_;
const T8& e8_; const typename DecayArray<T8>::type e8_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher8); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher8);
}; };
@ -598,19 +609,20 @@ class ElementsAreMatcher9 {
MatcherCast<const Element&>(e9_), MatcherCast<const Element&>(e9_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 9)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 9));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
const T6& e6_; const typename DecayArray<T6>::type e6_;
const T7& e7_; const typename DecayArray<T7>::type e7_;
const T8& e8_; const typename DecayArray<T8>::type e8_;
const T9& e9_; const typename DecayArray<T9>::type e9_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher9); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher9);
}; };
@ -643,20 +655,21 @@ class ElementsAreMatcher10 {
MatcherCast<const Element&>(e10_), MatcherCast<const Element&>(e10_),
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 10)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + 10));
} }
private: private:
const T1& e1_; const typename DecayArray<T1>::type e1_;
const T2& e2_; const typename DecayArray<T2>::type e2_;
const T3& e3_; const typename DecayArray<T3>::type e3_;
const T4& e4_; const typename DecayArray<T4>::type e4_;
const T5& e5_; const typename DecayArray<T5>::type e5_;
const T6& e6_; const typename DecayArray<T6>::type e6_;
const T7& e7_; const typename DecayArray<T7>::type e7_;
const T8& e8_; const typename DecayArray<T8>::type e8_;
const T9& e9_; const typename DecayArray<T9>::type e9_;
const T10& e10_; const typename DecayArray<T10>::type e10_;
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher10); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher10);
}; };
@ -1007,24 +1020,55 @@ inline internal::ElementsAreMatcher10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
T10>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); T10>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
} }
// ElementsAreArray(array) and ElementAreArray(array, count) are like // ElementsAreArray(array)
// ElementsAre(), except that they take an array of values or // ElementsAreArray(pointer, count)
// matchers. The former form infers the size of 'array', which must // ElementsAreArray(vector)
// be a static C-style array. In the latter form, 'array' can either // ElementsAreArray(first, last)
// be a static array or a pointer to a dynamically created array. //
// The ElementsAreArray() functions are like ElementsAre(...), except that
// they are given a sequence of matchers or values rather than taking each
// element as a function argument. The sequence can be specified as a
// C-style array, a pointer and count, a vector, or an STL iterator range.
//
// * The array form infers the size of 'array', which must be of a
// statically-sized C-style array type.
//
// * The (pointer, count) form can take either a statically-sized C-style
// array or a pointer to a dynamically created array. It does not take
// ownership of the pointer.
//
// * The vector form can take a std::vector either of values or of matchers.
//
// * The (first, last) form can take any STL iterator range.
//
// All forms of ElementsAreArray() make a copy of the input sequence.
template <typename T> template <typename T>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray( inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
const T* first, size_t count) { const T* first, size_t count) {
return internal::ElementsAreArrayMatcher<T>(first, count); return internal::ElementsAreArrayMatcher<T>(first, first + count);
} }
template <typename T, size_t N> template <typename T, size_t N>
inline internal::ElementsAreArrayMatcher<T> inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
ElementsAreArray(const T (&array)[N]) { const T (&array)[N]) {
return internal::ElementsAreArrayMatcher<T>(array, N); return internal::ElementsAreArrayMatcher<T>(array, array + N);
} }
template <typename T, typename A>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
const std::vector<T, A>& vec) {
return internal::ElementsAreArrayMatcher<T>(vec.begin(), vec.end());
}
template <typename Iter>
inline internal::ElementsAreArrayMatcher<
typename std::iterator_traits<Iter>::value_type>
ElementsAreArray(Iter first, Iter last) {
typedef typename std::iterator_traits<Iter>::value_type T;
return internal::ElementsAreArrayMatcher<T>(first, last);
}
// AllOf(m1, m2, ..., mk) matches any value that matches all of the given // AllOf(m1, m2, ..., mk) matches any value that matches all of the given
// sub-matchers. AllOf is called fully qualified to prevent ADL from firing. // sub-matchers. AllOf is called fully qualified to prevent ADL from firing.

View File

@ -40,6 +40,7 @@ $$ }} This line fixes auto-indentation of the following code in Emacs.
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#include <iterator>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@ -186,7 +187,9 @@ class ArgsMatcher {
GTEST_DISALLOW_ASSIGN_(ArgsMatcher); GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
}; };
// Implements ElementsAre() of 1-$n arguments. // Implements ElementsAre() of 1-$n arguments. The use of DecayArray in
// the implementation allows ElementsAre() to accept string literals, whose
// inferred type is const char[N] while we want to treat them as const char*.
$range i 1..n $range i 1..n
@ -214,7 +217,8 @@ $if i==1 [[
// a local array. // a local array.
const Matcher<const Element&> matcher = const Matcher<const Element&> matcher =
MatcherCast<const Element&>(e1_); MatcherCast<const Element&>(e1_);
return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher,
&matcher + 1));
]] $else [[ ]] $else [[
const Matcher<const Element&> matchers[] = { const Matcher<const Element&> matchers[] = {
@ -225,7 +229,8 @@ $for j [[
]] ]]
}; };
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, $i)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers + $i));
]] ]]
} }
@ -233,7 +238,7 @@ $for j [[
private: private:
$for j [[ $for j [[
const T$j& e$j[[]]_; const typename DecayArray<T$j>::type e$j[[]]_;
]] ]]
@ -344,24 +349,55 @@ inline internal::ElementsAreMatcher$i<$for j, [[T$j]]> ElementsAre($for j, [[con
]] ]]
// ElementsAreArray(array) and ElementAreArray(array, count) are like // ElementsAreArray(array)
// ElementsAre(), except that they take an array of values or // ElementsAreArray(pointer, count)
// matchers. The former form infers the size of 'array', which must // ElementsAreArray(vector)
// be a static C-style array. In the latter form, 'array' can either // ElementsAreArray(first, last)
// be a static array or a pointer to a dynamically created array. //
// The ElementsAreArray() functions are like ElementsAre(...), except that
// they are given a sequence of matchers or values rather than taking each
// element as a function argument. The sequence can be specified as a
// C-style array, a pointer and count, a vector, or an STL iterator range.
//
// * The array form infers the size of 'array', which must be of a
// statically-sized C-style array type.
//
// * The (pointer, count) form can take either a statically-sized C-style
// array or a pointer to a dynamically created array. It does not take
// ownership of the pointer.
//
// * The vector form can take a std::vector either of values or of matchers.
//
// * The (first, last) form can take any STL iterator range.
//
// All forms of ElementsAreArray() make a copy of the input sequence.
template <typename T> template <typename T>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray( inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
const T* first, size_t count) { const T* first, size_t count) {
return internal::ElementsAreArrayMatcher<T>(first, count); return internal::ElementsAreArrayMatcher<T>(first, first + count);
} }
template <typename T, size_t N> template <typename T, size_t N>
inline internal::ElementsAreArrayMatcher<T> inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
ElementsAreArray(const T (&array)[N]) { const T (&array)[N]) {
return internal::ElementsAreArrayMatcher<T>(array, N); return internal::ElementsAreArrayMatcher<T>(array, array + N);
} }
template <typename T, typename A>
inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
const std::vector<T, A>& vec) {
return internal::ElementsAreArrayMatcher<T>(vec.begin(), vec.end());
}
template <typename Iter>
inline internal::ElementsAreArrayMatcher<
typename std::iterator_traits<Iter>::value_type>
ElementsAreArray(Iter first, Iter last) {
typedef typename std::iterator_traits<Iter>::value_type T;
return internal::ElementsAreArrayMatcher<T>(first, last);
}
// AllOf(m1, m2, ..., mk) matches any value that matches all of the given // AllOf(m1, m2, ..., mk) matches any value that matches all of the given
// sub-matchers. AllOf is called fully qualified to prevent ADL from firing. // sub-matchers. AllOf is called fully qualified to prevent ADL from firing.

View File

@ -935,26 +935,33 @@ bool CaseInsensitiveStringEquals(const StringType& s1,
template <typename StringType> template <typename StringType>
class StrEqualityMatcher { class StrEqualityMatcher {
public: public:
typedef typename StringType::const_pointer ConstCharPointer;
StrEqualityMatcher(const StringType& str, bool expect_eq, StrEqualityMatcher(const StringType& str, bool expect_eq,
bool case_sensitive) bool case_sensitive)
: string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
// When expect_eq_ is true, returns true iff s is equal to string_; // Accepts pointer types, particularly:
// otherwise returns true iff s is not equal to string_. // const char*
bool MatchAndExplain(ConstCharPointer s, // char*
MatchResultListener* listener) const { // const wchar_t*
// wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
if (s == NULL) { if (s == NULL) {
return !expect_eq_; return !expect_eq_;
} }
return MatchAndExplain(StringType(s), listener); return MatchAndExplain(StringType(s), listener);
} }
bool MatchAndExplain(const StringType& s, // Matches anything that can convert to StringType.
//
// This is a template, not just a plain function with const StringType&,
// because StringPiece has some interfering non-explicit constructors.
template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const bool eq = case_sensitive_ ? s == string_ : const StringType& s2(s);
CaseInsensitiveStringEquals(s, string_); const bool eq = case_sensitive_ ? s2 == string_ :
CaseInsensitiveStringEquals(s2, string_);
return expect_eq_ == eq; return expect_eq_ == eq;
} }
@ -989,22 +996,28 @@ class StrEqualityMatcher {
template <typename StringType> template <typename StringType>
class HasSubstrMatcher { class HasSubstrMatcher {
public: public:
typedef typename StringType::const_pointer ConstCharPointer;
explicit HasSubstrMatcher(const StringType& substring) explicit HasSubstrMatcher(const StringType& substring)
: substring_(substring) {} : substring_(substring) {}
// These overloaded methods allow HasSubstr(substring) to be used as a // Accepts pointer types, particularly:
// Matcher<T> as long as T can be converted to string. Returns true // const char*
// iff s contains substring_ as a substring. // char*
bool MatchAndExplain(ConstCharPointer s, // const wchar_t*
MatchResultListener* listener) const { // wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != NULL && MatchAndExplain(StringType(s), listener); return s != NULL && MatchAndExplain(StringType(s), listener);
} }
bool MatchAndExplain(const StringType& s, // Matches anything that can convert to StringType.
//
// This is a template, not just a plain function with const StringType&,
// because StringPiece has some interfering non-explicit constructors.
template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return s.find(substring_) != StringType::npos; const StringType& s2(s);
return s2.find(substring_) != StringType::npos;
} }
// Describes what this matcher matches. // Describes what this matcher matches.
@ -1030,23 +1043,29 @@ class HasSubstrMatcher {
template <typename StringType> template <typename StringType>
class StartsWithMatcher { class StartsWithMatcher {
public: public:
typedef typename StringType::const_pointer ConstCharPointer;
explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {
} }
// These overloaded methods allow StartsWith(prefix) to be used as a // Accepts pointer types, particularly:
// Matcher<T> as long as T can be converted to string. Returns true // const char*
// iff s starts with prefix_. // char*
bool MatchAndExplain(ConstCharPointer s, // const wchar_t*
MatchResultListener* listener) const { // wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != NULL && MatchAndExplain(StringType(s), listener); return s != NULL && MatchAndExplain(StringType(s), listener);
} }
bool MatchAndExplain(const StringType& s, // Matches anything that can convert to StringType.
//
// This is a template, not just a plain function with const StringType&,
// because StringPiece has some interfering non-explicit constructors.
template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return s.length() >= prefix_.length() && const StringType& s2(s);
s.substr(0, prefix_.length()) == prefix_; return s2.length() >= prefix_.length() &&
s2.substr(0, prefix_.length()) == prefix_;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
@ -1071,22 +1090,28 @@ class StartsWithMatcher {
template <typename StringType> template <typename StringType>
class EndsWithMatcher { class EndsWithMatcher {
public: public:
typedef typename StringType::const_pointer ConstCharPointer;
explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
// These overloaded methods allow EndsWith(suffix) to be used as a // Accepts pointer types, particularly:
// Matcher<T> as long as T can be converted to string. Returns true // const char*
// iff s ends with suffix_. // char*
bool MatchAndExplain(ConstCharPointer s, // const wchar_t*
MatchResultListener* listener) const { // wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != NULL && MatchAndExplain(StringType(s), listener); return s != NULL && MatchAndExplain(StringType(s), listener);
} }
bool MatchAndExplain(const StringType& s, // Matches anything that can convert to StringType.
//
// This is a template, not just a plain function with const StringType&,
// because StringPiece has some interfering non-explicit constructors.
template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return s.length() >= suffix_.length() && const StringType& s2(s);
s.substr(s.length() - suffix_.length()) == suffix_; return s2.length() >= suffix_.length() &&
s2.substr(s2.length() - suffix_.length()) == suffix_;
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
@ -1113,19 +1138,26 @@ class MatchesRegexMatcher {
MatchesRegexMatcher(const RE* regex, bool full_match) MatchesRegexMatcher(const RE* regex, bool full_match)
: regex_(regex), full_match_(full_match) {} : regex_(regex), full_match_(full_match) {}
// These overloaded methods allow MatchesRegex(regex) to be used as // Accepts pointer types, particularly:
// a Matcher<T> as long as T can be converted to string. Returns // const char*
// true iff s matches regular expression regex. When full_match_ is // char*
// true, a full match is done; otherwise a partial match is done. // const wchar_t*
bool MatchAndExplain(const char* s, // wchar_t*
MatchResultListener* listener) const { template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != NULL && MatchAndExplain(internal::string(s), listener); return s != NULL && MatchAndExplain(internal::string(s), listener);
} }
bool MatchAndExplain(const internal::string& s, // Matches anything that can convert to internal::string.
//
// This is a template, not just a plain function with const internal::string&,
// because StringPiece has some interfering non-explicit constructors.
template <class MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
return full_match_ ? RE::FullMatch(s, *regex_) : const internal::string& s2(s);
RE::PartialMatch(s, *regex_); return full_match_ ? RE::FullMatch(s2, *regex_) :
RE::PartialMatch(s2, *regex_);
} }
void DescribeTo(::std::ostream* os) const { void DescribeTo(::std::ostream* os) const {
@ -2527,11 +2559,9 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
// Constructs the matcher from a sequence of element values or // Constructs the matcher from a sequence of element values or
// element matchers. // element matchers.
template <typename InputIter> template <typename InputIter>
ElementsAreMatcherImpl(InputIter first, size_t a_count) { ElementsAreMatcherImpl(InputIter first, InputIter last) {
matchers_.reserve(a_count); while (first != last) {
InputIter it = first; matchers_.push_back(MatcherCast<const Element&>(*first++));
for (size_t i = 0; i != a_count; ++i, ++it) {
matchers_.push_back(MatcherCast<const Element&>(*it));
} }
} }
@ -2642,7 +2672,8 @@ class ElementsAreMatcher0 {
Element; Element;
const Matcher<const Element&>* const matchers = NULL; const Matcher<const Element&>* const matchers = NULL;
return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0)); return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers,
matchers));
} }
}; };
@ -2650,21 +2681,17 @@ class ElementsAreMatcher0 {
template <typename T> template <typename T>
class ElementsAreArrayMatcher { class ElementsAreArrayMatcher {
public: public:
ElementsAreArrayMatcher(const T* first, size_t count) : template <typename Iter>
first_(first), count_(count) {} ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; return MakeMatcher(new ElementsAreMatcherImpl<Container>(
typedef typename internal::StlContainerView<RawContainer>::type::value_type matchers_.begin(), matchers_.end()));
Element;
return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
} }
private: private:
const T* const first_; const std::vector<T> matchers_;
const size_t count_;
GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher); GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher);
}; };

View File

@ -348,6 +348,19 @@ template <typename T> struct type_equals<T, T> : public true_type {};
template <typename T> struct remove_reference { typedef T type; }; // NOLINT template <typename T> struct remove_reference { typedef T type; }; // NOLINT
template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
// DecayArray<T>::type turns an array type U[N] to const U* and preserves
// other types. Useful for saving a copy of a function argument.
template <typename T> struct DecayArray { typedef T type; }; // NOLINT
template <typename T, size_t N> struct DecayArray<T[N]> {
typedef const T* type;
};
// Sometimes people use arrays whose size is not available at the use site
// (e.g. extern const char kNamePrefix[]). This specialization covers that
// case.
template <typename T> struct DecayArray<T[]> {
typedef const T* type;
};
// Invalid<T>() returns an invalid value of type T. This is useful // Invalid<T>() returns an invalid value of type T. This is useful
// when a value of type T is needed for compilation, but the statement // when a value of type T is needed for compilation, but the statement
// will not really be executed (or we don't care if the statement // will not really be executed (or we don't care if the statement

View File

@ -65,7 +65,7 @@
#define GMOCK_DECLARE_int32_(name) \ #define GMOCK_DECLARE_int32_(name) \
extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name)
#define GMOCK_DECLARE_string_(name) \ #define GMOCK_DECLARE_string_(name) \
extern GTEST_API_ ::testing::internal::String GMOCK_FLAG(name) extern GTEST_API_ ::std::string GMOCK_FLAG(name)
// Macros for defining flags. // Macros for defining flags.
#define GMOCK_DEFINE_bool_(name, default_val, doc) \ #define GMOCK_DEFINE_bool_(name, default_val, doc) \
@ -73,6 +73,6 @@
#define GMOCK_DEFINE_int32_(name, default_val, doc) \ #define GMOCK_DEFINE_int32_(name, default_val, doc) \
GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
#define GMOCK_DEFINE_string_(name, default_val, doc) \ #define GMOCK_DEFINE_string_(name, default_val, doc) \
GTEST_API_ ::testing::internal::String GMOCK_FLAG(name) = (default_val) GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val)
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_

View File

@ -62,7 +62,7 @@ static const char* ParseGoogleMockFlagValue(const char* str,
if (str == NULL || flag == NULL) return NULL; if (str == NULL || flag == NULL) return NULL;
// The flag must start with "--gmock_". // The flag must start with "--gmock_".
const String flag_str = String::Format("--gmock_%s", flag); const std::string flag_str = std::string("--gmock_") + flag;
const size_t flag_len = flag_str.length(); const size_t flag_len = flag_str.length();
if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
@ -107,7 +107,7 @@ static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
// On success, stores the value of the flag in *value, and returns // On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value. // true. On failure, returns false without changing *value.
static bool ParseGoogleMockStringFlag(const char* str, const char* flag, static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
String* value) { std::string* value) {
// Gets the value of the flag as a string. // Gets the value of the flag as a string.
const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
@ -131,7 +131,7 @@ void InitGoogleMockImpl(int* argc, CharType** argv) {
if (*argc <= 0) return; if (*argc <= 0) return;
for (int i = 1; i != *argc; i++) { for (int i = 1; i != *argc; i++) {
const String arg_string = StreamableToString(argv[i]); const std::string arg_string = StreamableToString(argv[i]);
const char* const arg = arg_string.c_str(); const char* const arg = arg_string.c_str();
// Do we see a Google Mock flag? // Do we see a Google Mock flag?

View File

@ -77,6 +77,7 @@ using testing::Ref;
using testing::StaticAssertTypeEq; using testing::StaticAssertTypeEq;
using testing::StrEq; using testing::StrEq;
using testing::Value; using testing::Value;
using testing::internal::ElementsAreArrayMatcher;
using testing::internal::string; using testing::internal::string;
// Returns the description of the given matcher. // Returns the description of the given matcher.
@ -527,6 +528,51 @@ TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) {
ElementsAre('l', 'o', '\0'))); ElementsAre('l', 'o', '\0')));
} }
TEST(ElementsAreTest, AcceptsStringLiteral) {
string array[] = { "hi", "one", "two" };
EXPECT_THAT(array, ElementsAre("hi", "one", "two"));
EXPECT_THAT(array, Not(ElementsAre("hi", "one", "too")));
}
#ifndef _MSC_VER
// The following test passes a value of type const char[] to a
// function template that expects const T&. Some versions of MSVC
// generates a compiler error C2665 for that. We believe it's a bug
// in MSVC. Therefore this test is #if-ed out for MSVC.
// Declared here with the size unknown. Defined AFTER the following test.
extern const char kHi[];
TEST(ElementsAreTest, AcceptsArrayWithUnknownSize) {
// The size of kHi is not known in this test, but ElementsAre() should
// still accept it.
string array1[] = { "hi" };
EXPECT_THAT(array1, ElementsAre(kHi));
string array2[] = { "ho" };
EXPECT_THAT(array2, Not(ElementsAre(kHi)));
}
const char kHi[] = "hi";
#endif // _MSC_VER
TEST(ElementsAreTest, MakesCopyOfArguments) {
int x = 1;
int y = 2;
// This should make a copy of x and y.
::testing::internal::ElementsAreMatcher2<int, int> polymorphic_matcher =
ElementsAre(x, y);
// Changing x and y now shouldn't affect the meaning of the above matcher.
x = y = 0;
const int array1[] = { 1, 2 };
EXPECT_THAT(array1, polymorphic_matcher);
const int array2[] = { 0, 0 };
EXPECT_THAT(array2, Not(polymorphic_matcher));
}
// Tests for ElementsAreArray(). Since ElementsAreArray() shares most // Tests for ElementsAreArray(). Since ElementsAreArray() shares most
// of the implementation with ElementsAre(), we don't test it as // of the implementation with ElementsAre(), we don't test it as
// thoroughly here. // thoroughly here.
@ -576,6 +622,39 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) {
EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray))); EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray)));
} }
TEST(ElementsAreArrayTest, CanBeCreatedWithVector) {
const int a[] = { 1, 2, 3 };
vector<int> test_vector(a, a + GMOCK_ARRAY_SIZE_(a));
const vector<int> expected(a, a + GMOCK_ARRAY_SIZE_(a));
EXPECT_THAT(test_vector, ElementsAreArray(expected));
test_vector.push_back(4);
EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
}
TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) {
const int a[] = { 1, 2, 3 };
const Matcher<int> kMatchers[] = { Eq(1), Eq(2), Eq(3) };
vector<int> test_vector(a, a + GMOCK_ARRAY_SIZE_(a));
const vector<Matcher<int> > expected(
kMatchers, kMatchers + GMOCK_ARRAY_SIZE_(kMatchers));
EXPECT_THAT(test_vector, ElementsAreArray(expected));
test_vector.push_back(4);
EXPECT_THAT(test_vector, Not(ElementsAreArray(expected)));
}
TEST(ElementsAreArrayTest, CanBeCreatedWithIteratorRange) {
const int a[] = { 1, 2, 3 };
const vector<int> test_vector(a, a + GMOCK_ARRAY_SIZE_(a));
const vector<int> expected(a, a + GMOCK_ARRAY_SIZE_(a));
EXPECT_THAT(test_vector, ElementsAreArray(expected.begin(), expected.end()));
// Pointers are iterators, too.
EXPECT_THAT(test_vector, ElementsAreArray(a, a + GMOCK_ARRAY_SIZE_(a)));
// The empty range of NULL pointers should also be okay.
int* const null_int = NULL;
EXPECT_THAT(test_vector, Not(ElementsAreArray(null_int, null_int)));
EXPECT_THAT((vector<int>()), ElementsAreArray(null_int, null_int));
}
// Since ElementsAre() and ElementsAreArray() share much of the // Since ElementsAre() and ElementsAreArray() share much of the
// implementation, we only do a sanity test for native arrays here. // implementation, we only do a sanity test for native arrays here.
TEST(ElementsAreArrayTest, WorksWithNativeArray) { TEST(ElementsAreArrayTest, WorksWithNativeArray) {
@ -587,6 +666,22 @@ TEST(ElementsAreArrayTest, WorksWithNativeArray) {
EXPECT_THAT(a, Not(ElementsAreArray(b, 1))); EXPECT_THAT(a, Not(ElementsAreArray(b, 1)));
} }
TEST(ElementsAreArrayTest, SourceLifeSpan) {
const int a[] = { 1, 2, 3 };
vector<int> test_vector(a, a + GMOCK_ARRAY_SIZE_(a));
vector<int> expect(a, a + GMOCK_ARRAY_SIZE_(a));
ElementsAreArrayMatcher<int> matcher_maker =
ElementsAreArray(expect.begin(), expect.end());
EXPECT_THAT(test_vector, matcher_maker);
// Changing in place the values that initialized matcher_maker should not
// affect matcher_maker anymore. It should have made its own copy of them.
typedef vector<int>::iterator Iter;
for (Iter it = expect.begin(); it != expect.end(); ++it) { *it += 10; }
EXPECT_THAT(test_vector, matcher_maker);
test_vector.push_back(3);
EXPECT_THAT(test_vector, Not(matcher_maker));
}
// Tests for the MATCHER*() macro family. // Tests for the MATCHER*() macro family.
// Tests that a simple MATCHER() definition works. // Tests that a simple MATCHER() definition works.
@ -1017,7 +1112,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
TEST(ContainsTest, ExplainsMatchResultCorrectly) { TEST(ContainsTest, ExplainsMatchResultCorrectly) {
const int a[2] = { 1, 2 }; const int a[2] = { 1, 2 };
Matcher<const int(&)[2]> m = Contains(2); Matcher<const int (&)[2]> m = Contains(2);
EXPECT_EQ("whose element #1 matches", Explain(m, a)); EXPECT_EQ("whose element #1 matches", Explain(m, a));
m = Contains(3); m = Contains(3);

View File

@ -343,13 +343,7 @@ TEST(ExpectTest, FailsNonfatallyOnFalse) {
class LogIsVisibleTest : public ::testing::Test { class LogIsVisibleTest : public ::testing::Test {
protected: protected:
virtual void SetUp() { virtual void SetUp() {
// The code needs to work when both ::string and ::std::string are original_verbose_ = GMOCK_FLAG(verbose);
// defined and the flag is implemented as a
// testing::internal::String. In this case, without the call to
// c_str(), the compiler will complain that it cannot figure out
// whether the String flag should be converted to a ::string or an
// ::std::string before being assigned to original_verbose_.
original_verbose_ = GMOCK_FLAG(verbose).c_str();
} }
virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; } virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; }
@ -415,7 +409,7 @@ TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
TEST(LogTest, NoSkippingStackFrameInOptMode) { TEST(LogTest, NoSkippingStackFrameInOptMode) {
CaptureStdout(); CaptureStdout();
Log(kWarning, "Test log.\n", 100); Log(kWarning, "Test log.\n", 100);
const String log = GetCapturedStdout(); const string log = GetCapturedStdout();
# if defined(NDEBUG) && GTEST_GOOGLE3_MODE_ # if defined(NDEBUG) && GTEST_GOOGLE3_MODE_
@ -502,7 +496,7 @@ TEST(TypeTraitsTest, remove_reference) {
// Verifies that Log() behaves correctly for the given verbosity level // Verifies that Log() behaves correctly for the given verbosity level
// and log severity. // and log severity.
String GrabOutput(void(*logger)(), const char* verbosity) { std::string GrabOutput(void(*logger)(), const char* verbosity) {
const string saved_flag = GMOCK_FLAG(verbose); const string saved_flag = GMOCK_FLAG(verbose);
GMOCK_FLAG(verbose) = verbosity; GMOCK_FLAG(verbose) = verbosity;
CaptureStdout(); CaptureStdout();
@ -525,7 +519,7 @@ void ExpectCallLogger() {
// Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info". // Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info".
TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) { TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) {
EXPECT_THAT(GrabOutput(ExpectCallLogger, kInfoVerbosity), EXPECT_THAT(std::string(GrabOutput(ExpectCallLogger, kInfoVerbosity)),
HasSubstr("EXPECT_CALL(mock, TestMethod())")); HasSubstr("EXPECT_CALL(mock, TestMethod())"));
} }
@ -548,7 +542,7 @@ void OnCallLogger() {
// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info". // Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
TEST(OnCallTest, LogsWhenVerbosityIsInfo) { TEST(OnCallTest, LogsWhenVerbosityIsInfo) {
EXPECT_THAT(GrabOutput(OnCallLogger, kInfoVerbosity), EXPECT_THAT(std::string(GrabOutput(OnCallLogger, kInfoVerbosity)),
HasSubstr("ON_CALL(mock, TestMethod())")); HasSubstr("ON_CALL(mock, TestMethod())"));
} }
@ -571,7 +565,7 @@ void OnCallAnyArgumentLogger() {
// Verifies that ON_CALL prints provided _ argument. // Verifies that ON_CALL prints provided _ argument.
TEST(OnCallTest, LogsAnythingArgument) { TEST(OnCallTest, LogsAnythingArgument) {
EXPECT_THAT(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity), EXPECT_THAT(std::string(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity)),
HasSubstr("ON_CALL(mock, TestMethodArg(_)")); HasSubstr("ON_CALL(mock, TestMethodArg(_)"));
} }

View File

@ -131,7 +131,6 @@ using testing::internal::IsReadableTypeName;
using testing::internal::JoinAsTuple; using testing::internal::JoinAsTuple;
using testing::internal::RE; using testing::internal::RE;
using testing::internal::StreamMatchResultListener; using testing::internal::StreamMatchResultListener;
using testing::internal::String;
using testing::internal::StringMatchResultListener; using testing::internal::StringMatchResultListener;
using testing::internal::Strings; using testing::internal::Strings;
using testing::internal::linked_ptr; using testing::internal::linked_ptr;

View File

@ -141,12 +141,12 @@ TEST(NiceMockTest, InfoForUninterestingCall) {
GMOCK_FLAG(verbose) = "info"; GMOCK_FLAG(verbose) = "info";
CaptureStdout(); CaptureStdout();
nice_foo.DoThis(); nice_foo.DoThis();
EXPECT_THAT(GetCapturedStdout(), EXPECT_THAT(std::string(GetCapturedStdout()),
HasSubstr("Uninteresting mock function call")); HasSubstr("Uninteresting mock function call"));
CaptureStdout(); CaptureStdout();
nice_foo.DoThat(true); nice_foo.DoThat(true);
EXPECT_THAT(GetCapturedStdout(), EXPECT_THAT(std::string(GetCapturedStdout()),
HasSubstr("Uninteresting mock function call")); HasSubstr("Uninteresting mock function call"));
GMOCK_FLAG(verbose) = saved_flag; GMOCK_FLAG(verbose) = saved_flag;
} }

View File

@ -94,7 +94,6 @@ using testing::internal::FormatFileLocation;
using testing::internal::kErrorVerbosity; using testing::internal::kErrorVerbosity;
using testing::internal::kInfoVerbosity; using testing::internal::kInfoVerbosity;
using testing::internal::kWarningVerbosity; using testing::internal::kWarningVerbosity;
using testing::internal::String;
using testing::internal::linked_ptr; using testing::internal::linked_ptr;
using testing::internal::string; using testing::internal::string;
@ -632,7 +631,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) {
b.DoB(1); b.DoB(1);
b.DoB(2); b.DoB(2);
} }
const String output = GetCapturedStdout(); const std::string output = GetCapturedStdout();
EXPECT_PRED_FORMAT2( EXPECT_PRED_FORMAT2(
IsSubstring, IsSubstring,
"Too many actions specified in EXPECT_CALL(b, DoB())...\n" "Too many actions specified in EXPECT_CALL(b, DoB())...\n"
@ -674,7 +673,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) {
CaptureStdout(); CaptureStdout();
b.DoB(); b.DoB();
const String output = GetCapturedStdout(); const std::string output = GetCapturedStdout();
EXPECT_PRED_FORMAT2( EXPECT_PRED_FORMAT2(
IsSubstring, IsSubstring,
"Too few actions specified in EXPECT_CALL(b, DoB())...\n" "Too few actions specified in EXPECT_CALL(b, DoB())...\n"
@ -869,13 +868,13 @@ TEST(ExpectCallTest, TakesDefaultActionWhenWillListIsExhausted) {
// expectation has no action clause at all. // expectation has no action clause at all.
EXPECT_EQ(1, b.DoB()); EXPECT_EQ(1, b.DoB());
EXPECT_EQ(2, b.DoB()); EXPECT_EQ(2, b.DoB());
const String output1 = GetCapturedStdout(); const std::string output1 = GetCapturedStdout();
EXPECT_STREQ("", output1.c_str()); EXPECT_STREQ("", output1.c_str());
CaptureStdout(); CaptureStdout();
EXPECT_EQ(0, b.DoB()); EXPECT_EQ(0, b.DoB());
EXPECT_EQ(0, b.DoB()); EXPECT_EQ(0, b.DoB());
const String output2 = GetCapturedStdout(); const std::string output2 = GetCapturedStdout();
EXPECT_THAT(output2.c_str(), EXPECT_THAT(output2.c_str(),
HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n" HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n"
"Called 3 times, but only 2 WillOnce()s are specified" "Called 3 times, but only 2 WillOnce()s are specified"
@ -895,7 +894,7 @@ TEST(FunctionMockerTest, ReportsExpectCallLocationForExhausedActions) {
CaptureStdout(); CaptureStdout();
EXPECT_EQ(0, b.DoB()); EXPECT_EQ(0, b.DoB());
const String output = GetCapturedStdout(); const std::string output = GetCapturedStdout();
// The warning message should contain the call location. // The warning message should contain the call location.
EXPECT_PRED_FORMAT2(IsSubstring, expect_call_location, output); EXPECT_PRED_FORMAT2(IsSubstring, expect_call_location, output);
} }
@ -1873,14 +1872,8 @@ class MockC {
class VerboseFlagPreservingFixture : public testing::Test { class VerboseFlagPreservingFixture : public testing::Test {
protected: protected:
// The code needs to work when both ::string and ::std::string are defined
// and the flag is implemented as a testing::internal::String. In this
// case, without the call to c_str(), the compiler will complain that it
// cannot figure out what overload of string constructor to use.
// TODO(vladl@google.com): Use internal::string instead of String for
// string flags in Google Test.
VerboseFlagPreservingFixture() VerboseFlagPreservingFixture()
: saved_verbose_flag_(GMOCK_FLAG(verbose).c_str()) {} : saved_verbose_flag_(GMOCK_FLAG(verbose)) {}
~VerboseFlagPreservingFixture() { GMOCK_FLAG(verbose) = saved_verbose_flag_; } ~VerboseFlagPreservingFixture() { GMOCK_FLAG(verbose) = saved_verbose_flag_; }
@ -1898,7 +1891,7 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) {
MockC c; MockC c;
CaptureStdout(); CaptureStdout();
c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable()); c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable());
const String output = GetCapturedStdout(); const std::string output = GetCapturedStdout();
EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output); EXPECT_PRED_FORMAT2(IsSubstring, "GMOCK WARNING", output);
EXPECT_PRED_FORMAT2(IsSubstring, "Stack trace:", output); EXPECT_PRED_FORMAT2(IsSubstring, "Stack trace:", output);
@ -1915,7 +1908,7 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) {
// stack trace. // stack trace.
CaptureStdout(); CaptureStdout();
c.NonVoidMethod(); c.NonVoidMethod();
const String output2 = GetCapturedStdout(); const std::string output2 = GetCapturedStdout();
EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2); EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2);
# endif // NDEBUG # endif // NDEBUG
@ -1928,7 +1921,7 @@ TEST(FunctionCallMessageTest, UninterestingCallPrintsArgumentsAndReturnValue) {
MockB b; MockB b;
CaptureStdout(); CaptureStdout();
b.DoB(); b.DoB();
const String output1 = GetCapturedStdout(); const std::string output1 = GetCapturedStdout();
EXPECT_PRED_FORMAT2( EXPECT_PRED_FORMAT2(
IsSubstring, IsSubstring,
"Uninteresting mock function call - returning default value.\n" "Uninteresting mock function call - returning default value.\n"
@ -1940,7 +1933,7 @@ TEST(FunctionCallMessageTest, UninterestingCallPrintsArgumentsAndReturnValue) {
MockC c; MockC c;
CaptureStdout(); CaptureStdout();
c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable()); c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable());
const String output2 = GetCapturedStdout(); const std::string output2 = GetCapturedStdout();
EXPECT_THAT(output2.c_str(), EXPECT_THAT(output2.c_str(),
ContainsRegex( ContainsRegex(
"Uninteresting mock function call - returning directly\\.\n" "Uninteresting mock function call - returning directly\\.\n"
@ -1958,7 +1951,7 @@ class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
// should_print is true, the output should match the given regex and // should_print is true, the output should match the given regex and
// contain the given function name in the stack trace. When it's // contain the given function name in the stack trace. When it's
// false, the output should be empty.) // false, the output should be empty.)
void VerifyOutput(const String& output, bool should_print, void VerifyOutput(const std::string& output, bool should_print,
const string& expected_substring, const string& expected_substring,
const string& function_name) { const string& function_name) {
if (should_print) { if (should_print) {