gmock merging -2
This commit is contained in:
		
							parent
							
								
									bb1a39beb6
								
							
						
					
					
						commit
						bcc0a1afa1
					
				@ -514,7 +514,7 @@ template <typename T, typename M>
 | 
			
		||||
class MatcherCastImpl {
 | 
			
		||||
 public:
 | 
			
		||||
  static Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
 | 
			
		||||
    // M can be a polymorhic matcher, in which case we want to use
 | 
			
		||||
    // M can be a polymorphic matcher, in which case we want to use
 | 
			
		||||
    // its conversion operator to create Matcher<T>.  Or it can be a value
 | 
			
		||||
    // that should be passed to the Matcher<T>'s constructor.
 | 
			
		||||
    //
 | 
			
		||||
@ -3303,14 +3303,23 @@ typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
 | 
			
		||||
GTEST_API_ ElementMatcherPairs
 | 
			
		||||
FindMaxBipartiteMatching(const MatchMatrix& g);
 | 
			
		||||
 | 
			
		||||
GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
 | 
			
		||||
                            MatchResultListener* listener);
 | 
			
		||||
struct UnorderedMatcherRequire {
 | 
			
		||||
  enum Flags {
 | 
			
		||||
    Superset = 1 << 0,
 | 
			
		||||
    Subset = 1 << 1,
 | 
			
		||||
    ExactMatch = Superset | Subset,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Untyped base class for implementing UnorderedElementsAre.  By
 | 
			
		||||
// putting logic that's not specific to the element type here, we
 | 
			
		||||
// reduce binary bloat and increase compilation speed.
 | 
			
		||||
class GTEST_API_ UnorderedElementsAreMatcherImplBase {
 | 
			
		||||
 protected:
 | 
			
		||||
  explicit UnorderedElementsAreMatcherImplBase(
 | 
			
		||||
      UnorderedMatcherRequire::Flags matcher_flags)
 | 
			
		||||
      : match_flags_(matcher_flags) {}
 | 
			
		||||
 | 
			
		||||
  // A vector of matcher describers, one for each element matcher.
 | 
			
		||||
  // Does not own the describers (and thus can be used only when the
 | 
			
		||||
  // element matchers are alive).
 | 
			
		||||
@ -3322,9 +3331,12 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
 | 
			
		||||
  // Describes the negation of this UnorderedElementsAre matcher.
 | 
			
		||||
  void DescribeNegationToImpl(::std::ostream* os) const;
 | 
			
		||||
 | 
			
		||||
  bool VerifyAllElementsAndMatchersAreMatched(
 | 
			
		||||
      const ::std::vector<std::string>& element_printouts,
 | 
			
		||||
      const MatchMatrix& matrix, MatchResultListener* listener) const;
 | 
			
		||||
  bool VerifyMatchMatrix(const ::std::vector<std::string>& element_printouts,
 | 
			
		||||
                         const MatchMatrix& matrix,
 | 
			
		||||
                         MatchResultListener* listener) const;
 | 
			
		||||
 | 
			
		||||
  bool FindPairing(const MatchMatrix& matrix,
 | 
			
		||||
                   MatchResultListener* listener) const;
 | 
			
		||||
 | 
			
		||||
  MatcherDescriberVec& matcher_describers() {
 | 
			
		||||
    return matcher_describers_;
 | 
			
		||||
@ -3334,13 +3346,17 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
 | 
			
		||||
    return Message() << n << " element" << (n == 1 ? "" : "s");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  UnorderedMatcherRequire::Flags match_flags_;
 | 
			
		||||
  MatcherDescriberVec matcher_describers_;
 | 
			
		||||
 | 
			
		||||
  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImplBase);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implements unordered ElementsAre and unordered ElementsAreArray.
 | 
			
		||||
// Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and
 | 
			
		||||
// IsSupersetOf.
 | 
			
		||||
template <typename Container>
 | 
			
		||||
class UnorderedElementsAreMatcherImpl
 | 
			
		||||
    : public MatcherInterface<Container>,
 | 
			
		||||
@ -3353,10 +3369,10 @@ class UnorderedElementsAreMatcherImpl
 | 
			
		||||
  typedef typename StlContainer::const_iterator StlContainerConstIterator;
 | 
			
		||||
  typedef typename StlContainer::value_type Element;
 | 
			
		||||
 | 
			
