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
ed6c9277
Commit
ed6c9277
authored
Feb 23, 2011
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Makes Google Mock compile much faster and use much less memory; reviewed by Nico…
Makes Google Mock compile much faster and use much less memory; reviewed by Nico Weber. This fixes issue 68.
parent
b3e90422
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
813 additions
and
570 deletions
+813
-570
gmock-actions.h
include/gmock/gmock-actions.h
+12
-51
gmock-generated-function-mockers.h
include/gmock/gmock-generated-function-mockers.h
+34
-29
gmock-generated-function-mockers.h.pump
include/gmock/gmock-generated-function-mockers.h.pump
+2
-1
gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+374
-478
gmock_doctor.py
scripts/gmock_doctor.py
+2
-2
gmock-spec-builders.cc
src/gmock-spec-builders.cc
+335
-3
gmock-actions_test.cc
test/gmock-actions_test.cc
+1
-2
gmock-spec-builders_test.cc
test/gmock-spec-builders_test.cc
+53
-4
No files found.
include/gmock/gmock-actions.h
View file @
ed6c9277
...
@@ -59,9 +59,6 @@ namespace testing {
...
@@ -59,9 +59,6 @@ namespace testing {
namespace
internal
{
namespace
internal
{
template
<
typename
F
>
class
MonomorphicDoDefaultActionImpl
;
template
<
typename
F1
,
typename
F2
>
template
<
typename
F1
,
typename
F2
>
class
ActionAdaptor
;
class
ActionAdaptor
;
...
@@ -255,8 +252,7 @@ class ActionInterface {
...
@@ -255,8 +252,7 @@ class ActionInterface {
typedef
typename
internal
::
Function
<
F
>::
Result
Result
;
typedef
typename
internal
::
Function
<
F
>::
Result
Result
;
typedef
typename
internal
::
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
typedef
typename
internal
::
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
ActionInterface
()
:
is_do_default_
(
false
)
{}
ActionInterface
()
{}
virtual
~
ActionInterface
()
{}
virtual
~
ActionInterface
()
{}
// Performs the action. This method is not const, as in general an
// Performs the action. This method is not const, as in general an
...
@@ -265,21 +261,7 @@ class ActionInterface {
...
@@ -265,21 +261,7 @@ class ActionInterface {
// remember the current element.
// remember the current element.
virtual
Result
Perform
(
const
ArgumentTuple
&
args
)
=
0
;
virtual
Result
Perform
(
const
ArgumentTuple
&
args
)
=
0
;
// Returns true iff this is the DoDefault() action.
bool
IsDoDefault
()
const
{
return
is_do_default_
;
}
private
:
private
:
template
<
typename
Function
>
friend
class
internal
::
MonomorphicDoDefaultActionImpl
;
// This private constructor is reserved for implementing
// DoDefault(), the default action for a given mock function.
explicit
ActionInterface
(
bool
is_do_default
)
:
is_do_default_
(
is_do_default
)
{}
// True iff this action is DoDefault().
const
bool
is_do_default_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ActionInterface
);
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ActionInterface
);
};
};
...
@@ -302,7 +284,8 @@ class Action {
...
@@ -302,7 +284,8 @@ class Action {
// STL containers.
// STL containers.
Action
()
:
impl_
(
NULL
)
{}
Action
()
:
impl_
(
NULL
)
{}
// Constructs an Action from its implementation.
// Constructs an Action from its implementation. A NULL impl is
// used to represent the "do-default" action.
explicit
Action
(
ActionInterface
<
F
>*
impl
)
:
impl_
(
impl
)
{}
explicit
Action
(
ActionInterface
<
F
>*
impl
)
:
impl_
(
impl
)
{}
// Copy constructor.
// Copy constructor.
...
@@ -316,7 +299,7 @@ class Action {
...
@@ -316,7 +299,7 @@ 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_
->
IsDoDefault
()
;
}
bool
IsDoDefault
()
const
{
return
impl_
.
get
()
==
NULL
;
}
// 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
...
@@ -325,6 +308,13 @@ class Action {
...
@@ -325,6 +308,13 @@ class Action {
// 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
(
const
ArgumentTuple
&
args
)
const
{
internal
::
Assert
(
!
IsDoDefault
(),
__FILE__
,
__LINE__
,
"You are using DoDefault() inside a composite action like "
"DoAll() or WithArgs(). This is not supported for technical "
"reasons. Please instead spell out the default action, or "
"assign the default action to an Action variable and use "
"the variable in various places."
);
return
impl_
->
Perform
(
args
);
return
impl_
->
Perform
(
args
);
}
}
...
@@ -633,42 +623,13 @@ class ReturnRefOfCopyAction {
...
@@ -633,42 +623,13 @@ class ReturnRefOfCopyAction {
GTEST_DISALLOW_ASSIGN_
(
ReturnRefOfCopyAction
);
GTEST_DISALLOW_ASSIGN_
(
ReturnRefOfCopyAction
);
};
};
// Implements the DoDefault() action for a particular function type F.
template
<
typename
F
>
class
MonomorphicDoDefaultActionImpl
:
public
ActionInterface
<
F
>
{
public
:
typedef
typename
Function
<
F
>::
Result
Result
;
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
MonomorphicDoDefaultActionImpl
()
:
ActionInterface
<
F
>
(
true
)
{}
// For technical reasons, DoDefault() cannot be used inside a
// composite action (e.g. DoAll(...)). It can only be used at the
// top level in an EXPECT_CALL(). If this function is called, the
// user must be using DoDefault() inside a composite action, and we
// have to generate a run-time error.
virtual
Result
Perform
(
const
ArgumentTuple
&
)
{
Assert
(
false
,
__FILE__
,
__LINE__
,
"You are using DoDefault() inside a composite action like "
"DoAll() or WithArgs(). This is not supported for technical "
"reasons. Please instead spell out the default action, or "
"assign the default action to an Action variable and use "
"the variable in various places."
);
return
internal
::
Invalid
<
Result
>
();
// The above statement will never be reached, but is required in
// order for this function to compile.
}
};
// Implements the polymorphic DoDefault() action.
// Implements the polymorphic DoDefault() action.
class
DoDefaultAction
{
class
DoDefaultAction
{
public
:
public
:
// 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
{
operator
Action
<
F
>
()
const
{
return
Action
<
F
>
(
NULL
);
}
return
Action
<
F
>
(
new
MonomorphicDoDefaultActionImpl
<
F
>
);
}
};
};
// Implements the Assign action to set a given pointer referent to a
// Implements the Assign action to set a given pointer referent to a
...
...
include/gmock/gmock-generated-function-mockers.h
View file @
ed6c9277
// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
// This file was GENERATED by command:
// pump.py gmock-generated-function-mockers.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright 2007, Google Inc.
// Copyright 2007, Google Inc.
// All rights reserved.
// All rights reserved.
...
@@ -352,7 +354,8 @@ using internal::FunctionMocker;
...
@@ -352,7 +354,8 @@ using internal::FunctionMocker;
} \
} \
::testing::MockSpec<F>& \
::testing::MockSpec<F>& \
gmock_##Method() constness { \
gmock_##Method() constness { \
return GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this).With(); \
GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(0, constness, Method).With(); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
...
@@ -367,8 +370,8 @@ using internal::FunctionMocker;
...
@@ -367,8 +370,8 @@ using internal::FunctionMocker;
} \
} \
::testing::MockSpec<F>& \
::testing::MockSpec<F>& \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
return GMOCK_MOCKER_(1, constness,
\
GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this
).With(gmock_a1); \
return GMOCK_MOCKER_(1, constness, Method
).With(gmock_a1); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
...
@@ -385,8 +388,8 @@ using internal::FunctionMocker;
...
@@ -385,8 +388,8 @@ using internal::FunctionMocker;
::testing::MockSpec<F>& \
::testing::MockSpec<F>& \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
return GMOCK_MOCKER_(2, constness,
\
GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this
).With(gmock_a1, gmock_a2); \
return GMOCK_MOCKER_(2, constness, Method
).With(gmock_a1, gmock_a2); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
...
@@ -406,8 +409,9 @@ using internal::FunctionMocker;
...
@@ -406,8 +409,9 @@ using internal::FunctionMocker;
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
return GMOCK_MOCKER_(3, constness, \
GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3); \
return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
...
@@ -429,9 +433,9 @@ using internal::FunctionMocker;
...
@@ -429,9 +433,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
return GMOCK_MOCKER_(4, constness,
\
GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4); \
gmock_a
3, gmock_a
4); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
...
@@ -455,9 +459,9 @@ using internal::FunctionMocker;
...
@@ -455,9 +459,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
return GMOCK_MOCKER_(5, constness,
\
GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4, gmock_a5); \
gmock_a
3, gmock_a
4, gmock_a5); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
...
@@ -483,9 +487,9 @@ using internal::FunctionMocker;
...
@@ -483,9 +487,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
return GMOCK_MOCKER_(6, constness,
\
GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4, gmock_a5, gmock_a6); \
gmock_a
3, gmock_a
4, gmock_a5, gmock_a6); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
...
@@ -513,9 +517,9 @@ using internal::FunctionMocker;
...
@@ -513,9 +517,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
return GMOCK_MOCKER_(7, constness,
\
GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
gmock_a
3, gmock_a
4, gmock_a5, gmock_a6, gmock_a7); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
...
@@ -545,9 +549,9 @@ using internal::FunctionMocker;
...
@@ -545,9 +549,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
return GMOCK_MOCKER_(8, constness,
\
GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
gmock_a
3, gmock_a
4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
...
@@ -580,9 +584,10 @@ using internal::FunctionMocker;
...
@@ -580,9 +584,10 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
return GMOCK_MOCKER_(9, constness, \
GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3, \
return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9); \
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
gmock_a9); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
...
@@ -617,9 +622,9 @@ using internal::FunctionMocker;
...
@@ -617,9 +622,9 @@ using internal::FunctionMocker;
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
return GMOCK_MOCKER_(10, constness,
\
GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this);
\
Method).RegisterOwner(this).With(gmock_a1, gmock_a2, gmock_a3
, \
return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2
, \
gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
gmock_a
3, gmock_a
4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
gmock_a10); \
gmock_a10); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
...
...
include/gmock/gmock-generated-function-mockers.h.pump
View file @
ed6c9277
...
@@ -140,7 +140,8 @@ $var matcher_as = [[$for j, \
...
@@ -140,7 +140,8 @@ $var matcher_as = [[$for j, \
} \
} \
::testing::MockSpec<F>& \
::testing::MockSpec<F>& \
gmock_##Method($matcher_as) constness { \
gmock_##Method($matcher_as) constness { \
return GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this).With($as); \
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_($i, constness, Method).With($as); \
} \
} \
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_($i, constness, Method)
mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_($i, constness, Method)
...
...
include/gmock/gmock-spec-builders.h
View file @
ed6c9277
...
@@ -113,53 +113,190 @@ template <typename F> class FunctionMockerBase;
...
@@ -113,53 +113,190 @@ template <typename F> class FunctionMockerBase;
// calls to ensure the integrity of the mock objects' states.
// calls to ensure the integrity of the mock objects' states.
GTEST_DECLARE_STATIC_MUTEX_
(
g_gmock_mutex
);
GTEST_DECLARE_STATIC_MUTEX_
(
g_gmock_mutex
);
// Untyped base class for ActionResultHolder<R>.
class
UntypedActionResultHolderBase
;
// Abstract base class of FunctionMockerBase. This is the
// Abstract base class of FunctionMockerBase. This is the
// type-agnostic part of the function mocker interface. Its pure
// type-agnostic part of the function mocker interface. Its pure
// virtual methods are implemented by FunctionMockerBase.
// virtual methods are implemented by FunctionMockerBase.
class
UntypedFunctionMockerBase
{
class
UntypedFunctionMockerBase
{
public
:
public
:
virtual
~
UntypedFunctionMockerBase
()
{}
UntypedFunctionMockerBase
();
virtual
~
UntypedFunctionMockerBase
();
// Verifies that all expectations on this mock function have been
// Verifies that all expectations on this mock function have been
// satisfied. Reports one or more Google Test non-fatal failures
// satisfied. Reports one or more Google Test non-fatal failures
// and returns false if not.
// and returns false if not.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
virtual
bool
VerifyAndClearExpectationsLocked
()
=
0
;
bool
VerifyAndClearExpectationsLocked
()
;
// Clears the ON_CALL()s set on this mock function.
// Clears the ON_CALL()s set on this mock function.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
virtual
void
ClearDefaultActionsLocked
()
=
0
;
virtual
void
ClearDefaultActionsLocked
()
=
0
;
// In all of the following Untyped* functions, it's the caller's
// responsibility to guarantee the correctness of the arguments'
// types.
// Performs the default action with the given arguments and returns
// the action's result. The call description string will be used in
// the error message to describe the call in the case the default
// action fails.
// L = *
virtual
UntypedActionResultHolderBase
*
UntypedPerformDefaultAction
(
const
void
*
untyped_args
,
const
string
&
call_description
)
const
=
0
;
// Performs the given action with the given arguments and returns
// the action's result.
// L = *
virtual
UntypedActionResultHolderBase
*
UntypedPerformAction
(
const
void
*
untyped_action
,
const
void
*
untyped_args
)
const
=
0
;
// Writes a message that the call is uninteresting (i.e. neither
// explicitly expected nor explicitly unexpected) to the given
// ostream.
// L < g_gmock_mutex
virtual
void
UntypedDescribeUninterestingCall
(
const
void
*
untyped_args
,
::
std
::
ostream
*
os
)
const
=
0
;
// Returns the expectation that matches the given function arguments
// (or NULL is there's no match); when a match is found,
// untyped_action is set to point to the action that should be
// performed (or NULL if the action is "do default"), and
// is_excessive is modified to indicate whether the call exceeds the
// expected number.
// L < g_gmock_mutex
virtual
const
ExpectationBase
*
UntypedFindMatchingExpectation
(
const
void
*
untyped_args
,
const
void
**
untyped_action
,
bool
*
is_excessive
,
::
std
::
ostream
*
what
,
::
std
::
ostream
*
why
)
=
0
;
// Prints the given function arguments to the ostream.
virtual
void
UntypedPrintArgs
(
const
void
*
untyped_args
,
::
std
::
ostream
*
os
)
const
=
0
;
// Sets the mock object this mock method belongs to, and registers
// this information in the global mock registry. Will be called
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
// method.
// TODO(wan@google.com): rename to SetAndRegisterOwner().
// L < g_gmock_mutex
void
RegisterOwner
(
const
void
*
mock_obj
);
// Sets the mock object this mock method belongs to, and sets the
// name of the mock function. Will be called upon each invocation
// of this mock function.
// L < g_gmock_mutex
void
SetOwnerAndName
(
const
void
*
mock_obj
,
const
char
*
name
);
// Returns the mock object this mock method belongs to. Must be
// called after RegisterOwner() or SetOwnerAndName() has been
// called.
// L < g_gmock_mutex
const
void
*
MockObject
()
const
;
// Returns the name of this mock method. Must be called after
// SetOwnerAndName() has been called.
// L < g_gmock_mutex
const
char
*
Name
()
const
;
// Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple
// threads concurrently. The caller is responsible for deleting the
// result.
// L < g_gmock_mutex
const
UntypedActionResultHolderBase
*
UntypedInvokeWith
(
const
void
*
untyped_args
);
protected
:
typedef
std
::
vector
<
const
void
*>
UntypedOnCallSpecs
;
typedef
std
::
vector
<
internal
::
linked_ptr
<
ExpectationBase
>
>
UntypedExpectations
;
// Returns an Expectation object that references and co-owns exp,
// which must be an expectation on this mock function.
Expectation
GetHandleOf
(
ExpectationBase
*
exp
);
// Address of the mock object this mock method belongs to. Only
// valid after this mock method has been called or
// ON_CALL/EXPECT_CALL has been invoked on it.
const
void
*
mock_obj_
;
// Protected by g_gmock_mutex.
// Name of the function being mocked. Only valid after this mock
// method has been called.
const
char
*
name_
;
// Protected by g_gmock_mutex.
// All default action specs for this function mocker.
UntypedOnCallSpecs
untyped_on_call_specs_
;
// All expectations for this function mocker.
UntypedExpectations
untyped_expectations_
;
};
// class UntypedFunctionMockerBase
};
// class UntypedFunctionMockerBase
// This template class implements a default action spec (i.e. an
// Untyped base class for OnCallSpec<F>.
// ON_CALL() statement).
class
UntypedOnCallSpecBase
{
public
:
// The arguments are the location of the ON_CALL() statement.
UntypedOnCallSpecBase
(
const
char
*
a_file
,
int
a_line
)
:
file_
(
a_file
),
line_
(
a_line
),
last_clause_
(
kNone
)
{}
// Where in the source file was the default action spec defined?
const
char
*
file
()
const
{
return
file_
;
}
int
line
()
const
{
return
line_
;
}
protected
:
// Gives each clause in the ON_CALL() statement a name.
enum
Clause
{
// Do not change the order of the enum members! The run-time
// syntax checking relies on it.
kNone
,
kWith
,
kWillByDefault
,
};
// Asserts that the ON_CALL() statement has a certain property.
void
AssertSpecProperty
(
bool
property
,
const
string
&
failure_message
)
const
{
Assert
(
property
,
file_
,
line_
,
failure_message
);
}
// Expects that the ON_CALL() statement has a certain property.
void
ExpectSpecProperty
(
bool
property
,
const
string
&
failure_message
)
const
{
Expect
(
property
,
file_
,
line_
,
failure_message
);
}
const
char
*
file_
;
int
line_
;
// The last clause in the ON_CALL() statement as seen so far.
// Initially kNone and changes as the statement is parsed.
Clause
last_clause_
;
};
// class UntypedOnCallSpecBase
// This template class implements an ON_CALL spec.
template
<
typename
F
>
template
<
typename
F
>
class
DefaultActionSpec
{
class
OnCallSpec
:
public
UntypedOnCallSpecBase
{
public
:
public
:
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
typedef
typename
Function
<
F
>::
ArgumentMatcherTuple
ArgumentMatcherTuple
;
typedef
typename
Function
<
F
>::
ArgumentMatcherTuple
ArgumentMatcherTuple
;
// Constructs a
DefaultAction
Spec object from the information inside
// Constructs a
n OnCall
Spec object from the information inside
// the parenthesis of an ON_CALL() statement.
// the parenthesis of an ON_CALL() statement.
DefaultActionSpec
(
const
char
*
a_file
,
int
a_line
,
OnCallSpec
(
const
char
*
a_file
,
int
a_line
,
const
ArgumentMatcherTuple
&
matchers
)
const
ArgumentMatcherTuple
&
matchers
)
:
file_
(
a_file
),
:
UntypedOnCallSpecBase
(
a_file
,
a_line
),
line_
(
a_line
),
matchers_
(
matchers
),
matchers_
(
matchers
),
// By default, extra_matcher_ should match anything. However,
// By default, extra_matcher_ should match anything. However,
// we cannot initialize it with _ as that triggers a compiler
// we cannot initialize it with _ as that triggers a compiler
// bug in Symbian's C++ compiler (cannot decide between two
// bug in Symbian's C++ compiler (cannot decide between two
// overloaded constructors of Matcher<const ArgumentTuple&>).
// overloaded constructors of Matcher<const ArgumentTuple&>).
extra_matcher_
(
A
<
const
ArgumentTuple
&>
()),
extra_matcher_
(
A
<
const
ArgumentTuple
&>
())
{
last_clause_
(
kNone
)
{
}
}
// Where in the source file was the default action spec defined?
const
char
*
file
()
const
{
return
file_
;
}
int
line
()
const
{
return
line_
;
}
// Implements the .With() clause.
// Implements the .With() clause.
DefaultAction
Spec
&
With
(
const
Matcher
<
const
ArgumentTuple
&>&
m
)
{
OnCall
Spec
&
With
(
const
Matcher
<
const
ArgumentTuple
&>&
m
)
{
// Makes sure this is called at most once.
// Makes sure this is called at most once.
ExpectSpecProperty
(
last_clause_
<
kWith
,
ExpectSpecProperty
(
last_clause_
<
kWith
,
".With() cannot appear "
".With() cannot appear "
...
@@ -171,7 +308,7 @@ class DefaultActionSpec {
...
@@ -171,7 +308,7 @@ class DefaultActionSpec {
}
}
// Implements the .WillByDefault() clause.
// Implements the .WillByDefault() clause.
DefaultAction
Spec
&
WillByDefault
(
const
Action
<
F
>&
action
)
{
OnCall
Spec
&
WillByDefault
(
const
Action
<
F
>&
action
)
{
ExpectSpecProperty
(
last_clause_
<
kWillByDefault
,
ExpectSpecProperty
(
last_clause_
<
kWillByDefault
,
".WillByDefault() must appear "
".WillByDefault() must appear "
"exactly once in an ON_CALL()."
);
"exactly once in an ON_CALL()."
);
...
@@ -197,25 +334,6 @@ class DefaultActionSpec {
...
@@ -197,25 +334,6 @@ class DefaultActionSpec {
}
}
private
:
private
:
// Gives each clause in the ON_CALL() statement a name.
enum
Clause
{
// Do not change the order of the enum members! The run-time
// syntax checking relies on it.
kNone
,
kWith
,
kWillByDefault
,
};
// Asserts that the ON_CALL() statement has a certain property.
void
AssertSpecProperty
(
bool
property
,
const
string
&
failure_message
)
const
{
Assert
(
property
,
file_
,
line_
,
failure_message
);
}
// Expects that the ON_CALL() statement has a certain property.
void
ExpectSpecProperty
(
bool
property
,
const
string
&
failure_message
)
const
{
Expect
(
property
,
file_
,
line_
,
failure_message
);
}
// The information in statement
// The information in statement
//
//
// ON_CALL(mock_object, Method(matchers))
// ON_CALL(mock_object, Method(matchers))
...
@@ -229,16 +347,10 @@ class DefaultActionSpec {
...
@@ -229,16 +347,10 @@ class DefaultActionSpec {
// matchers => matchers_
// matchers => matchers_
// multi-argument-matcher => extra_matcher_
// multi-argument-matcher => extra_matcher_
// action => action_
// action => action_
const
char
*
file_
;
int
line_
;
ArgumentMatcherTuple
matchers_
;
ArgumentMatcherTuple
matchers_
;
Matcher
<
const
ArgumentTuple
&>
extra_matcher_
;
Matcher
<
const
ArgumentTuple
&>
extra_matcher_
;
Action
<
F
>
action_
;
Action
<
F
>
action_
;
};
// class OnCallSpec
// The last clause in the ON_CALL() statement as seen so far.
// Initially kNone and changes as the statement is parsed.
Clause
last_clause_
;
};
// class DefaultActionSpec
// Possible reactions on uninteresting calls. TODO(wan@google.com):
// Possible reactions on uninteresting calls. TODO(wan@google.com):
// rename the enum values to the kFoo style.
// rename the enum values to the kFoo style.
...
@@ -269,6 +381,8 @@ class Mock {
...
@@ -269,6 +381,8 @@ class Mock {
// verification was successful.
// verification was successful.
static
bool
VerifyAndClear
(
void
*
mock_obj
);
static
bool
VerifyAndClear
(
void
*
mock_obj
);
private
:
private
:
friend
class
internal
::
UntypedFunctionMockerBase
;
// Needed for a function mocker to register itself (so that we know
// Needed for a function mocker to register itself (so that we know
// how to clear a mock object).
// how to clear a mock object).
template
<
typename
F
>
template
<
typename
F
>
...
@@ -389,6 +503,7 @@ class Expectation {
...
@@ -389,6 +503,7 @@ class Expectation {
friend
class
ExpectationSet
;
friend
class
ExpectationSet
;
friend
class
Sequence
;
friend
class
Sequence
;
friend
class
::
testing
::
internal
::
ExpectationBase
;
friend
class
::
testing
::
internal
::
ExpectationBase
;
friend
class
::
testing
::
internal
::
UntypedFunctionMockerBase
;
template
<
typename
F
>
template
<
typename
F
>
friend
class
::
testing
::
internal
::
FunctionMockerBase
;
friend
class
::
testing
::
internal
::
FunctionMockerBase
;
...
@@ -581,10 +696,15 @@ class ExpectationBase {
...
@@ -581,10 +696,15 @@ class ExpectationBase {
// Describes how many times a function call matching this
// Describes how many times a function call matching this
// expectation has occurred.
// expectation has occurred.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
virtual
void
DescribeCallCountTo
(
::
std
::
ostream
*
os
)
const
=
0
;
void
DescribeCallCountTo
(
::
std
::
ostream
*
os
)
const
;
// If this mock method has an extra matcher (i.e. .With(matcher)),
// describes it to the ostream.
virtual
void
MaybeDescribeExtraMatcherTo
(
::
std
::
ostream
*
os
)
=
0
;
protected
:
protected
:
friend
class
::
testing
::
Expectation
;
friend
class
::
testing
::
Expectation
;
friend
class
UntypedFunctionMockerBase
;
enum
Clause
{
enum
Clause
{
// Don't change the order of the enum members!
// Don't change the order of the enum members!
...
@@ -598,6 +718,8 @@ class ExpectationBase {
...
@@ -598,6 +718,8 @@ class ExpectationBase {
kRetiresOnSaturation
,
kRetiresOnSaturation
,
};
};
typedef
std
::
vector
<
const
void
*>
UntypedActions
;
// Returns an Expectation object that references and co-owns this
// Returns an Expectation object that references and co-owns this
// expectation.
// expectation.
virtual
Expectation
GetHandle
()
=
0
;
virtual
Expectation
GetHandle
()
=
0
;
...
@@ -690,13 +812,22 @@ class ExpectationBase {
...
@@ -690,13 +812,22 @@ class ExpectationBase {
call_count_
++
;
call_count_
++
;
}
}
private
:
// Checks the action count (i.e. the number of WillOnce() and
// WillRepeatedly() clauses) against the cardinality if this hasn't
// been done before. Prints a warning if there are too many or too
// few actions.
// L < mutex_
void
CheckActionCountIfNotDone
()
const
;
friend
class
::
testing
::
Sequence
;
friend
class
::
testing
::
Sequence
;
friend
class
::
testing
::
internal
::
ExpectationTester
;
friend
class
::
testing
::
internal
::
ExpectationTester
;
template
<
typename
Function
>
template
<
typename
Function
>
friend
class
TypedExpectation
;
friend
class
TypedExpectation
;
// Implements the .Times() clause.
void
UntypedTimes
(
const
Cardinality
&
a_cardinality
);
// This group of fields are part of the spec and won't change after
// This group of fields are part of the spec and won't change after
// an EXPECT_CALL() statement finishes.
// an EXPECT_CALL() statement finishes.
const
char
*
file_
;
// The file that contains the expectation.
const
char
*
file_
;
// The file that contains the expectation.
...
@@ -717,6 +848,13 @@ class ExpectationBase {
...
@@ -717,6 +848,13 @@ class ExpectationBase {
// and can change as the mock function is called.
// and can change as the mock function is called.
int
call_count_
;
// How many times this expectation has been invoked.
int
call_count_
;
// How many times this expectation has been invoked.
bool
retired_
;
// True iff this expectation has retired.
bool
retired_
;
// True iff this expectation has retired.
UntypedActions
untyped_actions_
;
bool
extra_matcher_specified_
;
bool
repeated_action_specified_
;
// True if a WillRepeatedly() was specified.
bool
retires_on_saturation_
;
Clause
last_clause_
;
mutable
bool
action_count_checked_
;
// Under mutex_.
mutable
Mutex
mutex_
;
// Protects action_count_checked_.
GTEST_DISALLOW_ASSIGN_
(
ExpectationBase
);
GTEST_DISALLOW_ASSIGN_
(
ExpectationBase
);
};
// class ExpectationBase
};
// class ExpectationBase
...
@@ -735,22 +873,21 @@ class TypedExpectation : public ExpectationBase {
...
@@ -735,22 +873,21 @@ class TypedExpectation : public ExpectationBase {
:
ExpectationBase
(
a_file
,
a_line
,
a_source_text
),
:
ExpectationBase
(
a_file
,
a_line
,
a_source_text
),
owner_
(
owner
),
owner_
(
owner
),
matchers_
(
m
),
matchers_
(
m
),
extra_matcher_specified_
(
false
),
// By default, extra_matcher_ should match anything. However,
// By default, extra_matcher_ should match anything. However,
// we cannot initialize it with _ as that triggers a compiler
// we cannot initialize it with _ as that triggers a compiler
// bug in Symbian's C++ compiler (cannot decide between two
// bug in Symbian's C++ compiler (cannot decide between two
// overloaded constructors of Matcher<const ArgumentTuple&>).
// overloaded constructors of Matcher<const ArgumentTuple&>).
extra_matcher_
(
A
<
const
ArgumentTuple
&>
()),
extra_matcher_
(
A
<
const
ArgumentTuple
&>
()),
repeated_action_specified_
(
false
),
repeated_action_
(
DoDefault
())
{}
repeated_action_
(
DoDefault
()),
retires_on_saturation_
(
false
),
last_clause_
(
kNone
),
action_count_checked_
(
false
)
{}
virtual
~
TypedExpectation
()
{
virtual
~
TypedExpectation
()
{
// Check the validity of the action count if it hasn't been done
// Check the validity of the action count if it hasn't been done
// yet (for example, if the expectation was never used).
// yet (for example, if the expectation was never used).
CheckActionCountIfNotDone
();
CheckActionCountIfNotDone
();
for
(
UntypedActions
::
const_iterator
it
=
untyped_actions_
.
begin
();
it
!=
untyped_actions_
.
end
();
++
it
)
{
delete
static_cast
<
const
Action
<
F
>*>
(
*
it
);
}
}
}
// Implements the .With() clause.
// Implements the .With() clause.
...
@@ -773,19 +910,7 @@ class TypedExpectation : public ExpectationBase {
...
@@ -773,19 +910,7 @@ class TypedExpectation : public ExpectationBase {
// Implements the .Times() clause.
// Implements the .Times() clause.
TypedExpectation
&
Times
(
const
Cardinality
&
a_cardinality
)
{
TypedExpectation
&
Times
(
const
Cardinality
&
a_cardinality
)
{
if
(
last_clause_
==
kTimes
)
{
ExpectationBase
::
UntypedTimes
(
a_cardinality
);
ExpectSpecProperty
(
false
,
".Times() cannot appear "
"more than once in an EXPECT_CALL()."
);
}
else
{
ExpectSpecProperty
(
last_clause_
<
kTimes
,
".Times() cannot appear after "
".InSequence(), .WillOnce(), .WillRepeatedly(), "
"or .RetiresOnSaturation()."
);
}
last_clause_
=
kTimes
;
ExpectationBase
::
SpecifyCardinality
(
a_cardinality
);
return
*
this
;
return
*
this
;
}
}
...
@@ -859,9 +984,9 @@ class TypedExpectation : public ExpectationBase {
...
@@ -859,9 +984,9 @@ class TypedExpectation : public ExpectationBase {
".WillRepeatedly() or .RetiresOnSaturation()."
);
".WillRepeatedly() or .RetiresOnSaturation()."
);
last_clause_
=
kWillOnce
;
last_clause_
=
kWillOnce
;
actions_
.
push_back
(
action
);
untyped_actions_
.
push_back
(
new
Action
<
F
>
(
action
)
);
if
(
!
cardinality_specified
())
{
if
(
!
cardinality_specified
())
{
set_cardinality
(
Exactly
(
static_cast
<
int
>
(
actions_
.
size
())));
set_cardinality
(
Exactly
(
static_cast
<
int
>
(
untyped_
actions_
.
size
())));
}
}
return
*
this
;
return
*
this
;
}
}
...
@@ -882,7 +1007,7 @@ class TypedExpectation : public ExpectationBase {
...
@@ -882,7 +1007,7 @@ class TypedExpectation : public ExpectationBase {
repeated_action_
=
action
;
repeated_action_
=
action
;
if
(
!
cardinality_specified
())
{
if
(
!
cardinality_specified
())
{
set_cardinality
(
AtLeast
(
static_cast
<
int
>
(
actions_
.
size
())));
set_cardinality
(
AtLeast
(
static_cast
<
int
>
(
untyped_
actions_
.
size
())));
}
}
// Now that no more action clauses can be specified, we check
// Now that no more action clauses can be specified, we check
...
@@ -916,38 +1041,12 @@ class TypedExpectation : public ExpectationBase {
...
@@ -916,38 +1041,12 @@ class TypedExpectation : public ExpectationBase {
return
extra_matcher_
;
return
extra_matcher_
;
}
}
// Returns the sequence of actions specified by the .WillOnce() clause.
const
std
::
vector
<
Action
<
F
>
>&
actions
()
const
{
return
actions_
;
}
// Returns the action specified by the .WillRepeatedly() clause.
// Returns the action specified by the .WillRepeatedly() clause.
const
Action
<
F
>&
repeated_action
()
const
{
return
repeated_action_
;
}
const
Action
<
F
>&
repeated_action
()
const
{
return
repeated_action_
;
}
// Returns true iff the .RetiresOnSaturation() clause was specified.
// If this mock method has an extra matcher (i.e. .With(matcher)),
bool
retires_on_saturation
()
const
{
return
retires_on_saturation_
;
}
// describes it to the ostream.
virtual
void
MaybeDescribeExtraMatcherTo
(
::
std
::
ostream
*
os
)
{
// Describes how many times a function call matching this
// expectation has occurred (implements
// ExpectationBase::DescribeCallCountTo()).
// L >= g_gmock_mutex
virtual
void
DescribeCallCountTo
(
::
std
::
ostream
*
os
)
const
{
g_gmock_mutex
.
AssertHeld
();
// Describes how many times the function is expected to be called.
*
os
<<
" Expected: to be "
;
cardinality
().
DescribeTo
(
os
);
*
os
<<
"
\n
Actual: "
;
Cardinality
::
DescribeActualCallCountTo
(
call_count
(),
os
);
// Describes the state of the expectation (e.g. is it satisfied?
// is it active?).
*
os
<<
" - "
<<
(
IsOverSaturated
()
?
"over-saturated"
:
IsSaturated
()
?
"saturated"
:
IsSatisfied
()
?
"satisfied"
:
"unsatisfied"
)
<<
" and "
<<
(
is_retired
()
?
"retired"
:
"active"
);
}
void
MaybeDescribeExtraMatcherTo
(
::
std
::
ostream
*
os
)
{
if
(
extra_matcher_specified_
)
{
if
(
extra_matcher_specified_
)
{
*
os
<<
" Expected args: "
;
*
os
<<
" Expected args: "
;
extra_matcher_
.
DescribeTo
(
os
);
extra_matcher_
.
DescribeTo
(
os
);
...
@@ -1044,7 +1143,7 @@ class TypedExpectation : public ExpectationBase {
...
@@ -1044,7 +1143,7 @@ class TypedExpectation : public ExpectationBase {
"call_count() is <= 0 when GetCurrentAction() is "
"call_count() is <= 0 when GetCurrentAction() is "
"called - this should never happen."
);
"called - this should never happen."
);
const
int
action_count
=
static_cast
<
int
>
(
actions
()
.
size
());
const
int
action_count
=
static_cast
<
int
>
(
untyped_actions_
.
size
());
if
(
action_count
>
0
&&
!
repeated_action_specified_
&&
if
(
action_count
>
0
&&
!
repeated_action_specified_
&&
count
>
action_count
)
{
count
>
action_count
)
{
// If there is at least one WillOnce() and no WillRepeatedly(),
// If there is at least one WillOnce() and no WillRepeatedly(),
...
@@ -1059,7 +1158,9 @@ class TypedExpectation : public ExpectationBase {
...
@@ -1059,7 +1158,9 @@ class TypedExpectation : public ExpectationBase {
Log
(
WARNING
,
ss
.
str
(),
1
);
Log
(
WARNING
,
ss
.
str
(),
1
);
}
}
return
count
<=
action_count
?
actions
()[
count
-
1
]
:
repeated_action
();
return
count
<=
action_count
?
*
static_cast
<
const
Action
<
F
>*>
(
untyped_actions_
[
count
-
1
])
:
repeated_action
();
}
}
// Given the arguments of a mock function call, if the call will
// Given the arguments of a mock function call, if the call will
...
@@ -1067,12 +1168,13 @@ class TypedExpectation : public ExpectationBase {
...
@@ -1067,12 +1168,13 @@ class TypedExpectation : public ExpectationBase {
// otherwise, returns the next action in this expectation. Also
// otherwise, returns the next action in this expectation. Also
// describes *what* happened to 'what', and explains *why* Google
// describes *what* happened to 'what', and explains *why* Google
// Mock does it to 'why'. This method is not const as it calls
// Mock does it to 'why'. This method is not const as it calls
// IncrementCallCount().
// IncrementCallCount(). A return value of NULL means the default
// action.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
Action
<
F
>
GetActionForArguments
(
const
FunctionMockerBase
<
F
>*
mocker
,
const
Action
<
F
>*
GetActionForArguments
(
const
FunctionMockerBase
<
F
>*
mocker
,
const
ArgumentTuple
&
args
,
const
ArgumentTuple
&
args
,
::
std
::
ostream
*
what
,
::
std
::
ostream
*
what
,
::
std
::
ostream
*
why
)
{
::
std
::
ostream
*
why
)
{
g_gmock_mutex
.
AssertHeld
();
g_gmock_mutex
.
AssertHeld
();
if
(
IsSaturated
())
{
if
(
IsSaturated
())
{
// We have an excessive call.
// We have an excessive call.
...
@@ -1081,92 +1183,30 @@ class TypedExpectation : public ExpectationBase {
...
@@ -1081,92 +1183,30 @@ class TypedExpectation : public ExpectationBase {
mocker
->
DescribeDefaultActionTo
(
args
,
what
);
mocker
->
DescribeDefaultActionTo
(
args
,
what
);
DescribeCallCountTo
(
why
);
DescribeCallCountTo
(
why
);
// TODO(wan
): allow the user to control whether unexpected calls
// TODO(wan
@google.com): allow the user to control whether
//
should fail immediately or continue using a flag
//
unexpected calls should fail immediately or continue using a
// --gmock_unexpected_calls_are_fatal.
//
flag
--gmock_unexpected_calls_are_fatal.
return
DoDefault
()
;
return
NULL
;
}
}
IncrementCallCount
();
IncrementCallCount
();
RetireAllPreRequisites
();
RetireAllPreRequisites
();
if
(
retires_on_saturation
()
&&
IsSaturated
())
{
if
(
retires_on_saturation
_
&&
IsSaturated
())
{
Retire
();
Retire
();
}
}
// Must be done after IncrementCount()!
// Must be done after IncrementCount()!
*
what
<<
"Mock function call matches "
<<
source_text
()
<<
"...
\n
"
;
*
what
<<
"Mock function call matches "
<<
source_text
()
<<
"...
\n
"
;
return
GetCurrentAction
(
mocker
,
args
);
return
&
(
GetCurrentAction
(
mocker
,
args
));
}
// Checks the action count (i.e. the number of WillOnce() and
// WillRepeatedly() clauses) against the cardinality if this hasn't
// been done before. Prints a warning if there are too many or too
// few actions.
// L < mutex_
void
CheckActionCountIfNotDone
()
const
{
bool
should_check
=
false
;
{
MutexLock
l
(
&
mutex_
);
if
(
!
action_count_checked_
)
{
action_count_checked_
=
true
;
should_check
=
true
;
}
}
if
(
should_check
)
{
if
(
!
cardinality_specified_
)
{
// The cardinality was inferred - no need to check the action
// count against it.
return
;
}
// The cardinality was explicitly specified.
const
int
action_count
=
static_cast
<
int
>
(
actions_
.
size
());
const
int
upper_bound
=
cardinality
().
ConservativeUpperBound
();
const
int
lower_bound
=
cardinality
().
ConservativeLowerBound
();
bool
too_many
;
// True if there are too many actions, or false
// if there are too few.
if
(
action_count
>
upper_bound
||
(
action_count
==
upper_bound
&&
repeated_action_specified_
))
{
too_many
=
true
;
}
else
if
(
0
<
action_count
&&
action_count
<
lower_bound
&&
!
repeated_action_specified_
)
{
too_many
=
false
;
}
else
{
return
;
}
::
std
::
stringstream
ss
;
DescribeLocationTo
(
&
ss
);
ss
<<
"Too "
<<
(
too_many
?
"many"
:
"few"
)
<<
" actions specified in "
<<
source_text
()
<<
"...
\n
"
<<
"Expected to be "
;
cardinality
().
DescribeTo
(
&
ss
);
ss
<<
", but has "
<<
(
too_many
?
""
:
"only "
)
<<
action_count
<<
" WillOnce()"
<<
(
action_count
==
1
?
""
:
"s"
);
if
(
repeated_action_specified_
)
{
ss
<<
" and a WillRepeatedly()"
;
}
ss
<<
"."
;
Log
(
WARNING
,
ss
.
str
(),
-
1
);
// -1 means "don't print stack trace".
}
}
}
// All the fields below won't change once the EXPECT_CALL()
// All the fields below won't change once the EXPECT_CALL()
// statement finishes.
// statement finishes.
FunctionMockerBase
<
F
>*
const
owner_
;
FunctionMockerBase
<
F
>*
const
owner_
;
ArgumentMatcherTuple
matchers_
;
ArgumentMatcherTuple
matchers_
;
bool
extra_matcher_specified_
;
Matcher
<
const
ArgumentTuple
&>
extra_matcher_
;
Matcher
<
const
ArgumentTuple
&>
extra_matcher_
;
std
::
vector
<
Action
<
F
>
>
actions_
;
bool
repeated_action_specified_
;
// True if a WillRepeatedly() was specified.
Action
<
F
>
repeated_action_
;
Action
<
F
>
repeated_action_
;
bool
retires_on_saturation_
;
Clause
last_clause_
;
mutable
bool
action_count_checked_
;
// Under mutex_.
mutable
Mutex
mutex_
;
// Protects action_count_checked_.
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
TypedExpectation
);
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
TypedExpectation
);
};
// class TypedExpectation
};
// class TypedExpectation
...
@@ -1181,6 +1221,11 @@ class TypedExpectation : public ExpectationBase {
...
@@ -1181,6 +1221,11 @@ class TypedExpectation : public ExpectationBase {
// template. To workaround this compiler bug, we define MockSpec in
// template. To workaround this compiler bug, we define MockSpec in
// ::testing::internal and import it into ::testing.
// ::testing::internal and import it into ::testing.
// Logs a message including file and line number information.
void
LogWithLocation
(
testing
::
internal
::
LogSeverity
severity
,
const
char
*
file
,
int
line
,
const
string
&
message
);
template
<
typename
F
>
template
<
typename
F
>
class
MockSpec
{
class
MockSpec
{
public
:
public
:
...
@@ -1195,11 +1240,11 @@ class MockSpec {
...
@@ -1195,11 +1240,11 @@ class MockSpec {
// Adds a new default action spec to the function mocker and returns
// Adds a new default action spec to the function mocker and returns
// the newly created spec.
// the newly created spec.
internal
::
DefaultAction
Spec
<
F
>&
InternalDefaultActionSetAt
(
internal
::
OnCall
Spec
<
F
>&
InternalDefaultActionSetAt
(
const
char
*
file
,
int
line
,
const
char
*
obj
,
const
char
*
call
)
{
const
char
*
file
,
int
line
,
const
char
*
obj
,
const
char
*
call
)
{
LogWithLocation
(
internal
::
INFO
,
file
,
line
,
LogWithLocation
(
internal
::
INFO
,
file
,
line
,
string
(
"ON_CALL("
)
+
obj
+
", "
+
call
+
") invoked"
);
string
(
"ON_CALL("
)
+
obj
+
", "
+
call
+
") invoked"
);
return
function_mocker_
->
AddNew
DefaultAction
Spec
(
file
,
line
,
matchers_
);
return
function_mocker_
->
AddNew
OnCall
Spec
(
file
,
line
,
matchers_
);
}
}
// Adds a new expectation spec to the function mocker and returns
// Adds a new expectation spec to the function mocker and returns
...
@@ -1220,15 +1265,6 @@ class MockSpec {
...
@@ -1220,15 +1265,6 @@ class MockSpec {
matchers_
=
matchers
;
matchers_
=
matchers
;
}
}
// Logs a message including file and line number information.
void
LogWithLocation
(
testing
::
internal
::
LogSeverity
severity
,
const
char
*
file
,
int
line
,
const
string
&
message
)
{
::
std
::
ostringstream
s
;
s
<<
file
<<
":"
<<
line
<<
": "
<<
message
<<
::
std
::
endl
;
Log
(
severity
,
s
.
str
(),
0
);
}
// The function mocker that owns this spec.
// The function mocker that owns this spec.
internal
::
FunctionMockerBase
<
F
>*
const
function_mocker_
;
internal
::
FunctionMockerBase
<
F
>*
const
function_mocker_
;
// The argument matchers specified in the spec.
// The argument matchers specified in the spec.
...
@@ -1253,42 +1289,58 @@ class MockSpec {
...
@@ -1253,42 +1289,58 @@ class MockSpec {
// copyable type or void (T doesn't need to be default-constructable).
// copyable type or void (T doesn't need to be default-constructable).
// It hides the syntactic difference between void and other types, and
// It hides the syntactic difference between void and other types, and
// is used to unify the code for invoking both void-returning and
// is used to unify the code for invoking both void-returning and
// non-void-returning mock functions. This generic definition is used
// non-void-returning mock functions.
// when T is not void.
// Untyped base class for ActionResultHolder<T>.
class
UntypedActionResultHolderBase
{
public
:
virtual
~
UntypedActionResultHolderBase
()
{}
// Prints the held value as an action's result to os.
virtual
void
PrintAsActionResult
(
::
std
::
ostream
*
os
)
const
=
0
;
};
// This generic definition is used when T is not void.
template
<
typename
T
>
template
<
typename
T
>
class
ActionResultHolder
{
class
ActionResultHolder
:
public
UntypedActionResultHolderBase
{
public
:
public
:
explicit
ActionResultHolder
(
T
a_value
)
:
value_
(
a_value
)
{}
explicit
ActionResultHolder
(
T
a_value
)
:
value_
(
a_value
)
{}
// The compiler-generated copy constructor and assignment operator
// The compiler-generated copy constructor and assignment operator
// are exactly what we need, so we don't need to define them.
// are exactly what we need, so we don't need to define them.
T
value
()
const
{
return
value_
;
}
// Returns the held value and deletes this object.
T
GetValueAndDelete
()
const
{
T
retval
(
value_
);
delete
this
;
return
retval
;
}
// Prints the held value as an action's result to os.
// Prints the held value as an action's result to os.
void
PrintAsActionResult
(
::
std
::
ostream
*
os
)
const
{
v
irtual
v
oid
PrintAsActionResult
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"
\n
Returns: "
;
*
os
<<
"
\n
Returns: "
;
// T may be a reference type, so we don't use UniversalPrint().
// T may be a reference type, so we don't use UniversalPrint().
UniversalPrinter
<
T
>::
Print
(
value_
,
os
);
UniversalPrinter
<
T
>::
Print
(
value_
,
os
);
}
}
// Performs the given mock function's default action and returns the
// Performs the given mock function's default action and returns the
// result in a ActionResultHolder.
// result in a
new-ed
ActionResultHolder.
template
<
typename
F
unction
,
typename
Arguments
>
template
<
typename
F
>
static
ActionResultHolder
PerformDefaultAction
(
static
ActionResultHolder
*
PerformDefaultAction
(
const
FunctionMockerBase
<
F
unction
>*
func_mocker
,
const
FunctionMockerBase
<
F
>*
func_mocker
,
const
Arguments
&
args
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
,
const
string
&
call_description
)
{
const
string
&
call_description
)
{
return
ActionResultHolder
(
return
new
ActionResultHolder
(
func_mocker
->
PerformDefaultAction
(
args
,
call_description
));
func_mocker
->
PerformDefaultAction
(
args
,
call_description
));
}
}
// Performs the given action and returns the result in a
// Performs the given action and returns the result in a
new-ed
// ActionResultHolder.
// ActionResultHolder.
template
<
typename
Function
,
typename
Arguments
>
template
<
typename
F
>
static
ActionResultHolder
PerformAction
(
const
Action
<
Function
>&
action
,
static
ActionResultHolder
*
const
Arguments
&
args
)
{
PerformAction
(
const
Action
<
F
>&
action
,
return
ActionResultHolder
(
action
.
Perform
(
args
));
const
typename
Function
<
F
>::
ArgumentTuple
&
args
)
{
return
new
ActionResultHolder
(
action
.
Perform
(
args
));
}
}
private
:
private
:
...
@@ -1300,26 +1352,29 @@ class ActionResultHolder {
...
@@ -1300,26 +1352,29 @@ class ActionResultHolder {
// Specialization for T = void.
// Specialization for T = void.
template
<>
template
<>
class
ActionResultHolder
<
void
>
{
class
ActionResultHolder
<
void
>
:
public
UntypedActionResultHolderBase
{
public
:
public
:
ActionResultHolder
()
{}
void
GetValueAndDelete
()
const
{
delete
this
;
}
void
value
()
const
{}
void
PrintAsActionResult
(
::
std
::
ostream
*
/* os */
)
const
{}
virtual
void
PrintAsActionResult
(
::
std
::
ostream
*
/* os */
)
const
{}
template
<
typename
Function
,
typename
Arguments
>
// Performs the given mock function's default action and returns NULL;
static
ActionResultHolder
PerformDefaultAction
(
template
<
typename
F
>
const
FunctionMockerBase
<
Function
>*
func_mocker
,
static
ActionResultHolder
*
PerformDefaultAction
(
const
Arguments
&
args
,
const
FunctionMockerBase
<
F
>*
func_mocker
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
,
const
string
&
call_description
)
{
const
string
&
call_description
)
{
func_mocker
->
PerformDefaultAction
(
args
,
call_description
);
func_mocker
->
PerformDefaultAction
(
args
,
call_description
);
return
ActionResultHolder
()
;
return
NULL
;
}
}
template
<
typename
Function
,
typename
Arguments
>
// Performs the given action and returns NULL.
static
ActionResultHolder
PerformAction
(
const
Action
<
Function
>&
action
,
template
<
typename
F
>
const
Arguments
&
args
)
{
static
ActionResultHolder
*
PerformAction
(
const
Action
<
F
>&
action
,
const
typename
Function
<
F
>::
ArgumentTuple
&
args
)
{
action
.
Perform
(
args
);
action
.
Perform
(
args
);
return
ActionResultHolder
()
;
return
NULL
;
}
}
};
};
...
@@ -1333,7 +1388,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1333,7 +1388,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
typedef
typename
Function
<
F
>::
ArgumentMatcherTuple
ArgumentMatcherTuple
;
typedef
typename
Function
<
F
>::
ArgumentMatcherTuple
ArgumentMatcherTuple
;
FunctionMockerBase
()
:
mock_obj_
(
NULL
),
name_
(
""
),
current_spec_
(
this
)
{}
FunctionMockerBase
()
:
current_spec_
(
this
)
{}
// The destructor verifies that all expectations on this mock
// The destructor verifies that all expectations on this mock
// function have been satisfied. If not, it will report Google Test
// function have been satisfied. If not, it will report Google Test
...
@@ -1343,19 +1398,20 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1343,19 +1398,20 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
MutexLock
l
(
&
g_gmock_mutex
);
MutexLock
l
(
&
g_gmock_mutex
);
VerifyAndClearExpectationsLocked
();
VerifyAndClearExpectationsLocked
();
Mock
::
UnregisterLocked
(
this
);
Mock
::
UnregisterLocked
(
this
);
ClearDefaultActionsLocked
();
}
}
// Returns the ON_CALL spec that matches this mock function with the
// Returns the ON_CALL spec that matches this mock function with the
// given arguments; returns NULL if no matching ON_CALL is found.
// given arguments; returns NULL if no matching ON_CALL is found.
// L = *
// L = *
const
DefaultActionSpec
<
F
>*
FindDefaultAction
Spec
(
const
OnCallSpec
<
F
>*
FindOnCall
Spec
(
const
ArgumentTuple
&
args
)
const
{
const
ArgumentTuple
&
args
)
const
{
for
(
typename
std
::
vector
<
DefaultActionSpec
<
F
>
>
::
const_reverse_iterator
it
for
(
UntypedOnCallSpecs
::
const_reverse_iterator
it
=
default_action
s_
.
rbegin
();
=
untyped_on_call_spec
s_
.
rbegin
();
it
!=
default_action
s_
.
rend
();
++
it
)
{
it
!=
untyped_on_call_spec
s_
.
rend
();
++
it
)
{
const
DefaultActionSpec
<
F
>&
spec
=
*
it
;
const
OnCallSpec
<
F
>*
spec
=
static_cast
<
const
OnCallSpec
<
F
>*>
(
*
it
)
;
if
(
spec
.
Matches
(
args
))
if
(
spec
->
Matches
(
args
))
return
&
spec
;
return
spec
;
}
}
return
NULL
;
return
NULL
;
...
@@ -1368,7 +1424,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1368,7 +1424,8 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// L = *
// L = *
Result
PerformDefaultAction
(
const
ArgumentTuple
&
args
,
Result
PerformDefaultAction
(
const
ArgumentTuple
&
args
,
const
string
&
call_description
)
const
{
const
string
&
call_description
)
const
{
const
DefaultActionSpec
<
F
>*
const
spec
=
FindDefaultActionSpec
(
args
);
const
OnCallSpec
<
F
>*
const
spec
=
this
->
FindOnCallSpec
(
args
);
if
(
spec
!=
NULL
)
{
if
(
spec
!=
NULL
)
{
return
spec
->
GetAction
().
Perform
(
args
);
return
spec
->
GetAction
().
Perform
(
args
);
}
}
...
@@ -1378,91 +1435,70 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1378,91 +1435,70 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
return
DefaultValue
<
Result
>::
Get
();
return
DefaultValue
<
Result
>::
Get
();
}
}
//
Registers this function mocker and the mock object owning it;
//
Performs the default action with the given arguments and returns
//
returns a reference to the function mocker object. This is only
//
the action's result. The call description string will be used in
//
called by the ON_CALL() and EXPECT_CALL() macros.
//
the error message to describe the call in the case the default
//
L < g_gmock_mutex
//
action fails. The caller is responsible for deleting the result.
FunctionMocker
<
F
>&
RegisterOwner
(
const
void
*
mock_obj
)
{
// L = *
{
virtual
UntypedActionResultHolderBase
*
UntypedPerformDefaultAction
(
MutexLock
l
(
&
g_gmock_mutex
);
const
void
*
untyped_args
,
// must point to an ArgumentTuple
mock_obj_
=
mock_obj
;
const
string
&
call_description
)
const
{
}
const
ArgumentTuple
&
args
=
Mock
::
Register
(
mock_obj
,
thi
s
);
*
static_cast
<
const
ArgumentTuple
*>
(
untyped_arg
s
);
return
*::
testing
::
internal
::
DownCast_
<
FunctionMocker
<
F
>*>
(
this
);
return
ResultHolder
::
PerformDefaultAction
(
this
,
args
,
call_description
);
}
}
// The following two functions are from UntypedFunctionMockerBase.
// Performs the given action with the given arguments and returns
// the action's result. The caller is responsible for deleting the
// Verifies that all expectations on this mock function have been
// result.
// satisfied. Reports one or more Google Test non-fatal failures
// L = *
// and returns false if not.
virtual
UntypedActionResultHolderBase
*
UntypedPerformAction
(
// L >= g_gmock_mutex
const
void
*
untyped_action
,
const
void
*
untyped_args
)
const
{
virtual
bool
VerifyAndClearExpectationsLocked
();
// Make a copy of the action before performing it, in case the
// action deletes the mock object (and thus deletes itself).
// Clears the ON_CALL()s set on this mock function.
const
Action
<
F
>
action
=
*
static_cast
<
const
Action
<
F
>*>
(
untyped_action
);
const
ArgumentTuple
&
args
=
*
static_cast
<
const
ArgumentTuple
*>
(
untyped_args
);
return
ResultHolder
::
PerformAction
(
action
,
args
);
}
// Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
// clears the ON_CALL()s set on this mock function.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
virtual
void
ClearDefaultActionsLocked
()
{
virtual
void
ClearDefaultActionsLocked
()
{
g_gmock_mutex
.
AssertHeld
();
g_gmock_mutex
.
AssertHeld
();
default_actions_
.
clear
();
for
(
UntypedOnCallSpecs
::
const_iterator
it
=
}
untyped_on_call_specs_
.
begin
();
it
!=
untyped_on_call_specs_
.
end
();
++
it
)
{
// Sets the name of the function being mocked. Will be called upon
delete
static_cast
<
const
OnCallSpec
<
F
>*>
(
*
it
);
// each invocation of this mock function.
// L < g_gmock_mutex
void
SetOwnerAndName
(
const
void
*
mock_obj
,
const
char
*
name
)
{
// We protect name_ under g_gmock_mutex in case this mock function
// is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
mock_obj_
=
mock_obj
;
name_
=
name
;
}
// Returns the address of the mock object this method belongs to.
// Must be called after SetOwnerAndName() has been called.
// L < g_gmock_mutex
const
void
*
MockObject
()
const
{
const
void
*
mock_obj
;
{
// We protect mock_obj_ under g_gmock_mutex in case this mock
// function is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
mock_obj
=
mock_obj_
;
}
}
return
mock_obj
;
untyped_on_call_specs_
.
clear
();
}
// Returns the name of the function being mocked. Must be called
// after SetOwnerAndName() has been called.
// L < g_gmock_mutex
const
char
*
Name
()
const
{
const
char
*
name
;
{
// We protect name_ under g_gmock_mutex in case this mock
// function is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
name
=
name_
;
}
return
name
;
}
}
protected
:
protected
:
template
<
typename
Function
>
template
<
typename
Function
>
friend
class
MockSpec
;
friend
class
MockSpec
;
typedef
ActionResultHolder
<
Result
>
ResultHolder
;
// Returns the result of invoking this mock function with the given
// Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple
// arguments. This function can be safely called from multiple
// threads concurrently.
// threads concurrently.
// L < g_gmock_mutex
// L < g_gmock_mutex
Result
InvokeWith
(
const
ArgumentTuple
&
args
);
Result
InvokeWith
(
const
ArgumentTuple
&
args
)
{
return
static_cast
<
const
ResultHolder
*>
(
this
->
UntypedInvokeWith
(
&
args
))
->
GetValueAndDelete
();
}
// Adds and returns a default action spec for this mock function.
// Adds and returns a default action spec for this mock function.
// L < g_gmock_mutex
// L < g_gmock_mutex
DefaultActionSpec
<
F
>&
AddNewDefaultAction
Spec
(
OnCallSpec
<
F
>&
AddNewOnCall
Spec
(
const
char
*
file
,
int
line
,
const
char
*
file
,
int
line
,
const
ArgumentMatcherTuple
&
m
)
{
const
ArgumentMatcherTuple
&
m
)
{
Mock
::
RegisterUseByOnCallOrExpectCall
(
MockObject
(),
file
,
line
);
Mock
::
RegisterUseByOnCallOrExpectCall
(
MockObject
(),
file
,
line
);
default_actions_
.
push_back
(
DefaultActionSpec
<
F
>
(
file
,
line
,
m
));
OnCallSpec
<
F
>*
const
on_call_spec
=
new
OnCallSpec
<
F
>
(
file
,
line
,
m
);
return
default_actions_
.
back
();
untyped_on_call_specs_
.
push_back
(
on_call_spec
);
return
*
on_call_spec
;
}
}
// Adds and returns an expectation spec for this mock function.
// Adds and returns an expectation spec for this mock function.
...
@@ -1473,14 +1509,15 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1473,14 +1509,15 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
const
string
&
source_text
,
const
string
&
source_text
,
const
ArgumentMatcherTuple
&
m
)
{
const
ArgumentMatcherTuple
&
m
)
{
Mock
::
RegisterUseByOnCallOrExpectCall
(
MockObject
(),
file
,
line
);
Mock
::
RegisterUseByOnCallOrExpectCall
(
MockObject
(),
file
,
line
);
const
linked_ptr
<
TypedExpectation
<
F
>
>
expectation
(
TypedExpectation
<
F
>*
const
expectation
=
new
TypedExpectation
<
F
>
(
this
,
file
,
line
,
source_text
,
m
));
new
TypedExpectation
<
F
>
(
this
,
file
,
line
,
source_text
,
m
);
expectations_
.
push_back
(
expectation
);
const
linked_ptr
<
ExpectationBase
>
untyped_expectation
(
expectation
);
untyped_expectations_
.
push_back
(
untyped_expectation
);
// Adds this expectation into the implicit sequence if there is one.
// Adds this expectation into the implicit sequence if there is one.
Sequence
*
const
implicit_sequence
=
g_gmock_implicit_sequence
.
get
();
Sequence
*
const
implicit_sequence
=
g_gmock_implicit_sequence
.
get
();
if
(
implicit_sequence
!=
NULL
)
{
if
(
implicit_sequence
!=
NULL
)
{
implicit_sequence
->
AddExpectation
(
Expectation
(
expectation
));
implicit_sequence
->
AddExpectation
(
Expectation
(
untyped_
expectation
));
}
}
return
*
expectation
;
return
*
expectation
;
...
@@ -1493,33 +1530,14 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1493,33 +1530,14 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
private
:
private
:
template
<
typename
Func
>
friend
class
TypedExpectation
;
template
<
typename
Func
>
friend
class
TypedExpectation
;
typedef
std
::
vector
<
internal
::
linked_ptr
<
TypedExpectation
<
F
>
>
>
// Some utilities needed for implementing UntypedInvokeWith().
TypedExpectations
;
// Returns an Expectation object that references and co-owns exp,
// which must be an expectation on this mock function.
Expectation
GetHandleOf
(
TypedExpectation
<
F
>*
exp
)
{
for
(
typename
TypedExpectations
::
const_iterator
it
=
expectations_
.
begin
();
it
!=
expectations_
.
end
();
++
it
)
{
if
(
it
->
get
()
==
exp
)
{
return
Expectation
(
*
it
);
}
}
Assert
(
false
,
__FILE__
,
__LINE__
,
"Cannot find expectation."
);
return
Expectation
();
// The above statement is just to make the code compile, and will
// never be executed.
}
// Some utilities needed for implementing InvokeWith().
// Describes what default action will be performed for the given
// Describes what default action will be performed for the given
// arguments.
// arguments.
// L = *
// L = *
void
DescribeDefaultActionTo
(
const
ArgumentTuple
&
args
,
void
DescribeDefaultActionTo
(
const
ArgumentTuple
&
args
,
::
std
::
ostream
*
os
)
const
{
::
std
::
ostream
*
os
)
const
{
const
DefaultActionSpec
<
F
>*
const
spec
=
FindDefaultAction
Spec
(
args
);
const
OnCallSpec
<
F
>*
const
spec
=
FindOnCall
Spec
(
args
);
if
(
spec
==
NULL
)
{
if
(
spec
==
NULL
)
{
*
os
<<
(
internal
::
type_equals
<
Result
,
void
>::
value
?
*
os
<<
(
internal
::
type_equals
<
Result
,
void
>::
value
?
...
@@ -1535,14 +1553,23 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1535,14 +1553,23 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// explicitly expected nor explicitly unexpected) to the given
// explicitly expected nor explicitly unexpected) to the given
// ostream.
// ostream.
// L < g_gmock_mutex
// L < g_gmock_mutex
void
DescribeUninterestingCall
(
const
ArgumentTuple
&
args
,
virtual
void
UntypedDescribeUninterestingCall
(
const
void
*
untyped_args
,
::
std
::
ostream
*
os
)
const
{
::
std
::
ostream
*
os
)
const
{
const
ArgumentTuple
&
args
=
*
static_cast
<
const
ArgumentTuple
*>
(
untyped_args
);
*
os
<<
"Uninteresting mock function call - "
;
*
os
<<
"Uninteresting mock function call - "
;
DescribeDefaultActionTo
(
args
,
os
);
DescribeDefaultActionTo
(
args
,
os
);
*
os
<<
" Function call: "
<<
Name
();
*
os
<<
" Function call: "
<<
Name
();
UniversalPrint
(
args
,
os
);
UniversalPrint
(
args
,
os
);
}
}
// Returns the expectation that matches the given function arguments
// (or NULL is there's no match); when a match is found,
// untyped_action is set to point to the action that should be
// performed (or NULL if the action is "do default"), and
// is_excessive is modified to indicate whether the call exceeds the
// expected number.
//
// Critical section: We must find the matching expectation and the
// Critical section: We must find the matching expectation and the
// corresponding action that needs to be taken in an ATOMIC
// corresponding action that needs to be taken in an ATOMIC
// transaction. Otherwise another thread may call this mock
// transaction. Otherwise another thread may call this mock
...
@@ -1553,23 +1580,36 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1553,23 +1580,36 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// action does (it can invoke an arbitrary user function or even a
// action does (it can invoke an arbitrary user function or even a
// mock function) and excessive locking could cause a dead lock.
// mock function) and excessive locking could cause a dead lock.
// L < g_gmock_mutex
// L < g_gmock_mutex
bool
FindMatchingExpectationAndAction
(
virtual
const
ExpectationBase
*
UntypedFindMatchingExpectation
(
const
ArgumentTuple
&
args
,
TypedExpectation
<
F
>**
exp
,
Action
<
F
>*
action
,
const
void
*
untyped_args
,
bool
*
is_excessive
,
::
std
::
ostream
*
what
,
::
std
::
ostream
*
why
)
{
const
void
**
untyped_action
,
bool
*
is_excessive
,
::
std
::
ostream
*
what
,
::
std
::
ostream
*
why
)
{
const
ArgumentTuple
&
args
=
*
static_cast
<
const
ArgumentTuple
*>
(
untyped_args
);
MutexLock
l
(
&
g_gmock_mutex
);
MutexLock
l
(
&
g_gmock_mutex
);
*
exp
=
this
->
FindMatchingExpectationLocked
(
args
);
TypedExpectation
<
F
>*
exp
=
this
->
FindMatchingExpectationLocked
(
args
);
if
(
*
exp
==
NULL
)
{
// A match wasn't found.
if
(
exp
==
NULL
)
{
// A match wasn't found.
*
action
=
DoDefault
();
this
->
FormatUnexpectedCallMessageLocked
(
args
,
what
,
why
);
this
->
FormatUnexpectedCallMessageLocked
(
args
,
what
,
why
);
return
false
;
return
NULL
;
}
}
// This line must be done before calling GetActionForArguments(),
// This line must be done before calling GetActionForArguments(),
// which will increment the call count for *exp and thus affect
// which will increment the call count for *exp and thus affect
// its saturation status.
// its saturation status.
*
is_excessive
=
(
*
exp
)
->
IsSaturated
();
*
is_excessive
=
exp
->
IsSaturated
();
*
action
=
(
*
exp
)
->
GetActionForArguments
(
this
,
args
,
what
,
why
);
const
Action
<
F
>*
action
=
exp
->
GetActionForArguments
(
this
,
args
,
what
,
why
);
return
true
;
if
(
action
!=
NULL
&&
action
->
IsDoDefault
())
action
=
NULL
;
// Normalize "do default" to NULL.
*
untyped_action
=
action
;
return
exp
;
}
// Prints the given function arguments to the ostream.
virtual
void
UntypedPrintArgs
(
const
void
*
untyped_args
,
::
std
::
ostream
*
os
)
const
{
const
ArgumentTuple
&
args
=
*
static_cast
<
const
ArgumentTuple
*>
(
untyped_args
);
UniversalPrint
(
args
,
os
);
}
}
// Returns the expectation that matches the arguments, or NULL if no
// Returns the expectation that matches the arguments, or NULL if no
...
@@ -1578,10 +1618,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1578,10 +1618,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
TypedExpectation
<
F
>*
FindMatchingExpectationLocked
(
TypedExpectation
<
F
>*
FindMatchingExpectationLocked
(
const
ArgumentTuple
&
args
)
const
{
const
ArgumentTuple
&
args
)
const
{
g_gmock_mutex
.
AssertHeld
();
g_gmock_mutex
.
AssertHeld
();
for
(
typename
TypedExpectations
::
const_reverse_iterator
it
=
for
(
typename
UntypedExpectations
::
const_reverse_iterator
it
=
expectations_
.
rbegin
();
untyped_expectations_
.
rbegin
();
it
!=
expectations_
.
rend
();
++
it
)
{
it
!=
untyped_expectations_
.
rend
();
++
it
)
{
TypedExpectation
<
F
>*
const
exp
=
it
->
get
();
TypedExpectation
<
F
>*
const
exp
=
static_cast
<
TypedExpectation
<
F
>*>
(
it
->
get
());
if
(
exp
->
ShouldHandleArguments
(
args
))
{
if
(
exp
->
ShouldHandleArguments
(
args
))
{
return
exp
;
return
exp
;
}
}
...
@@ -1606,41 +1647,29 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1606,41 +1647,29 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
void
PrintTriedExpectationsLocked
(
const
ArgumentTuple
&
args
,
void
PrintTriedExpectationsLocked
(
const
ArgumentTuple
&
args
,
::
std
::
ostream
*
why
)
const
{
::
std
::
ostream
*
why
)
const
{
g_gmock_mutex
.
AssertHeld
();
g_gmock_mutex
.
AssertHeld
();
const
int
count
=
static_cast
<
int
>
(
expectations_
.
size
());
const
int
count
=
static_cast
<
int
>
(
untyped_
expectations_
.
size
());
*
why
<<
"Google Mock tried the following "
<<
count
<<
" "
*
why
<<
"Google Mock tried the following "
<<
count
<<
" "
<<
(
count
==
1
?
"expectation, but it didn't match"
:
<<
(
count
==
1
?
"expectation, but it didn't match"
:
"expectations, but none matched"
)
"expectations, but none matched"
)
<<
":
\n
"
;
<<
":
\n
"
;
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
TypedExpectation
<
F
>*
const
expectation
=
static_cast
<
TypedExpectation
<
F
>*>
(
untyped_expectations_
[
i
].
get
());
*
why
<<
"
\n
"
;
*
why
<<
"
\n
"
;
expectation
s_
[
i
]
->
DescribeLocationTo
(
why
);
expectation
->
DescribeLocationTo
(
why
);
if
(
count
>
1
)
{
if
(
count
>
1
)
{
*
why
<<
"tried expectation #"
<<
i
<<
": "
;
*
why
<<
"tried expectation #"
<<
i
<<
": "
;
}
}
*
why
<<
expectation
s_
[
i
]
->
source_text
()
<<
"...
\n
"
;
*
why
<<
expectation
->
source_text
()
<<
"...
\n
"
;
expectation
s_
[
i
]
->
ExplainMatchResultTo
(
args
,
why
);
expectation
->
ExplainMatchResultTo
(
args
,
why
);
expectation
s_
[
i
]
->
DescribeCallCountTo
(
why
);
expectation
->
DescribeCallCountTo
(
why
);
}
}
}
}
// Address of the mock object this mock method belongs to. Only
// valid after this mock method has been called or
// ON_CALL/EXPECT_CALL has been invoked on it.
const
void
*
mock_obj_
;
// Protected by g_gmock_mutex.
// Name of the function being mocked. Only valid after this mock
// method has been called.
const
char
*
name_
;
// Protected by g_gmock_mutex.
// The current spec (either default action spec or expectation spec)
// The current spec (either default action spec or expectation spec)
// being described on this function mocker.
// being described on this function mocker.
MockSpec
<
F
>
current_spec_
;
MockSpec
<
F
>
current_spec_
;
// All default action specs for this function mocker.
std
::
vector
<
DefaultActionSpec
<
F
>
>
default_actions_
;
// All expectations for this function mocker.
TypedExpectations
expectations_
;
// There is no generally useful and implementable semantics of
// There is no generally useful and implementable semantics of
// copying a mock object, so copying a mock is usually a user error.
// copying a mock object, so copying a mock is usually a user error.
// Thus we disallow copying function mockers. If the user really
// Thus we disallow copying function mockers. If the user really
...
@@ -1666,144 +1695,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
...
@@ -1666,144 +1695,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// satisfied. Reports one or more Google Test non-fatal failures and
// satisfied. Reports one or more Google Test non-fatal failures and
// returns false if not.
// returns false if not.
// L >= g_gmock_mutex
// L >= g_gmock_mutex
template
<
typename
F
>
bool
FunctionMockerBase
<
F
>::
VerifyAndClearExpectationsLocked
()
{
g_gmock_mutex
.
AssertHeld
();
bool
expectations_met
=
true
;
for
(
typename
TypedExpectations
::
const_iterator
it
=
expectations_
.
begin
();
it
!=
expectations_
.
end
();
++
it
)
{
TypedExpectation
<
F
>*
const
exp
=
it
->
get
();
if
(
exp
->
IsOverSaturated
())
{
// There was an upper-bound violation. Since the error was
// already reported when it occurred, there is no need to do
// anything here.
expectations_met
=
false
;
}
else
if
(
!
exp
->
IsSatisfied
())
{
expectations_met
=
false
;
::
std
::
stringstream
ss
;
ss
<<
"Actual function call count doesn't match "
<<
exp
->
source_text
()
<<
"...
\n
"
;
// No need to show the source file location of the expectation
// in the description, as the Expect() call that follows already
// takes care of it.
exp
->
MaybeDescribeExtraMatcherTo
(
&
ss
);
exp
->
DescribeCallCountTo
(
&
ss
);
Expect
(
false
,
exp
->
file
(),
exp
->
line
(),
ss
.
str
());
}
}
expectations_
.
clear
();
return
expectations_met
;
}
// Reports an uninteresting call (whose description is in msg) in the
// Reports an uninteresting call (whose description is in msg) in the
// manner specified by 'reaction'.
// manner specified by 'reaction'.
void
ReportUninterestingCall
(
CallReaction
reaction
,
const
string
&
msg
);
void
ReportUninterestingCall
(
CallReaction
reaction
,
const
string
&
msg
);
// Calculates the result of invoking this mock function with the given
// arguments, prints it, and returns it.
// L < g_gmock_mutex
template
<
typename
F
>
typename
Function
<
F
>::
Result
FunctionMockerBase
<
F
>::
InvokeWith
(
const
typename
Function
<
F
>::
ArgumentTuple
&
args
)
{
typedef
ActionResultHolder
<
Result
>
ResultHolder
;
if
(
expectations_
.
size
()
==
0
)
{
// No expectation is set on this mock method - we have an
// uninteresting call.
// We must get Google Mock's reaction on uninteresting calls
// made on this mock object BEFORE performing the action,
// because the action may DELETE the mock object and make the
// following expression meaningless.
const
CallReaction
reaction
=
Mock
::
GetReactionOnUninterestingCalls
(
MockObject
());
// True iff we need to print this call's arguments and return
// value. This definition must be kept in sync with
// the behavior of ReportUninterestingCall().
const
bool
need_to_report_uninteresting_call
=
// If the user allows this uninteresting call, we print it
// only when he wants informational messages.
reaction
==
ALLOW
?
LogIsVisible
(
INFO
)
:
// If the user wants this to be a warning, we print it only
// when he wants to see warnings.
reaction
==
WARN
?
LogIsVisible
(
WARNING
)
:
// Otherwise, the user wants this to be an error, and we
// should always print detailed information in the error.
true
;
if
(
!
need_to_report_uninteresting_call
)
{
// Perform the action without printing the call information.
return
PerformDefaultAction
(
args
,
""
);
}
// Warns about the uninteresting call.
::
std
::
stringstream
ss
;
DescribeUninterestingCall
(
args
,
&
ss
);
// Calculates the function result.
const
ResultHolder
result
=
ResultHolder
::
PerformDefaultAction
(
this
,
args
,
ss
.
str
());
// Prints the function result.
result
.
PrintAsActionResult
(
&
ss
);
ReportUninterestingCall
(
reaction
,
ss
.
str
());
return
result
.
value
();
}
bool
is_excessive
=
false
;
::
std
::
stringstream
ss
;
::
std
::
stringstream
why
;
::
std
::
stringstream
loc
;
Action
<
F
>
action
;
TypedExpectation
<
F
>*
exp
;
// The FindMatchingExpectationAndAction() function acquires and
// releases g_gmock_mutex.
const
bool
found
=
FindMatchingExpectationAndAction
(
args
,
&
exp
,
&
action
,
&
is_excessive
,
&
ss
,
&
why
);
// True iff we need to print the call's arguments and return value.
// This definition must be kept in sync with the uses of Expect()
// and Log() in this function.
const
bool
need_to_report_call
=
!
found
||
is_excessive
||
LogIsVisible
(
INFO
);
if
(
!
need_to_report_call
)
{
// Perform the action without printing the call information.
return
action
.
IsDoDefault
()
?
PerformDefaultAction
(
args
,
""
)
:
action
.
Perform
(
args
);
}
ss
<<
" Function call: "
<<
Name
();
UniversalPrint
(
args
,
&
ss
);
// In case the action deletes a piece of the expectation, we
// generate the message beforehand.
if
(
found
&&
!
is_excessive
)
{
exp
->
DescribeLocationTo
(
&
loc
);
}
const
ResultHolder
result
=
action
.
IsDoDefault
()
?
ResultHolder
::
PerformDefaultAction
(
this
,
args
,
ss
.
str
())
:
ResultHolder
::
PerformAction
(
action
,
args
);
result
.
PrintAsActionResult
(
&
ss
);
ss
<<
"
\n
"
<<
why
.
str
();
if
(
!
found
)
{
// No expectation matches this call - reports a failure.
Expect
(
false
,
NULL
,
-
1
,
ss
.
str
());
}
else
if
(
is_excessive
)
{
// We had an upper-bound violation and the failure message is in ss.
Expect
(
false
,
exp
->
file
(),
exp
->
line
(),
ss
.
str
());
}
else
{
// We had an expected call and the matching expectation is
// described in ss.
Log
(
INFO
,
loc
.
str
()
+
ss
.
str
(),
2
);
}
return
result
.
value
();
}
}
// namespace internal
}
// namespace internal
// The style guide prohibits "using" statements in a namespace scope
// The style guide prohibits "using" statements in a namespace scope
...
...
scripts/gmock_doctor.py
View file @
ed6c9277
...
@@ -261,8 +261,8 @@ def _IncompleteByReferenceArgumentDiagnoser(msg):
...
@@ -261,8 +261,8 @@ def _IncompleteByReferenceArgumentDiagnoser(msg):
r'(.*\n)*?'
+
r'(.*\n)*?'
+
_CLANG_NON_GMOCK_FILE_LINE_RE
+
_CLANG_NON_GMOCK_FILE_LINE_RE
+
r'note: in instantiation of member function '
r'note: in instantiation of member function '
r'\'testing::internal
::FunctionMocker<.*>::Invoke\'
'
r'\'testing::internal
2::TypeWithoutFormatter<.*>::
'
r'requested here'
)
r'
PrintValue\'
requested here'
)
diagnosis
=
"""
diagnosis
=
"""
In order to mock this function, Google Mock needs to see the definition
In order to mock this function, Google Mock needs to see the definition
of type "
%(type)
s" - declaration alone is not enough. Either #include
of type "
%(type)
s" - declaration alone is not enough. Either #include
...
...
src/gmock-spec-builders.cc
View file @
ed6c9277
...
@@ -55,6 +55,15 @@ namespace internal {
...
@@ -55,6 +55,15 @@ namespace internal {
// mockers, and all expectations.
// mockers, and all expectations.
GTEST_DEFINE_STATIC_MUTEX_
(
g_gmock_mutex
);
GTEST_DEFINE_STATIC_MUTEX_
(
g_gmock_mutex
);
// Logs a message including file and line number information.
void
LogWithLocation
(
testing
::
internal
::
LogSeverity
severity
,
const
char
*
file
,
int
line
,
const
string
&
message
)
{
::
std
::
ostringstream
s
;
s
<<
file
<<
":"
<<
line
<<
": "
<<
message
<<
::
std
::
endl
;
Log
(
severity
,
s
.
str
(),
0
);
}
// Constructs an ExpectationBase object.
// Constructs an ExpectationBase object.
ExpectationBase
::
ExpectationBase
(
const
char
*
a_file
,
ExpectationBase
::
ExpectationBase
(
const
char
*
a_file
,
int
a_line
,
int
a_line
,
...
@@ -65,8 +74,12 @@ ExpectationBase::ExpectationBase(const char* a_file,
...
@@ -65,8 +74,12 @@ ExpectationBase::ExpectationBase(const char* a_file,
cardinality_specified_
(
false
),
cardinality_specified_
(
false
),
cardinality_
(
Exactly
(
1
)),
cardinality_
(
Exactly
(
1
)),
call_count_
(
0
),
call_count_
(
0
),
retired_
(
false
)
{
retired_
(
false
),
}
extra_matcher_specified_
(
false
),
repeated_action_specified_
(
false
),
retires_on_saturation_
(
false
),
last_clause_
(
kNone
),
action_count_checked_
(
false
)
{}
// Destructs an ExpectationBase object.
// Destructs an ExpectationBase object.
ExpectationBase
::~
ExpectationBase
()
{}
ExpectationBase
::~
ExpectationBase
()
{}
...
@@ -132,6 +145,99 @@ void ExpectationBase::FindUnsatisfiedPrerequisites(
...
@@ -132,6 +145,99 @@ void ExpectationBase::FindUnsatisfiedPrerequisites(
}
}
}
}
// Describes how many times a function call matching this
// expectation has occurred.
// L >= g_gmock_mutex
void
ExpectationBase
::
DescribeCallCountTo
(
::
std
::
ostream
*
os
)
const
{
g_gmock_mutex
.
AssertHeld
();
// Describes how many times the function is expected to be called.
*
os
<<
" Expected: to be "
;
cardinality
().
DescribeTo
(
os
);
*
os
<<
"
\n
Actual: "
;
Cardinality
::
DescribeActualCallCountTo
(
call_count
(),
os
);
// Describes the state of the expectation (e.g. is it satisfied?
// is it active?).
*
os
<<
" - "
<<
(
IsOverSaturated
()
?
"over-saturated"
:
IsSaturated
()
?
"saturated"
:
IsSatisfied
()
?
"satisfied"
:
"unsatisfied"
)
<<
" and "
<<
(
is_retired
()
?
"retired"
:
"active"
);
}
// Checks the action count (i.e. the number of WillOnce() and
// WillRepeatedly() clauses) against the cardinality if this hasn't
// been done before. Prints a warning if there are too many or too
// few actions.
// L < mutex_
void
ExpectationBase
::
CheckActionCountIfNotDone
()
const
{
bool
should_check
=
false
;
{
MutexLock
l
(
&
mutex_
);
if
(
!
action_count_checked_
)
{
action_count_checked_
=
true
;
should_check
=
true
;
}
}
if
(
should_check
)
{
if
(
!
cardinality_specified_
)
{
// The cardinality was inferred - no need to check the action
// count against it.
return
;
}
// The cardinality was explicitly specified.
const
int
action_count
=
static_cast
<
int
>
(
untyped_actions_
.
size
());
const
int
upper_bound
=
cardinality
().
ConservativeUpperBound
();
const
int
lower_bound
=
cardinality
().
ConservativeLowerBound
();
bool
too_many
;
// True if there are too many actions, or false
// if there are too few.
if
(
action_count
>
upper_bound
||
(
action_count
==
upper_bound
&&
repeated_action_specified_
))
{
too_many
=
true
;
}
else
if
(
0
<
action_count
&&
action_count
<
lower_bound
&&
!
repeated_action_specified_
)
{
too_many
=
false
;
}
else
{
return
;
}
::
std
::
stringstream
ss
;
DescribeLocationTo
(
&
ss
);
ss
<<
"Too "
<<
(
too_many
?
"many"
:
"few"
)
<<
" actions specified in "
<<
source_text
()
<<
"...
\n
"
<<
"Expected to be "
;
cardinality
().
DescribeTo
(
&
ss
);
ss
<<
", but has "
<<
(
too_many
?
""
:
"only "
)
<<
action_count
<<
" WillOnce()"
<<
(
action_count
==
1
?
""
:
"s"
);
if
(
repeated_action_specified_
)
{
ss
<<
" and a WillRepeatedly()"
;
}
ss
<<
"."
;
Log
(
WARNING
,
ss
.
str
(),
-
1
);
// -1 means "don't print stack trace".
}
}
// Implements the .Times() clause.
void
ExpectationBase
::
UntypedTimes
(
const
Cardinality
&
a_cardinality
)
{
if
(
last_clause_
==
kTimes
)
{
ExpectSpecProperty
(
false
,
".Times() cannot appear "
"more than once in an EXPECT_CALL()."
);
}
else
{
ExpectSpecProperty
(
last_clause_
<
kTimes
,
".Times() cannot appear after "
".InSequence(), .WillOnce(), .WillRepeatedly(), "
"or .RetiresOnSaturation()."
);
}
last_clause_
=
kTimes
;
SpecifyCardinality
(
a_cardinality
);
}
// Points to the implicit sequence introduced by a living InSequence
// Points to the implicit sequence introduced by a living InSequence
// object (if any) in the current thread or NULL.
// object (if any) in the current thread or NULL.
ThreadLocal
<
Sequence
*>
g_gmock_implicit_sequence
;
ThreadLocal
<
Sequence
*>
g_gmock_implicit_sequence
;
...
@@ -151,6 +257,233 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) {
...
@@ -151,6 +257,233 @@ void ReportUninterestingCall(CallReaction reaction, const string& msg) {
}
}
}
}
UntypedFunctionMockerBase
::
UntypedFunctionMockerBase
()
:
mock_obj_
(
NULL
),
name_
(
""
)
{}
UntypedFunctionMockerBase
::~
UntypedFunctionMockerBase
()
{}
// Sets the mock object this mock method belongs to, and registers
// this information in the global mock registry. Will be called
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
// method.
// L < g_gmock_mutex
void
UntypedFunctionMockerBase
::
RegisterOwner
(
const
void
*
mock_obj
)
{
{
MutexLock
l
(
&
g_gmock_mutex
);
mock_obj_
=
mock_obj
;
}
Mock
::
Register
(
mock_obj
,
this
);
}
// Sets the mock object this mock method belongs to, and sets the name
// of the mock function. Will be called upon each invocation of this
// mock function.
// L < g_gmock_mutex
void
UntypedFunctionMockerBase
::
SetOwnerAndName
(
const
void
*
mock_obj
,
const
char
*
name
)
{
// We protect name_ under g_gmock_mutex in case this mock function
// is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
mock_obj_
=
mock_obj
;
name_
=
name
;
}
// Returns the name of the function being mocked. Must be called
// after RegisterOwner() or SetOwnerAndName() has been called.
// L < g_gmock_mutex
const
void
*
UntypedFunctionMockerBase
::
MockObject
()
const
{
const
void
*
mock_obj
;
{
// We protect mock_obj_ under g_gmock_mutex in case this mock
// function is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
Assert
(
mock_obj_
!=
NULL
,
__FILE__
,
__LINE__
,
"MockObject() must not be called before RegisterOwner() or "
"SetOwnerAndName() has been called."
);
mock_obj
=
mock_obj_
;
}
return
mock_obj
;
}
// Returns the name of this mock method. Must be called after
// SetOwnerAndName() has been called.
// L < g_gmock_mutex
const
char
*
UntypedFunctionMockerBase
::
Name
()
const
{
const
char
*
name
;
{
// We protect name_ under g_gmock_mutex in case this mock
// function is called from two threads concurrently.
MutexLock
l
(
&
g_gmock_mutex
);
Assert
(
name_
!=
NULL
,
__FILE__
,
__LINE__
,
"Name() must not be called before SetOwnerAndName() has "
"been called."
);
name
=
name_
;
}
return
name
;
}
// 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.
// L < g_gmock_mutex
const
UntypedActionResultHolderBase
*
UntypedFunctionMockerBase
::
UntypedInvokeWith
(
const
void
*
const
untyped_args
)
{
if
(
untyped_expectations_
.
size
()
==
0
)
{
// No expectation is set on this mock method - we have an
// uninteresting call.
// We must get Google Mock's reaction on uninteresting calls
// made on this mock object BEFORE performing the action,
// because the action may DELETE the mock object and make the
// following expression meaningless.
const
CallReaction
reaction
=
Mock
::
GetReactionOnUninterestingCalls
(
MockObject
());
// True iff we need to print this call's arguments and return
// value. This definition must be kept in sync with
// the behavior of ReportUninterestingCall().
const
bool
need_to_report_uninteresting_call
=
// If the user allows this uninteresting call, we print it
// only when he wants informational messages.
reaction
==
ALLOW
?
LogIsVisible
(
INFO
)
:
// If the user wants this to be a warning, we print it only
// when he wants to see warnings.
reaction
==
WARN
?
LogIsVisible
(
WARNING
)
:
// Otherwise, the user wants this to be an error, and we
// should always print detailed information in the error.
true
;
if
(
!
need_to_report_uninteresting_call
)
{
// Perform the action without printing the call information.
return
this
->
UntypedPerformDefaultAction
(
untyped_args
,
""
);
}
// Warns about the uninteresting call.
::
std
::
stringstream
ss
;
this
->
UntypedDescribeUninterestingCall
(
untyped_args
,
&
ss
);
// Calculates the function result.
const
UntypedActionResultHolderBase
*
const
result
=
this
->
UntypedPerformDefaultAction
(
untyped_args
,
ss
.
str
());
// Prints the function result.
if
(
result
!=
NULL
)
result
->
PrintAsActionResult
(
&
ss
);
ReportUninterestingCall
(
reaction
,
ss
.
str
());
return
result
;
}
bool
is_excessive
=
false
;
::
std
::
stringstream
ss
;
::
std
::
stringstream
why
;
::
std
::
stringstream
loc
;
const
void
*
untyped_action
=
NULL
;
// The UntypedFindMatchingExpectation() function acquires and
// releases g_gmock_mutex.
const
ExpectationBase
*
const
untyped_expectation
=
this
->
UntypedFindMatchingExpectation
(
untyped_args
,
&
untyped_action
,
&
is_excessive
,
&
ss
,
&
why
);
const
bool
found
=
untyped_expectation
!=
NULL
;
// True iff we need to print the call's arguments and return value.
// This definition must be kept in sync with the uses of Expect()
// and Log() in this function.
const
bool
need_to_report_call
=
!
found
||
is_excessive
||
LogIsVisible
(
INFO
);
if
(
!
need_to_report_call
)
{
// Perform the action without printing the call information.
return
untyped_action
==
NULL
?
this
->
UntypedPerformDefaultAction
(
untyped_args
,
""
)
:
this
->
UntypedPerformAction
(
untyped_action
,
untyped_args
);
}
ss
<<
" Function call: "
<<
Name
();
this
->
UntypedPrintArgs
(
untyped_args
,
&
ss
);
// In case the action deletes a piece of the expectation, we
// generate the message beforehand.
if
(
found
&&
!
is_excessive
)
{
untyped_expectation
->
DescribeLocationTo
(
&
loc
);
}
const
UntypedActionResultHolderBase
*
const
result
=
untyped_action
==
NULL
?
this
->
UntypedPerformDefaultAction
(
untyped_args
,
ss
.
str
())
:
this
->
UntypedPerformAction
(
untyped_action
,
untyped_args
);
if
(
result
!=
NULL
)
result
->
PrintAsActionResult
(
&
ss
);
ss
<<
"
\n
"
<<
why
.
str
();
if
(
!
found
)
{
// No expectation matches this call - reports a failure.
Expect
(
false
,
NULL
,
-
1
,
ss
.
str
());
}
else
if
(
is_excessive
)
{
// We had an upper-bound violation and the failure message is in ss.
Expect
(
false
,
untyped_expectation
->
file
(),
untyped_expectation
->
line
(),
ss
.
str
());
}
else
{
// We had an expected call and the matching expectation is
// described in ss.
Log
(
INFO
,
loc
.
str
()
+
ss
.
str
(),
2
);
}
return
result
;
}
// Returns an Expectation object that references and co-owns exp,
// which must be an expectation on this mock function.
Expectation
UntypedFunctionMockerBase
::
GetHandleOf
(
ExpectationBase
*
exp
)
{
for
(
UntypedExpectations
::
const_iterator
it
=
untyped_expectations_
.
begin
();
it
!=
untyped_expectations_
.
end
();
++
it
)
{
if
(
it
->
get
()
==
exp
)
{
return
Expectation
(
*
it
);
}
}
Assert
(
false
,
__FILE__
,
__LINE__
,
"Cannot find expectation."
);
return
Expectation
();
// The above statement is just to make the code compile, and will
// never be executed.
}
// Verifies that all expectations on this mock function have been
// satisfied. Reports one or more Google Test non-fatal failures
// and returns false if not.
// L >= g_gmock_mutex
bool
UntypedFunctionMockerBase
::
VerifyAndClearExpectationsLocked
()
{
g_gmock_mutex
.
AssertHeld
();
bool
expectations_met
=
true
;
for
(
UntypedExpectations
::
const_iterator
it
=
untyped_expectations_
.
begin
();
it
!=
untyped_expectations_
.
end
();
++
it
)
{
ExpectationBase
*
const
untyped_expectation
=
it
->
get
();
if
(
untyped_expectation
->
IsOverSaturated
())
{
// There was an upper-bound violation. Since the error was
// already reported when it occurred, there is no need to do
// anything here.
expectations_met
=
false
;
}
else
if
(
!
untyped_expectation
->
IsSatisfied
())
{
expectations_met
=
false
;
::
std
::
stringstream
ss
;
ss
<<
"Actual function call count doesn't match "
<<
untyped_expectation
->
source_text
()
<<
"...
\n
"
;
// No need to show the source file location of the expectation
// in the description, as the Expect() call that follows already
// takes care of it.
untyped_expectation
->
MaybeDescribeExtraMatcherTo
(
&
ss
);
untyped_expectation
->
DescribeCallCountTo
(
&
ss
);
Expect
(
false
,
untyped_expectation
->
file
(),
untyped_expectation
->
line
(),
ss
.
str
());
}
}
untyped_expectations_
.
clear
();
return
expectations_met
;
}
}
// namespace internal
}
// namespace internal
// Class Mock.
// Class Mock.
...
@@ -190,7 +523,6 @@ class MockObjectRegistry {
...
@@ -190,7 +523,6 @@ class MockObjectRegistry {
// object alive. Therefore we report any living object as test
// object alive. Therefore we report any living object as test
// failure, unless the user explicitly asked us to ignore it.
// failure, unless the user explicitly asked us to ignore it.
~
MockObjectRegistry
()
{
~
MockObjectRegistry
()
{
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
// a macro.
// a macro.
...
...
test/gmock-actions_test.cc
View file @
ed6c9277
...
@@ -334,8 +334,7 @@ class MyActionImpl : public ActionInterface<MyFunction> {
...
@@ -334,8 +334,7 @@ class MyActionImpl : public ActionInterface<MyFunction> {
TEST
(
ActionInterfaceTest
,
CanBeImplementedByDefiningPerform
)
{
TEST
(
ActionInterfaceTest
,
CanBeImplementedByDefiningPerform
)
{
MyActionImpl
my_action_impl
;
MyActionImpl
my_action_impl
;
(
void
)
my_action_impl
;
EXPECT_FALSE
(
my_action_impl
.
IsDoDefault
());
}
}
TEST
(
ActionInterfaceTest
,
MakeAction
)
{
TEST
(
ActionInterfaceTest
,
MakeAction
)
{
...
...
test/gmock-spec-builders_test.cc
View file @
ed6c9277
...
@@ -103,6 +103,34 @@ using testing::internal::CaptureStdout;
...
@@ -103,6 +103,34 @@ using testing::internal::CaptureStdout;
using
testing
::
internal
::
GetCapturedStdout
;
using
testing
::
internal
::
GetCapturedStdout
;
#endif
#endif
class
Incomplete
;
class
MockIncomplete
{
public
:
// This line verifies that a mock method can take a by-reference
// argument of an incomplete type.
MOCK_METHOD1
(
ByRefFunc
,
void
(
const
Incomplete
&
x
));
};
// Tells Google Mock how to print a value of type Incomplete.
void
PrintTo
(
const
Incomplete
&
x
,
::
std
::
ostream
*
os
);
TEST
(
MockMethodTest
,
CanInstantiateWithIncompleteArgType
)
{
// Even though this mock class contains a mock method that takes
// by-reference an argument whose type is incomplete, we can still
// use the mock, as long as Google Mock knows how to print the
// argument.
MockIncomplete
incomplete
;
EXPECT_CALL
(
incomplete
,
ByRefFunc
(
_
))
.
Times
(
AnyNumber
());
}
// The definition of the printer for the argument type doesn't have to
// be visible where the mock is used.
void
PrintTo
(
const
Incomplete
&
/* x */
,
::
std
::
ostream
*
os
)
{
*
os
<<
"incomplete"
;
}
class
Result
{};
class
Result
{};
class
MockA
{
class
MockA
{
...
@@ -1327,12 +1355,33 @@ TEST(SequenceTest, Retirement) {
...
@@ -1327,12 +1355,33 @@ TEST(SequenceTest, Retirement) {
TEST
(
ExpectationTest
,
ConstrutorsWork
)
{
TEST
(
ExpectationTest
,
ConstrutorsWork
)
{
MockA
a
;
MockA
a
;
Expectation
e1
;
// Default ctor.
Expectation
e1
;
// Default ctor.
Expectation
e2
=
EXPECT_CALL
(
a
,
DoA
(
1
));
// Ctor from EXPECT_CALL.
Expectation
e3
=
e2
;
// Copy ctor.
// Ctor from various forms of EXPECT_CALL.
Expectation
e2
=
EXPECT_CALL
(
a
,
DoA
(
2
));
Expectation
e3
=
EXPECT_CALL
(
a
,
DoA
(
3
)).
With
(
_
);
{
Sequence
s
;
Expectation
e4
=
EXPECT_CALL
(
a
,
DoA
(
4
)).
Times
(
1
);
Expectation
e5
=
EXPECT_CALL
(
a
,
DoA
(
5
)).
InSequence
(
s
);
}
Expectation
e6
=
EXPECT_CALL
(
a
,
DoA
(
6
)).
After
(
e2
);
Expectation
e7
=
EXPECT_CALL
(
a
,
DoA
(
7
)).
WillOnce
(
Return
());
Expectation
e8
=
EXPECT_CALL
(
a
,
DoA
(
8
)).
WillRepeatedly
(
Return
());
Expectation
e9
=
EXPECT_CALL
(
a
,
DoA
(
9
)).
RetiresOnSaturation
();
Expectation
e10
=
e2
;
// Copy ctor.
EXPECT_THAT
(
e1
,
Ne
(
e2
));
EXPECT_THAT
(
e1
,
Ne
(
e2
));
EXPECT_THAT
(
e2
,
Eq
(
e3
));
EXPECT_THAT
(
e2
,
Eq
(
e10
));
a
.
DoA
(
1
);
a
.
DoA
(
2
);
a
.
DoA
(
3
);
a
.
DoA
(
4
);
a
.
DoA
(
5
);
a
.
DoA
(
6
);
a
.
DoA
(
7
);
a
.
DoA
(
8
);
a
.
DoA
(
9
);
}
}
TEST
(
ExpectationTest
,
AssignmentWorks
)
{
TEST
(
ExpectationTest
,
AssignmentWorks
)
{
...
...
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