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
67cc6608
Commit
67cc6608
authored
Mar 24, 2020
by
Xiaoyi Zhang
Browse files
Merge pull request #2350 from adambadura:MockFunctionFromStdFunction
PiperOrigin-RevId: 302677275
parents
1ced315a
53740ebc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
143 additions
and
38 deletions
+143
-38
googlemock/include/gmock/gmock-spec-builders.h
googlemock/include/gmock/gmock-spec-builders.h
+92
-38
googlemock/test/gmock-function-mocker_test.cc
googlemock/test/gmock-function-mocker_test.cc
+51
-0
No files found.
googlemock/include/gmock/gmock-spec-builders.h
View file @
67cc6608
...
...
@@ -1786,10 +1786,79 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
}
// namespace internal
// A MockFunction<F> class has one mock method whose type is F. It is
// useful when you just want your test code to emit some messages and
// have Google Mock verify the right messages are sent (and perhaps at
// the right times). For example, if you are exercising code:
namespace
internal
{
template
<
typename
F
>
class
MockFunction
;
template
<
typename
R
,
typename
...
Args
>
class
MockFunction
<
R
(
Args
...)
>
{
public:
MockFunction
(
const
MockFunction
&
)
=
delete
;
MockFunction
&
operator
=
(
const
MockFunction
&
)
=
delete
;
std
::
function
<
R
(
Args
...)
>
AsStdFunction
()
{
return
[
this
](
Args
...
args
)
->
R
{
return
this
->
Call
(
std
::
forward
<
Args
>
(
args
)...);
};
}
// Implementation detail: the expansion of the MOCK_METHOD macro.
R
Call
(
Args
...
args
)
{
mock_
.
SetOwnerAndName
(
this
,
"Call"
);
return
mock_
.
Invoke
(
std
::
forward
<
Args
>
(
args
)...);
}
MockSpec
<
R
(
Args
...)
>
gmock_Call
(
Matcher
<
Args
>
...
m
)
{
mock_
.
RegisterOwner
(
this
);
return
mock_
.
With
(
std
::
move
(
m
)...);
}
MockSpec
<
R
(
Args
...)
>
gmock_Call
(
const
WithoutMatchers
&
,
R
(
*
)(
Args
...))
{
return
this
->
gmock_Call
(
::
testing
::
A
<
Args
>
()...);
}
protected:
MockFunction
()
=
default
;
~
MockFunction
()
=
default
;
private:
FunctionMocker
<
R
(
Args
...)
>
mock_
;
};
/*
The SignatureOf<F> struct is a meta-function returning function signature
corresponding to the provided F argument.
It makes use of MockFunction easier by allowing it to accept more F arguments
than just function signatures.
Specializations provided here cover only a signature type itself and
std::function. However, if need be it can be easily extended to cover also other
types (like for example boost::function).
*/
template
<
typename
F
>
struct
SignatureOf
;
template
<
typename
R
,
typename
...
Args
>
struct
SignatureOf
<
R
(
Args
...)
>
{
using
type
=
R
(
Args
...);
};
template
<
typename
F
>
struct
SignatureOf
<
std
::
function
<
F
>>
:
SignatureOf
<
F
>
{};
template
<
typename
F
>
using
SignatureOfT
=
typename
SignatureOf
<
F
>::
type
;
}
// namespace internal
// A MockFunction<F> type has one mock method whose type is
// internal::SignatureOfT<F>. It is useful when you just want your
// test code to emit some messages and have Google Mock verify the
// right messages are sent (and perhaps at the right times). For
// example, if you are exercising code:
//
// Foo(1);
// Foo(2);
...
...
@@ -1823,49 +1892,34 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
// Bar("a") is called by which call to Foo().
//
// MockFunction<F> can also be used to exercise code that accepts
// std::function<
F
> callbacks. To do so, use
AsStdFunction() method
// to create std::function proxy forwarding to
original object's Call.
// Example:
// std::function<
internal::SignatureOfT<F>
> callbacks. To do so, use
//
AsStdFunction() method
to create std::function proxy forwarding to
//
original object's Call.
Example:
//
// TEST(FooTest, RunsCallbackWithBarArgument) {
// MockFunction<int(string)> callback;
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
// Foo(callback.AsStdFunction());
// }
//
// The internal::SignatureOfT<F> indirection allows to use other types
// than just function signature type. This is typically useful when
// providing a mock for a predefined std::function type. Example:
//
// using FilterPredicate = std::function<bool(string)>;
// void MyFilterAlgorithm(FilterPredicate predicate);
//
// TEST(FooTest, FilterPredicateAlwaysAccepts) {
// MockFunction<FilterPredicate> predicateMock;
// EXPECT_CALL(predicateMock, Call(_)).WillRepeatedly(Return(true));
// MyFilterAlgorithm(predicateMock.AsStdFunction());
// }
template
<
typename
F
>
class
MockFunction
;
class
MockFunction
:
public
internal
::
MockFunction
<
internal
::
SignatureOfT
<
F
>>
{
using
Base
=
internal
::
MockFunction
<
internal
::
SignatureOfT
<
F
>>
;
template
<
typename
R
,
typename
...
Args
>
class
MockFunction
<
R
(
Args
...)
>
{
public:
MockFunction
()
{}
MockFunction
(
const
MockFunction
&
)
=
delete
;
MockFunction
&
operator
=
(
const
MockFunction
&
)
=
delete
;
std
::
function
<
R
(
Args
...)
>
AsStdFunction
()
{
return
[
this
](
Args
...
args
)
->
R
{
return
this
->
Call
(
std
::
forward
<
Args
>
(
args
)...);
};
}
// Implementation detail: the expansion of the MOCK_METHOD macro.
R
Call
(
Args
...
args
)
{
mock_
.
SetOwnerAndName
(
this
,
"Call"
);
return
mock_
.
Invoke
(
std
::
forward
<
Args
>
(
args
)...);
}
internal
::
MockSpec
<
R
(
Args
...)
>
gmock_Call
(
Matcher
<
Args
>
...
m
)
{
mock_
.
RegisterOwner
(
this
);
return
mock_
.
With
(
std
::
move
(
m
)...);
}
internal
::
MockSpec
<
R
(
Args
...)
>
gmock_Call
(
const
internal
::
WithoutMatchers
&
,
R
(
*
)(
Args
...))
{
return
this
->
gmock_Call
(
::
testing
::
A
<
Args
>
()...);
}
private:
internal
::
FunctionMocker
<
R
(
Args
...)
>
mock_
;
using
Base
::
Base
;
};
// The style guide prohibits "using" statements in a namespace scope
...
...
googlemock/test/gmock-function-mocker_test.cc
View file @
67cc6608
...
...
@@ -40,6 +40,7 @@
# include <objbase.h>
#endif // GTEST_OS_WINDOWS
#include <functional>
#include <map>
#include <string>
#include <type_traits>
...
...
@@ -778,6 +779,56 @@ TEST(MockMethodMockFunctionTest, AsStdFunctionWithReferenceParameter) {
EXPECT_EQ
(
-
1
,
call
(
foo
.
AsStdFunction
(),
i
));
}
namespace
{
template
<
typename
Expected
,
typename
F
>
static
constexpr
bool
IsMockFunctionTemplateArgumentDeducedTo
(
const
MockFunction
<
F
>&
)
{
return
std
::
is_same
<
F
,
Expected
>::
value
;
}
}
// namespace
template
<
typename
F
>
class
MockMethodMockFunctionSignatureTest
:
public
Test
{};
using
MockMethodMockFunctionSignatureTypes
=
Types
<
void
(),
int
(),
void
(
int
),
int
(
int
),
int
(
bool
,
int
),
int
(
bool
,
char
,
int
,
int
,
int
,
int
,
int
,
char
,
int
,
bool
)
>
;
TYPED_TEST_SUITE
(
MockMethodMockFunctionSignatureTest
,
MockMethodMockFunctionSignatureTypes
);
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionTemplateArgumentDeducedForRawSignature
)
{
using
Argument
=
TypeParam
;
MockFunction
<
Argument
>
foo
;
EXPECT_TRUE
(
IsMockFunctionTemplateArgumentDeducedTo
<
Argument
>
(
foo
));
}
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionTemplateArgumentDeducedForStdFunction
)
{
using
Argument
=
std
::
function
<
TypeParam
>
;
MockFunction
<
Argument
>
foo
;
EXPECT_TRUE
(
IsMockFunctionTemplateArgumentDeducedTo
<
Argument
>
(
foo
));
}
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionCallMethodSignatureTheSameForRawSignatureAndStdFunction
)
{
using
ForRawSignature
=
decltype
(
&
MockFunction
<
TypeParam
>::
Call
);
using
ForStdFunction
=
decltype
(
&
MockFunction
<
std
::
function
<
TypeParam
>>::
Call
);
EXPECT_TRUE
((
std
::
is_same
<
ForRawSignature
,
ForStdFunction
>::
value
));
}
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionAsStdFunctionMethodSignatureTheSameForRawSignatureAndStdFunction
)
{
using
ForRawSignature
=
decltype
(
&
MockFunction
<
TypeParam
>::
AsStdFunction
);
using
ForStdFunction
=
decltype
(
&
MockFunction
<
std
::
function
<
TypeParam
>>::
AsStdFunction
);
EXPECT_TRUE
((
std
::
is_same
<
ForRawSignature
,
ForStdFunction
>::
value
));
}
struct
MockMethodSizes0
{
MOCK_METHOD
(
void
,
func
,
());
...
...
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