Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
576d689c
Unverified
Commit
576d689c
authored
Feb 27, 2018
by
Xiaoyi Zhang
Committed by
GitHub
Feb 27, 2018
Browse files
Merge branch 'master' into variant_matcher
parents
b951c652
a9f2368d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
334 additions
and
126 deletions
+334
-126
googlemock/include/gmock/gmock-matchers.h
googlemock/include/gmock/gmock-matchers.h
+187
-44
googlemock/src/gmock-matchers.cc
googlemock/src/gmock-matchers.cc
+119
-77
googlemock/test/gmock_link_test.h
googlemock/test/gmock_link_test.h
+22
-2
googletest/cmake/internal_utils.cmake
googletest/cmake/internal_utils.cmake
+1
-1
googletest/include/gtest/internal/gtest-port.h
googletest/include/gtest/internal/gtest-port.h
+5
-2
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
576d689c
...
@@ -514,7 +514,7 @@ template <typename T, typename M>
...
@@ -514,7 +514,7 @@ template <typename T, typename M>
class
MatcherCastImpl
{
class
MatcherCastImpl
{
public:
public:
static
Matcher
<
T
>
Cast
(
const
M
&
polymorphic_matcher_or_value
)
{
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 polymor
p
hic matcher, in which case we want to use
// its conversion operator to create Matcher<T>. Or it can be a value
// its conversion operator to create Matcher<T>. Or it can be a value
// that should be passed to the Matcher<T>'s constructor.
// that should be passed to the Matcher<T>'s constructor.
//
//
...
@@ -3303,14 +3303,23 @@ typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
...
@@ -3303,14 +3303,23 @@ typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
GTEST_API_
ElementMatcherPairs
GTEST_API_
ElementMatcherPairs
FindMaxBipartiteMatching
(
const
MatchMatrix
&
g
);
FindMaxBipartiteMatching
(
const
MatchMatrix
&
g
);
GTEST_API_
bool
FindPairing
(
const
MatchMatrix
&
matrix
,
struct
UnorderedMatcherRequire
{
MatchResultListener
*
listener
);
enum
Flags
{
Superset
=
1
<<
0
,
Subset
=
1
<<
1
,
ExactMatch
=
Superset
|
Subset
,
};
};
// Untyped base class for implementing UnorderedElementsAre. By
// Untyped base class for implementing UnorderedElementsAre. By
// putting logic that's not specific to the element type here, we
// putting logic that's not specific to the element type here, we
// reduce binary bloat and increase compilation speed.
// reduce binary bloat and increase compilation speed.
class
GTEST_API_
UnorderedElementsAreMatcherImplBase
{
class
GTEST_API_
UnorderedElementsAreMatcherImplBase
{
protected:
protected:
explicit
UnorderedElementsAreMatcherImplBase
(
UnorderedMatcherRequire
::
Flags
matcher_flags
)
:
match_flags_
(
matcher_flags
)
{}
// A vector of matcher describers, one for each element matcher.
// A vector of matcher describers, one for each element matcher.
// Does not own the describers (and thus can be used only when the
// Does not own the describers (and thus can be used only when the
// element matchers are alive).
// element matchers are alive).
...
@@ -3322,9 +3331,12 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
...
@@ -3322,9 +3331,12 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
// Describes the negation of this UnorderedElementsAre matcher.
// Describes the negation of this UnorderedElementsAre matcher.
void
DescribeNegationToImpl
(
::
std
::
ostream
*
os
)
const
;
void
DescribeNegationToImpl
(
::
std
::
ostream
*
os
)
const
;
bool
VerifyAllElementsAndMatchersAreMatched
(
bool
VerifyMatchMatrix
(
const
::
std
::
vector
<
std
::
string
>&
element_printouts
,
const
::
std
::
vector
<
std
::
string
>&
element_printouts
,
const
MatchMatrix
&
matrix
,
const
MatchMatrix
&
matrix
,
MatchResultListener
*
listener
)
const
;
MatchResultListener
*
listener
)
const
;
bool
FindPairing
(
const
MatchMatrix
&
matrix
,
MatchResultListener
*
listener
)
const
;
MatcherDescriberVec
&
matcher_describers
()
{
MatcherDescriberVec
&
matcher_describers
()
{
return
matcher_describers_
;
return
matcher_describers_
;
...
@@ -3334,13 +3346,17 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
...
@@ -3334,13 +3346,17 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
return
Message
()
<<
n
<<
" element"
<<
(
n
==
1
?
""
:
"s"
);
return
Message
()
<<
n
<<
" element"
<<
(
n
==
1
?
""
:
"s"
);
}
}
UnorderedMatcherRequire
::
Flags
match_flags
()
const
{
return
match_flags_
;
}
private:
private:
UnorderedMatcherRequire
::
Flags
match_flags_
;
MatcherDescriberVec
matcher_describers_
;
MatcherDescriberVec
matcher_describers_
;
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreMatcherImplBase
);
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreMatcherImplBase
);
};
};
// Implements unordered ElementsAre and unordered ElementsAreArray.
// Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and
// IsSupersetOf.
template
<
typename
Container
>
template
<
typename
Container
>
class
UnorderedElementsAreMatcherImpl
class
UnorderedElementsAreMatcherImpl
:
public
MatcherInterface
<
Container
>
,
:
public
MatcherInterface
<
Container
>
,
...
@@ -3353,10 +3369,10 @@ class UnorderedElementsAreMatcherImpl
...
@@ -3353,10 +3369,10 @@ class UnorderedElementsAreMatcherImpl
typedef
typename
StlContainer
::
const_iterator
StlContainerConstIterator
;
typedef
typename
StlContainer
::
const_iterator
StlContainerConstIterator
;
typedef
typename
StlContainer
::
value_type
Element
;
typedef
typename
StlContainer
::
value_type
Element
;
// Constructs the matcher from a sequence of element values or
// element matchers.
template
<
typename
InputIter
>
template
<
typename
InputIter
>
UnorderedElementsAreMatcherImpl
(
InputIter
first
,
InputIter
last
)
{
UnorderedElementsAreMatcherImpl
(
UnorderedMatcherRequire
::
Flags
matcher_flags
,
InputIter
first
,
InputIter
last
)
:
UnorderedElementsAreMatcherImplBase
(
matcher_flags
)
{
for
(;
first
!=
last
;
++
first
)
{
for
(;
first
!=
last
;
++
first
)
{
matchers_
.
push_back
(
MatcherCast
<
const
Element
&>
(
*
first
));
matchers_
.
push_back
(
MatcherCast
<
const
Element
&>
(
*
first
));
matcher_describers
().
push_back
(
matchers_
.
back
().
GetDescriber
());
matcher_describers
().
push_back
(
matchers_
.
back
().
GetDescriber
());
...
@@ -3377,34 +3393,32 @@ class UnorderedElementsAreMatcherImpl
...
@@ -3377,34 +3393,32 @@ class UnorderedElementsAreMatcherImpl
MatchResultListener
*
listener
)
const
{
MatchResultListener
*
listener
)
const
{
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
StlContainerReference
stl_container
=
View
::
ConstReference
(
container
);
::
std
::
vector
<
std
::
string
>
element_printouts
;
::
std
::
vector
<
std
::
string
>
element_printouts
;
MatchMatrix
matrix
=
AnalyzeElements
(
stl_container
.
begin
(),
MatchMatrix
matrix
=
stl_container
.
end
(),
AnalyzeElements
(
stl_container
.
begin
(),
stl_container
.
end
(),
&
element_printouts
,
&
element_printouts
,
listener
);
listener
);
const
size_t
actual_count
=
matrix
.
LhsSize
();
if
(
matrix
.
LhsSize
()
==
0
&&
matrix
.
RhsSize
()
==
0
)
{
if
(
actual_count
==
0
&&
matchers_
.
empty
())
{
return
true
;
return
true
;
}
}
if
(
actual_count
!=
matchers_
.
size
())
{
// The element count doesn't match. If the container is empty,
if
(
match_flags
()
==
UnorderedMatcherRequire
::
ExactMatch
)
{
// there's no need to explain anything as Google Mock already
if
(
matrix
.
LhsSize
()
!=
matrix
.
RhsSize
())
{
// prints the empty container. Otherwise we just need to show
// The element count doesn't match. If the container is empty,
// how many elements there actually are.
// there's no need to explain anything as Google Mock already
if
(
actual_count
!=
0
&&
listener
->
IsInterested
())
{
// prints the empty container. Otherwise we just need to show
*
listener
<<
"which has "
<<
Elements
(
actual_count
);
// 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
,
return
VerifyMatchMatrix
(
element_printouts
,
matrix
,
listener
)
&&
matrix
,
listener
)
&&
FindPairing
(
matrix
,
listener
);
FindPairing
(
matrix
,
listener
);
}
}
private:
private:
typedef
::
std
::
vector
<
Matcher
<
const
Element
&>
>
MatcherVec
;
template
<
typename
ElementIter
>
template
<
typename
ElementIter
>
MatchMatrix
AnalyzeElements
(
ElementIter
elem_first
,
ElementIter
elem_last
,
MatchMatrix
AnalyzeElements
(
ElementIter
elem_first
,
ElementIter
elem_last
,
::
std
::
vector
<
std
::
string
>*
element_printouts
,
::
std
::
vector
<
std
::
string
>*
element_printouts
,
...
@@ -3431,7 +3445,7 @@ class UnorderedElementsAreMatcherImpl
...
@@ -3431,7 +3445,7 @@ class UnorderedElementsAreMatcherImpl
return
matrix
;
return
matrix
;
}
}
MatcherVec
matchers_
;
::
std
::
vector
<
Matcher
<
const
Element
&>
>
matchers_
;
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreMatcherImpl
);
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreMatcherImpl
);
};
};
...
@@ -3464,7 +3478,7 @@ class UnorderedElementsAreMatcher {
...
@@ -3464,7 +3478,7 @@ class UnorderedElementsAreMatcher {
TransformTupleValues
(
CastAndAppendTransform
<
const
Element
&>
(),
matchers_
,
TransformTupleValues
(
CastAndAppendTransform
<
const
Element
&>
(),
matchers_
,
::
std
::
back_inserter
(
matchers
));
::
std
::
back_inserter
(
matchers
));
return
MakeMatcher
(
new
UnorderedElementsAreMatcherImpl
<
Container
>
(
return
MakeMatcher
(
new
UnorderedElementsAreMatcherImpl
<
Container
>
(
matchers
.
begin
(),
matchers
.
end
()));
UnorderedMatcherRequire
::
ExactMatch
,
matchers
.
begin
(),
matchers
.
end
()));
}
}
private:
private:
...
@@ -3497,24 +3511,23 @@ class ElementsAreMatcher {
...
@@ -3497,24 +3511,23 @@ class ElementsAreMatcher {
GTEST_DISALLOW_ASSIGN_
(
ElementsAreMatcher
);
GTEST_DISALLOW_ASSIGN_
(
ElementsAreMatcher
);
};
};
// Implements UnorderedElementsAreArray().
// Implements UnorderedElementsAreArray()
, IsSubsetOf(), and IsSupersetOf()
.
template
<
typename
T
>
template
<
typename
T
>
class
UnorderedElementsAreArrayMatcher
{
class
UnorderedElementsAreArrayMatcher
{
public:
public:
UnorderedElementsAreArrayMatcher
()
{}
template
<
typename
Iter
>
template
<
typename
Iter
>
UnorderedElementsAreArrayMatcher
(
Iter
first
,
Iter
last
)
UnorderedElementsAreArrayMatcher
(
UnorderedMatcherRequire
::
Flags
match_flags
,
:
matchers_
(
first
,
last
)
{}
Iter
first
,
Iter
last
)
:
match_flags_
(
match_flags
),
matchers_
(
first
,
last
)
{}
template
<
typename
Container
>
template
<
typename
Container
>
operator
Matcher
<
Container
>
()
const
{
operator
Matcher
<
Container
>
()
const
{
return
MakeMatcher
(
return
MakeMatcher
(
new
UnorderedElementsAreMatcherImpl
<
Container
>
(
new
UnorderedElementsAreMatcherImpl
<
Container
>
(
matchers_
.
begin
(),
match_flags_
,
matchers_
.
begin
(),
matchers_
.
end
()));
matchers_
.
end
()));
}
}
private:
private:
UnorderedMatcherRequire
::
Flags
match_flags_
;
::
std
::
vector
<
T
>
matchers_
;
::
std
::
vector
<
T
>
matchers_
;
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreArrayMatcher
);
GTEST_DISALLOW_ASSIGN_
(
UnorderedElementsAreArrayMatcher
);
...
@@ -3685,7 +3698,7 @@ class VariantMatcher {
...
@@ -3685,7 +3698,7 @@ class VariantMatcher {
}
// namespace internal
}
// namespace internal
// ElementsAreArray(
first,
last)
// ElementsAreArray(
iterator_first, iterator_
last)
// ElementsAreArray(pointer, count)
// ElementsAreArray(pointer, count)
// ElementsAreArray(array)
// ElementsAreArray(array)
// ElementsAreArray(container)
// ElementsAreArray(container)
...
@@ -3734,20 +3747,26 @@ ElementsAreArray(::std::initializer_list<T> xs) {
...
@@ -3734,20 +3747,26 @@ ElementsAreArray(::std::initializer_list<T> xs) {
}
}
#endif
#endif
// UnorderedElementsAreArray(
first,
last)
// UnorderedElementsAreArray(
iterator_first, iterator_
last)
// UnorderedElementsAreArray(pointer, count)
// UnorderedElementsAreArray(pointer, count)
// UnorderedElementsAreArray(array)
// UnorderedElementsAreArray(array)
// UnorderedElementsAreArray(container)
// UnorderedElementsAreArray(container)
// UnorderedElementsAreArray({ e1, e2, ..., en })
// UnorderedElementsAreArray({ e1, e2, ..., en })
//
//
// The UnorderedElementsAreArray() functions are like
// UnorderedElementsAreArray() verifies that a bijective mapping onto a
// ElementsAreArray(...), but allow matching the elements in any order.
// 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
>
template
<
typename
Iter
>
inline
internal
::
UnorderedElementsAreArrayMatcher
<
inline
internal
::
UnorderedElementsAreArrayMatcher
<
typename
::
std
::
iterator_traits
<
Iter
>::
value_type
>
typename
::
std
::
iterator_traits
<
Iter
>::
value_type
>
UnorderedElementsAreArray
(
Iter
first
,
Iter
last
)
{
UnorderedElementsAreArray
(
Iter
first
,
Iter
last
)
{
typedef
typename
::
std
::
iterator_traits
<
Iter
>::
value_type
T
;
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
>
template
<
typename
T
>
...
@@ -3789,7 +3808,9 @@ UnorderedElementsAreArray(::std::initializer_list<T> xs) {
...
@@ -3789,7 +3808,9 @@ UnorderedElementsAreArray(::std::initializer_list<T> xs) {
const
internal
::
AnythingMatcher
_
=
{};
const
internal
::
AnythingMatcher
_
=
{};
// Creates a matcher that matches any value of the given type T.
// Creates a matcher that matches any value of the given type T.
template
<
typename
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.
// Creates a matcher that matches any value of the given type T.
template
<
typename
T
>
template
<
typename
T
>
...
@@ -4359,6 +4380,128 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
...
@@ -4359,6 +4380,128 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
return
internal
::
ContainsMatcher
<
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
// Matches an STL-style container or a native array that contains only
// elements matching the given value or matcher.
// elements matching the given value or matcher.
//
//
...
...
googlemock/src/gmock-matchers.cc
View file @
576d689c
...
@@ -38,6 +38,7 @@
...
@@ -38,6 +38,7 @@
#include "gmock/gmock-generated-matchers.h"
#include "gmock/gmock-generated-matchers.h"
#include <string.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <sstream>
#include <string>
#include <string>
...
@@ -181,8 +182,7 @@ class MaxBipartiteMatchState {
...
@@ -181,8 +182,7 @@ class MaxBipartiteMatchState {
explicit
MaxBipartiteMatchState
(
const
MatchMatrix
&
graph
)
explicit
MaxBipartiteMatchState
(
const
MatchMatrix
&
graph
)
:
graph_
(
&
graph
),
:
graph_
(
&
graph
),
left_
(
graph_
->
LhsSize
(),
kUnused
),
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}.
// Returns the edges of a maximal match, each in the form {left, right}.
ElementMatcherPairs
Compute
()
{
ElementMatcherPairs
Compute
()
{
...
@@ -239,10 +239,8 @@ class MaxBipartiteMatchState {
...
@@ -239,10 +239,8 @@ class MaxBipartiteMatchState {
//
//
bool
TryAugment
(
size_t
ilhs
,
::
std
::
vector
<
char
>*
seen
)
{
bool
TryAugment
(
size_t
ilhs
,
::
std
::
vector
<
char
>*
seen
)
{
for
(
size_t
irhs
=
0
;
irhs
<
graph_
->
RhsSize
();
++
irhs
)
{
for
(
size_t
irhs
=
0
;
irhs
<
graph_
->
RhsSize
();
++
irhs
)
{
if
((
*
seen
)[
irhs
])
if
((
*
seen
)[
irhs
])
continue
;
continue
;
if
(
!
graph_
->
HasEdge
(
ilhs
,
irhs
))
continue
;
if
(
!
graph_
->
HasEdge
(
ilhs
,
irhs
))
continue
;
// There's an available edge from ilhs to irhs.
// There's an available edge from ilhs to irhs.
(
*
seen
)[
irhs
]
=
1
;
(
*
seen
)[
irhs
]
=
1
;
// Next a search is performed to determine whether
// Next a search is performed to determine whether
...
@@ -285,8 +283,7 @@ class MaxBipartiteMatchState {
...
@@ -285,8 +283,7 @@ class MaxBipartiteMatchState {
const
size_t
MaxBipartiteMatchState
::
kUnused
;
const
size_t
MaxBipartiteMatchState
::
kUnused
;
GTEST_API_
ElementMatcherPairs
GTEST_API_
ElementMatcherPairs
FindMaxBipartiteMatching
(
const
MatchMatrix
&
g
)
{
FindMaxBipartiteMatching
(
const
MatchMatrix
&
g
)
{
return
MaxBipartiteMatchState
(
g
).
Compute
();
return
MaxBipartiteMatchState
(
g
).
Compute
();
}
}
...
@@ -295,7 +292,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
...
@@ -295,7 +292,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
typedef
ElementMatcherPairs
::
const_iterator
Iter
;
typedef
ElementMatcherPairs
::
const_iterator
Iter
;
::
std
::
ostream
&
os
=
*
stream
;
::
std
::
ostream
&
os
=
*
stream
;
os
<<
"{"
;
os
<<
"{"
;
const
char
*
sep
=
""
;
const
char
*
sep
=
""
;
for
(
Iter
it
=
pairs
.
begin
();
it
!=
pairs
.
end
();
++
it
)
{
for
(
Iter
it
=
pairs
.
begin
();
it
!=
pairs
.
end
();
++
it
)
{
os
<<
sep
<<
"
\n
("
os
<<
sep
<<
"
\n
("
<<
"element #"
<<
it
->
first
<<
", "
<<
"element #"
<<
it
->
first
<<
", "
...
@@ -305,38 +302,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
...
@@ -305,38 +302,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
os
<<
"
\n
}"
;
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
()
{
bool
MatchMatrix
::
NextGraph
()
{
for
(
size_t
ilhs
=
0
;
ilhs
<
LhsSize
();
++
ilhs
)
{
for
(
size_t
ilhs
=
0
;
ilhs
<
LhsSize
();
++
ilhs
)
{
for
(
size_t
irhs
=
0
;
irhs
<
RhsSize
();
++
irhs
)
{
for
(
size_t
irhs
=
0
;
irhs
<
RhsSize
();
++
irhs
)
{
...
@@ -362,7 +327,7 @@ void MatchMatrix::Randomize() {
...
@@ -362,7 +327,7 @@ void MatchMatrix::Randomize() {
std
::
string
MatchMatrix
::
DebugString
()
const
{
std
::
string
MatchMatrix
::
DebugString
()
const
{
::
std
::
stringstream
ss
;
::
std
::
stringstream
ss
;
const
char
*
sep
=
""
;
const
char
*
sep
=
""
;
for
(
size_t
i
=
0
;
i
<
LhsSize
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
LhsSize
();
++
i
)
{
ss
<<
sep
;
ss
<<
sep
;
for
(
size_t
j
=
0
;
j
<
RhsSize
();
++
j
)
{
for
(
size_t
j
=
0
;
j
<
RhsSize
();
++
j
)
{
...
@@ -375,44 +340,83 @@ std::string MatchMatrix::DebugString() const {
...
@@ -375,44 +340,83 @@ std::string MatchMatrix::DebugString() const {
void
UnorderedElementsAreMatcherImplBase
::
DescribeToImpl
(
void
UnorderedElementsAreMatcherImplBase
::
DescribeToImpl
(
::
std
::
ostream
*
os
)
const
{
::
std
::
ostream
*
os
)
const
{
if
(
matcher_describers_
.
empty
())
{
switch
(
match_flags
())
{
*
os
<<
"is empty"
;
case
UnorderedMatcherRequire
::
ExactMatch
:
return
;
if
(
matcher_describers_
.
empty
())
{
}
*
os
<<
"is empty"
;
if
(
matcher_describers_
.
size
()
==
1
)
{
return
;
*
os
<<
"has "
<<
Elements
(
1
)
<<
" and that element "
;
}
matcher_describers_
[
0
]
->
DescribeTo
(
os
);
if
(
matcher_describers_
.
size
()
==
1
)
{
return
;
*
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
=
""
;
const
char
*
sep
=
""
;
for
(
size_t
i
=
0
;
i
!=
matcher_describers_
.
size
();
++
i
)
{
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
);
matcher_describers_
[
i
]
->
DescribeTo
(
os
);
sep
=
", and
\n
"
;
if
(
match_flags
()
==
UnorderedMatcherRequire
::
ExactMatch
)
{
sep
=
", and
\n
"
;
}
else
{
sep
=
"
\n
"
;
}
}
}
}
}
void
UnorderedElementsAreMatcherImplBase
::
DescribeNegationToImpl
(
void
UnorderedElementsAreMatcherImplBase
::
DescribeNegationToImpl
(
::
std
::
ostream
*
os
)
const
{
::
std
::
ostream
*
os
)
const
{
if
(
matcher_describers_
.
empty
())
{
switch
(
match_flags
())
{
*
os
<<
"isn't empty"
;
case
UnorderedMatcherRequire
::
ExactMatch
:
return
;
if
(
matcher_describers_
.
empty
())
{
}
*
os
<<
"isn't empty"
;
if
(
matcher_describers_
.
size
()
==
1
)
{
return
;
*
os
<<
"doesn't have "
<<
Elements
(
1
)
}
<<
", or has "
<<
Elements
(
1
)
<<
" that "
;
if
(
matcher_describers_
.
size
()
==
1
)
{
matcher_describers_
[
0
]
->
DescribeNegationTo
(
os
);
*
os
<<
"doesn't have "
<<
Elements
(
1
)
<<
", or has "
<<
Elements
(
1
)
return
;
<<
" 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
=
""
;
const
char
*
sep
=
""
;
for
(
size_t
i
=
0
;
i
!=
matcher_describers_
.
size
();
++
i
)
{
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
);
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(
...
@@ -421,10 +425,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
// and better error reporting.
// and better error reporting.
// Returns false, writing an explanation to 'listener', if and only
// Returns false, writing an explanation to 'listener', if and only
// if the success criteria are not met.
// if the success criteria are not met.
bool
UnorderedElementsAreMatcherImplBase
::
bool
UnorderedElementsAreMatcherImplBase
::
VerifyMatchMatrix
(
VerifyAllElementsAndMatchersAreMatched
(
const
::
std
::
vector
<
std
::
string
>&
element_printouts
,
const
::
std
::
vector
<
std
::
string
>&
element_printouts
,
const
MatchMatrix
&
matrix
,
MatchResultListener
*
listener
)
const
{
const
MatchMatrix
&
matrix
,
MatchResultListener
*
listener
)
const
{
bool
result
=
true
;
bool
result
=
true
;
::
std
::
vector
<
char
>
element_matched
(
matrix
.
LhsSize
(),
0
);
::
std
::
vector
<
char
>
element_matched
(
matrix
.
LhsSize
(),
0
);
::
std
::
vector
<
char
>
matcher_matched
(
matrix
.
RhsSize
(),
0
);
::
std
::
vector
<
char
>
matcher_matched
(
matrix
.
RhsSize
(),
0
);
...
@@ -437,12 +440,11 @@ bool UnorderedElementsAreMatcherImplBase::
...
@@ -437,12 +440,11 @@ bool UnorderedElementsAreMatcherImplBase::
}
}
}
}
{
if
(
match_flags
()
&
UnorderedMatcherRequire
::
Superset
)
{
const
char
*
sep
=
const
char
*
sep
=
"where the following matchers don't match any elements:
\n
"
;
"where the following matchers don't match any elements:
\n
"
;
for
(
size_t
mi
=
0
;
mi
<
matcher_matched
.
size
();
++
mi
)
{
for
(
size_t
mi
=
0
;
mi
<
matcher_matched
.
size
();
++
mi
)
{
if
(
matcher_matched
[
mi
])
if
(
matcher_matched
[
mi
])
continue
;
continue
;
result
=
false
;
result
=
false
;
if
(
listener
->
IsInterested
())
{
if
(
listener
->
IsInterested
())
{
*
listener
<<
sep
<<
"matcher #"
<<
mi
<<
": "
;
*
listener
<<
sep
<<
"matcher #"
<<
mi
<<
": "
;
...
@@ -452,7 +454,7 @@ bool UnorderedElementsAreMatcherImplBase::
...
@@ -452,7 +454,7 @@ bool UnorderedElementsAreMatcherImplBase::
}
}
}
}
{
if
(
match_flags
()
&
UnorderedMatcherRequire
::
Subset
)
{
const
char
*
sep
=
const
char
*
sep
=
"where the following elements don't match any matchers:
\n
"
;
"where the following elements don't match any matchers:
\n
"
;
const
char
*
outer_sep
=
""
;
const
char
*
outer_sep
=
""
;
...
@@ -460,8 +462,7 @@ bool UnorderedElementsAreMatcherImplBase::
...
@@ -460,8 +462,7 @@ bool UnorderedElementsAreMatcherImplBase::
outer_sep
=
"
\n
and "
;
outer_sep
=
"
\n
and "
;
}
}
for
(
size_t
ei
=
0
;
ei
<
element_matched
.
size
();
++
ei
)
{
for
(
size_t
ei
=
0
;
ei
<
element_matched
.
size
();
++
ei
)
{
if
(
element_matched
[
ei
])
if
(
element_matched
[
ei
])
continue
;
continue
;
result
=
false
;
result
=
false
;
if
(
listener
->
IsInterested
())
{
if
(
listener
->
IsInterested
())
{
*
listener
<<
outer_sep
<<
sep
<<
"element #"
<<
ei
<<
": "
*
listener
<<
outer_sep
<<
sep
<<
"element #"
<<
ei
<<
": "
...
@@ -474,5 +475,46 @@ bool UnorderedElementsAreMatcherImplBase::
...
@@ -474,5 +475,46 @@ bool UnorderedElementsAreMatcherImplBase::
return
result
;
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 internal
}
// namespace testing
}
// namespace testing
googlemock/test/gmock_link_test.h
View file @
576d689c
...
@@ -120,13 +120,15 @@
...
@@ -120,13 +120,15 @@
# include <errno.h>
# include <errno.h>
#endif
#endif
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
#include <iostream>
#include <iostream>
#include <vector>
#include <vector>
#include "gtest/gtest.h"
#include "gtest/internal/gtest-port.h"
using
testing
::
_
;
using
testing
::
_
;
using
testing
::
A
;
using
testing
::
A
;
using
testing
::
Action
;
using
testing
::
AllOf
;
using
testing
::
AllOf
;
using
testing
::
AnyOf
;
using
testing
::
AnyOf
;
using
testing
::
Assign
;
using
testing
::
Assign
;
...
@@ -148,6 +150,8 @@ using testing::Invoke;
...
@@ -148,6 +150,8 @@ using testing::Invoke;
using
testing
::
InvokeArgument
;
using
testing
::
InvokeArgument
;
using
testing
::
InvokeWithoutArgs
;
using
testing
::
InvokeWithoutArgs
;
using
testing
::
IsNull
;
using
testing
::
IsNull
;
using
testing
::
IsSubsetOf
;
using
testing
::
IsSupersetOf
;
using
testing
::
Le
;
using
testing
::
Le
;
using
testing
::
Lt
;
using
testing
::
Lt
;
using
testing
::
Matcher
;
using
testing
::
Matcher
;
...
@@ -592,6 +596,22 @@ TEST(LinkTest, TestMatcherElementsAreArray) {
...
@@ -592,6 +596,22 @@ TEST(LinkTest, TestMatcherElementsAreArray) {
ON_CALL
(
mock
,
VoidFromVector
(
ElementsAreArray
(
arr
))).
WillByDefault
(
Return
());
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.
// Tests the linkage of the ContainerEq matcher.
TEST
(
LinkTest
,
TestMatcherContainerEq
)
{
TEST
(
LinkTest
,
TestMatcherContainerEq
)
{
Mock
mock
;
Mock
mock
;
...
...
googletest/cmake/internal_utils.cmake
View file @
576d689c
...
@@ -91,7 +91,7 @@ macro(config_compiler_and_linker)
...
@@ -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
}
-D_UNICODE -DUNICODE -DWIN32 -D_WIN32"
)
set
(
cxx_base_flags
"
${
cxx_base_flags
}
-DSTRICT -DWIN32_LEAN_AND_MEAN"
)
set
(
cxx_base_flags
"
${
cxx_base_flags
}
-DSTRICT -DWIN32_LEAN_AND_MEAN"
)
set
(
cxx_exception_flags
"-EHsc -D_HAS_EXCEPTIONS=1"
)
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-"
)
set
(
cxx_no_rtti_flags
"-GR-"
)
elseif
(
CMAKE_COMPILER_IS_GNUCXX
)
elseif
(
CMAKE_COMPILER_IS_GNUCXX
)
set
(
cxx_base_flags
"-Wall -Wshadow -Werror"
)
set
(
cxx_base_flags
"-Wall -Wshadow -Werror"
)
...
...
googletest/include/gtest/internal/gtest-port.h
View file @
576d689c
...
@@ -471,8 +471,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
...
@@ -471,8 +471,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#ifndef GTEST_HAS_EXCEPTIONS
#ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need
// The user didn't tell us whether exceptions are enabled, so we need
// to figure it out.
// to figure it out.
# if defined(_MSC_VER) || defined(__BORLANDC__)
# if defined(_MSC_VER) && defined(_CPPUNWIND)
// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
// 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.
// macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default.
// Assumes that exceptions are enabled by default.
# ifndef _HAS_EXCEPTIONS
# ifndef _HAS_EXCEPTIONS
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment