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
2bd1750b
"vscode:/vscode.git/clone" did not exist on "8c859e48647458af66594a069dacc5a5f513df3a"
Commit
2bd1750b
authored
Feb 27, 2018
by
Gennadiy Civil
Browse files
gmock merging -2
parent
7d15497f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
328 additions
and
123 deletions
+328
-123
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
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
2bd1750b
...
@@ -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
);
...
@@ -3625,7 +3638,7 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
...
@@ -3625,7 +3638,7 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
}
// 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)
...
@@ -3674,20 +3687,26 @@ ElementsAreArray(::std::initializer_list<T> xs) {
...
@@ -3674,20 +3687,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
>
...
@@ -3729,7 +3748,9 @@ UnorderedElementsAreArray(::std::initializer_list<T> xs) {
...
@@ -3729,7 +3748,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
>
...
@@ -4299,6 +4320,128 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
...
@@ -4299,6 +4320,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 @
2bd1750b
...
@@ -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 @
2bd1750b
...
@@ -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
;
...
...
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