diff --git a/include/gmock/gmock-generated-matchers.h b/include/gmock/gmock-generated-matchers.h index 5527ed3e..bc3f610c 100644 --- a/include/gmock/gmock-generated-matchers.h +++ b/include/gmock/gmock-generated-matchers.h @@ -38,6 +38,7 @@ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#include #include #include #include @@ -305,7 +306,9 @@ class 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 class ElementsAreMatcher1 { @@ -326,11 +329,12 @@ class ElementsAreMatcher1 { // a local array. const Matcher matcher = MatcherCast(e1_); - return MakeMatcher(new ElementsAreMatcherImpl(&matcher, 1)); + return MakeMatcher(new ElementsAreMatcherImpl(&matcher, + &matcher + 1)); } private: - const T1& e1_; + const typename DecayArray::type e1_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher1); }; @@ -351,12 +355,13 @@ class ElementsAreMatcher2 { MatcherCast(e2_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 2)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 2)); } private: - const T1& e1_; - const T2& e2_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher2); }; @@ -379,13 +384,14 @@ class ElementsAreMatcher3 { MatcherCast(e3_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 3)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 3)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher3); }; @@ -409,14 +415,15 @@ class ElementsAreMatcher4 { MatcherCast(e4_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 4)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 4)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher4); }; @@ -441,15 +448,16 @@ class ElementsAreMatcher5 { MatcherCast(e5_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 5)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 5)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher5); }; @@ -477,16 +485,17 @@ class ElementsAreMatcher6 { MatcherCast(e6_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 6)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 6)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; - const T6& e6_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; + const typename DecayArray::type e6_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher6); }; @@ -515,17 +524,18 @@ class ElementsAreMatcher7 { MatcherCast(e7_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 7)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 7)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; - const T6& e6_; - const T7& e7_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; + const typename DecayArray::type e6_; + const typename DecayArray::type e7_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher7); }; @@ -555,18 +565,19 @@ class ElementsAreMatcher8 { MatcherCast(e8_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 8)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 8)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; - const T6& e6_; - const T7& e7_; - const T8& e8_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; + const typename DecayArray::type e6_; + const typename DecayArray::type e7_; + const typename DecayArray::type e8_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher8); }; @@ -598,19 +609,20 @@ class ElementsAreMatcher9 { MatcherCast(e9_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 9)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 9)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; - const T6& e6_; - const T7& e7_; - const T8& e8_; - const T9& e9_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; + const typename DecayArray::type e6_; + const typename DecayArray::type e7_; + const typename DecayArray::type e8_; + const typename DecayArray::type e9_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher9); }; @@ -643,20 +655,21 @@ class ElementsAreMatcher10 { MatcherCast(e10_), }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 10)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + 10)); } private: - const T1& e1_; - const T2& e2_; - const T3& e3_; - const T4& e4_; - const T5& e5_; - const T6& e6_; - const T7& e7_; - const T8& e8_; - const T9& e9_; - const T10& e10_; + const typename DecayArray::type e1_; + const typename DecayArray::type e2_; + const typename DecayArray::type e3_; + const typename DecayArray::type e4_; + const typename DecayArray::type e5_; + const typename DecayArray::type e6_; + const typename DecayArray::type e7_; + const typename DecayArray::type e8_; + const typename DecayArray::type e9_; + const typename DecayArray::type e10_; GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher10); }; @@ -1007,24 +1020,55 @@ inline internal::ElementsAreMatcher10(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10); } -// ElementsAreArray(array) and ElementAreArray(array, count) are like -// ElementsAre(), except that they take an array of values or -// matchers. The former form infers the size of 'array', which must -// be a static C-style array. In the latter form, 'array' can either -// be a static array or a pointer to a dynamically created array. - +// ElementsAreArray(array) +// ElementsAreArray(pointer, count) +// ElementsAreArray(vector) +// ElementsAreArray(first, last) +// +// 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 inline internal::ElementsAreArrayMatcher ElementsAreArray( const T* first, size_t count) { - return internal::ElementsAreArrayMatcher(first, count); + return internal::ElementsAreArrayMatcher(first, first + count); } template -inline internal::ElementsAreArrayMatcher -ElementsAreArray(const T (&array)[N]) { - return internal::ElementsAreArrayMatcher(array, N); +inline internal::ElementsAreArrayMatcher ElementsAreArray( + const T (&array)[N]) { + return internal::ElementsAreArrayMatcher(array, array + N); } +template +inline internal::ElementsAreArrayMatcher ElementsAreArray( + const std::vector& vec) { + return internal::ElementsAreArrayMatcher(vec.begin(), vec.end()); +} + +template +inline internal::ElementsAreArrayMatcher< + typename std::iterator_traits::value_type> +ElementsAreArray(Iter first, Iter last) { + typedef typename std::iterator_traits::value_type T; + return internal::ElementsAreArrayMatcher(first, last); +} + + // 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. diff --git a/include/gmock/gmock-generated-matchers.h.pump b/include/gmock/gmock-generated-matchers.h.pump index 7cdb84bf..a8d7612d 100644 --- a/include/gmock/gmock-generated-matchers.h.pump +++ b/include/gmock/gmock-generated-matchers.h.pump @@ -40,6 +40,7 @@ $$ }} This line fixes auto-indentation of the following code in Emacs. #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#include #include #include #include @@ -186,7 +187,9 @@ class 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 @@ -214,7 +217,8 @@ $if i==1 [[ // a local array. const Matcher matcher = MatcherCast(e1_); - return MakeMatcher(new ElementsAreMatcherImpl(&matcher, 1)); + return MakeMatcher(new ElementsAreMatcherImpl(&matcher, + &matcher + 1)); ]] $else [[ const Matcher matchers[] = { @@ -225,7 +229,8 @@ $for j [[ ]] }; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, $i)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers + $i)); ]] } @@ -233,7 +238,7 @@ $for j [[ private: $for j [[ - const T$j& e$j[[]]_; + const typename DecayArray::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 -// ElementsAre(), except that they take an array of values or -// matchers. The former form infers the size of 'array', which must -// be a static C-style array. In the latter form, 'array' can either -// be a static array or a pointer to a dynamically created array. - +// ElementsAreArray(array) +// ElementsAreArray(pointer, count) +// ElementsAreArray(vector) +// ElementsAreArray(first, last) +// +// 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 inline internal::ElementsAreArrayMatcher ElementsAreArray( const T* first, size_t count) { - return internal::ElementsAreArrayMatcher(first, count); + return internal::ElementsAreArrayMatcher(first, first + count); } template -inline internal::ElementsAreArrayMatcher -ElementsAreArray(const T (&array)[N]) { - return internal::ElementsAreArrayMatcher(array, N); +inline internal::ElementsAreArrayMatcher ElementsAreArray( + const T (&array)[N]) { + return internal::ElementsAreArrayMatcher(array, array + N); } +template +inline internal::ElementsAreArrayMatcher ElementsAreArray( + const std::vector& vec) { + return internal::ElementsAreArrayMatcher(vec.begin(), vec.end()); +} + +template +inline internal::ElementsAreArrayMatcher< + typename std::iterator_traits::value_type> +ElementsAreArray(Iter first, Iter last) { + typedef typename std::iterator_traits::value_type T; + return internal::ElementsAreArrayMatcher(first, last); +} + + // 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. diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index 4f1c433c..751574ca 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -935,26 +935,33 @@ bool CaseInsensitiveStringEquals(const StringType& s1, template class StrEqualityMatcher { public: - typedef typename StringType::const_pointer ConstCharPointer; - StrEqualityMatcher(const StringType& str, bool expect_eq, bool 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_; - // otherwise returns true iff s is not equal to string_. - bool MatchAndExplain(ConstCharPointer s, - MatchResultListener* listener) const { + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { if (s == NULL) { return !expect_eq_; } 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 + bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - const bool eq = case_sensitive_ ? s == string_ : - CaseInsensitiveStringEquals(s, string_); + const StringType& s2(s); + const bool eq = case_sensitive_ ? s2 == string_ : + CaseInsensitiveStringEquals(s2, string_); return expect_eq_ == eq; } @@ -989,22 +996,28 @@ class StrEqualityMatcher { template class HasSubstrMatcher { public: - typedef typename StringType::const_pointer ConstCharPointer; - explicit HasSubstrMatcher(const StringType& substring) : substring_(substring) {} - // These overloaded methods allow HasSubstr(substring) to be used as a - // Matcher as long as T can be converted to string. Returns true - // iff s contains substring_ as a substring. - bool MatchAndExplain(ConstCharPointer s, - MatchResultListener* listener) const { + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { 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 + bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - return s.find(substring_) != StringType::npos; + const StringType& s2(s); + return s2.find(substring_) != StringType::npos; } // Describes what this matcher matches. @@ -1030,23 +1043,29 @@ class HasSubstrMatcher { template class StartsWithMatcher { public: - typedef typename StringType::const_pointer ConstCharPointer; - explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { } - // These overloaded methods allow StartsWith(prefix) to be used as a - // Matcher as long as T can be converted to string. Returns true - // iff s starts with prefix_. - bool MatchAndExplain(ConstCharPointer s, - MatchResultListener* listener) const { + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { 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 + bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - return s.length() >= prefix_.length() && - s.substr(0, prefix_.length()) == prefix_; + const StringType& s2(s); + return s2.length() >= prefix_.length() && + s2.substr(0, prefix_.length()) == prefix_; } void DescribeTo(::std::ostream* os) const { @@ -1071,22 +1090,28 @@ class StartsWithMatcher { template class EndsWithMatcher { public: - typedef typename StringType::const_pointer ConstCharPointer; - explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} - // These overloaded methods allow EndsWith(suffix) to be used as a - // Matcher as long as T can be converted to string. Returns true - // iff s ends with suffix_. - bool MatchAndExplain(ConstCharPointer s, - MatchResultListener* listener) const { + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { 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 + bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - return s.length() >= suffix_.length() && - s.substr(s.length() - suffix_.length()) == suffix_; + const StringType& s2(s); + return s2.length() >= suffix_.length() && + s2.substr(s2.length() - suffix_.length()) == suffix_; } void DescribeTo(::std::ostream* os) const { @@ -1113,19 +1138,26 @@ class MatchesRegexMatcher { MatchesRegexMatcher(const RE* regex, bool full_match) : regex_(regex), full_match_(full_match) {} - // These overloaded methods allow MatchesRegex(regex) to be used as - // a Matcher as long as T can be converted to string. Returns - // true iff s matches regular expression regex. When full_match_ is - // true, a full match is done; otherwise a partial match is done. - bool MatchAndExplain(const char* s, - MatchResultListener* listener) const { + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { 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 + bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - return full_match_ ? RE::FullMatch(s, *regex_) : - RE::PartialMatch(s, *regex_); + const internal::string& s2(s); + return full_match_ ? RE::FullMatch(s2, *regex_) : + RE::PartialMatch(s2, *regex_); } void DescribeTo(::std::ostream* os) const { @@ -2527,11 +2559,9 @@ class ElementsAreMatcherImpl : public MatcherInterface { // Constructs the matcher from a sequence of element values or // element matchers. template - ElementsAreMatcherImpl(InputIter first, size_t a_count) { - matchers_.reserve(a_count); - InputIter it = first; - for (size_t i = 0; i != a_count; ++i, ++it) { - matchers_.push_back(MatcherCast(*it)); + ElementsAreMatcherImpl(InputIter first, InputIter last) { + while (first != last) { + matchers_.push_back(MatcherCast(*first++)); } } @@ -2642,7 +2672,8 @@ class ElementsAreMatcher0 { Element; const Matcher* const matchers = NULL; - return MakeMatcher(new ElementsAreMatcherImpl(matchers, 0)); + return MakeMatcher(new ElementsAreMatcherImpl(matchers, + matchers)); } }; @@ -2650,21 +2681,17 @@ class ElementsAreMatcher0 { template class ElementsAreArrayMatcher { public: - ElementsAreArrayMatcher(const T* first, size_t count) : - first_(first), count_(count) {} + template + ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} template operator Matcher() const { - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; - typedef typename internal::StlContainerView::type::value_type - Element; - - return MakeMatcher(new ElementsAreMatcherImpl(first_, count_)); + return MakeMatcher(new ElementsAreMatcherImpl( + matchers_.begin(), matchers_.end())); } private: - const T* const first_; - const size_t count_; + const std::vector matchers_; GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher); }; diff --git a/include/gmock/internal/gmock-internal-utils.h b/include/gmock/internal/gmock-internal-utils.h index d63fb223..f9b6b809 100644 --- a/include/gmock/internal/gmock-internal-utils.h +++ b/include/gmock/internal/gmock-internal-utils.h @@ -348,6 +348,19 @@ template struct type_equals : public true_type {}; template struct remove_reference { typedef T type; }; // NOLINT template struct remove_reference { typedef T type; }; // NOLINT +// DecayArray::type turns an array type U[N] to const U* and preserves +// other types. Useful for saving a copy of a function argument. +template struct DecayArray { typedef T type; }; // NOLINT +template struct DecayArray { + 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 struct DecayArray { + typedef const T* type; +}; + // Invalid() returns an invalid value of type T. This is useful // 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 diff --git a/include/gmock/internal/gmock-port.h b/include/gmock/internal/gmock-port.h index 6a515d87..b6c5c7f1 100644 --- a/include/gmock/internal/gmock-port.h +++ b/include/gmock/internal/gmock-port.h @@ -65,7 +65,7 @@ #define GMOCK_DECLARE_int32_(name) \ extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(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. #define GMOCK_DEFINE_bool_(name, default_val, doc) \ @@ -73,6 +73,6 @@ #define GMOCK_DEFINE_int32_(name, default_val, doc) \ GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) #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_ diff --git a/src/gmock.cc b/src/gmock.cc index e06acc5c..1c06985d 100644 --- a/src/gmock.cc +++ b/src/gmock.cc @@ -62,7 +62,7 @@ static const char* ParseGoogleMockFlagValue(const char* str, if (str == NULL || flag == NULL) return NULL; // 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(); 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 // true. On failure, returns false without changing *value. static bool ParseGoogleMockStringFlag(const char* str, const char* flag, - String* value) { + std::string* value) { // Gets the value of the flag as a string. const char* const value_str = ParseGoogleMockFlagValue(str, flag, false); @@ -131,7 +131,7 @@ void InitGoogleMockImpl(int* argc, CharType** argv) { if (*argc <= 0) return; 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(); // Do we see a Google Mock flag? diff --git a/test/gmock-generated-matchers_test.cc b/test/gmock-generated-matchers_test.cc index b35c4505..4b7e6e05 100644 --- a/test/gmock-generated-matchers_test.cc +++ b/test/gmock-generated-matchers_test.cc @@ -77,6 +77,7 @@ using testing::Ref; using testing::StaticAssertTypeEq; using testing::StrEq; using testing::Value; +using testing::internal::ElementsAreArrayMatcher; using testing::internal::string; // Returns the description of the given matcher. @@ -527,6 +528,51 @@ TEST(ElementsAreTest, WorksWithTwoDimensionalNativeArray) { 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 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 // of the implementation with ElementsAre(), we don't test it as // thoroughly here. @@ -576,6 +622,39 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) { EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray))); } +TEST(ElementsAreArrayTest, CanBeCreatedWithVector) { + const int a[] = { 1, 2, 3 }; + vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); + const vector 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 kMatchers[] = { Eq(1), Eq(2), Eq(3) }; + vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); + const vector > 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 test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); + const vector 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()), ElementsAreArray(null_int, null_int)); +} + // Since ElementsAre() and ElementsAreArray() share much of the // implementation, we only do a sanity test for native arrays here. TEST(ElementsAreArrayTest, WorksWithNativeArray) { @@ -587,6 +666,22 @@ TEST(ElementsAreArrayTest, WorksWithNativeArray) { EXPECT_THAT(a, Not(ElementsAreArray(b, 1))); } +TEST(ElementsAreArrayTest, SourceLifeSpan) { + const int a[] = { 1, 2, 3 }; + vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); + vector expect(a, a + GMOCK_ARRAY_SIZE_(a)); + ElementsAreArrayMatcher 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::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 that a simple MATCHER() definition works. @@ -1017,7 +1112,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) { TEST(ContainsTest, ExplainsMatchResultCorrectly) { const int a[2] = { 1, 2 }; - Matcher m = Contains(2); + Matcher m = Contains(2); EXPECT_EQ("whose element #1 matches", Explain(m, a)); m = Contains(3); diff --git a/test/gmock-internal-utils_test.cc b/test/gmock-internal-utils_test.cc index d53282eb..3c78f647 100644 --- a/test/gmock-internal-utils_test.cc +++ b/test/gmock-internal-utils_test.cc @@ -343,13 +343,7 @@ TEST(ExpectTest, FailsNonfatallyOnFalse) { class LogIsVisibleTest : public ::testing::Test { protected: virtual void SetUp() { - // 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 - // 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(); + original_verbose_ = GMOCK_FLAG(verbose); } virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; } @@ -415,7 +409,7 @@ TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) { TEST(LogTest, NoSkippingStackFrameInOptMode) { CaptureStdout(); Log(kWarning, "Test log.\n", 100); - const String log = GetCapturedStdout(); + const string log = GetCapturedStdout(); # if defined(NDEBUG) && GTEST_GOOGLE3_MODE_ @@ -502,7 +496,7 @@ TEST(TypeTraitsTest, remove_reference) { // Verifies that Log() behaves correctly for the given verbosity level // 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); GMOCK_FLAG(verbose) = verbosity; CaptureStdout(); @@ -525,7 +519,7 @@ void ExpectCallLogger() { // Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info". TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) { - EXPECT_THAT(GrabOutput(ExpectCallLogger, kInfoVerbosity), + EXPECT_THAT(std::string(GrabOutput(ExpectCallLogger, kInfoVerbosity)), 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". TEST(OnCallTest, LogsWhenVerbosityIsInfo) { - EXPECT_THAT(GrabOutput(OnCallLogger, kInfoVerbosity), + EXPECT_THAT(std::string(GrabOutput(OnCallLogger, kInfoVerbosity)), HasSubstr("ON_CALL(mock, TestMethod())")); } @@ -571,7 +565,7 @@ void OnCallAnyArgumentLogger() { // Verifies that ON_CALL prints provided _ argument. TEST(OnCallTest, LogsAnythingArgument) { - EXPECT_THAT(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity), + EXPECT_THAT(std::string(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity)), HasSubstr("ON_CALL(mock, TestMethodArg(_)")); } diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 6e5d5c31..de3f8d73 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -131,7 +131,6 @@ using testing::internal::IsReadableTypeName; using testing::internal::JoinAsTuple; using testing::internal::RE; using testing::internal::StreamMatchResultListener; -using testing::internal::String; using testing::internal::StringMatchResultListener; using testing::internal::Strings; using testing::internal::linked_ptr; diff --git a/test/gmock-nice-strict_test.cc b/test/gmock-nice-strict_test.cc index e3344180..315a8221 100644 --- a/test/gmock-nice-strict_test.cc +++ b/test/gmock-nice-strict_test.cc @@ -141,12 +141,12 @@ TEST(NiceMockTest, InfoForUninterestingCall) { GMOCK_FLAG(verbose) = "info"; CaptureStdout(); nice_foo.DoThis(); - EXPECT_THAT(GetCapturedStdout(), + EXPECT_THAT(std::string(GetCapturedStdout()), HasSubstr("Uninteresting mock function call")); CaptureStdout(); nice_foo.DoThat(true); - EXPECT_THAT(GetCapturedStdout(), + EXPECT_THAT(std::string(GetCapturedStdout()), HasSubstr("Uninteresting mock function call")); GMOCK_FLAG(verbose) = saved_flag; } diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc index 9177b322..0e2e0090 100644 --- a/test/gmock-spec-builders_test.cc +++ b/test/gmock-spec-builders_test.cc @@ -94,7 +94,6 @@ using testing::internal::FormatFileLocation; using testing::internal::kErrorVerbosity; using testing::internal::kInfoVerbosity; using testing::internal::kWarningVerbosity; -using testing::internal::String; using testing::internal::linked_ptr; using testing::internal::string; @@ -632,7 +631,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooManyActions) { b.DoB(1); b.DoB(2); } - const String output = GetCapturedStdout(); + const std::string output = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Too many actions specified in EXPECT_CALL(b, DoB())...\n" @@ -674,7 +673,7 @@ TEST(ExpectCallSyntaxTest, WarnsOnTooFewActions) { CaptureStdout(); b.DoB(); - const String output = GetCapturedStdout(); + const std::string output = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Too few actions specified in EXPECT_CALL(b, DoB())...\n" @@ -869,13 +868,13 @@ TEST(ExpectCallTest, TakesDefaultActionWhenWillListIsExhausted) { // expectation has no action clause at all. EXPECT_EQ(1, b.DoB()); EXPECT_EQ(2, b.DoB()); - const String output1 = GetCapturedStdout(); + const std::string output1 = GetCapturedStdout(); EXPECT_STREQ("", output1.c_str()); CaptureStdout(); EXPECT_EQ(0, b.DoB()); EXPECT_EQ(0, b.DoB()); - const String output2 = GetCapturedStdout(); + const std::string output2 = GetCapturedStdout(); EXPECT_THAT(output2.c_str(), HasSubstr("Actions ran out in EXPECT_CALL(b, DoB())...\n" "Called 3 times, but only 2 WillOnce()s are specified" @@ -895,7 +894,7 @@ TEST(FunctionMockerTest, ReportsExpectCallLocationForExhausedActions) { CaptureStdout(); EXPECT_EQ(0, b.DoB()); - const String output = GetCapturedStdout(); + const std::string output = GetCapturedStdout(); // The warning message should contain the call location. EXPECT_PRED_FORMAT2(IsSubstring, expect_call_location, output); } @@ -1873,14 +1872,8 @@ class MockC { class VerboseFlagPreservingFixture : public testing::Test { 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() - : saved_verbose_flag_(GMOCK_FLAG(verbose).c_str()) {} + : saved_verbose_flag_(GMOCK_FLAG(verbose)) {} ~VerboseFlagPreservingFixture() { GMOCK_FLAG(verbose) = saved_verbose_flag_; } @@ -1898,7 +1891,7 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) { MockC c; CaptureStdout(); 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, "Stack trace:", output); @@ -1915,7 +1908,7 @@ TEST(FunctionCallMessageTest, UninterestingCallGeneratesFyiWithStackTrace) { // stack trace. CaptureStdout(); c.NonVoidMethod(); - const String output2 = GetCapturedStdout(); + const std::string output2 = GetCapturedStdout(); EXPECT_PRED_FORMAT2(IsSubstring, "NonVoidMethod(", output2); # endif // NDEBUG @@ -1928,7 +1921,7 @@ TEST(FunctionCallMessageTest, UninterestingCallPrintsArgumentsAndReturnValue) { MockB b; CaptureStdout(); b.DoB(); - const String output1 = GetCapturedStdout(); + const std::string output1 = GetCapturedStdout(); EXPECT_PRED_FORMAT2( IsSubstring, "Uninteresting mock function call - returning default value.\n" @@ -1940,7 +1933,7 @@ TEST(FunctionCallMessageTest, UninterestingCallPrintsArgumentsAndReturnValue) { MockC c; CaptureStdout(); c.VoidMethod(false, 5, "Hi", NULL, Printable(), Unprintable()); - const String output2 = GetCapturedStdout(); + const std::string output2 = GetCapturedStdout(); EXPECT_THAT(output2.c_str(), ContainsRegex( "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 // contain the given function name in the stack trace. When it's // 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& function_name) { if (should_print) {