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
53740ebc
Commit
53740ebc
authored
Jul 11, 2019
by
Adam Badura
Browse files
Add support for std::function in MockFunction (#2277)
parent
e41f31f2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
113 additions
and
40 deletions
+113
-40
googlemock/include/gmock/gmock-spec-builders.h
googlemock/include/gmock/gmock-spec-builders.h
+93
-39
googlemock/test/gmock-function-mocker_test.cc
googlemock/test/gmock-function-mocker_test.cc
+20
-1
No files found.
googlemock/include/gmock/gmock-spec-builders.h
View file @
53740ebc
...
@@ -1786,10 +1786,80 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
...
@@ -1786,10 +1786,80 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
}
// namespace internal
}
// namespace internal
// A MockFunction<F> class has one mock method whose type is F. It is
namespace
internal
{
// 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
template
<
typename
F
>
// the right times). For example, if you are exercising code:
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(1);
// Foo(2);
// Foo(2);
...
@@ -1823,49 +1893,33 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
...
@@ -1823,49 +1893,33 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
// Bar("a") is called by which call to Foo().
// Bar("a") is called by which call to Foo().
//
//
// MockFunction<F> can also be used to exercise code that accepts
// MockFunction<F> can also be used to exercise code that accepts
// std::function<
F
> callbacks. To do so, use
AsStdFunction() method
// std::function<
internal::SignatureOfT<F>
> callbacks. To do so, use
// to create std::function proxy forwarding to
original object's Call.
//
AsStdFunction() method
to create std::function proxy forwarding to
// Example:
//
original object's Call.
Example:
//
//
// TEST(FooTest, RunsCallbackWithBarArgument) {
// TEST(FooTest, RunsCallbackWithBarArgument) {
// MockFunction<int(string)> callback;
// MockFunction<int(string)> callback;
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
// Foo(callback.AsStdFunction());
// 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
>
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:
public:
MockFunction
()
{}
using
Base
::
Base
;
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_
;
};
};
// The style guide prohibits "using" statements in a namespace scope
// The style guide prohibits "using" statements in a namespace scope
...
...
googlemock/test/gmock-function-mocker_test.cc
View file @
53740ebc
...
@@ -40,6 +40,7 @@
...
@@ -40,6 +40,7 @@
# include <objbase.h>
# include <objbase.h>
#endif // GTEST_OS_WINDOWS
#endif // GTEST_OS_WINDOWS
#include <functional>
#include <map>
#include <map>
#include <string>
#include <string>
#include <type_traits>
#include <type_traits>
...
@@ -802,12 +803,30 @@ using MockMethodMockFunctionSignatureTypes = Types<
...
@@ -802,12 +803,30 @@ using MockMethodMockFunctionSignatureTypes = Types<
>
;
>
;
TYPED_TEST_SUITE
(
MockMethodMockFunctionSignatureTest
,
MockMethodMockFunctionSignatureTypes
);
TYPED_TEST_SUITE
(
MockMethodMockFunctionSignatureTest
,
MockMethodMockFunctionSignatureTypes
);
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionTemplateArgumentDeduced
)
{
TYPED_TEST
(
MockMethodMockFunctionSignatureTest
,
IsMockFunctionTemplateArgumentDeduced
ForRawSignature
)
{
using
Argument
=
TypeParam
;
using
Argument
=
TypeParam
;
MockFunction
<
Argument
>
foo
;
MockFunction
<
Argument
>
foo
;
EXPECT_TRUE
(
IsMockFunctionTemplateArgumentDeducedTo
<
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
{
struct
MockMethodSizes0
{
MOCK_METHOD
(
void
,
func
,
());
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