diff options
author | Gennadiy Civil <misterg@google.com> | 2018-04-25 17:10:41 (GMT) |
---|---|---|
committer | Gennadiy Civil <misterg@google.com> | 2018-04-25 17:10:41 (GMT) |
commit | b539167cf0254f521b791e908f6d3a5ff3f30245 (patch) | |
tree | a0609a9dda7ebefb285bae6e6b0f5e1c577c1051 /googlemock/include/gmock/gmock-matchers.h | |
parent | 1114a0202a3147c1ce548c9a2883ce29e80df9e3 (diff) | |
download | googletest-b539167cf0254f521b791e908f6d3a5ff3f30245.zip googletest-b539167cf0254f521b791e908f6d3a5ff3f30245.tar.gz googletest-b539167cf0254f521b791e908f6d3a5ff3f30245.tar.bz2 |
merging,
Diffstat (limited to 'googlemock/include/gmock/gmock-matchers.h')
-rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 219 |
1 files changed, 91 insertions, 128 deletions
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 3a2b944..e0a7864 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -1718,25 +1718,27 @@ class NotMatcher { // that will prevent different instantiations of BothOfMatcher from // sharing the same BothOfMatcherImpl<T> class. template <typename T> -class BothOfMatcherImpl +class AllOfMatcherImpl : public MatcherInterface<GTEST_REFERENCE_TO_CONST_(T)> { public: - BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2) - : matcher1_(matcher1), matcher2_(matcher2) {} + explicit AllOfMatcherImpl(std::vector<Matcher<T> > matchers) + : matchers_(internal::move(matchers)) {} virtual void DescribeTo(::std::ostream* os) const { *os << "("; - matcher1_.DescribeTo(os); - *os << ") and ("; - matcher2_.DescribeTo(os); + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") and ("; + matchers_[i].DescribeTo(os); + } *os << ")"; } virtual void DescribeNegationTo(::std::ostream* os) const { *os << "("; - matcher1_.DescribeNegationTo(os); - *os << ") or ("; - matcher2_.DescribeNegationTo(os); + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") or ("; + matchers_[i].DescribeNegationTo(os); + } *os << ")"; } @@ -1744,93 +1746,38 @@ class BothOfMatcherImpl MatchResultListener* listener) const { // If either matcher1_ or matcher2_ doesn't match x, we only need // to explain why one of them fails. - StringMatchResultListener listener1; - if (!matcher1_.MatchAndExplain(x, &listener1)) { - *listener << listener1.str(); - return false; - } + std::string all_match_result; - StringMatchResultListener listener2; - if (!matcher2_.MatchAndExplain(x, &listener2)) { - *listener << listener2.str(); - return false; + for (size_t i = 0; i < matchers_.size(); ++i) { + StringMatchResultListener slistener; + if (matchers_[i].MatchAndExplain(x, &slistener)) { + if (all_match_result.empty()) { + all_match_result = slistener.str(); + } else { + std::string result = slistener.str(); + if (!result.empty()) { + all_match_result += ", and "; + all_match_result += result; + } + } + } else { + *listener << slistener.str(); + return false; + } } // Otherwise we need to explain why *both* of them match. - const std::string s1 = listener1.str(); - const std::string s2 = listener2.str(); - - if (s1 == "") { - *listener << s2; - } else { - *listener << s1; - if (s2 != "") { - *listener << ", and " << s2; - } - } + *listener << all_match_result; return true; } private: - const Matcher<T> matcher1_; - const Matcher<T> matcher2_; + const std::vector<Matcher<T> > matchers_; - GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl); + GTEST_DISALLOW_ASSIGN_(AllOfMatcherImpl); }; #if GTEST_LANG_CXX11 -// MatcherList provides mechanisms for storing a variable number of matchers in -// a list structure (ListType) and creating a combining matcher from such a -// list. -// The template is defined recursively using the following template parameters: -// * kSize is the length of the MatcherList. -// * Head is the type of the first matcher of the list. -// * Tail denotes the types of the remaining matchers of the list. -template <int kSize, typename Head, typename... Tail> -struct MatcherList { - typedef MatcherList<kSize - 1, Tail...> MatcherListTail; - typedef ::std::pair<Head, typename MatcherListTail::ListType> ListType; - - // BuildList stores variadic type values in a nested pair structure. - // Example: - // MatcherList<3, int, string, float>::BuildList(5, "foo", 2.0) will return - // the corresponding result of type pair<int, pair<string, float>>. - static ListType BuildList(const Head& matcher, const Tail&... tail) { - return ListType(matcher, MatcherListTail::BuildList(tail...)); - } - - // CreateMatcher<T> creates a Matcher<T> from a given list of matchers (built - // by BuildList()). CombiningMatcher<T> is used to combine the matchers of the - // list. CombiningMatcher<T> must implement MatcherInterface<T> and have a - // constructor taking two Matcher<T>s as input. - template <typename T, template <typename /* T */> class CombiningMatcher> - static Matcher<T> CreateMatcher(const ListType& matchers) { - return Matcher<T>(new CombiningMatcher<T>( - SafeMatcherCast<T>(matchers.first), - MatcherListTail::template CreateMatcher<T, CombiningMatcher>( - matchers.second))); - } -}; - -// The following defines the base case for the recursive definition of -// MatcherList. -template <typename Matcher1, typename Matcher2> -struct MatcherList<2, Matcher1, Matcher2> { - typedef ::std::pair<Matcher1, Matcher2> ListType; - - static ListType BuildList(const Matcher1& matcher1, - const Matcher2& matcher2) { - return ::std::pair<Matcher1, Matcher2>(matcher1, matcher2); - } - - template <typename T, template <typename /* T */> class CombiningMatcher> - static Matcher<T> CreateMatcher(const ListType& matchers) { - return Matcher<T>(new CombiningMatcher<T>( - SafeMatcherCast<T>(matchers.first), - SafeMatcherCast<T>(matchers.second))); - } -}; - // VariadicMatcher is used for the variadic implementation of // AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). // CombiningMatcher<T> is used to recursively combine the provided matchers @@ -1839,27 +1786,40 @@ template <template <typename T> class CombiningMatcher, typename... Args> class VariadicMatcher { public: VariadicMatcher(const Args&... matchers) // NOLINT - : matchers_(MatcherListType::BuildList(matchers...)) {} + : matchers_(matchers...) { + static_assert(sizeof...(Args) > 0, "Must have at least one matcher."); + } // This template type conversion operator allows an // VariadicMatcher<Matcher1, Matcher2...> object to match any type that // all of the provided matchers (Matcher1, Matcher2, ...) can match. template <typename T> operator Matcher<T>() const { - return MatcherListType::template CreateMatcher<T, CombiningMatcher>( - matchers_); + std::vector<Matcher<T> > values; + CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>()); + return Matcher<T>(new CombiningMatcher<T>(internal::move(values))); } private: - typedef MatcherList<sizeof...(Args), Args...> MatcherListType; + template <typename T, size_t I> + void CreateVariadicMatcher(std::vector<Matcher<T> >* values, + std::integral_constant<size_t, I>) const { + values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_))); + CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>()); + } + + template <typename T> + void CreateVariadicMatcher( + std::vector<Matcher<T> >*, + std::integral_constant<size_t, sizeof...(Args)>) const {} - const typename MatcherListType::ListType matchers_; + tuple<Args...> matchers_; GTEST_DISALLOW_ASSIGN_(VariadicMatcher); }; template <typename... Args> -using AllOfMatcher = VariadicMatcher<BothOfMatcherImpl, Args...>; +using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>; #endif // GTEST_LANG_CXX11 @@ -1876,8 +1836,10 @@ class BothOfMatcher { // both Matcher1 and Matcher2 can match. template <typename T> operator Matcher<T>() const { - return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_), - SafeMatcherCast<T>(matcher2_))); + std::vector<Matcher<T> > values; + values.push_back(SafeMatcherCast<T>(matcher1_)); + values.push_back(SafeMatcherCast<T>(matcher2_)); + return Matcher<T>(new AllOfMatcherImpl<T>(internal::move(values))); } private: @@ -1892,70 +1854,69 @@ class BothOfMatcher { // that will prevent different instantiations of AnyOfMatcher from // sharing the same EitherOfMatcherImpl<T> class. template <typename T> -class EitherOfMatcherImpl +class AnyOfMatcherImpl : public MatcherInterface<GTEST_REFERENCE_TO_CONST_(T)> { public: - EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2) - : matcher1_(matcher1), matcher2_(matcher2) {} + explicit AnyOfMatcherImpl(std::vector<Matcher<T> > matchers) + : matchers_(internal::move(matchers)) {} virtual void DescribeTo(::std::ostream* os) const { *os << "("; - matcher1_.DescribeTo(os); - *os << ") or ("; - matcher2_.DescribeTo(os); + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") or ("; + matchers_[i].DescribeTo(os); + } *os << ")"; } virtual void DescribeNegationTo(::std::ostream* os) const { *os << "("; - matcher1_.DescribeNegationTo(os); - *os << ") and ("; - matcher2_.DescribeNegationTo(os); + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") and ("; + matchers_[i].DescribeNegationTo(os); + } *os << ")"; } virtual bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) x, MatchResultListener* listener) const { + std::string no_match_result; + // If either matcher1_ or matcher2_ matches x, we just need to // explain why *one* of them matches. - StringMatchResultListener listener1; - if (matcher1_.MatchAndExplain(x, &listener1)) { - *listener << listener1.str(); - return true; - } - - StringMatchResultListener listener2; - if (matcher2_.MatchAndExplain(x, &listener2)) { - *listener << listener2.str(); - return true; + for (size_t i = 0; i < matchers_.size(); ++i) { + StringMatchResultListener slistener; + if (matchers_[i].MatchAndExplain(x, &slistener)) { + *listener << slistener.str(); + return true; + } else { + if (no_match_result.empty()) { + no_match_result = slistener.str(); + } else { + std::string result = slistener.str(); + if (!result.empty()) { + no_match_result += ", and "; + no_match_result += result; + } + } + } } // Otherwise we need to explain why *both* of them fail. - const std::string s1 = listener1.str(); - const std::string s2 = listener2.str(); - - if (s1 == "") { - *listener << s2; - } else { - *listener << s1; - if (s2 != "") { - *listener << ", and " << s2; - } - } + *listener << no_match_result; return false; } private: - const Matcher<T> matcher1_; - const Matcher<T> matcher2_; + const std::vector<Matcher<T> > matchers_; - GTEST_DISALLOW_ASSIGN_(EitherOfMatcherImpl); + GTEST_DISALLOW_ASSIGN_(AnyOfMatcherImpl); }; #if GTEST_LANG_CXX11 // AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). template <typename... Args> -using AnyOfMatcher = VariadicMatcher<EitherOfMatcherImpl, Args...>; +using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; #endif // GTEST_LANG_CXX11 @@ -1973,8 +1934,10 @@ class EitherOfMatcher { // both Matcher1 and Matcher2 can match. template <typename T> operator Matcher<T>() const { - return Matcher<T>(new EitherOfMatcherImpl<T>( - SafeMatcherCast<T>(matcher1_), SafeMatcherCast<T>(matcher2_))); + std::vector<Matcher<T> > values; + values.push_back(SafeMatcherCast<T>(matcher1_)); + values.push_back(SafeMatcherCast<T>(matcher2_)); + return Matcher<T>(new AnyOfMatcherImpl<T>(internal::move(values))); } private: |