		||||
  // Constructs the matcher from a sequence of element values or
 | 
			
		||||
  // element matchers.
 | 
			
		||||
  template <typename InputIter>
 | 
			
		||||
  UnorderedElementsAreMatcherImpl(InputIter first, InputIter last) {
 | 
			
		||||
  UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags,
 | 
			
		||||
                                  InputIter first, InputIter last)
 | 
			
		||||
      : UnorderedElementsAreMatcherImplBase(matcher_flags) {
 | 
			
		||||
    for (; first != last; ++first) {
 | 
			
		||||
      matchers_.push_back(MatcherCast<const Element&>(*first));
 | 
			
		||||
      matcher_describers().push_back(matchers_.back().GetDescriber());
 | 
			
		||||
@ -3377,34 +3393,32 @@ class UnorderedElementsAreMatcherImpl
 | 
			
		||||
                               MatchResultListener* listener) const {
 | 
			
		||||
    StlContainerReference stl_container = View::ConstReference(container);
 | 
			
		||||
    ::std::vector<std::string> element_printouts;
 | 
			
		||||
    MatchMatrix matrix = AnalyzeElements(stl_container.begin(),
 | 
			
		||||
                                         stl_container.end(),
 | 
			
		||||
                                         &element_printouts,
 | 
			
		||||
                                         listener);
 | 
			
		||||
    MatchMatrix matrix =
 | 
			
		||||
        AnalyzeElements(stl_container.begin(), stl_container.end(),
 | 
			
		||||
                        &element_printouts, listener);
 | 
			
		||||
 | 
			
		||||
    const size_t actual_count = matrix.LhsSize();
 | 
			
		||||
    if (actual_count == 0 && matchers_.empty()) {
 | 
			
		||||
    if (matrix.LhsSize() == 0 && matrix.RhsSize() == 0) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (actual_count != matchers_.size()) {
 | 
			
		||||
      // The element count doesn't match.  If the container is empty,
 | 
			
		||||
      // there's no need to explain anything as Google Mock already
 | 
			
		||||
      // prints the empty container. Otherwise we just need to show
 | 
			
		||||
      // how many elements there actually are.
 | 
			
		||||
      if (actual_count != 0 && listener->IsInterested()) {
 | 
			
		||||
        *listener << "which has " << Elements(actual_count);
 | 
			
		||||
 | 
			
		||||
    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
 | 
			
		||||
      if (matrix.LhsSize() != matrix.RhsSize()) {
 | 
			
		||||
        // The element count doesn't match.  If the container is empty,
 | 
			
		||||
        // there's no need to explain anything as Google Mock already
 | 
			
		||||
        // prints the empty container. Otherwise we just need to show
 | 
			
		||||
        // how many elements there actually are.
 | 
			
		||||
        if (matrix.LhsSize() != 0 && listener->IsInterested()) {
 | 
			
		||||
          *listener << "which has " << Elements(matrix.LhsSize());
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return VerifyAllElementsAndMatchersAreMatched(element_printouts,
 | 
			
		||||
                                                  matrix, listener) &&
 | 
			
		||||
    return VerifyMatchMatrix(element_printouts, matrix, listener) &&
 | 
			
		||||
           FindPairing(matrix, listener);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  typedef ::std::vector<Matcher<const Element&> > MatcherVec;
 | 
			
		||||
 | 
			
		||||
  template <typename ElementIter>
 | 
			
		||||
  MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last,
 | 
			
		||||
                              ::std::vector<std::string>* element_printouts,
 | 
			
		||||
@ -3431,7 +3445,7 @@ class UnorderedElementsAreMatcherImpl
 | 
			
		||||
    return matrix;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  MatcherVec matchers_;
 | 
			
		||||
  ::std::vector<Matcher<const Element&> > matchers_;
 | 
			
		||||
 | 
			
		||||
  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImpl);
 | 
			
		||||
};
 | 
			
		||||
@ -3464,7 +3478,7 @@ class UnorderedElementsAreMatcher {
 | 
			
		||||
    TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
 | 
			
		||||
                         ::std::back_inserter(matchers));
 | 
			
		||||
    return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
 | 
			
		||||
                           matchers.begin(), matchers.end()));
 | 
			
		||||
        UnorderedMatcherRequire::ExactMatch, matchers.begin(), matchers.end()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
@ -3497,24 +3511,23 @@ class ElementsAreMatcher {
 | 
			
		||||
  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implements UnorderedElementsAreArray().
 | 
			
		||||
// Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf().
 | 
			
		||||
template <typename T>
 | 
			
		||||
class UnorderedElementsAreArrayMatcher {
 | 
			
		||||
 public:
 | 
			
		||||
  UnorderedElementsAreArrayMatcher() {}
 | 
			
		||||
 | 
			
		||||
  template <typename Iter>
 | 
			
		||||
  UnorderedElementsAreArrayMatcher(Iter first, Iter last)
 | 
			
		||||
      : matchers_(first, last) {}
 | 
			
		||||
  UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags,
 | 
			
		||||
                                   Iter first, Iter last)
 | 
			
		||||
      : match_flags_(match_flags), matchers_(first, last) {}
 | 
			
		||||
 | 
			
		||||
  template <typename Container>
 | 
			
		||||
  operator Matcher<Container>() const {
 | 
			
		||||
    return MakeMatcher(
 | 
			
		||||
        new UnorderedElementsAreMatcherImpl<Container>(matchers_.begin(),
 | 
			
		||||
                                                       matchers_.end()));
 | 
			
		||||
    return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
 | 
			
		||||
        match_flags_, matchers_.begin(), matchers_.end()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  UnorderedMatcherRequire::Flags match_flags_;
 | 
			
		||||
  ::std::vector<T> matchers_;
 | 
			
		||||
 | 
			
		||||
  GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreArrayMatcher);
 | 
			
		||||
@ -3625,7 +3638,7 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// ElementsAreArray(first, last)
 | 
			
		||||
// ElementsAreArray(iterator_first, iterator_last)
 | 
			
		||||
// ElementsAreArray(pointer, count)
 | 
			
		||||
// ElementsAreArray(array)
 | 
			
		||||
// ElementsAreArray(container)
 | 
			
		||||
@ -3674,20 +3687,26 @@ ElementsAreArray(::std::initializer_list<T> xs) {
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// UnorderedElementsAreArray(first, last)
 | 
			
		||||
// UnorderedElementsAreArray(iterator_first, iterator_last)
 | 
			
		||||
// UnorderedElementsAreArray(pointer, count)
 | 
			
		||||
// UnorderedElementsAreArray(array)
 | 
			
		||||
// UnorderedElementsAreArray(container)
 | 
			
		||||
// UnorderedElementsAreArray({ e1, e2, ..., en })
 | 
			
		||||
//
 | 
			
		||||
// The UnorderedElementsAreArray() functions are like
 | 
			
		||||
// ElementsAreArray(...), but allow matching the elements in any order.
 | 
			
		||||
// UnorderedElementsAreArray() verifies that a bijective mapping onto a
 | 
			
		||||
// collection of matchers exists.
 | 
			
		||||
//
 | 
			
		||||
// 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::UnorderedElementsAreArrayMatcher<
 | 
			
		||||
    typename ::std::iterator_traits<Iter>::value_type>
 | 
			
		||||
UnorderedElementsAreArray(Iter first, Iter last) {
 | 
			
		||||
  typedef typename ::std::iterator_traits<Iter>::value_type T;
 | 
			
		||||
  return internal::UnorderedElementsAreArrayMatcher<T>(first, last);
 | 
			
		||||
  return internal::UnorderedElementsAreArrayMatcher<T>(
 | 
			
		||||
      internal::UnorderedMatcherRequire::ExactMatch, first, last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
@ -3729,7 +3748,9 @@ UnorderedElementsAreArray(::std::initializer_list<T> xs) {
 | 
			
		||||
const internal::AnythingMatcher _ = {};
 | 
			
		||||
// Creates a matcher that matches any value of the given type T.
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline Matcher<T> A() { return MakeMatcher(new internal::AnyMatcherImpl<T>()); }
 | 
			
		||||
inline Matcher<T> A() {
 | 
			
		||||
  return Matcher<T>(new internal::AnyMatcherImpl<T>());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates a matcher that matches any value of the given type T.
 | 
			
		||||
template <typename T>
 | 
			
		||||
@ -4299,6 +4320,128 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
 | 
			
		||||
  return internal::ContainsMatcher<M>(matcher);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsSupersetOf(iterator_first, iterator_last)
 | 
			
		||||
// IsSupersetOf(pointer, count)
 | 
			
		||||
// IsSupersetOf(array)
 | 
			
		||||
// IsSupersetOf(container)
 | 
			
		||||
// IsSupersetOf({e1, e2, ..., en})
 | 
			
		||||
//
 | 
			
		||||
// IsSupersetOf() verifies that a surjective partial mapping onto a collection
 | 
			
		||||
// of matchers exists. In other words, a container matches
 | 
			
		||||
// IsSupersetOf({e1, ..., en}) if and only if there is a permutation
 | 
			
		||||
// {y1, ..., yn} of some of the container's elements where y1 matches e1,
 | 
			
		||||
// ..., and yn matches en. Obviously, the size of the container must be >= n
 | 
			
		||||
// in order to have a match. Examples:
 | 
			
		||||
//
 | 
			
		||||
// - {1, 2, 3} matches IsSupersetOf({Ge(3), Ne(0)}), as 3 matches Ge(3) and
 | 
			
		||||
//   1 matches Ne(0).
 | 
			
		||||
// - {1, 2} doesn't match IsSupersetOf({Eq(1), Lt(2)}), even though 1 matches
 | 
			
		||||
//   both Eq(1) and Lt(2). The reason is that different matchers must be used
 | 
			
		||||
//   for elements in different slots of the container.
 | 
			
		||||
// - {1, 1, 2} matches IsSupersetOf({Eq(1), Lt(2)}), as (the first) 1 matches
 | 
			
		||||
//   Eq(1) and (the second) 1 matches Lt(2).
 | 
			
		||||
// - {1, 2, 3} matches IsSupersetOf(Gt(1), Gt(1)), as 2 matches (the first)
 | 
			
		||||
//   Gt(1) and 3 matches (the second) Gt(1).
 | 
			
		||||
//
 | 
			
		||||
// 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::UnorderedElementsAreArrayMatcher<
 | 
			
		||||
    typename ::std::iterator_traits<Iter>::value_type>
 | 
			
		||||
IsSupersetOf(Iter first, Iter last) {
 | 
			
		||||
  typedef typename ::std::iterator_traits<Iter>::value_type T;
 | 
			
		||||
  return internal::UnorderedElementsAreArrayMatcher<T>(
 | 
			
		||||
      internal::UnorderedMatcherRequire::Superset, first, last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
 | 
			
		||||
    const T* pointer, size_t count) {
 | 
			
		||||
  return IsSupersetOf(pointer, pointer + count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T, size_t N>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
 | 
			
		||||
    const T (&array)[N]) {
 | 
			
		||||
  return IsSupersetOf(array, N);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Container>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<
 | 
			
		||||
    typename Container::value_type>
 | 
			
		||||
IsSupersetOf(const Container& container) {
 | 
			
		||||
  return IsSupersetOf(container.begin(), container.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if GTEST_HAS_STD_INITIALIZER_LIST_
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
 | 
			
		||||
    ::std::initializer_list<T> xs) {
 | 
			
		||||
  return IsSupersetOf(xs.begin(), xs.end());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// IsSubsetOf(iterator_first, iterator_last)
 | 
			
		||||
// IsSubsetOf(pointer, count)
 | 
			
		||||
// IsSubsetOf(array)
 | 
			
		||||
// IsSubsetOf(container)
 | 
			
		||||
// IsSubsetOf({e1, e2, ..., en})
 | 
			
		||||
//
 | 
			
		||||
// IsSubsetOf() verifies that an injective mapping onto a collection of matchers
 | 
			
		||||
// exists.  In other words, a container matches IsSubsetOf({e1, ..., en}) if and
 | 
			
		||||
// only if there is a subset of matchers {m1, ..., mk} which would match the
 | 
			
		||||
// container using UnorderedElementsAre.  Obviously, the size of the container
 | 
			
		||||
// must be <= n in order to have a match. Examples:
 | 
			
		||||
//
 | 
			
		||||
// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
 | 
			
		||||
// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
 | 
			
		||||
//   matches Lt(0).
 | 
			
		||||
// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
 | 
			
		||||
//   match Gt(0). The reason is that different matchers must be used for
 | 
			
		||||
//   elements in different slots of the container.
 | 
			
		||||
//
 | 
			
		||||
// 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::UnorderedElementsAreArrayMatcher<
 | 
			
		||||
    typename ::std::iterator_traits<Iter>::value_type>
 | 
			
		||||
IsSubsetOf(Iter first, Iter last) {
 | 
			
		||||
  typedef typename ::std::iterator_traits<Iter>::value_type T;
 | 
			
		||||
  return internal::UnorderedElementsAreArrayMatcher<T>(
 | 
			
		||||
      internal::UnorderedMatcherRequire::Subset, first, last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
 | 
			
		||||
    const T* pointer, size_t count) {
 | 
			
		||||
  return IsSubsetOf(pointer, pointer + count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T, size_t N>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
 | 
			
		||||
    const T (&array)[N]) {
 | 
			
		||||
  return IsSubsetOf(array, N);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Container>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<
 | 
			
		||||
    typename Container::value_type>
 | 
			
		||||
IsSubsetOf(const Container& container) {
 | 
			
		||||
  return IsSubsetOf(container.begin(), container.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if GTEST_HAS_STD_INITIALIZER_LIST_
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
 | 
			
		||||
    ::std::initializer_list<T> xs) {
 | 
			
		||||
  return IsSubsetOf(xs.begin(), xs.end());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Matches an STL-style container or a native array that contains only
 | 
			
		||||
// elements matching the given value or matcher.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@
 | 
			
		||||
#include "gmock/gmock-generated-matchers.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
@ -181,8 +182,7 @@ class MaxBipartiteMatchState {
 | 
			
		||||
  explicit MaxBipartiteMatchState(const MatchMatrix& graph)
 | 
			
		||||
      : graph_(&graph),
 | 
			
		||||
        left_(graph_->LhsSize(), kUnused),
 | 
			
		||||
        right_(graph_->RhsSize(), kUnused) {
 | 
			
		||||
  }
 | 
			
		||||
        right_(graph_->RhsSize(), kUnused) {}
 | 
			
		||||
 | 
			
		||||
  // Returns the edges of a maximal match, each in the form {left, right}.
 | 
			
		||||
  ElementMatcherPairs Compute() {
 | 
			
		||||
@ -239,10 +239,8 @@ class MaxBipartiteMatchState {
 | 
			
		||||
  //
 | 
			
		||||
  bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
 | 
			
		||||
    for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
 | 
			
		||||
      if ((*seen)[irhs])
 | 
			
		||||
        continue;
 | 
			
		||||
      if (!graph_->HasEdge(ilhs, irhs))
 | 
			
		||||
        continue;
 | 
			
		||||
      if ((*seen)[irhs]) continue;
 | 
			
		||||
      if (!graph_->HasEdge(ilhs, irhs)) continue;
 | 
			
		||||
      // There's an available edge from ilhs to irhs.
 | 
			
		||||
      (*seen)[irhs] = 1;
 | 
			
		||||
      // Next a search is performed to determine whether
 | 
			
		||||
@ -285,8 +283,7 @@ class MaxBipartiteMatchState {
 | 
			
		||||
 | 
			
		||||
const size_t MaxBipartiteMatchState::kUnused;
 | 
			
		||||
 | 
			
		||||
GTEST_API_ ElementMatcherPairs
 | 
			
		||||
FindMaxBipartiteMatching(const MatchMatrix& g) {
 | 
			
		||||
GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g) {
 | 
			
		||||
  return MaxBipartiteMatchState(g).Compute();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -295,7 +292,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
 | 
			
		||||
  typedef ElementMatcherPairs::const_iterator Iter;
 | 
			
		||||
  ::std::ostream& os = *stream;
 | 
			
		||||
  os << "{";
 | 
			
		||||
  const char *sep = "";
 | 
			
		||||
  const char* sep = "";
 | 
			
		||||
  for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
 | 
			
		||||
    os << sep << "\n  ("
 | 
			
		||||
       << "element #" << it->first << ", "
 | 
			
		||||
@ -305,38 +302,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
 | 
			
		||||
  os << "\n}";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tries to find a pairing, and explains the result.
 | 
			
		||||
GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
 | 
			
		||||
                            MatchResultListener* listener) {
 | 
			
		||||
  ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
 | 
			
		||||
 | 
			
		||||
  size_t max_flow = matches.size();
 | 
			
		||||
  bool result = (max_flow == matrix.RhsSize());
 | 
			
		||||
 | 
			
		||||
  if (!result) {
 | 
			
		||||
    if (listener->IsInterested()) {
 | 
			
		||||
      *listener << "where no permutation of the elements can "
 | 
			
		||||
                   "satisfy all matchers, and the closest match is "
 | 
			
		||||
                << max_flow << " of " << matrix.RhsSize()
 | 
			
		||||
                << " matchers with the pairings:\n";
 | 
			
		||||
      LogElementMatcherPairVec(matches, listener->stream());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (matches.size() > 1) {
 | 
			
		||||
    if (listener->IsInterested()) {
 | 
			
		||||
      const char *sep = "where:\n";
 | 
			
		||||
      for (size_t mi = 0; mi < matches.size(); ++mi) {
 | 
			
		||||
        *listener << sep << " - element #" << matches[mi].first
 | 
			
		||||
                  << " is matched by matcher #" << matches[mi].second;
 | 
			
		||||
        sep = ",\n";
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MatchMatrix::NextGraph() {
 | 
			
		||||
  for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
 | 
			
		||||
    for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
 | 
			
		||||
@ -362,7 +327,7 @@ void MatchMatrix::Randomize() {
 | 
			
		||||
 | 
			
		||||
std::string MatchMatrix::DebugString() const {
 | 
			
		||||
  ::std::stringstream ss;
 | 
			
		||||
  const char *sep = "";
 | 
			
		||||
  const char* sep = "";
 | 
			
		||||
  for (size_t i = 0; i < LhsSize(); ++i) {
 | 
			
		||||
    ss << sep;
 | 
			
		||||
    for (size_t j = 0; j < RhsSize(); ++j) {
 | 
			
		||||
@ -375,44 +340,83 @@ std::string MatchMatrix::DebugString() const {
 | 
			
		||||
 | 
			
		||||
void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
 | 
			
		||||
    ::std::ostream* os) const {
 | 
			
		||||
  if (matcher_describers_.empty()) {
 | 
			
		||||
    *os << "is empty";
 | 
			
		||||
    return;
 | 
			
		||||
  switch (match_flags()) {
 | 
			
		||||
    case UnorderedMatcherRequire::ExactMatch:
 | 
			
		||||
      if (matcher_describers_.empty()) {
 | 
			
		||||
        *os << "is empty";
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (matcher_describers_.size() == 1) {
 | 
			
		||||
        *os << "has " << Elements(1) << " and that element ";
 | 
			
		||||
        matcher_describers_[0]->DescribeTo(os);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      *os << "has " << Elements(matcher_describers_.size())
 | 
			
		||||
          << " and there exists some permutation of elements such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
    case UnorderedMatcherRequire::Superset:
 | 
			
		||||
      *os << "a surjection from elements to requirements exists such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
    case UnorderedMatcherRequire::Subset:
 | 
			
		||||
      *os << "an injection from elements to requirements exists such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  if (matcher_describers_.size() == 1) {
 | 
			
		||||
    *os << "has " << Elements(1) << " and that element ";
 | 
			
		||||
    matcher_describers_[0]->DescribeTo(os);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  *os << "has " << Elements(matcher_describers_.size())
 | 
			
		||||
      << " and there exists some permutation of elements such that:\n";
 | 
			
		||||
 | 
			
		||||
  const char* sep = "";
 | 
			
		||||
  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
 | 
			
		||||
    *os << sep << " - element #" << i << " ";
 | 
			
		||||
    *os << sep;
 | 
			
		||||
    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
 | 
			
		||||
      *os << " - element #" << i << " ";
 | 
			
		||||
    } else {
 | 
			
		||||
      *os << " - an element ";
 | 
			
		||||
    }
 | 
			
		||||
    matcher_describers_[i]->DescribeTo(os);
 | 
			
		||||
    sep = ", and\n";
 | 
			
		||||
    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
 | 
			
		||||
      sep = ", and\n";
 | 
			
		||||
    } else {
 | 
			
		||||
      sep = "\n";
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
 | 
			
		||||
    ::std::ostream* os) const {
 | 
			
		||||
  if (matcher_describers_.empty()) {
 | 
			
		||||
    *os << "isn't empty";
 | 
			
		||||
    return;
 | 
			
		||||
  switch (match_flags()) {
 | 
			
		||||
    case UnorderedMatcherRequire::ExactMatch:
 | 
			
		||||
      if (matcher_describers_.empty()) {
 | 
			
		||||
        *os << "isn't empty";
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (matcher_describers_.size() == 1) {
 | 
			
		||||
        *os << "doesn't have " << Elements(1) << ", or has " << Elements(1)
 | 
			
		||||
            << " that ";
 | 
			
		||||
        matcher_describers_[0]->DescribeNegationTo(os);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      *os << "doesn't have " << Elements(matcher_describers_.size())
 | 
			
		||||
          << ", or there exists no permutation of elements such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
    case UnorderedMatcherRequire::Superset:
 | 
			
		||||
      *os << "no surjection from elements to requirements exists such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
    case UnorderedMatcherRequire::Subset:
 | 
			
		||||
      *os << "no injection from elements to requirements exists such that:\n";
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  if (matcher_describers_.size() == 1) {
 | 
			
		||||
    *os << "doesn't have " << Elements(1)
 | 
			
		||||
        << ", or has " << Elements(1) << " that ";
 | 
			
		||||
    matcher_describers_[0]->DescribeNegationTo(os);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  *os << "doesn't have " << Elements(matcher_describers_.size())
 | 
			
		||||
      << ", or there exists no permutation of elements such that:\n";
 | 
			
		||||
  const char* sep = "";
 | 
			
		||||
  for (size_t i = 0; i != matcher_describers_.size(); ++i) {
 | 
			
		||||
    *os << sep << " - element #" << i << " ";
 | 
			
		||||
    *os << sep;
 | 
			
		||||
    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
 | 
			
		||||
      *os << " - element #" << i << " ";
 | 
			
		||||
    } else {
 | 
			
		||||
      *os << " - an element ";
 | 
			
		||||
    }
 | 
			
		||||
    matcher_describers_[i]->DescribeTo(os);
 | 
			
		||||
    sep = ", and\n";
 | 
			
		||||
    if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
 | 
			
		||||
      sep = ", and\n";
 | 
			
		||||
    } else {
 | 
			
		||||
      sep = "\n";
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -421,10 +425,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
 | 
			
		||||
// and better error reporting.
 | 
			
		||||
// Returns false, writing an explanation to 'listener', if and only
 | 
			
		||||
// if the success criteria are not met.
 | 
			
		||||
bool UnorderedElementsAreMatcherImplBase::
 | 
			
		||||
    VerifyAllElementsAndMatchersAreMatched(
 | 
			
		||||
        const ::std::vector<std::string>& element_printouts,
 | 
			
		||||
        const MatchMatrix& matrix, MatchResultListener* listener) const {
 | 
			
		||||
bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
 | 
			
		||||
    const ::std::vector<std::string>& element_printouts,
 | 
			
		||||
    const MatchMatrix& matrix, MatchResultListener* listener) const {
 | 
			
		||||
  bool result = true;
 | 
			
		||||
  ::std::vector<char> element_matched(matrix.LhsSize(), 0);
 | 
			
		||||
  ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
 | 
			
		||||
@ -437,12 +440,11 @@ bool UnorderedElementsAreMatcherImplBase::
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
  if (match_flags() & UnorderedMatcherRequire::Superset) {
 | 
			
		||||
    const char* sep =
 | 
			
		||||
        "where the following matchers don't match any elements:\n";
 | 
			
		||||
    for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
 | 
			
		||||
      if (matcher_matched[mi])
 | 
			
		||||
        continue;
 | 
			
		||||
      if (matcher_matched[mi]) continue;
 | 
			
		||||
      result = false;
 | 
			
		||||
      if (listener->IsInterested()) {
 | 
			
		||||
        *listener << sep << "matcher #" << mi << ": ";
 | 
			
		||||
@ -452,7 +454,7 @@ bool UnorderedElementsAreMatcherImplBase::
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
  if (match_flags() & UnorderedMatcherRequire::Subset) {
 | 
			
		||||
    const char* sep =
 | 
			
		||||
        "where the following elements don't match any matchers:\n";
 | 
			
		||||
    const char* outer_sep = "";
 | 
			
		||||
@ -460,8 +462,7 @@ bool UnorderedElementsAreMatcherImplBase::
 | 
			
		||||
      outer_sep = "\nand ";
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t ei = 0; ei < element_matched.size(); ++ei) {
 | 
			
		||||
      if (element_matched[ei])
 | 
			
		||||
        continue;
 | 
			
		||||
      if (element_matched[ei]) continue;
 | 
			
		||||
      result = false;
 | 
			
		||||
      if (listener->IsInterested()) {
 | 
			
		||||
        *listener << outer_sep << sep << "element #" << ei << ": "
 | 
			
		||||
@ -474,5 +475,46 @@ bool UnorderedElementsAreMatcherImplBase::
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool UnorderedElementsAreMatcherImplBase::FindPairing(
 | 
			
		||||
    const MatchMatrix& matrix, MatchResultListener* listener) const {
 | 
			
		||||
  ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
 | 
			
		||||
 | 
			
		||||
  size_t max_flow = matches.size();
 | 
			
		||||
  if ((match_flags() & UnorderedMatcherRequire::Superset) &&
 | 
			
		||||
      max_flow < matrix.RhsSize()) {
 | 
			
		||||
    if (listener->IsInterested()) {
 | 
			
		||||
      *listener << "where no permutation of the elements can satisfy all "
 | 
			
		||||
                   "matchers, and the closest match is "
 | 
			
		||||
                << max_flow << " of " << matrix.RhsSize()
 | 
			
		||||
                << " matchers with the pairings:\n";
 | 
			
		||||
      LogElementMatcherPairVec(matches, listener->stream());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  if ((match_flags() & UnorderedMatcherRequire::Subset) &&
 | 
			
		||||
      max_flow < matrix.LhsSize()) {
 | 
			
		||||
    if (listener->IsInterested()) {
 | 
			
		||||
      *listener
 | 
			
		||||
          << "where not all elements can be matched, and the closest match is "
 | 
			
		||||
          << max_flow << " of " << matrix.RhsSize()
 | 
			
		||||
          << " matchers with the pairings:\n";
 | 
			
		||||
      LogElementMatcherPairVec(matches, listener->stream());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (matches.size() > 1) {
 | 
			
		||||
    if (listener->IsInterested()) {
 | 
			
		||||
      const char* sep = "where:\n";
 | 
			
		||||
      for (size_t mi = 0; mi < matches.size(); ++mi) {
 | 
			
		||||
        *listener << sep << " - element #" << matches[mi].first
 | 
			
		||||
                  << " is matched by matcher #" << matches[mi].second;
 | 
			
		||||
        sep = ",\n";
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
@ -120,13 +120,15 @@
 | 
			
		||||
# include <errno.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "gmock/internal/gmock-port.h"
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include "gtest/internal/gtest-port.h"
 | 
			
		||||
 | 
			
		||||
using testing::_;
 | 
			
		||||
using testing::A;
 | 
			
		||||
using testing::Action;
 | 
			
		||||
using testing::AllOf;
 | 
			
		||||
using testing::AnyOf;
 | 
			
		||||
using testing::Assign;
 | 
			
		||||
@ -148,6 +150,8 @@ using testing::Invoke;
 | 
			
		||||
using testing::InvokeArgument;
 | 
			
		||||
using testing::InvokeWithoutArgs;
 | 
			
		||||
using testing::IsNull;
 | 
			
		||||
using testing::IsSubsetOf;
 | 
			
		||||
using testing::IsSupersetOf;
 | 
			
		||||
using testing::Le;
 | 
			
		||||
using testing::Lt;
 | 
			
		||||
using testing::Matcher;
 | 
			
		||||
@ -592,6 +596,22 @@ TEST(LinkTest, TestMatcherElementsAreArray) {
 | 
			
		||||
  ON_CALL(mock, VoidFromVector(ElementsAreArray(arr))).WillByDefault(Return());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests the linkage of the IsSubsetOf matcher.
 | 
			
		||||
TEST(LinkTest, TestMatcherIsSubsetOf) {
 | 
			
		||||
  Mock mock;
 | 
			
		||||
  char arr[] = {'a', 'b'};
 | 
			
		||||
 | 
			
		||||
  ON_CALL(mock, VoidFromVector(IsSubsetOf(arr))).WillByDefault(Return());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests the linkage of the IsSupersetOf matcher.
 | 
			
		||||
TEST(LinkTest, TestMatcherIsSupersetOf) {
 | 
			
		||||
  Mock mock;
 | 
			
		||||
  char arr[] = {'a', 'b'};
 | 
			
		||||
 | 
			
		||||
  ON_CALL(mock, VoidFromVector(IsSupersetOf(arr))).WillByDefault(Return());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests the linkage of the ContainerEq matcher.
 | 
			
		||||
TEST(LinkTest, TestMatcherContainerEq) {
 | 
			
		||||
  Mock mock;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user