diff options
| -rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 113 | ||||
| -rw-r--r-- | googlemock/test/gmock-generated-matchers_test.cc | 142 | 
2 files changed, 255 insertions, 0 deletions
| diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 2cb70286..fa24fd2f 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -1175,6 +1175,37 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {  template <typename... Args>  using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; +// Wrapper for implementation of Any/AllOfArray(). +template <template <class> class MatcherImpl, typename T> +class SomeOfArrayMatcher { + public: +  // Constructs the matcher from a sequence of element values or +  // element matchers. +  template <typename Iter> +  SomeOfArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} + +  template <typename U> +  operator Matcher<U>() const {  // NOLINT +    using RawU = typename std::decay<U>::type; +    std::vector<Matcher<RawU>> matchers; +    for (const auto& matcher : matchers_) { +      matchers.push_back(MatcherCast<RawU>(matcher)); +    } +    return Matcher<U>(new MatcherImpl<RawU>(std::move(matchers))); +  } + + private: +  const ::std::vector<T> matchers_; + +  GTEST_DISALLOW_ASSIGN_(SomeOfArrayMatcher); +}; + +template <typename T> +using AllOfArrayMatcher = SomeOfArrayMatcher<AllOfMatcherImpl, T>; + +template <typename T> +using AnyOfArrayMatcher = SomeOfArrayMatcher<AnyOfMatcherImpl, T>; +  // Used for implementing Truly(pred), which turns a predicate into a  // matcher.  template <typename Predicate> @@ -4376,6 +4407,88 @@ internal::AnyOfMatcher<typename std::decay<const Args&>::type...> AnyOf(        matchers...);  } +// AnyOfArray(array) +// AnyOfArray(pointer, count) +// AnyOfArray(container) +// AnyOfArray({ e1, e2, ..., en }) +// AnyOfArray(iterator_first, iterator_last) +// +// AnyOfArray() verifies whether a given value matches any member of a +// collection of matchers. +// +// AllOfArray(array) +// AllOfArray(pointer, count) +// AllOfArray(container) +// AllOfArray({ e1, e2, ..., en }) +// AllOfArray(iterator_first, iterator_last) +// +// AllOfArray() verifies whether a given value matches all members of a +// collection of matchers. +// +// The matchers can be specified as an array, a pointer and count, a container, +// an initializer list, or an STL iterator range. In each of these cases, the +// underlying matchers can be either values or matchers. + +template <typename Iter> +inline internal::AnyOfArrayMatcher< +    typename ::std::iterator_traits<Iter>::value_type> +AnyOfArray(Iter first, Iter last) { +  return internal::AnyOfArrayMatcher< +      typename ::std::iterator_traits<Iter>::value_type>(first, last); +} + +template <typename Iter> +inline internal::AllOfArrayMatcher< +    typename ::std::iterator_traits<Iter>::value_type> +AllOfArray(Iter first, Iter last) { +  return internal::AllOfArrayMatcher< +      typename ::std::iterator_traits<Iter>::value_type>(first, last); +} + +template <typename T> +inline internal::AnyOfArrayMatcher<T> AnyOfArray(const T* ptr, size_t count) { +  return AnyOfArray(ptr, ptr + count); +} + +template <typename T> +inline internal::AllOfArrayMatcher<T> AllOfArray(const T* ptr, size_t count) { +  return AllOfArray(ptr, ptr + count); +} + +template <typename T, size_t N> +inline internal::AnyOfArrayMatcher<T> AnyOfArray(const T (&array)[N]) { +  return AnyOfArray(array, N); +} + +template <typename T, size_t N> +inline internal::AllOfArrayMatcher<T> AllOfArray(const T (&array)[N]) { +  return AllOfArray(array, N); +} + +template <typename Container> +inline internal::AnyOfArrayMatcher<typename Container::value_type> AnyOfArray( +    const Container& container) { +  return AnyOfArray(container.begin(), container.end()); +} + +template <typename Container> +inline internal::AllOfArrayMatcher<typename Container::value_type> AllOfArray( +    const Container& container) { +  return AllOfArray(container.begin(), container.end()); +} + +template <typename T> +inline internal::AnyOfArrayMatcher<T> AnyOfArray( +    ::std::initializer_list<T> xs) { +  return AnyOfArray(xs.begin(), xs.end()); +} + +template <typename T> +inline internal::AllOfArrayMatcher<T> AllOfArray( +    ::std::initializer_list<T> xs) { +  return AllOfArray(xs.begin(), xs.end()); +} +  // 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. diff --git a/googlemock/test/gmock-generated-matchers_test.cc b/googlemock/test/gmock-generated-matchers_test.cc index 426e9545..d79cef99 100644 --- a/googlemock/test/gmock-generated-matchers_test.cc +++ b/googlemock/test/gmock-generated-matchers_test.cc @@ -64,7 +64,9 @@ using std::stringstream;  using std::vector;  using testing::_;  using testing::AllOf; +using testing::AllOfArray;  using testing::AnyOf; +using testing::AnyOfArray;  using testing::Args;  using testing::Contains;  using testing::ElementsAre; @@ -1094,6 +1096,146 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {    EXPECT_THAT(a, Contains(Not(Contains(5))));  } +TEST(AllOfArrayTest, BasicForms) { +  // Iterator +  std::vector<int> v0{}; +  std::vector<int> v1{1}; +  std::vector<int> v2{2, 3}; +  std::vector<int> v3{4, 4, 4}; +  EXPECT_THAT(0, AllOfArray(v0.begin(), v0.end())); +  EXPECT_THAT(1, AllOfArray(v1.begin(), v1.end())); +  EXPECT_THAT(2, Not(AllOfArray(v1.begin(), v1.end()))); +  EXPECT_THAT(3, Not(AllOfArray(v2.begin(), v2.end()))); +  EXPECT_THAT(4, AllOfArray(v3.begin(), v3.end())); +  // Pointer +  size +  int ar[6] = {1, 2, 3, 4, 4, 4}; +  EXPECT_THAT(0, AllOfArray(ar, 0)); +  EXPECT_THAT(1, AllOfArray(ar, 1)); +  EXPECT_THAT(2, Not(AllOfArray(ar, 1))); +  EXPECT_THAT(3, Not(AllOfArray(ar + 1, 3))); +  EXPECT_THAT(4, AllOfArray(ar + 3, 3)); +  // Array +  // int ar0[0];  Not usable +  int ar1[1] = {1}; +  int ar2[2] = {2, 3}; +  int ar3[3] = {4, 4, 4}; +  // EXPECT_THAT(0, Not(AllOfArray(ar0)));  // Cannot work +  EXPECT_THAT(1, AllOfArray(ar1)); +  EXPECT_THAT(2, Not(AllOfArray(ar1))); +  EXPECT_THAT(3, Not(AllOfArray(ar2))); +  EXPECT_THAT(4, AllOfArray(ar3)); +  // Container +  EXPECT_THAT(0, AllOfArray(v0)); +  EXPECT_THAT(1, AllOfArray(v1)); +  EXPECT_THAT(2, Not(AllOfArray(v1))); +  EXPECT_THAT(3, Not(AllOfArray(v2))); +  EXPECT_THAT(4, AllOfArray(v3)); +  // Initializer +  EXPECT_THAT(0, AllOfArray<int>({}));  // Requires template arg. +  EXPECT_THAT(1, AllOfArray({1})); +  EXPECT_THAT(2, Not(AllOfArray({1}))); +  EXPECT_THAT(3, Not(AllOfArray({2, 3}))); +  EXPECT_THAT(4, AllOfArray({4, 4, 4})); +} + +TEST(AllOfArrayTest, Matchers) { +  // vector +  std::vector<Matcher<int>> matchers{Ge(1), Lt(2)}; +  EXPECT_THAT(0, Not(AllOfArray(matchers))); +  EXPECT_THAT(1, AllOfArray(matchers)); +  EXPECT_THAT(2, Not(AllOfArray(matchers))); +  // initializer_list +  EXPECT_THAT(0, Not(AllOfArray({Ge(0), Ge(1)}))); +  EXPECT_THAT(1, AllOfArray({Ge(0), Ge(1)})); +} + +TEST(AnyOfArrayTest, BasicForms) { +  // Iterator +  std::vector<int> v0{}; +  std::vector<int> v1{1}; +  std::vector<int> v2{2, 3}; +  EXPECT_THAT(0, Not(AnyOfArray(v0.begin(), v0.end()))); +  EXPECT_THAT(1, AnyOfArray(v1.begin(), v1.end())); +  EXPECT_THAT(2, Not(AnyOfArray(v1.begin(), v1.end()))); +  EXPECT_THAT(3, AnyOfArray(v2.begin(), v2.end())); +  EXPECT_THAT(4, Not(AnyOfArray(v2.begin(), v2.end()))); +  // Pointer +  size +  int ar[3] = {1, 2, 3}; +  EXPECT_THAT(0, Not(AnyOfArray(ar, 0))); +  EXPECT_THAT(1, AnyOfArray(ar, 1)); +  EXPECT_THAT(2, Not(AnyOfArray(ar, 1))); +  EXPECT_THAT(3, AnyOfArray(ar + 1, 3)); +  EXPECT_THAT(4, Not(AnyOfArray(ar + 1, 3))); +  // Array +  // int ar0[0];  Not usable +  int ar1[1] = {1}; +  int ar2[2] = {2, 3}; +  // EXPECT_THAT(0, Not(AnyOfArray(ar0)));  // Cannot work +  EXPECT_THAT(1, AnyOfArray(ar1)); +  EXPECT_THAT(2, Not(AnyOfArray(ar1))); +  EXPECT_THAT(3, AnyOfArray(ar2)); +  EXPECT_THAT(4, Not(AnyOfArray(ar2))); +  // Container +  EXPECT_THAT(0, Not(AnyOfArray(v0))); +  EXPECT_THAT(1, AnyOfArray(v1)); +  EXPECT_THAT(2, Not(AnyOfArray(v1))); +  EXPECT_THAT(3, AnyOfArray(v2)); +  EXPECT_THAT(4, Not(AnyOfArray(v2))); +  // Initializer +  EXPECT_THAT(0, Not(AnyOfArray<int>({})));  // Requires template arg. +  EXPECT_THAT(1, AnyOfArray({1})); +  EXPECT_THAT(2, Not(AnyOfArray({1}))); +  EXPECT_THAT(3, AnyOfArray({2, 3})); +  EXPECT_THAT(4, Not(AnyOfArray({2, 3}))); +} + +TEST(AnyOfArrayTest, Matchers) { +  // We negate test AllOfArrayTest.Matchers. +  // vector +  std::vector<Matcher<int>> matchers{Lt(1), Ge(2)}; +  EXPECT_THAT(0, AnyOfArray(matchers)); +  EXPECT_THAT(1, Not(AnyOfArray(matchers))); +  EXPECT_THAT(2, AnyOfArray(matchers)); +  // initializer_list +  EXPECT_THAT(0, AnyOfArray({Lt(0), Lt(1)})); +  EXPECT_THAT(1, Not(AllOfArray({Lt(0), Lt(1)}))); +} + +TEST(AnyOfArrayTest, ExplainsMatchResultCorrectly) { +  // AnyOfArray and AllOfArry use the same underlying template-template, +  // thus it is sufficient to test one here. +  const std::vector<int> v0{}; +  const std::vector<int> v1{1}; +  const std::vector<int> v2{2, 3}; +  const Matcher<int> m0 = AnyOfArray(v0); +  const Matcher<int> m1 = AnyOfArray(v1); +  const Matcher<int> m2 = AnyOfArray(v2); +  EXPECT_EQ("", Explain(m0, 0)); +  EXPECT_EQ("", Explain(m1, 1)); +  EXPECT_EQ("", Explain(m1, 2)); +  EXPECT_EQ("", Explain(m2, 3)); +  EXPECT_EQ("", Explain(m2, 4)); +  EXPECT_EQ("()", Describe(m0)); +  EXPECT_EQ("(is equal to 1)", Describe(m1)); +  EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2)); +  EXPECT_EQ("()", DescribeNegation(m0)); +  EXPECT_EQ("(isn't equal to 1)", DescribeNegation(m1)); +  EXPECT_EQ("(isn't equal to 2) and (isn't equal to 3)", DescribeNegation(m2)); +  // Explain with matchers +  const Matcher<int> g1 = AnyOfArray({GreaterThan(1)}); +  const Matcher<int> g2 = AnyOfArray({GreaterThan(1), GreaterThan(2)}); +  // Explains the first positiv match and all prior negative matches... +  EXPECT_EQ("which is 1 less than 1", Explain(g1, 0)); +  EXPECT_EQ("which is the same as 1", Explain(g1, 1)); +  EXPECT_EQ("which is 1 more than 1", Explain(g1, 2)); +  EXPECT_EQ("which is 1 less than 1, and which is 2 less than 2", +            Explain(g2, 0)); +  EXPECT_EQ("which is the same as 1, and which is 1 less than 2", +            Explain(g2, 1)); +  EXPECT_EQ("which is 1 more than 1",  // Only the first +            Explain(g2, 2)); +} +  TEST(AllOfTest, HugeMatcher) {    // Verify that using AllOf with many arguments doesn't cause    // the compiler to exceed template instantiation depth limit. | 
