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
b5c81098
Commit
b5c81098
authored
Jan 29, 2014
by
kosak
Browse files
Support mocking methods with move-only return types.
parent
b93d0f10
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
208 additions
and
44 deletions
+208
-44
include/gmock/gmock-actions.h
include/gmock/gmock-actions.h
+47
-11
include/gmock/gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+81
-25
include/gmock/internal/gmock-internal-utils.h
include/gmock/internal/gmock-internal-utils.h
+18
-5
src/gmock-spec-builders.cc
src/gmock-spec-builders.cc
+3
-3
test/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