diff options
author | Abseil Team <absl-team@google.com> | 2018-12-03 15:48:03 (GMT) |
---|---|---|
committer | Gennadiy Civil <misterg@google.com> | 2018-12-03 17:54:02 (GMT) |
commit | a42cdf2abdc0ab7ddfbafc098cafdd6152ae1b70 (patch) | |
tree | d16aaa083e86889b5f9a592df3b221be65a5ce21 /googlemock | |
parent | 8fbf9d16a63a8b0cd629b24089f9470deef75120 (diff) | |
download | googletest-a42cdf2abdc0ab7ddfbafc098cafdd6152ae1b70.zip googletest-a42cdf2abdc0ab7ddfbafc098cafdd6152ae1b70.tar.gz googletest-a42cdf2abdc0ab7ddfbafc098cafdd6152ae1b70.tar.bz2 |
Googletest export
Replace pump'd Args() matcher with variadic templates.
PiperOrigin-RevId: 223794430
Diffstat (limited to 'googlemock')
-rw-r--r-- | googlemock/include/gmock/gmock-generated-matchers.h | 337 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-generated-matchers.h.pump | 163 | ||||
-rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 84 | ||||
-rw-r--r-- | googlemock/test/gmock-generated-matchers_test.cc | 152 | ||||
-rw-r--r-- | googlemock/test/gmock-matchers_test.cc | 152 |
5 files changed, 233 insertions, 655 deletions
diff --git a/googlemock/include/gmock/gmock-generated-matchers.h b/googlemock/include/gmock/gmock-generated-matchers.h index 1a88c71..b77b3f1 100644 --- a/googlemock/include/gmock/gmock-generated-matchers.h +++ b/googlemock/include/gmock/gmock-generated-matchers.h @@ -47,343 +47,6 @@ #include <vector> #include "gmock/gmock-matchers.h" -namespace testing { -namespace internal { - -// The type of the i-th (0-based) field of Tuple. -#define GMOCK_FIELD_TYPE_(Tuple, i) \ - typename ::std::tuple_element<i, Tuple>::type - -// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a -// tuple of type Tuple. It has two members: -// -// type: a tuple type whose i-th field is the ki-th field of Tuple. -// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple. -// -// For example, in class TupleFields<std::tuple<bool, char, int>, 2, 0>, -// we have: -// -// type is std::tuple<int, bool>, and -// GetSelectedFields(std::make_tuple(true, 'a', 42)) is (42, true). - -template <class Tuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1, - int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1, - int k9 = -1> -class TupleFields; - -// This generic version is used when there are 10 selectors. -template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6, - int k7, int k8, int k9> -class TupleFields { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4), GMOCK_FIELD_TYPE_(Tuple, k5), - GMOCK_FIELD_TYPE_(Tuple, k6), GMOCK_FIELD_TYPE_(Tuple, k7), - GMOCK_FIELD_TYPE_(Tuple, k8), GMOCK_FIELD_TYPE_(Tuple, k9)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t), std::get<k5>(t), std::get<k6>(t), - std::get<k7>(t), std::get<k8>(t), std::get<k9>(t)); - } -}; - -// The following specialization is used for 0 ~ 9 selectors. - -template <class Tuple> -class TupleFields<Tuple, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<> type; - static type GetSelectedFields(const Tuple& /* t */) { - return type(); - } -}; - -template <class Tuple, int k0> -class TupleFields<Tuple, k0, -1, -1, -1, -1, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t)); - } -}; - -template <class Tuple, int k0, int k1> -class TupleFields<Tuple, k0, k1, -1, -1, -1, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2> -class TupleFields<Tuple, k0, k1, k2, -1, -1, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3> -class TupleFields<Tuple, k0, k1, k2, k3, -1, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3, int k4> -class TupleFields<Tuple, k0, k1, k2, k3, k4, -1, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5> -class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, -1, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4), GMOCK_FIELD_TYPE_(Tuple, k5)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t), std::get<k5>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6> -class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, -1, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4), GMOCK_FIELD_TYPE_(Tuple, k5), - GMOCK_FIELD_TYPE_(Tuple, k6)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t), std::get<k5>(t), std::get<k6>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6, - int k7> -class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, -1, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4), GMOCK_FIELD_TYPE_(Tuple, k5), - GMOCK_FIELD_TYPE_(Tuple, k6), GMOCK_FIELD_TYPE_(Tuple, k7)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t), std::get<k5>(t), std::get<k6>(t), - std::get<k7>(t)); - } -}; - -template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6, - int k7, int k8> -class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, -1> { - public: - typedef ::std::tuple<GMOCK_FIELD_TYPE_(Tuple, k0), GMOCK_FIELD_TYPE_(Tuple, - k1), GMOCK_FIELD_TYPE_(Tuple, k2), GMOCK_FIELD_TYPE_(Tuple, k3), - GMOCK_FIELD_TYPE_(Tuple, k4), GMOCK_FIELD_TYPE_(Tuple, k5), - GMOCK_FIELD_TYPE_(Tuple, k6), GMOCK_FIELD_TYPE_(Tuple, k7), - GMOCK_FIELD_TYPE_(Tuple, k8)> type; - static type GetSelectedFields(const Tuple& t) { - return type(std::get<k0>(t), std::get<k1>(t), std::get<k2>(t), - std::get<k3>(t), std::get<k4>(t), std::get<k5>(t), std::get<k6>(t), - std::get<k7>(t), std::get<k8>(t)); - } -}; - -#undef GMOCK_FIELD_TYPE_ - -// Implements the Args() matcher. -template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1, - int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1, - int k9 = -1> -class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { - public: - // ArgsTuple may have top-level const or reference modifiers. - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; - typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, - k6, k7, k8, k9>::type SelectedArgs; - typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher; - - template <typename InnerMatcher> - explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) - : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {} - - virtual bool MatchAndExplain(ArgsTuple args, - MatchResultListener* listener) const { - const SelectedArgs& selected_args = GetSelectedArgs(args); - if (!listener->IsInterested()) - return inner_matcher_.Matches(selected_args); - - PrintIndices(listener->stream()); - *listener << "are " << PrintToString(selected_args); - - StringMatchResultListener inner_listener; - const bool match = inner_matcher_.MatchAndExplain(selected_args, - &inner_listener); - PrintIfNotEmpty(inner_listener.str(), listener->stream()); - return match; - } - - virtual void DescribeTo(::std::ostream* os) const { - *os << "are a tuple "; - PrintIndices(os); - inner_matcher_.DescribeTo(os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "are a tuple "; - PrintIndices(os); - inner_matcher_.DescribeNegationTo(os); - } - - private: - static SelectedArgs GetSelectedArgs(ArgsTuple args) { - return TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, - k9>::GetSelectedFields(args); - } - - // Prints the indices of the selected fields. - static void PrintIndices(::std::ostream* os) { - *os << "whose fields ("; - const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 }; - for (int i = 0; i < 10; i++) { - if (indices[i] < 0) - break; - - if (i >= 1) - *os << ", "; - - *os << "#" << indices[i]; - } - *os << ") "; - } - - const MonomorphicInnerMatcher inner_matcher_; - - GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl); -}; - -template <class InnerMatcher, int k0 = -1, int k1 = -1, int k2 = -1, - int k3 = -1, int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, - int k8 = -1, int k9 = -1> -class ArgsMatcher { - public: - explicit ArgsMatcher(const InnerMatcher& inner_matcher) - : inner_matcher_(inner_matcher) {} - - template <typename ArgsTuple> - operator Matcher<ArgsTuple>() const { - return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k0, k1, k2, k3, k4, k5, - k6, k7, k8, k9>(inner_matcher_)); - } - - private: - const InnerMatcher inner_matcher_; - - GTEST_DISALLOW_ASSIGN_(ArgsMatcher); -}; - -} // namespace internal - -// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected -// fields of it matches a_matcher. C++ doesn't support default -// arguments for function templates, so we have to overload it. -template <typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher>(matcher); -} - -template <int k1, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1>(matcher); -} - -template <int k1, int k2, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2>(matcher); -} - -template <int k1, int k2, int k3, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3>(matcher); -} - -template <int k1, int k2, int k3, int k4, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, - typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, - k7>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, - typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, - k8>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, - int k9, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, - k9>(matcher); -} - -template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, - int k9, int k10, typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9, - k10> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, - k9, k10>(matcher); -} - - -} // namespace testing - - // The MATCHER* family of macros can be used in a namespace scope to // define custom matchers easily. // diff --git a/googlemock/include/gmock/gmock-generated-matchers.h.pump b/googlemock/include/gmock/gmock-generated-matchers.h.pump index 322e0ff..8be4869 100644 --- a/googlemock/include/gmock/gmock-generated-matchers.h.pump +++ b/googlemock/include/gmock/gmock-generated-matchers.h.pump @@ -49,169 +49,6 @@ $$ }} This line fixes auto-indentation of the following code in Emacs. #include <vector> #include "gmock/gmock-matchers.h" -namespace testing { -namespace internal { - -$range i 0..n-1 - -// The type of the i-th (0-based) field of Tuple. -#define GMOCK_FIELD_TYPE_(Tuple, i) \ - typename ::std::tuple_element<i, Tuple>::type - -// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a -// tuple of type Tuple. It has two members: -// -// type: a tuple type whose i-th field is the ki-th field of Tuple. -// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple. -// -// For example, in class TupleFields<std::tuple<bool, char, int>, 2, 0>, -// we have: -// -// type is std::tuple<int, bool>, and -// GetSelectedFields(std::make_tuple(true, 'a', 42)) is (42, true). - -template <class Tuple$for i [[, int k$i = -1]]> -class TupleFields; - -// This generic version is used when there are $n selectors. -template <class Tuple$for i [[, int k$i]]> -class TupleFields { - public: - typedef ::std::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type; - static type GetSelectedFields(const Tuple& t) { - return type($for i, [[std::get<k$i>(t)]]); - } -}; - -// The following specialization is used for 0 ~ $(n-1) selectors. - -$for i [[ -$$ }}} -$range j 0..i-1 -$range k 0..n-1 - -template <class Tuple$for j [[, int k$j]]> -class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> { - public: - typedef ::std::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type; - static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) { - return type($for j, [[std::get<k$j>(t)]]); - } -}; - -]] - -#undef GMOCK_FIELD_TYPE_ - -// Implements the Args() matcher. - -$var ks = [[$for i, [[k$i]]]] -template <class ArgsTuple$for i [[, int k$i = -1]]> -class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { - public: - // ArgsTuple may have top-level const or reference modifiers. - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; - typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs; - typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher; - - template <typename InnerMatcher> - explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) - : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {} - - virtual bool MatchAndExplain(ArgsTuple args, - MatchResultListener* listener) const { - const SelectedArgs& selected_args = GetSelectedArgs(args); - if (!listener->IsInterested()) - return inner_matcher_.Matches(selected_args); - - PrintIndices(listener->stream()); - *listener << "are " << PrintToString(selected_args); - - StringMatchResultListener inner_listener; - const bool match = inner_matcher_.MatchAndExplain(selected_args, - &inner_listener); - PrintIfNotEmpty(inner_listener.str(), listener->stream()); - return match; - } - - virtual void DescribeTo(::std::ostream* os) const { - *os << "are a tuple "; - PrintIndices(os); - inner_matcher_.DescribeTo(os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "are a tuple "; - PrintIndices(os); - inner_matcher_.DescribeNegationTo(os); - } - - private: - static SelectedArgs GetSelectedArgs(ArgsTuple args) { - return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args); - } - - // Prints the indices of the selected fields. - static void PrintIndices(::std::ostream* os) { - *os << "whose fields ("; - const int indices[$n] = { $ks }; - for (int i = 0; i < $n; i++) { - if (indices[i] < 0) - break; - - if (i >= 1) - *os << ", "; - - *os << "#" << indices[i]; - } - *os << ") "; - } - - const MonomorphicInnerMatcher inner_matcher_; - - GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl); -}; - -template <class InnerMatcher$for i [[, int k$i = -1]]> -class ArgsMatcher { - public: - explicit ArgsMatcher(const InnerMatcher& inner_matcher) - : inner_matcher_(inner_matcher) {} - - template <typename ArgsTuple> - operator Matcher<ArgsTuple>() const { - return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_)); - } - - private: - const InnerMatcher inner_matcher_; - - GTEST_DISALLOW_ASSIGN_(ArgsMatcher); -}; - -} // namespace internal - -// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected -// fields of it matches a_matcher. C++ doesn't support default -// arguments for function templates, so we have to overload it. - -$range i 0..n -$for i [[ -$range j 1..i -template <$for j [[int k$j, ]]typename InnerMatcher> -inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]> -Args(const InnerMatcher& matcher) { - return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher); -} - - -]] - -} // namespace testing -$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not -$$ // show up in the generated code. - - // The MATCHER* family of macros can be used in a namespace scope to // define custom matchers easily. // diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index ba057de..69dfd83 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -3424,6 +3424,80 @@ class AnyCastMatcher { }; } // namespace any_cast_matcher + +// Implements the Args() matcher. +template <class ArgsTuple, size_t... k> +class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> { + public: + using RawArgsTuple = typename std::decay<ArgsTuple>::type; + using SelectedArgs = + std::tuple<typename std::tuple_element<k, RawArgsTuple>::type...>; + using MonomorphicInnerMatcher = Matcher<const SelectedArgs&>; + + template <typename InnerMatcher> + explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) + : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {} + + bool MatchAndExplain(ArgsTuple args, + MatchResultListener* listener) const override { + // Workaround spurious C4100 on MSVC<=15.7 when k is empty. + (void)args; + const SelectedArgs& selected_args = + std::forward_as_tuple(std::get<k>(args)...); + if (!listener->IsInterested()) return inner_matcher_.Matches(selected_args); + + PrintIndices(listener->stream()); + *listener << "are " << PrintToString(selected_args); + + StringMatchResultListener inner_listener; + const bool match = + inner_matcher_.MatchAndExplain(selected_args, &inner_listener); + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + return match; + } + + void DescribeTo(::std::ostream* os) const override { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeNegationTo(os); + } + + private: + // Prints the indices of the selected fields. + static void PrintIndices(::std::ostream* os) { + *os << "whose fields ("; + const char* sep = ""; + // Workaround spurious C4189 on MSVC<=15.7 when k is empty. + (void)sep; + const char* dummy[] = {"", (*os << sep << "#" << k, sep = ", ")...}; + (void)dummy; + *os << ") "; + } + + MonomorphicInnerMatcher inner_matcher_; +}; + +template <class InnerMatcher, size_t... k> +class ArgsMatcher { + public: + explicit ArgsMatcher(InnerMatcher inner_matcher) + : inner_matcher_(std::move(inner_matcher)) {} + + template <typename ArgsTuple> + operator Matcher<ArgsTuple>() const { // NOLINT + return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k...>(inner_matcher_)); + } + + private: + InnerMatcher inner_matcher_; +}; + } // namespace internal // ElementsAreArray(iterator_first, iterator_last) @@ -4371,6 +4445,16 @@ internal::AnyOfMatcher<typename std::decay<const Args&>::type...> AnyOf( matchers...); } +// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected +// fields of it matches a_matcher. C++ doesn't support default +// arguments for function templates, so we have to overload it. +template <size_t... k, typename InnerMatcher> +internal::ArgsMatcher<typename std::decay<InnerMatcher>::type, k...> Args( + InnerMatcher&& matcher) { + return internal::ArgsMatcher<typename std::decay<InnerMatcher>::type, k...>( + std::forward<InnerMatcher>(matcher)); +} + // AllArgs(m) is a synonym of m. This is useful in // // EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq())); diff --git a/googlemock/test/gmock-generated-matchers_test.cc b/googlemock/test/gmock-generated-matchers_test.cc index fdbfb54..c66f675 100644 --- a/googlemock/test/gmock-generated-matchers_test.cc +++ b/googlemock/test/gmock-generated-matchers_test.cc @@ -112,154 +112,6 @@ std::string Explain(const MatcherType& m, const Value& x) { return ss.str(); } -// Tests Args<k0, ..., kn>(m). - -TEST(ArgsTest, AcceptsZeroTemplateArg) { - const std::tuple<int, bool> t(5, true); - EXPECT_THAT(t, Args<>(Eq(std::tuple<>()))); - EXPECT_THAT(t, Not(Args<>(Ne(std::tuple<>())))); -} - -TEST(ArgsTest, AcceptsOneTemplateArg) { - const std::tuple<int, bool> t(5, true); - EXPECT_THAT(t, Args<0>(Eq(std::make_tuple(5)))); - EXPECT_THAT(t, Args<1>(Eq(std::make_tuple(true)))); - EXPECT_THAT(t, Not(Args<1>(Eq(std::make_tuple(false))))); -} - -TEST(ArgsTest, AcceptsTwoTemplateArgs) { - const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT - - EXPECT_THAT(t, (Args<0, 1>(Lt()))); - EXPECT_THAT(t, (Args<1, 2>(Lt()))); - EXPECT_THAT(t, Not(Args<0, 2>(Gt()))); -} - -TEST(ArgsTest, AcceptsRepeatedTemplateArgs) { - const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT - EXPECT_THAT(t, (Args<0, 0>(Eq()))); - EXPECT_THAT(t, Not(Args<1, 1>(Ne()))); -} - -TEST(ArgsTest, AcceptsDecreasingTemplateArgs) { - const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT - EXPECT_THAT(t, (Args<2, 0>(Gt()))); - EXPECT_THAT(t, Not(Args<2, 1>(Lt()))); -} - -// The MATCHER*() macros trigger warning C4100 (unreferenced formal -// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in -// the macro definition, as the warnings are generated when the macro -// is expanded and macro expansion cannot contain #pragma. Therefore -// we suppress them here. -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4100) -#endif - -MATCHER(SumIsZero, "") { - return std::get<0>(arg) + std::get<1>(arg) + std::get<2>(arg) == 0; -} - -TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) { - EXPECT_THAT(std::make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero()))); - EXPECT_THAT(std::make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero()))); -} - -TEST(ArgsTest, CanBeNested) { - const std::tuple<short, int, long, int> t(4, 5, 6L, 6); // NOLINT - EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq())))); - EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt())))); -} - -TEST(ArgsTest, CanMatchTupleByValue) { - typedef std::tuple<char, int, int> Tuple3; - const Matcher<Tuple3> m = Args<1, 2>(Lt()); - EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2))); - EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2))); -} - -TEST(ArgsTest, CanMatchTupleByReference) { - typedef std::tuple<char, char, int> Tuple3; - const Matcher<const Tuple3&> m = Args<0, 1>(Lt()); - EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2))); - EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2))); -} - -// Validates that arg is printed as str. -MATCHER_P(PrintsAs, str, "") { - return testing::PrintToString(arg) == str; -} - -TEST(ArgsTest, AcceptsTenTemplateArgs) { - EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), - (Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( - PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); - EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), - Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( - PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); -} - -TEST(ArgsTest, DescirbesSelfCorrectly) { - const Matcher<std::tuple<int, bool, char> > m = Args<2, 0>(Lt()); - EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair where " - "the first < the second", - Describe(m)); -} - -TEST(ArgsTest, DescirbesNestedArgsCorrectly) { - const Matcher<const std::tuple<int, bool, char, int>&> m = - Args<0, 2, 3>(Args<2, 0>(Lt())); - EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple " - "whose fields (#2, #0) are a pair where the first < the second", - Describe(m)); -} - -TEST(ArgsTest, DescribesNegationCorrectly) { - const Matcher<std::tuple<int, char> > m = Args<1, 0>(Gt()); - EXPECT_EQ("are a tuple whose fields (#1, #0) aren't a pair " - "where the first > the second", - DescribeNegation(m)); -} - -TEST(ArgsTest, ExplainsMatchResultWithoutInnerExplanation) { - const Matcher<std::tuple<bool, int, int> > m = Args<1, 2>(Eq()); - EXPECT_EQ("whose fields (#1, #2) are (42, 42)", - Explain(m, std::make_tuple(false, 42, 42))); - EXPECT_EQ("whose fields (#1, #2) are (42, 43)", - Explain(m, std::make_tuple(false, 42, 43))); -} - -// For testing Args<>'s explanation. -class LessThanMatcher : public MatcherInterface<std::tuple<char, int> > { - public: - virtual void DescribeTo(::std::ostream* os) const {} - - virtual bool MatchAndExplain(std::tuple<char, int> value, - MatchResultListener* listener) const { - const int diff = std::get<0>(value) - std::get<1>(value); - if (diff > 0) { - *listener << "where the first value is " << diff - << " more than the second"; - } - return diff < 0; - } -}; - -Matcher<std::tuple<char, int> > LessThan() { - return MakeMatcher(new LessThanMatcher); -} - -TEST(ArgsTest, ExplainsMatchResultWithInnerExplanation) { - const Matcher<std::tuple<char, int, int> > m = Args<0, 2>(LessThan()); - EXPECT_EQ( - "whose fields (#0, #2) are ('a' (97, 0x61), 42), " - "where the first value is 55 more than the second", - Explain(m, std::make_tuple('a', 42, 42))); - EXPECT_EQ("whose fields (#0, #2) are ('\\0', 43)", - Explain(m, std::make_tuple('\0', 42, 43))); -} - // For testing ExplainMatchResultTo(). class GreaterThanMatcher : public MatcherInterface<int> { public: @@ -1288,10 +1140,6 @@ TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) { } // namespace adl_test -#ifdef _MSC_VER -# pragma warning(pop) -#endif - #if GTEST_LANG_CXX11 TEST(AllOfTest, WorksOnMoveOnlyType) { diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 347c2c7..cb2d1ae 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -32,6 +32,14 @@ // // This file tests some commonly used argument matchers. +// Silence warning C4244: 'initializing': conversion from 'int' to 'short', +// possible loss of data and C4100, unreferenced local parameter +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4244) +# pragma warning(disable:4100) +#endif + #include "gmock/gmock-matchers.h" #include "gmock/gmock-more-matchers.h" @@ -6748,8 +6756,6 @@ TEST(AnyWithTest, ExplainsSelf) { EXPECT_THAT(Explain(m, SampleAnyType(2)), "whose value 2 doesn't match"); } -#if GTEST_LANG_CXX11 - TEST(PointeeTest, WorksOnMoveOnlyType) { std::unique_ptr<int> p(new int(3)); EXPECT_THAT(p, Pointee(Eq(3))); @@ -6762,7 +6768,147 @@ TEST(NotTest, WorksOnMoveOnlyType) { EXPECT_THAT(p, Not(Pointee(Eq(2)))); } -#endif // GTEST_LANG_CXX11 +// Tests Args<k0, ..., kn>(m). + +TEST(ArgsTest, AcceptsZeroTemplateArg) { + const std::tuple<int, bool> t(5, true); + EXPECT_THAT(t, Args<>(Eq(std::tuple<>()))); + EXPECT_THAT(t, Not(Args<>(Ne(std::tuple<>())))); +} + +TEST(ArgsTest, AcceptsOneTemplateArg) { + const std::tuple<int, bool> t(5, true); + EXPECT_THAT(t, Args<0>(Eq(std::make_tuple(5)))); + EXPECT_THAT(t, Args<1>(Eq(std::make_tuple(true)))); + EXPECT_THAT(t, Not(Args<1>(Eq(std::make_tuple(false))))); +} + +TEST(ArgsTest, AcceptsTwoTemplateArgs) { + const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT + + EXPECT_THAT(t, (Args<0, 1>(Lt()))); + EXPECT_THAT(t, (Args<1, 2>(Lt()))); + EXPECT_THAT(t, Not(Args<0, 2>(Gt()))); +} + +TEST(ArgsTest, AcceptsRepeatedTemplateArgs) { + const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT + EXPECT_THAT(t, (Args<0, 0>(Eq()))); + EXPECT_THAT(t, Not(Args<1, 1>(Ne()))); +} + +TEST(ArgsTest, AcceptsDecreasingTemplateArgs) { + const std::tuple<short, int, long> t(4, 5, 6L); // NOLINT + EXPECT_THAT(t, (Args<2, 0>(Gt()))); + EXPECT_THAT(t, Not(Args<2, 1>(Lt()))); +} + +MATCHER(SumIsZero, "") { + return std::get<0>(arg) + std::get<1>(arg) + std::get<2>(arg) == 0; +} + +TEST(ArgsTest, AcceptsMoreTemplateArgsThanArityOfOriginalTuple) { + EXPECT_THAT(std::make_tuple(-1, 2), (Args<0, 0, 1>(SumIsZero()))); + EXPECT_THAT(std::make_tuple(1, 2), Not(Args<0, 0, 1>(SumIsZero()))); +} + +TEST(ArgsTest, CanBeNested) { + const std::tuple<short, int, long, int> t(4, 5, 6L, 6); // NOLINT + EXPECT_THAT(t, (Args<1, 2, 3>(Args<1, 2>(Eq())))); + EXPECT_THAT(t, (Args<0, 1, 3>(Args<0, 2>(Lt())))); +} + +TEST(ArgsTest, CanMatchTupleByValue) { + typedef std::tuple<char, int, int> Tuple3; + const Matcher<Tuple3> m = Args<1, 2>(Lt()); + EXPECT_TRUE(m.Matches(Tuple3('a', 1, 2))); + EXPECT_FALSE(m.Matches(Tuple3('b', 2, 2))); +} + +TEST(ArgsTest, CanMatchTupleByReference) { + typedef std::tuple<char, char, int> Tuple3; + const Matcher<const Tuple3&> m = Args<0, 1>(Lt()); + EXPECT_TRUE(m.Matches(Tuple3('a', 'b', 2))); + EXPECT_FALSE(m.Matches(Tuple3('b', 'b', 2))); +} + +// Validates that arg is printed as str. +MATCHER_P(PrintsAs, str, "") { + return testing::PrintToString(arg) == str; +} + +TEST(ArgsTest, AcceptsTenTemplateArgs) { + EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), + (Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( + PrintsAs("(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); + EXPECT_THAT(std::make_tuple(0, 1L, 2, 3L, 4, 5, 6, 7, 8, 9), + Not(Args<9, 8, 7, 6, 5, 4, 3, 2, 1, 0>( + PrintsAs("(0, 8, 7, 6, 5, 4, 3, 2, 1, 0)")))); +} + +TEST(ArgsTest, DescirbesSelfCorrectly) { + const Matcher<std::tuple<int, bool, char> > m = Args<2, 0>(Lt()); + EXPECT_EQ("are a tuple whose fields (#2, #0) are a pair where " + "the first < the second", + Describe(m)); +} + +TEST(ArgsTest, DescirbesNestedArgsCorrectly) { + const Matcher<const std::tuple<int, bool, char, int>&> m = + Args<0, 2, 3>(Args<2, 0>(Lt())); + EXPECT_EQ("are a tuple whose fields (#0, #2, #3) are a tuple " + "whose fields (#2, #0) are a pair where the first < the second", + Describe(m)); +} + +TEST(ArgsTest, DescribesNegationCorrectly) { + const Matcher<std::tuple<int, char> > m = Args<1, 0>(Gt()); + EXPECT_EQ("are a tuple whose fields (#1, #0) aren't a pair " + "where the first > the second", + DescribeNegation(m)); +} + +TEST(ArgsTest, ExplainsMatchResultWithoutInnerExplanation) { + const Matcher<std::tuple<bool, int, int> > m = Args<1, 2>(Eq()); + EXPECT_EQ("whose fields (#1, #2) are (42, 42)", + Explain(m, std::make_tuple(false, 42, 42))); + EXPECT_EQ("whose fields (#1, #2) are (42, 43)", + Explain(m, std::make_tuple(false, 42, 43))); +} + +// For testing Args<>'s explanation. +class LessThanMatcher : public MatcherInterface<std::tuple<char, int> > { + public: + virtual void DescribeTo(::std::ostream* os) const {} + + virtual bool MatchAndExplain(std::tuple<char, int> value, + MatchResultListener* listener) const { + const int diff = std::get<0>(value) - std::get<1>(value); + if (diff > 0) { + *listener << "where the first value is " << diff + << " more than the second"; + } + return diff < 0; + } +}; + +Matcher<std::tuple<char, int> > LessThan() { + return MakeMatcher(new LessThanMatcher); +} + +TEST(ArgsTest, ExplainsMatchResultWithInnerExplanation) { + const Matcher<std::tuple<char, int, int> > m = Args<0, 2>(LessThan()); + EXPECT_EQ( + "whose fields (#0, #2) are ('a' (97, 0x61), 42), " + "where the first value is 55 more than the second", + Explain(m, std::make_tuple('a', 42, 42))); + EXPECT_EQ("whose fields (#0, #2) are ('\\0', 43)", + Explain(m, std::make_tuple('\0', 42, 43))); +} } // namespace gmock_matchers_test } // namespace testing + +#ifdef _MSC_VER +# pragma warning(pop) +#endif |