Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
b5c81098
Commit
b5c81098
authored
Jan 29, 2014
by
kosak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support mocking methods with move-only return types.
parent
b93d0f10
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
208 additions
and
44 deletions
+208
-44
gmock-actions.h
include/gmock/gmock-actions.h
+47
-11
gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+81
-25
gmock-internal-utils.h
include/gmock/internal/gmock-internal-utils.h
+18
-5
gmock-spec-builders.cc
src/gmock-spec-builders.cc
+3
-3
gmock-actions_test.cc
test/gmock-actions_test.cc
+59
-0
No files found.
include/gmock/gmock-actions.h
View file @
b5c81098
...
...
@@ -163,18 +163,27 @@ class DefaultValue {
// Sets the default value for type T; requires T to be
// copy-constructable and have a public destructor.
static
void
Set
(
T
x
)
{
delete
value_
;
value_
=
new
T
(
x
);
delete
producer_
;
producer_
=
new
FixedValueProducer
(
x
);
}
// Provides a factory function to be called to generate the default value.
// This method can be used even if T is only move-constructible, but it is not
// limited to that case.
typedef
T
(
*
FactoryFunction
)();
static
void
SetFactory
(
FactoryFunction
factory
)
{
delete
producer_
;
producer_
=
new
FactoryValueProducer
(
factory
);
}
// Unsets the default value for type T.
static
void
Clear
()
{
delete
value
_
;
value
_
=
NULL
;
delete
producer
_
;
producer
_
=
NULL
;
}
// Returns true iff the user has set the default value for type T.
static
bool
IsSet
()
{
return
value
_
!=
NULL
;
}
static
bool
IsSet
()
{
return
producer
_
!=
NULL
;
}
// Returns true if T has a default return value set by the user or there
// exists a built-in default value.
...
...
@@ -183,15 +192,42 @@ class DefaultValue {
}
// Returns the default value for type T if the user has set one;
// otherwise returns the built-in default value
if there is one;
//
otherwise aborts the process
.
// otherwise returns the built-in default value
. Requires that Exists()
//
is true, which ensures that the return value is well-defined
.
static
T
Get
()
{
return
value
_
==
NULL
?
internal
::
BuiltInDefaultValue
<
T
>::
Get
()
:
*
value_
;
return
producer
_
==
NULL
?
internal
::
BuiltInDefaultValue
<
T
>::
Get
()
:
producer_
->
Produce
()
;
}
private
:
static
const
T
*
value_
;
class
ValueProducer
{
public
:
virtual
~
ValueProducer
()
{}
virtual
T
Produce
()
=
0
;
};
class
FixedValueProducer
:
public
ValueProducer
{
public
:
explicit
FixedValueProducer
(
T
value
)
:
value_
(
value
)
{}
virtual
T
Produce
()
{
return
value_
;
}
private
:
const
T
value_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
FixedValueProducer
);
};
class
FactoryValueProducer
:
public
ValueProducer
{
public
:
explicit
FactoryValueProducer
(
FactoryFunction
factory
)
:
factory_
(
factory
)
{}
virtual
T
Produce
()
{
return
factory_
();
}
private
:
const
FactoryFunction
factory_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
FactoryValueProducer
);
};
static
ValueProducer
*
producer_
;
};
// This partial specialization allows a user to set default values for
...
...
@@ -241,7 +277,7 @@ class DefaultValue<void> {
// Points to the user-set default value for type T.
template
<
typename
T
>
const
T
*
DefaultValue
<
T
>::
value
_
=
NULL
;
typename
DefaultValue
<
T
>::
ValueProducer
*
DefaultValue
<
T
>::
producer
_
=
NULL
;
// Points to the user-set default value for type T&.
template
<
typename
T
>
...
...
include/gmock/gmock-spec-builders.h
View file @
b5c81098
...
...
@@ -211,7 +211,7 @@ class GTEST_API_ UntypedFunctionMockerBase {
// arguments. This function can be safely called from multiple
// threads concurrently. The caller is responsible for deleting the
// result.
const
UntypedActionResultHolderBase
*
UntypedInvokeWith
(
UntypedActionResultHolderBase
*
UntypedInvokeWith
(
const
void
*
untyped_args
)
GTEST_LOCK_EXCLUDED_
(
g_gmock_mutex
);
...
...
@@ -1289,6 +1289,58 @@ class MockSpec {
GTEST_DISALLOW_ASSIGN_
(
MockSpec
);
};
// class MockSpec
// Wrapper type for generically holding an ordinary value or lvalue reference.
// If T is not a reference type, it must be copyable or movable.
// ReferenceOrValueWrapper<T> is movable, and will also be copyable unless
// T is a move-only value type (which means that it will always be copyable
// if the current platform does not support move semantics).
//
// The primary template defines handling for values, but function header
// comments describe the contract for the whole template (including
// specializations).
template
<
typename
T
>
class
ReferenceOrValueWrapper
{
public
:
// Constructs a wrapper from the given value/reference.
explicit
ReferenceOrValueWrapper
(
T
value
)
:
value_
(
GTEST_MOVE_
(
value
))
{}
// Unwraps and returns the underlying value/reference, exactly as
// originally passed. The behavior of calling this more than once on
// the same object is unspecified.
T
Unwrap
()
{
return
GTEST_MOVE_
(
value_
);
}
// Provides nondestructive access to the underlying value/reference.
// Always returns a const reference (more precisely,
// const RemoveReference<T>&). The behavior of calling this after
// calling Unwrap on the same object is unspecified.
const
T
&
Peek
()
const
{
return
value_
;
}
private
:
T
value_
;
};
// Specialization for lvalue reference types. See primary template
// for documentation.
template
<
typename
T
>
class
ReferenceOrValueWrapper
<
T
&>
{
public
:
// Workaround for debatable pass-by-reference lint warning (c-library-team
// policy precludes NOLINT in this context)
typedef
T
&
reference
;
explicit
ReferenceOrValueWrapper
(
reference
ref
)
:
value_ptr_
(
&
ref
)
{}
T
&
Unwrap
()
{
return
*
value_ptr_
;
}
const
T
&
Peek
()
const
{
return
*
value_ptr_
;
}
private
:
T
*
value_ptr_
;
};
// MSVC warns about using 'this' in base member initializer list, so
// we need to temporarily disable the warning. We have to do it for
// the entire class to suppress the warning, even though it's about
...
...
@@ -1320,23 +1372,16 @@ class UntypedActionResultHolderBase {
template
<
typename
T
>
class
ActionResultHolder
:
public
UntypedActionResultHolderBase
{
public
:
explicit
ActionResultHolder
(
T
a_value
)
:
value_
(
a_value
)
{}
// The compiler-generated copy constructor and assignment operator
// are exactly what we need, so we don't need to define them.
// Returns the held value and deletes this object.
T
GetValueAndDelete
()
const
{
T
retval
(
value_
);
delete
this
;
return
retval
;
// Returns the held value. Must not be called more than once.
T
Unwrap
()
{
return
result_
.
Unwrap
();
}
// Prints the held value as an action's result to os.
virtual
void
PrintAsActionResult
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"
\n
Returns: "
;
// T may be a reference type, so we don't use UniversalPrint().
UniversalPrinter
<
T
>::
Print
(
value_
,
os
);
UniversalPrinter
<
T
>::
Print
(
result_
.
Peek
()
,
os
);
}
// Performs the given mock function's default action and returns the
...
...
@@ -1346,8 +1391,8 @@ class ActionResultHolder : public UntypedActionResultHolderBase {
const
FunctionMockerBase
<
F
>*
func_mocker
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
,
const
string
&
call_description
)
{
return
new
ActionResultHolder
(
func_mocker
->
PerformDefaultAction
(
args
,
call_description
));
return
new
ActionResultHolder
(
Wrapper
(
func_mocker
->
PerformDefaultAction
(
args
,
call_description
))
)
;
}
// Performs the given action and returns the result in a new-ed
...
...
@@ -1356,42 +1401,52 @@ class ActionResultHolder : public UntypedActionResultHolderBase {
static
ActionResultHolder
*
PerformAction
(
const
Action
<
F
>&
action
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
)
{
return
new
ActionResultHolder
(
action
.
Perform
(
args
));
return
new
ActionResultHolder
(
Wrapper
(
action
.
Perform
(
args
)
));
}
private
:
T
value_
;
typedef
ReferenceOrValueWrapper
<
T
>
Wrapper
;
// T could be a reference type, so = isn't supported.
GTEST_DISALLOW_ASSIGN_
(
ActionResultHolder
);
explicit
ActionResultHolder
(
Wrapper
result
)
:
result_
(
GTEST_MOVE_
(
result
))
{}
Wrapper
result_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ActionResultHolder
);
};
// Specialization for T = void.
template
<>
class
ActionResultHolder
<
void
>
:
public
UntypedActionResultHolderBase
{
public
:
void
GetValueAndDelete
()
const
{
delete
this
;
}
void
Unwrap
()
{
}
virtual
void
PrintAsActionResult
(
::
std
::
ostream
*
/* os */
)
const
{}
// Performs the given mock function's default action and returns NULL;
// Performs the given mock function's default action and returns ownership
// of an empty ActionResultHolder*.
template
<
typename
F
>
static
ActionResultHolder
*
PerformDefaultAction
(
const
FunctionMockerBase
<
F
>*
func_mocker
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
,
const
string
&
call_description
)
{
func_mocker
->
PerformDefaultAction
(
args
,
call_description
);
return
NULL
;
return
new
ActionResultHolder
;
}
// Performs the given action and returns NULL.
// Performs the given action and returns ownership of an empty
// ActionResultHolder*.
template
<
typename
F
>
static
ActionResultHolder
*
PerformAction
(
const
Action
<
F
>&
action
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
)
{
action
.
Perform
(
args
);
return
NULL
;
return
new
ActionResultHolder
;
}
private
:
ActionResultHolder
()
{}
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ActionResultHolder
);
};
// The base of the function mocker class for the given function type.
...
...
@@ -1526,8 +1581,9 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// threads concurrently.
Result
InvokeWith
(
const
ArgumentTuple
&
args
)
GTEST_LOCK_EXCLUDED_
(
g_gmock_mutex
)
{
return
static_cast
<
const
ResultHolder
*>
(
this
->
UntypedInvokeWith
(
&
args
))
->
GetValueAndDelete
();
scoped_ptr
<
ResultHolder
>
holder
(
DownCast_
<
ResultHolder
*>
(
this
->
UntypedInvokeWith
(
&
args
)));
return
holder
->
Unwrap
();
}
// Adds and returns a default action spec for this mock function.
...
...
include/gmock/internal/gmock-internal-utils.h
View file @
b5c81098
...
...
@@ -361,17 +361,30 @@ template <typename T> struct DecayArray<T[]> {
typedef
const
T
*
type
;
};
// Invalid<T>() returns an invalid value of type T. This is useful
// Disable MSVC warnings for infinite recursion, since in this case the
// the recursion is unreachable.
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4717)
#endif
// Invalid<T>() is usable as an expression of type T, but will terminate
// the program with an assertion failure if actually run. This is useful
// when a value of type T is needed for compilation, but the statement
// will not really be executed (or we don't care if the statement
// crashes).
template
<
typename
T
>
inline
T
Invalid
()
{
return
const_cast
<
typename
remove_reference
<
T
>::
type
&>
(
*
static_cast
<
volatile
typename
remove_reference
<
T
>::
type
*>
(
NULL
));
Assert
(
false
,
""
,
-
1
,
"Internal error: attempt to return invalid value"
);
// This statement is unreachable, and would never terminate even if it
// could be reached. It is provided only to placate compiler warnings
// about missing return statements.
return
Invalid
<
T
>
();
}
template
<>
inline
void
Invalid
<
void
>
()
{}
#ifdef _MSC_VER
# pragma warning(pop)
#endif
// Given a raw type (i.e. having no top-level reference or const
// modifier) RawContainer that's either an STL-style container or a
...
...
src/gmock-spec-builders.cc
View file @
b5c81098
...
...
@@ -332,7 +332,7 @@ const char* UntypedFunctionMockerBase::Name() const
// Calculates the result of invoking this mock function with the given
// arguments, prints it, and returns it. The caller is responsible
// for deleting the result.
const
UntypedActionResultHolderBase
*
UntypedActionResultHolderBase
*
UntypedFunctionMockerBase
::
UntypedInvokeWith
(
const
void
*
const
untyped_args
)
GTEST_LOCK_EXCLUDED_
(
g_gmock_mutex
)
{
if
(
untyped_expectations_
.
size
()
==
0
)
{
...
...
@@ -370,7 +370,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
this
->
UntypedDescribeUninterestingCall
(
untyped_args
,
&
ss
);
// Calculates the function result.
const
UntypedActionResultHolderBase
*
const
result
=
UntypedActionResultHolderBase
*
const
result
=
this
->
UntypedPerformDefaultAction
(
untyped_args
,
ss
.
str
());
// Prints the function result.
...
...
@@ -417,7 +417,7 @@ UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
untyped_expectation
->
DescribeLocationTo
(
&
loc
);
}
const
UntypedActionResultHolderBase
*
const
result
=
UntypedActionResultHolderBase
*
const
result
=
untyped_action
==
NULL
?
this
->
UntypedPerformDefaultAction
(
untyped_args
,
ss
.
str
())
:
this
->
UntypedPerformAction
(
untyped_action
,
untyped_args
);
...
...
test/gmock-actions_test.cc
View file @
b5c81098
...
...
@@ -36,6 +36,7 @@
#include "gmock/gmock-actions.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include <string>
#include "gmock/gmock.h"
#include "gmock/internal/gmock-port.h"
...
...
@@ -263,6 +264,21 @@ TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
},
""
);
}
#if GTEST_LANG_CXX11
TEST
(
DefaultValueDeathTest
,
GetWorksForMoveOnlyIfSet
)
{
EXPECT_FALSE
(
DefaultValue
<
std
::
unique_ptr
<
int
>>::
Exists
());
EXPECT_DEATH_IF_SUPPORTED
({
DefaultValue
<
std
::
unique_ptr
<
int
>>::
Get
();
},
""
);
DefaultValue
<
std
::
unique_ptr
<
int
>>::
SetFactory
([]
{
return
std
::
unique_ptr
<
int
>
(
new
int
(
42
));
});
EXPECT_TRUE
(
DefaultValue
<
std
::
unique_ptr
<
int
>>::
Exists
());
std
::
unique_ptr
<
int
>
i
=
DefaultValue
<
std
::
unique_ptr
<
int
>>::
Get
();
EXPECT_EQ
(
42
,
*
i
);
}
#endif // GTEST_LANG_CXX11
// Tests that DefaultValue<void>::Get() returns void.
TEST
(
DefaultValueTest
,
GetWorksForVoid
)
{
return
DefaultValue
<
void
>::
Get
();
...
...
@@ -620,6 +636,10 @@ class MockClass {
MOCK_METHOD1
(
IntFunc
,
int
(
bool
flag
));
// NOLINT
MOCK_METHOD0
(
Foo
,
MyClass
());
#if GTEST_LANG_CXX11
MOCK_METHOD0
(
MakeUnique
,
std
::
unique_ptr
<
int
>
());
MOCK_METHOD0
(
MakeVectorUnique
,
std
::
vector
<
std
::
unique_ptr
<
int
>>
());
#endif
private
:
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
MockClass
);
...
...
@@ -1253,4 +1273,43 @@ TEST(ByRefTest, PrintsCorrectly) {
EXPECT_EQ
(
expected
.
str
(),
actual
.
str
());
}
#if GTEST_LANG_CXX11
std
::
unique_ptr
<
int
>
UniquePtrSource
()
{
return
std
::
unique_ptr
<
int
>
(
new
int
(
19
));
}
std
::
vector
<
std
::
unique_ptr
<
int
>>
VectorUniquePtrSource
()
{
std
::
vector
<
std
::
unique_ptr
<
int
>>
out
;
out
.
emplace_back
(
new
int
(
7
));
return
out
;
}
TEST
(
MockMethodTest
,
CanReturnMoveOnlyValue
)
{
MockClass
mock
;
// Check default value
DefaultValue
<
std
::
unique_ptr
<
int
>>::
SetFactory
([]
{
return
std
::
unique_ptr
<
int
>
(
new
int
(
42
));
});
EXPECT_EQ
(
42
,
*
mock
.
MakeUnique
());
EXPECT_CALL
(
mock
,
MakeUnique
())
.
WillRepeatedly
(
Invoke
(
UniquePtrSource
));
EXPECT_CALL
(
mock
,
MakeVectorUnique
())
.
WillRepeatedly
(
Invoke
(
VectorUniquePtrSource
));
std
::
unique_ptr
<
int
>
result1
=
mock
.
MakeUnique
();
EXPECT_EQ
(
19
,
*
result1
);
std
::
unique_ptr
<
int
>
result2
=
mock
.
MakeUnique
();
EXPECT_EQ
(
19
,
*
result2
);
EXPECT_NE
(
result1
,
result2
);
std
::
vector
<
std
::
unique_ptr
<
int
>>
vresult
=
mock
.
MakeVectorUnique
();
EXPECT_EQ
(
1
,
vresult
.
size
());
EXPECT_NE
(
nullptr
,
vresult
[
0
]);
EXPECT_EQ
(
7
,
*
vresult
[
0
]);
}
#endif // GTEST_LANG_CXX11
}
// 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