diff options
| -rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 231 | ||||
| -rw-r--r-- | googlemock/src/gmock-matchers.cc | 196 | ||||
| -rw-r--r-- | googlemock/test/gmock_link_test.h | 24 | ||||
| -rw-r--r-- | googletest/cmake/internal_utils.cmake | 2 | ||||
| -rw-r--r-- | googletest/include/gtest/internal/gtest-port.h | 7 | 
5 files changed, 334 insertions, 126 deletions
| diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 85b5b13b..9522c850 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -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); @@ -3685,7 +3698,7 @@ class VariantMatcher {  }  // namespace internal -// ElementsAreArray(first, last) +// ElementsAreArray(iterator_first, iterator_last)  // ElementsAreArray(pointer, count)  // ElementsAreArray(array)  // ElementsAreArray(container) @@ -3734,20 +3747,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> @@ -3789,7 +3808,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> @@ -4359,6 +4380,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.  // diff --git a/googlemock/src/gmock-matchers.cc b/googlemock/src/gmock-matchers.cc index f37d5c2d..88e40088 100644 --- a/googlemock/src/gmock-matchers.cc +++ b/googlemock/src/gmock-matchers.cc @@ -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; -  } -  if (matcher_describers_.size() == 1) { -    *os << "has " << Elements(1) << " and that element "; -    matcher_describers_[0]->DescribeTo(os); -    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;    } -  *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; -  } -  if (matcher_describers_.size() == 1) { -    *os << "doesn't have " << Elements(1) -        << ", or has " << Elements(1) << " that "; -    matcher_describers_[0]->DescribeNegationTo(os); -    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;    } -  *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 diff --git a/googlemock/test/gmock_link_test.h b/googlemock/test/gmock_link_test.h index 1f55f5bd..5f855d19 100644 --- a/googlemock/test/gmock_link_test.h +++ b/googlemock/test/gmock_link_test.h @@ -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; diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake index 2c978332..3277cc5c 100644 --- a/googletest/cmake/internal_utils.cmake +++ b/googletest/cmake/internal_utils.cmake @@ -91,7 +91,7 @@ macro(config_compiler_and_linker)      set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")      set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")      set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1") -    set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0") +    set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")      set(cxx_no_rtti_flags "-GR-")    elseif (CMAKE_COMPILER_IS_GNUCXX)      set(cxx_base_flags "-Wall -Wshadow -Werror") diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index 2c819c9f..4d5aa043 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -471,8 +471,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;  #ifndef GTEST_HAS_EXCEPTIONS  // The user didn't tell us whether exceptions are enabled, so we need  // to figure it out. -# if defined(_MSC_VER) || defined(__BORLANDC__) -// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +# if defined(_MSC_VER) && defined(_CPPUNWIND) +// MSVC defines _CPPUNWIND to 1 iff exceptions are enabled. +#  define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__BORLANDC__) +// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS  // macro to enable exceptions, so we'll do the same.  // Assumes that exceptions are enabled by default.  #  ifndef _HAS_EXCEPTIONS | 
