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
88fc7d75
Commit
88fc7d75
authored
Apr 06, 2018
by
Gennadiy Civil
Browse files
merging gmock-actions 2
parent
bee1d13f
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
216 additions
and
18 deletions
+216
-18
googlemock/include/gmock/gmock-actions.h
googlemock/include/gmock/gmock-actions.h
+73
-17
googlemock/test/gmock-actions_test.cc
googlemock/test/gmock-actions_test.cc
+143
-1
No files found.
googlemock/include/gmock/gmock-actions.h
View file @
88fc7d75
...
@@ -360,14 +360,20 @@ class Action {
...
@@ -360,14 +360,20 @@ class Action {
// Constructs a null Action. Needed for storing Action objects in
// Constructs a null Action. Needed for storing Action objects in
// STL containers.
// STL containers.
Action
()
:
impl_
(
NULL
)
{}
Action
()
{}
// Constructs an Action from its implementation. A NULL impl is
#if GTEST_LANG_CXX11
// used to represent the "do-default" action.
// Construct an Action from a specified callable.
explicit
Action
(
ActionInterface
<
F
>*
impl
)
:
impl_
(
impl
)
{}
// This cannot take std::function directly, because then Action would not be
// directly constructible from lambda (it would require two conversions).
template
<
typename
G
,
typename
=
typename
::
std
::
enable_if
<
::
std
::
is_constructible
<::
std
::
function
<
F
>,
G
>::
value
>::
type
>
Action
(
G
&&
fun
)
:
fun_
(
::
std
::
forward
<
G
>
(
fun
))
{}
// NOLINT
#endif
// Co
py co
nstruct
or
.
// Construct
s an Action from its implementation
.
Action
(
const
Action
&
action
)
:
impl_
(
action
.
impl
_
)
{}
explicit
Action
(
ActionInterface
<
F
>*
impl
)
:
impl_
(
impl
)
{}
// This constructor allows us to turn an Action<Func> object into an
// This constructor allows us to turn an Action<Func> object into an
// Action<F>, as long as F's arguments can be implicitly converted
// Action<F>, as long as F's arguments can be implicitly converted
...
@@ -377,7 +383,13 @@ class Action {
...
@@ -377,7 +383,13 @@ class Action {
explicit
Action
(
const
Action
<
Func
>&
action
);
explicit
Action
(
const
Action
<
Func
>&
action
);
// Returns true iff this is the DoDefault() action.
// Returns true iff this is the DoDefault() action.
bool
IsDoDefault
()
const
{
return
impl_
.
get
()
==
NULL
;
}
bool
IsDoDefault
()
const
{
#if GTEST_LANG_CXX11
return
impl_
==
nullptr
&&
fun_
==
nullptr
;
#else
return
impl_
==
NULL
;
#endif
}
// Performs the action. Note that this method is const even though
// Performs the action. Note that this method is const even though
// the corresponding method in ActionInterface is not. The reason
// the corresponding method in ActionInterface is not. The reason
...
@@ -385,14 +397,15 @@ class Action {
...
@@ -385,14 +397,15 @@ class Action {
// another concrete action, not that the concrete action it binds to
// another concrete action, not that the concrete action it binds to
// cannot change state. (Think of the difference between a const
// cannot change state. (Think of the difference between a const
// pointer and a pointer to const.)
// pointer and a pointer to const.)
Result
Perform
(
const
ArgumentTuple
&
args
)
const
{
Result
Perform
(
ArgumentTuple
args
)
const
{
internal
::
Assert
(
if
(
IsDoDefault
())
{
!
IsDoDefault
(),
__FILE__
,
__LINE__
,
internal
::
IllegalDoDefault
(
__FILE__
,
__LINE__
);
"You are using DoDefault() inside a composite action like "
}
"DoAll() or WithArgs(). This is not supported for technical "
#if GTEST_LANG_CXX11
"reasons. Please instead spell out the default action, or "
if
(
fun_
!=
nullptr
)
{
"assign the default action to an Action variable and use "
return
internal
::
Apply
(
fun_
,
::
std
::
move
(
args
));
"the variable in various places."
);
}
#endif
return
impl_
->
Perform
(
args
);
return
impl_
->
Perform
(
args
);
}
}
...
@@ -400,6 +413,18 @@ class Action {
...
@@ -400,6 +413,18 @@ class Action {
template
<
typename
F1
,
typename
F2
>
template
<
typename
F1
,
typename
F2
>
friend
class
internal
::
ActionAdaptor
;
friend
class
internal
::
ActionAdaptor
;
template
<
typename
G
>
friend
class
Action
;
// In C++11, Action can be implemented either as a generic functor (through
// std::function), or legacy ActionInterface. In C++98, only ActionInterface
// is available. The invariants are as follows:
// * in C++98, impl_ is null iff this is the default action
// * in C++11, at most one of fun_ & impl_ may be nonnull; both are null iff
// this is the default action
#if GTEST_LANG_CXX11
::
std
::
function
<
F
>
fun_
;
#endif
internal
::
linked_ptr
<
ActionInterface
<
F
>
>
impl_
;
internal
::
linked_ptr
<
ActionInterface
<
F
>
>
impl_
;
};
};
...
@@ -531,6 +556,9 @@ struct ByMoveWrapper {
...
@@ -531,6 +556,9 @@ struct ByMoveWrapper {
// statement, and conversion of the result of Return to Action<T(U)> is a
// statement, and conversion of the result of Return to Action<T(U)> is a
// good place for that.
// good place for that.
//
//
// The real life example of the above scenario happens when an invocation
// of gtl::Container() is passed into Return.
//
template
<
typename
R
>
template
<
typename
R
>
class
ReturnAction
{
class
ReturnAction
{
public:
public:
...
@@ -750,7 +778,7 @@ class DoDefaultAction {
...
@@ -750,7 +778,7 @@ class DoDefaultAction {
// This template type conversion operator allows DoDefault() to be
// This template type conversion operator allows DoDefault() to be
// used in any function.
// used in any function.
template
<
typename
F
>
template
<
typename
F
>
operator
Action
<
F
>
()
const
{
return
Action
<
F
>
(
NULL
);
}
operator
Action
<
F
>
()
const
{
return
Action
<
F
>
();
}
// NOLINT
};
};
// Implements the Assign action to set a given pointer referent to a
// Implements the Assign action to set a given pointer referent to a
...
@@ -886,6 +914,28 @@ class InvokeMethodWithoutArgsAction {
...
@@ -886,6 +914,28 @@ class InvokeMethodWithoutArgsAction {
GTEST_DISALLOW_ASSIGN_
(
InvokeMethodWithoutArgsAction
);
GTEST_DISALLOW_ASSIGN_
(
InvokeMethodWithoutArgsAction
);
};
};
// Implements the InvokeWithoutArgs(callback) action.
template
<
typename
CallbackType
>
class
InvokeCallbackWithoutArgsAction
{
public:
// The c'tor takes ownership of the callback.
explicit
InvokeCallbackWithoutArgsAction
(
CallbackType
*
callback
)
:
callback_
(
callback
)
{
callback
->
CheckIsRepeatable
();
// Makes sure the callback is permanent.
}
// This type conversion operator template allows Invoke(callback) to
// be used wherever the callback's return type can be implicitly
// converted to that of the mock function.
template
<
typename
Result
,
typename
ArgumentTuple
>
Result
Perform
(
const
ArgumentTuple
&
)
const
{
return
callback_
->
Run
();
}
private:
const
internal
::
linked_ptr
<
CallbackType
>
callback_
;
GTEST_DISALLOW_ASSIGN_
(
InvokeCallbackWithoutArgsAction
);
};
// Implements the IgnoreResult(action) action.
// Implements the IgnoreResult(action) action.
template
<
typename
A
>
template
<
typename
A
>
class
IgnoreResultAction
{
class
IgnoreResultAction
{
...
@@ -1053,7 +1103,13 @@ typedef internal::IgnoredValue Unused;
...
@@ -1053,7 +1103,13 @@ typedef internal::IgnoredValue Unused;
template
<
typename
To
>
template
<
typename
To
>
template
<
typename
From
>
template
<
typename
From
>
Action
<
To
>::
Action
(
const
Action
<
From
>&
from
)
Action
<
To
>::
Action
(
const
Action
<
From
>&
from
)
:
impl_
(
new
internal
::
ActionAdaptor
<
To
,
From
>
(
from
))
{}
:
#if GTEST_LANG_CXX11
fun_
(
from
.
fun_
),
#endif
impl_
(
from
.
impl_
==
NULL
?
NULL
:
new
internal
::
ActionAdaptor
<
To
,
From
>
(
from
))
{
}
// Creates an action that returns 'value'. 'value' is passed by value
// Creates an action that returns 'value'. 'value' is passed by value
// instead of const reference - otherwise Return("string literal")
// instead of const reference - otherwise Return("string literal")
...
...
googlemock/test/gmock-actions_test.cc
View file @
88fc7d75
...
@@ -65,6 +65,7 @@ using testing::ReturnRef;
...
@@ -65,6 +65,7 @@ using testing::ReturnRef;
using
testing
::
ReturnRefOfCopy
;
using
testing
::
ReturnRefOfCopy
;
using
testing
::
SetArgPointee
;
using
testing
::
SetArgPointee
;
using
testing
::
SetArgumentPointee
;
using
testing
::
SetArgumentPointee
;
using
testing
::
Unused
;
using
testing
::
_
;
using
testing
::
_
;
using
testing
::
get
;
using
testing
::
get
;
using
testing
::
internal
::
BuiltInDefaultValue
;
using
testing
::
internal
::
BuiltInDefaultValue
;
...
@@ -705,6 +706,8 @@ class MockClass {
...
@@ -705,6 +706,8 @@ class MockClass {
MOCK_METHOD0
(
MakeUniqueBase
,
std
::
unique_ptr
<
Base
>
());
MOCK_METHOD0
(
MakeUniqueBase
,
std
::
unique_ptr
<
Base
>
());
MOCK_METHOD0
(
MakeVectorUnique
,
std
::
vector
<
std
::
unique_ptr
<
int
>>
());
MOCK_METHOD0
(
MakeVectorUnique
,
std
::
vector
<
std
::
unique_ptr
<
int
>>
());
MOCK_METHOD1
(
TakeUnique
,
int
(
std
::
unique_ptr
<
int
>
));
MOCK_METHOD1
(
TakeUnique
,
int
(
std
::
unique_ptr
<
int
>
));
MOCK_METHOD2
(
TakeUnique
,
int
(
const
std
::
unique_ptr
<
int
>&
,
std
::
unique_ptr
<
int
>
));
#endif
#endif
private:
private:
...
@@ -756,7 +759,7 @@ TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
...
@@ -756,7 +759,7 @@ TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
}
}
// Tests that DoDefault() returns the default value set by
// Tests that DoDefault() returns the default value set by
// DefaultValue<T>::Set() when it's not overrid
d
en by an ON_CALL().
// DefaultValue<T>::Set() when it's not overriden by an ON_CALL().
TEST
(
DoDefaultTest
,
ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne
)
{
TEST
(
DoDefaultTest
,
ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne
)
{
DefaultValue
<
int
>::
Set
(
1
);
DefaultValue
<
int
>::
Set
(
1
);
MockClass
mock
;
MockClass
mock
;
...
@@ -1411,6 +1414,145 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
...
@@ -1411,6 +1414,145 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
EXPECT_EQ
(
7
,
*
vresult
[
0
]);
EXPECT_EQ
(
7
,
*
vresult
[
0
]);
}
}
TEST
(
MockMethodTest
,
CanTakeMoveOnlyValue
)
{
MockClass
mock
;
auto
make
=
[](
int
i
)
{
return
std
::
unique_ptr
<
int
>
(
new
int
(
i
));
};
EXPECT_CALL
(
mock
,
TakeUnique
(
_
)).
WillRepeatedly
([](
std
::
unique_ptr
<
int
>
i
)
{
return
*
i
;
});
// DoAll() does not compile, since it would move from its arguments twice.
// EXPECT_CALL(mock, TakeUnique(_, _))
// .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
// Return(1)));
EXPECT_CALL
(
mock
,
TakeUnique
(
testing
::
Pointee
(
7
)))
.
WillOnce
(
Return
(
-
7
))
.
RetiresOnSaturation
();
EXPECT_CALL
(
mock
,
TakeUnique
(
testing
::
IsNull
()))
.
WillOnce
(
Return
(
-
1
))
.
RetiresOnSaturation
();
EXPECT_EQ
(
5
,
mock
.
TakeUnique
(
make
(
5
)));
EXPECT_EQ
(
-
7
,
mock
.
TakeUnique
(
make
(
7
)));
EXPECT_EQ
(
7
,
mock
.
TakeUnique
(
make
(
7
)));
EXPECT_EQ
(
7
,
mock
.
TakeUnique
(
make
(
7
)));
EXPECT_EQ
(
-
1
,
mock
.
TakeUnique
({}));
// Some arguments are moved, some passed by reference.
auto
lvalue
=
make
(
6
);
EXPECT_CALL
(
mock
,
TakeUnique
(
_
,
_
))
.
WillOnce
([](
const
std
::
unique_ptr
<
int
>&
i
,
std
::
unique_ptr
<
int
>
j
)
{
return
*
i
*
*
j
;
});
EXPECT_EQ
(
42
,
mock
.
TakeUnique
(
lvalue
,
make
(
7
)));
// The unique_ptr can be saved by the action.
std
::
unique_ptr
<
int
>
saved
;
EXPECT_CALL
(
mock
,
TakeUnique
(
_
)).
WillOnce
([
&
saved
](
std
::
unique_ptr
<
int
>
i
)
{
saved
=
std
::
move
(
i
);
return
0
;
});
EXPECT_EQ
(
0
,
mock
.
TakeUnique
(
make
(
42
)));
EXPECT_EQ
(
42
,
*
saved
);
}
#endif // GTEST_HAS_STD_UNIQUE_PTR_
#endif // GTEST_HAS_STD_UNIQUE_PTR_
#if GTEST_LANG_CXX11
// Tests for std::function based action.
int
Add
(
int
val
,
int
&
ref
,
int
*
ptr
)
{
// NOLINT
int
result
=
val
+
ref
+
*
ptr
;
ref
=
42
;
*
ptr
=
43
;
return
result
;
}
int
Deref
(
std
::
unique_ptr
<
int
>
ptr
)
{
return
*
ptr
;
}
struct
Double
{
template
<
typename
T
>
T
operator
()(
T
t
)
{
return
2
*
t
;
}
};
std
::
unique_ptr
<
int
>
UniqueInt
(
int
i
)
{
return
std
::
unique_ptr
<
int
>
(
new
int
(
i
));
}
TEST
(
FunctorActionTest
,
ActionFromFunction
)
{
Action
<
int
(
int
,
int
&
,
int
*
)
>
a
=
&
Add
;
int
x
=
1
,
y
=
2
,
z
=
3
;
EXPECT_EQ
(
6
,
a
.
Perform
(
std
::
forward_as_tuple
(
x
,
y
,
&
z
)));
EXPECT_EQ
(
42
,
y
);
EXPECT_EQ
(
43
,
z
);
Action
<
int
(
std
::
unique_ptr
<
int
>
)
>
a1
=
&
Deref
;
EXPECT_EQ
(
7
,
a1
.
Perform
(
std
::
make_tuple
(
UniqueInt
(
7
))));
}
TEST
(
FunctorActionTest
,
ActionFromLambda
)
{
Action
<
int
(
bool
,
int
)
>
a1
=
[](
bool
b
,
int
i
)
{
return
b
?
i
:
0
;
};
EXPECT_EQ
(
5
,
a1
.
Perform
(
make_tuple
(
true
,
5
)));
EXPECT_EQ
(
0
,
a1
.
Perform
(
make_tuple
(
false
,
5
)));
std
::
unique_ptr
<
int
>
saved
;
Action
<
void
(
std
::
unique_ptr
<
int
>
)
>
a2
=
[
&
saved
](
std
::
unique_ptr
<
int
>
p
)
{
saved
=
std
::
move
(
p
);
};
a2
.
Perform
(
make_tuple
(
UniqueInt
(
5
)));
EXPECT_EQ
(
5
,
*
saved
);
}
TEST
(
FunctorActionTest
,
PolymorphicFunctor
)
{
Action
<
int
(
int
)
>
ai
=
Double
();
EXPECT_EQ
(
2
,
ai
.
Perform
(
make_tuple
(
1
)));
Action
<
double
(
double
)
>
ad
=
Double
();
// Double? Double double!
EXPECT_EQ
(
3.0
,
ad
.
Perform
(
make_tuple
(
1.5
)));
}
TEST
(
FunctorActionTest
,
TypeConversion
)
{
// Numeric promotions are allowed.
const
Action
<
bool
(
int
)
>
a1
=
[](
int
i
)
{
return
i
>
1
;
};
const
Action
<
int
(
bool
)
>
a2
=
Action
<
int
(
bool
)
>
(
a1
);
EXPECT_EQ
(
1
,
a1
.
Perform
(
make_tuple
(
42
)));
EXPECT_EQ
(
0
,
a2
.
Perform
(
make_tuple
(
42
)));
// Implicit constructors are allowed.
const
Action
<
bool
(
std
::
string
)
>
s1
=
[](
std
::
string
s
)
{
return
!
s
.
empty
();
};
const
Action
<
int
(
const
char
*
)
>
s2
=
Action
<
int
(
const
char
*
)
>
(
s1
);
EXPECT_EQ
(
0
,
s2
.
Perform
(
make_tuple
(
""
)));
EXPECT_EQ
(
1
,
s2
.
Perform
(
make_tuple
(
"hello"
)));
// Also between the lambda and the action itself.
const
Action
<
bool
(
std
::
string
)
>
x
=
[](
Unused
)
{
return
42
;
};
EXPECT_TRUE
(
x
.
Perform
(
make_tuple
(
"hello"
)));
}
TEST
(
FunctorActionTest
,
UnusedArguments
)
{
// Verify that users can ignore uninteresting arguments.
Action
<
int
(
int
,
std
::
unique_ptr
<
int
>
,
const
int
&
)
>
a
=
[](
int
i
,
Unused
,
Unused
)
{
return
2
*
i
;
};
EXPECT_EQ
(
6
,
a
.
Perform
(
make_tuple
(
3
,
UniqueInt
(
7
),
9
)));
}
// Test that basic built-in actions work with move-only arguments.
// TODO(rburny): Currently, almost all ActionInterface-based actions will not
// work, even if they only try to use other, copyable arguments. Implement them
// if necessary (but note that DoAll cannot work on non-copyable types anyway -
// so maybe it's better to make users use lambdas instead.
TEST
(
MoveOnlyArgumentsTest
,
ReturningActions
)
{
Action
<
int
(
std
::
unique_ptr
<
int
>
)
>
a
=
Return
(
1
);
EXPECT_EQ
(
1
,
a
.
Perform
(
make_tuple
(
nullptr
)));
a
=
testing
::
WithoutArgs
([]()
{
return
7
;
});
EXPECT_EQ
(
7
,
a
.
Perform
(
make_tuple
(
nullptr
)));
Action
<
void
(
std
::
unique_ptr
<
int
>
,
int
*
)
>
a2
=
testing
::
SetArgPointee
<
1
>
(
3
);
int
x
=
0
;
a2
.
Perform
(
make_tuple
(
nullptr
,
&
x
));
EXPECT_EQ
(
x
,
3
);
}
#endif // GTEST_LANG_CXX11
}
// Unnamed namespace
}
// Unnamed namespace
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