Merge branch 'master' into variant_matcher
This commit is contained in:
@@ -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.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user