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
9413f2ff
Commit
9413f2ff
authored
May 29, 2009
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Avoids unnecessary printing of call into to internal buffers;
Made the universal value printer safer when printing char[]; Removed duplicated code in InvokeWith; Improved gmock_doctor.py.
parent
16cf4739
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
396 additions
and
281 deletions
+396
-281
gmock-printers.h
include/gmock/gmock-printers.h
+37
-30
gmock-spec-builders.h
include/gmock/gmock-spec-builders.h
+172
-176
gmock-internal-utils.h
include/gmock/internal/gmock-internal-utils.h
+4
-0
gmock_doctor.py
scripts/gmock_doctor.py
+63
-30
gmock-internal-utils.cc
src/gmock-internal-utils.cc
+17
-10
gmock-printers.cc
src/gmock-printers.cc
+5
-0
gmock-spec-builders.cc
src/gmock-spec-builders.cc
+2
-2
gmock-internal-utils_test.cc
test/gmock-internal-utils_test.cc
+28
-0
gmock-printers_test.cc
test/gmock-printers_test.cc
+21
-33
gmock-spec-builders_test.cc
test/gmock-spec-builders_test.cc
+47
-0
No files found.
include/gmock/gmock-printers.h
View file @
9413f2ff
...
...
@@ -580,6 +580,41 @@ class UniversalPrinter {
#endif // _MSC_VER
};
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template
<
typename
T
>
void
UniversalPrintArray
(
const
T
*
begin
,
size_t
len
,
::
std
::
ostream
*
os
)
{
if
(
len
==
0
)
{
*
os
<<
"{}"
;
}
else
{
*
os
<<
"{ "
;
const
size_t
kThreshold
=
18
;
const
size_t
kChunkSize
=
8
;
// If the array has more than kThreshold elements, we'll have to
// omit some details by printing only the first and the last
// kChunkSize elements.
// TODO(wan@google.com): let the user control the threshold using a flag.
if
(
len
<=
kThreshold
)
{
PrintRawArrayTo
(
begin
,
len
,
os
);
}
else
{
PrintRawArrayTo
(
begin
,
kChunkSize
,
os
);
*
os
<<
", ..., "
;
PrintRawArrayTo
(
begin
+
len
-
kChunkSize
,
kChunkSize
,
os
);
}
*
os
<<
" }"
;
}
}
// This overload prints a (const) char array compactly.
void
UniversalPrintArray
(
const
char
*
begin
,
size_t
len
,
::
std
::
ostream
*
os
);
// Prints an array of 'len' elements, starting at address 'begin', to a string.
template
<
typename
T
>
string
UniversalPrintArrayToString
(
const
T
*
begin
,
size_t
len
)
{
::
std
::
stringstream
ss
;
UniversalPrintArray
(
begin
,
len
,
&
ss
);
return
ss
.
str
();
}
// Implements printing an array type T[N].
template
<
typename
T
,
size_t
N
>
class
UniversalPrinter
<
T
[
N
]
>
{
...
...
@@ -587,41 +622,13 @@ class UniversalPrinter<T[N]> {
// Prints the given array, omitting some elements when there are too
// many.
static
void
Print
(
const
T
(
&
a
)[
N
],
::
std
::
ostream
*
os
)
{
// Prints a char array as a C string. Note that we compare 'const
// T' with 'const char' instead of comparing T with char, in case
// that T is already a const type.
if
(
internal
::
type_equals
<
const
T
,
const
char
>::
value
)
{
UniversalPrinter
<
const
T
*>::
Print
(
a
,
os
);
return
;
}
if
(
N
==
0
)
{
*
os
<<
"{}"
;
}
else
{
*
os
<<
"{ "
;
const
size_t
kThreshold
=
18
;
const
size_t
kChunkSize
=
8
;
// If the array has more than kThreshold elements, we'll have to
// omit some details by printing only the first and the last
// kChunkSize elements.
// TODO(wan): let the user control the threshold using a flag.
if
(
N
<=
kThreshold
)
{
PrintRawArrayTo
(
a
,
N
,
os
);
}
else
{
PrintRawArrayTo
(
a
,
kChunkSize
,
os
);
*
os
<<
", ..., "
;
PrintRawArrayTo
(
a
+
N
-
kChunkSize
,
kChunkSize
,
os
);
}
*
os
<<
" }"
;
}
UniversalPrintArray
(
a
,
N
,
os
);
}
// A convenient wrapper for Print() that returns the print-out as a
// string.
static
string
PrintToString
(
const
T
(
&
a
)[
N
])
{
::
std
::
stringstream
ss
;
Print
(
a
,
&
ss
);
return
ss
.
str
();
return
UniversalPrintArrayToString
(
a
,
N
);
}
};
...
...
include/gmock/gmock-spec-builders.h
View file @
9413f2ff
...
...
@@ -93,10 +93,6 @@ class ExpectationTester;
template
<
typename
F
>
class
FunctionMockerBase
;
// Helper class for implementing FunctionMockerBase<F>::InvokeWith().
template
<
typename
Result
,
typename
F
>
class
InvokeWithHelper
;
// Protects the mock object registry (in class Mock), all function
// mockers, and all expectations.
//
...
...
@@ -269,9 +265,6 @@ class Mock {
template
<
typename
F
>
friend
class
internal
::
FunctionMockerBase
;
template
<
typename
R
,
typename
Args
>
friend
class
internal
::
InvokeWithHelper
;
template
<
typename
M
>
friend
class
NiceMock
;
...
...
@@ -763,9 +756,6 @@ class Expectation : public ExpectationBase {
template
<
typename
Function
>
friend
class
FunctionMockerBase
;
template
<
typename
R
,
typename
Function
>
friend
class
InvokeWithHelper
;
// The following methods will be called only after the EXPECT_CALL()
// statement finishes and when the current thread holds
// g_gmock_mutex.
...
...
@@ -1042,6 +1032,78 @@ class MockSpec {
#pragma warning(disable:4355) // Temporarily disables warning 4355.
#endif // _MSV_VER
// C++ treats the void type specially. For example, you cannot define
// a void-typed variable or pass a void value to a function.
// ActionResultHolder<T> holds a value of type T, where T must be a
// copyable type or void (T doesn't need to be default-constructable).
// It hides the syntactic difference between void and other types, and
// is used to unify the code for invoking both void-returning and
// non-void-returning mock functions. This generic definition is used
// when T is not void.
template
<
typename
T
>
class
ActionResultHolder
{
public
:
explicit
ActionResultHolder
(
T
value
)
:
value_
(
value
)
{}
// The compiler-generated copy constructor and assignment operator
// are exactly what we need, so we don't need to define them.
T
value
()
const
{
return
value_
;
}
// Prints the held value as an action's result to os.
void
PrintAsActionResult
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"
\n
Returns: "
;
UniversalPrinter
<
T
>::
Print
(
value_
,
os
);
}
// Performs the given mock function's default action and returns the
// result in a ActionResultHolder.
template
<
typename
Function
,
typename
Arguments
>
static
ActionResultHolder
PerformDefaultAction
(
const
FunctionMockerBase
<
Function
>*
func_mocker
,
const
Arguments
&
args
,
const
string
&
call_description
)
{
return
ActionResultHolder
(
func_mocker
->
PerformDefaultAction
(
args
,
call_description
));
}
// Performs the given action and returns the result in a
// ActionResultHolder.
template
<
typename
Function
,
typename
Arguments
>
static
ActionResultHolder
PerformAction
(
const
Action
<
Function
>&
action
,
const
Arguments
&
args
)
{
return
ActionResultHolder
(
action
.
Perform
(
args
));
}
private
:
T
value_
;
};
// Specialization for T = void.
template
<>
class
ActionResultHolder
<
void
>
{
public
:
ActionResultHolder
()
{}
void
value
()
const
{}
void
PrintAsActionResult
(
::
std
::
ostream
*
/* os */
)
const
{}
template
<
typename
Function
,
typename
Arguments
>
static
ActionResultHolder
PerformDefaultAction
(
const
FunctionMockerBase
<
Function
>*
func_mocker
,
const
Arguments
&
args
,
const
string
&
call_description
)
{
func_mocker
->
PerformDefaultAction
(
args
,
call_description
);
return
ActionResultHolder
();
}
template
<
typename
Function
,
typename
Arguments
>
static
ActionResultHolder
PerformAction
(
const
Action
<
Function
>&
action
,
const
Arguments
&
args
)
{
action
.
Perform
(
args
);
return
ActionResultHolder
();
}
};
// The base of the function mocker class for the given function type.
// We put the methods in this class instead of its child to avoid code
// bloat.
...
...
@@ -1167,16 +1229,11 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
template
<
typename
Function
>
friend
class
MockSpec
;
template
<
typename
R
,
typename
Function
>
friend
class
InvokeWithHelper
;
// Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple
// threads concurrently.
// L < g_gmock_mutex
Result
InvokeWith
(
const
ArgumentTuple
&
args
)
{
return
InvokeWithHelper
<
Result
,
F
>::
InvokeAndPrintResult
(
this
,
args
);
}
Result
InvokeWith
(
const
ArgumentTuple
&
args
);
// Adds and returns a default action spec for this mock function.
// L < g_gmock_mutex
...
...
@@ -1417,170 +1474,109 @@ bool FunctionMockerBase<F>::VerifyAndClearExpectationsLocked() {
// manner specified by 'reaction'.
void
ReportUninterestingCall
(
CallReaction
reaction
,
const
string
&
msg
);
// When an uninteresting or unexpected mock function is called, we
// want to print its return value to assist the user debugging. Since
// there's nothing to print when the function returns void, we need to
// specialize the logic of FunctionMockerBase<F>::InvokeWith() for
// void return values.
//
// C++ doesn't allow us to specialize a member function template
// unless we also specialize its enclosing class, so we had to let
// InvokeWith() delegate its work to a helper class InvokeWithHelper,
// which can then be specialized.
//
// Note that InvokeWithHelper must be a class template (as opposed to
// a function template), as only class templates can be partially
// specialized.
template
<
typename
Result
,
typename
F
>
class
InvokeWithHelper
{
public
:
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
// Calculates the result of invoking the function mocked by mocker
// with the given arguments, prints it, and returns it.
// L < g_gmock_mutex
static
Result
InvokeAndPrintResult
(
FunctionMockerBase
<
F
>*
mocker
,
const
ArgumentTuple
&
args
)
{
if
(
mocker
->
expectations_
.
size
()
==
0
)
{
// No expectation is set on this mock method - we have an
// uninteresting call.
// Warns about the uninteresting call.
::
std
::
stringstream
ss
;
mocker
->
DescribeUninterestingCall
(
args
,
&
ss
);
// 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
(
mocker
->
MockObject
());
// Calculates the function result.
Result
result
=
mocker
->
PerformDefaultAction
(
args
,
ss
.
str
());
// Prints the function result.
ss
<<
"
\n
Returns: "
;
UniversalPrinter
<
Result
>::
Print
(
result
,
&
ss
);
ReportUninterestingCall
(
reaction
,
ss
.
str
());
return
result
;
}
bool
is_excessive
=
false
;
::
std
::
stringstream
ss
;
::
std
::
stringstream
why
;
::
std
::
stringstream
loc
;
Action
<
F
>
action
;
Expectation
<
F
>*
exp
;
// The FindMatchingExpectationAndAction() function acquires and
// releases g_gmock_mutex.
const
bool
found
=
mocker
->
FindMatchingExpectationAndAction
(
args
,
&
exp
,
&
action
,
&
is_excessive
,
&
ss
,
&
why
);
ss
<<
" Function call: "
<<
mocker
->
Name
();
UniversalPrinter
<
ArgumentTuple
>::
Print
(
args
,
&
ss
);
// In case the action deletes a piece of the expectation, we
// generate the message beforehand.
if
(
found
&&
!
is_excessive
)
{
exp
->
DescribeLocationTo
(
&
loc
);
}
Result
result
=
action
.
IsDoDefault
()
?
mocker
->
PerformDefaultAction
(
args
,
ss
.
str
())
:
action
.
Perform
(
args
);
ss
<<
"
\n
Returns: "
;
UniversalPrinter
<
Result
>::
Print
(
result
,
&
ss
);
ss
<<
"
\n
"
<<
why
.
str
();
if
(
found
)
{
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
(),
3
);
}
}
else
{
// No expectation matches this call - reports a failure.
Expect
(
false
,
NULL
,
-
1
,
ss
.
str
());
}
return
result
;
}
};
// class InvokeWithHelper
// This specialization helps to implement
// FunctionMockerBase<F>::InvokeWith() for void-returning functions.
// Calculates the result of invoking this mock function with the given
// arguments, prints it, and returns it.
// L < g_gmock_mutex
template
<
typename
F
>
class
InvokeWithHelper
<
void
,
F
>
{
public
:
typedef
typename
Function
<
F
>::
ArgumentTuple
ArgumentTuple
;
// Invokes the function mocked by mocker with the given arguments.
// L < g_gmock_mutex
static
void
InvokeAndPrintResult
(
FunctionMockerBase
<
F
>*
mocker
,
const
ArgumentTuple
&
args
)
{
const
int
count
=
static_cast
<
int
>
(
mocker
->
expectations_
.
size
());
if
(
count
==
0
)
{
// No expectation is set on this mock method - we have an
// uninteresting call.
::
std
::
stringstream
ss
;
mocker
->
DescribeUninterestingCall
(
args
,
&
ss
);
// 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
(
mocker
->
MockObject
());
mocker
->
PerformDefaultAction
(
args
,
ss
.
str
());
ReportUninterestingCall
(
reaction
,
ss
.
str
());
return
;
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
,
""
);
}
bool
is_excessive
=
false
;
// Warns about the uninteresting call.
::
std
::
stringstream
ss
;
::
std
::
stringstream
why
;
::
std
::
stringstream
loc
;
Action
<
F
>
action
;
Expectation
<
F
>*
exp
;
// The FindMatchingExpectationAndAction() function acquires and
// releases g_gmock_mutex.
const
bool
found
=
mocker
->
FindMatchingExpectationAndAction
(
args
,
&
exp
,
&
action
,
&
is_excessive
,
&
ss
,
&
why
);
ss
<<
" Function call: "
<<
mocker
->
Name
();
UniversalPrinter
<
ArgumentTuple
>::
Print
(
args
,
&
ss
);
ss
<<
"
\n
"
<<
why
.
str
();
// In case the action deletes a piece of the expectation, we
// generate the message beforehand.
if
(
found
&&
!
is_excessive
)
{
exp
->
DescribeLocationTo
(
&
loc
);
}
if
(
action
.
IsDoDefault
())
{
mocker
->
PerformDefaultAction
(
args
,
ss
.
str
());
}
else
{
action
.
Perform
(
args
);
}
if
(
found
)
{
// A matching expectation and corresponding action were found.
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
(),
3
);
}
}
else
{
// No matching expectation was found - reports an error.
Expect
(
false
,
NULL
,
-
1
,
ss
.
str
());
}
}
};
// class InvokeWithHelper<void, F>
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
;
Expectation
<
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
();
UniversalPrinter
<
ArgumentTuple
>::
Print
(
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
...
...
include/gmock/internal/gmock-internal-utils.h
View file @
9413f2ff
...
...
@@ -438,6 +438,10 @@ const char kWarningVerbosity[] = "warning";
// No logs are printed.
const
char
kErrorVerbosity
[]
=
"error"
;
// Returns true iff a log with the given severity is visible according
// to the --gmock_verbose flag.
bool
LogIsVisible
(
LogSeverity
severity
);
// Prints the given message to stdout iff 'severity' >= the level
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
// 0, also prints the stack trace excluding the top
...
...
scripts/gmock_doctor.py
View file @
9413f2ff
...
...
@@ -36,7 +36,7 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import
re
import
sys
_VERSION
=
'1.0.
0
'
_VERSION
=
'1.0.
1
'
_COMMON_GMOCK_SYMBOLS
=
[
# Matchers
...
...
@@ -46,8 +46,12 @@ _COMMON_GMOCK_SYMBOLS = [
'AllOf'
,
'An'
,
'AnyOf'
,
'ContainerEq'
,
'Contains'
,
'ContainsRegex'
,
'DoubleEq'
,
'ElementsAre'
,
'ElementsAreArray'
,
'EndsWith'
,
'Eq'
,
'Field'
,
...
...
@@ -60,6 +64,8 @@ _COMMON_GMOCK_SYMBOLS = [
'Lt'
,
'MatcherCast'
,
'MatchesRegex'
,
'NanSensitiveDoubleEq'
,
'NanSensitiveFloatEq'
,
'Ne'
,
'Not'
,
'NotNull'
,
...
...
@@ -67,6 +73,8 @@ _COMMON_GMOCK_SYMBOLS = [
'PointeeIsInitializedProto'
,
'Property'
,
'Ref'
,
'ResultOf'
,
'SafeMatcherCast'
,
'StartsWith'
,
'StrCaseEq'
,
'StrCaseNe'
,
...
...
@@ -76,7 +84,9 @@ _COMMON_GMOCK_SYMBOLS = [
'TypedEq'
,
# Actions
'Assign'
,
'ByRef'
,
'DeleteArg'
,
'DoAll'
,
'DoDefault'
,
'IgnoreResult'
,
...
...
@@ -84,11 +94,18 @@ _COMMON_GMOCK_SYMBOLS = [
'InvokeArgument'
,
'InvokeWithoutArgs'
,
'Return'
,
'ReturnNew'
,
'ReturnNull'
,
'ReturnRef'
,
'SaveArg'
,
'SetArgReferee'
,
'SetArgumentPointee'
,
'SetArrayArgument'
,
'SetErrnoAndReturn'
,
'Throw'
,
'WithArg'
,
'WithArgs'
,
'WithoutArgs'
,
# Cardinalities
'AnyNumber'
,
...
...
@@ -106,6 +123,9 @@ _COMMON_GMOCK_SYMBOLS = [
'Mock'
,
]
# Regex for matching source file path and line number in gcc's errors.
_FILE_LINE_RE
=
r'(?P<file>.*):(?P<line>\d+):\s+'
def
_FindAllMatches
(
regex
,
s
):
"""Generates all matches of regex in string s."""
...
...
@@ -128,6 +148,7 @@ def _GenericDiagnoser(short_name, long_name, regex, diagnosis, msg):
(short name of disease, long name of disease, diagnosis).
"""
diagnosis
=
'
%(file)
s:
%(line)
s:'
+
diagnosis
for
m
in
_FindAllMatches
(
regex
,
msg
):
yield
(
short_name
,
long_name
,
diagnosis
%
m
.
groupdict
())
...
...
@@ -136,9 +157,9 @@ def _NeedToReturnReferenceDiagnoser(msg):
"""Diagnoses the NRR disease, given the error messages by gcc."""
regex
=
(
r'In member function \'testing::internal::ReturnAction<R>.*\n'
r'(?P<file>.*):(?P<line>\d+):\s+
instantiated from here\n'
+
_FILE_LINE_RE
+
r'
instantiated from here\n'
r'.*gmock-actions\.h.*error: creating array with negative size'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
You are using an Return() action in a function that returns a reference.
Please use ReturnRef() instead."""
return
_GenericDiagnoser
(
'NRR'
,
'Need to Return Reference'
,
...
...
@@ -148,11 +169,11 @@ Please use ReturnRef() instead."""
def
_NeedToReturnSomethingDiagnoser
(
msg
):
"""Diagnoses the NRS disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):\s+'
regex
=
(
_FILE_LINE_RE
+
r'(instantiated from here\n.'
r'*gmock-actions\.h.*error: void value not ignored)'
r'|(error: control reaches end of non-void function)'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
You are using an action that returns void, but it needs to return
*something*. Please tell it *what* to return. Perhaps you can use
the pattern DoAll(some_action, Return(some_value))?"""
...
...
@@ -163,10 +184,10 @@ the pattern DoAll(some_action, Return(some_value))?"""
def
_NeedToReturnNothingDiagnoser
(
msg
):
"""Diagnoses the NRN disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):\s+
instantiated from here\n'
regex
=
(
_FILE_LINE_RE
+
r'
instantiated from here\n'
r'.*gmock-actions\.h.*error: return-statement with a value, '
r'in function returning \'void\''
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
You are using an action that returns *something*, but it needs to return
void. Please use a void-returning action instead.
...
...
@@ -179,10 +200,10 @@ to re-arrange the order of actions in a DoAll(), if you are using one?"""
def
_IncompleteByReferenceArgumentDiagnoser
(
msg
):
"""Diagnoses the IBRA disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):\s+
instantiated from here\n'
regex
=
(
_FILE_LINE_RE
+
r'
instantiated from here\n'
r'.*gmock-printers\.h.*error: invalid application of '
r'\'sizeof\' to incomplete type \'(?P<type>.*)\''
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
In order to mock this function, Google Mock needs to see the definition
of type "
%(type)
s" - declaration alone is not enough. Either #include
the header that defines it, or change the argument to be passed
...
...
@@ -194,9 +215,9 @@ by pointer."""
def
_OverloadedFunctionMatcherDiagnoser
(
msg
):
"""Diagnoses the OFM disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):
error: no matching function for '
regex
=
(
_FILE_LINE_RE
+
r'
error: no matching function for '
r'call to \'Truly\(<unresolved overloaded function type>\)'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
The argument you gave to Truly() is an overloaded function. Please tell
gcc which overloaded version you want to use.
...
...
@@ -211,10 +232,9 @@ you should write
def
_OverloadedFunctionActionDiagnoser
(
msg
):
"""Diagnoses the OFA disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+): error: '
r'no matching function for call to \'Invoke\('
regex
=
(
_FILE_LINE_RE
+
r'error: no matching function for call to \'Invoke\('
r'<unresolved overloaded function type>'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
You are passing an overloaded function to Invoke(). Please tell gcc
which overloaded version you want to use.
...
...
@@ -229,10 +249,10 @@ you should write something like
def
_OverloadedMethodActionDiagnoser1
(
msg
):
"""Diagnoses the OMA disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):
error: '
regex
=
(
_FILE_LINE_RE
+
r'
error: '
r'.*no matching function for call to \'Invoke\(.*, '
r'unresolved overloaded function type>'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
The second argument you gave to Invoke() is an overloaded method. Please
tell gcc which overloaded version you want to use.
...
...
@@ -250,10 +270,10 @@ you should write something like
def
_MockObjectPointerDiagnoser
(
msg
):
"""Diagnoses the MOP disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):
error: request for member '
regex
=
(
_FILE_LINE_RE
+
r'
error: request for member '
r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\''
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
not a *pointer* to it. Please write '*(
%(mock_object)
s)' instead of
'
%(mock_object)
s' as your first argument.
...
...
@@ -279,9 +299,9 @@ you should use the EXPECT_CALL like this:
def
_OverloadedMethodActionDiagnoser2
(
msg
):
"""Diagnoses the OMA disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):
error: no matching function for '
regex
=
(
_FILE_LINE_RE
+
r'
error: no matching function for '
r'call to \'Invoke\(.+, <unresolved overloaded function type>\)'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
The second argument you gave to Invoke() is an overloaded method. Please
tell gcc which overloaded version you want to use.
...
...
@@ -299,9 +319,9 @@ you should write something like
def
_NeedToUseSymbolDiagnoser
(
msg
):
"""Diagnoses the NUS disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):
error: \'(?P<symbol>.+)\' '
regex
=
(
_FILE_LINE_RE
+
r'
error: \'(?P<symbol>.+)\' '
r'(was not declared in this scope|has not been declared)'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
'
%(symbol)
s' is defined by Google Mock in the testing namespace.
Did you forget to write
using testing::
%(symbol)
s;
...
...
@@ -315,11 +335,10 @@ Did you forget to write
def
_NeedToUseReturnNullDiagnoser
(
msg
):
"""Diagnoses the NRNULL disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):\s+
instantiated from here\n'
regex
=
(
_FILE_LINE_RE
+
r'
instantiated from here\n'
r'.*gmock-actions\.h.*error: invalid conversion from '
r'\'long int\' to \'(?P<type>.+\*)'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
diagnosis
=
"""
You are probably calling Return(NULL) and the compiler isn't sure how to turn
NULL into a
%(type)
s*. Use ReturnNull() instead.
Note: the line number may be off; please fix all instances of Return(NULL)."""
...
...
@@ -330,13 +349,11 @@ Note: the line number may be off; please fix all instances of Return(NULL)."""
def
_WrongMockMethodMacroDiagnoser
(
msg
):
"""Diagnoses the WMM disease, given the error messages by gcc."""
regex
=
(
r'(?P<file>.*):(?P<line>\d+):\s+'
regex
=
(
_FILE_LINE_RE
+
r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
r'.*\n'
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>'
)
diagnosis
=
"""
%(file)
s:
%(line)
s:
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>'
)
diagnosis
=
"""
You are using MOCK_METHOD
%(wrong_args)
s to define a mock method that has
%(args)
s arguments. Use MOCK_METHOD
%(args)
s (or MOCK_CONST_METHOD
%(args)
s,
MOCK_METHOD
%(args)
s_T, MOCK_CONST_METHOD
%(args)
s_T as appropriate) instead."""
...
...
@@ -344,6 +361,21 @@ MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
regex
,
diagnosis
,
msg
)
def
_WrongParenPositionDiagnoser
(
msg
):
"""Diagnoses the WPP disease, given the error messages by gcc."""
regex
=
(
_FILE_LINE_RE
+
r'error:.*testing::internal::MockSpec<.* has no member named \''
r'(?P<method>\w+)\''
)
diagnosis
=
"""
The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
".
%(method)
s". For example, you should write:
EXPECT_CALL(my_mock, Foo(_)).
%(method)
s(...);
instead of:
EXPECT_CALL(my_mock, Foo(_).
%(method)
s(...));"""
return
_GenericDiagnoser
(
'WPP'
,
'Wrong parenthesis position'
,
regex
,
diagnosis
,
msg
)
_DIAGNOSERS
=
[
_IncompleteByReferenceArgumentDiagnoser
,
...
...
@@ -358,6 +390,7 @@ _DIAGNOSERS = [
_OverloadedMethodActionDiagnoser1
,
_OverloadedMethodActionDiagnoser2
,
_WrongMockMethodMacroDiagnoser
,
_WrongParenPositionDiagnoser
,
]
...
...
src/gmock-internal-utils.cc
View file @
9413f2ff
...
...
@@ -101,6 +101,22 @@ FailureReporterInterface* GetFailureReporter() {
// Protects global resources (stdout in particular) used by Log().
static
Mutex
g_log_mutex
(
Mutex
::
NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX
);
// Returns true iff a log with the given severity is visible according
// to the --gmock_verbose flag.
bool
LogIsVisible
(
LogSeverity
severity
)
{
if
(
GMOCK_FLAG
(
verbose
)
==
kInfoVerbosity
)
{
// Always show the log if --gmock_verbose=info.
return
true
;
}
else
if
(
GMOCK_FLAG
(
verbose
)
==
kErrorVerbosity
)
{
// Always hide it if --gmock_verbose=error.
return
false
;
}
else
{
// If --gmock_verbose is neither "info" nor "error", we treat it
// as "warning" (its default value).
return
severity
==
WARNING
;
}
}
// Prints the given message to stdout iff 'severity' >= the level
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
// 0, also prints the stack trace excluding the top
...
...
@@ -110,17 +126,8 @@ static Mutex g_log_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX);
// conservative.
void
Log
(
LogSeverity
severity
,
const
string
&
message
,
int
stack_frames_to_skip
)
{
if
(
GMOCK_FLAG
(
verbose
)
==
kErrorVerbosity
)
{
// The user is not interested in logs.
if
(
!
LogIsVisible
(
severity
))
return
;
}
else
if
(
GMOCK_FLAG
(
verbose
)
!=
kInfoVerbosity
)
{
// The user is interested in warnings but not informational logs.
// Note that invalid values of GMOCK_FLAG(verbose) are treated as
// "warning", which is the default value of the flag.
if
(
severity
==
INFO
)
{
return
;
}
}
// Ensures that logs from different threads don't interleave.
MutexLock
l
(
&
g_log_mutex
);
...
...
src/gmock-printers.cc
View file @
9413f2ff
...
...
@@ -242,6 +242,11 @@ static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
*
os
<<
"
\"
"
;
}
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
void
UniversalPrintArray
(
const
char
*
begin
,
size_t
len
,
ostream
*
os
)
{
PrintCharsAsStringTo
(
begin
,
len
,
os
);
}
// Prints the given array of wide characters to the ostream.
// The array starts at *begin, the length is len, it may include L'\0'
// characters and may not be null-terminated.
...
...
src/gmock-spec-builders.cc
View file @
9413f2ff
...
...
@@ -139,10 +139,10 @@ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
void
ReportUninterestingCall
(
CallReaction
reaction
,
const
string
&
msg
)
{
switch
(
reaction
)
{
case
ALLOW
:
Log
(
INFO
,
msg
,
4
);
Log
(
INFO
,
msg
,
3
);
break
;
case
WARN
:
Log
(
WARNING
,
msg
,
4
);
Log
(
WARNING
,
msg
,
3
);
break
;
default:
// FAIL
Expect
(
false
,
NULL
,
-
1
,
msg
);
...
...
test/gmock-internal-utils_test.cc
View file @
9413f2ff
...
...
@@ -494,6 +494,34 @@ TEST(ExpectTest, FailsNonfatallyOnFalse) {
},
"Expectation failed"
);
}
// Tests LogIsVisible().
class
LogIsVisibleTest
:
public
::
testing
::
Test
{
protected
:
virtual
void
SetUp
()
{
original_verbose_
=
GMOCK_FLAG
(
verbose
);
}
virtual
void
TearDown
()
{
GMOCK_FLAG
(
verbose
)
=
original_verbose_
;
}
string
original_verbose_
;
};
TEST_F
(
LogIsVisibleTest
,
AlwaysReturnsTrueIfVerbosityIsInfo
)
{
GMOCK_FLAG
(
verbose
)
=
kInfoVerbosity
;
EXPECT_TRUE
(
LogIsVisible
(
INFO
));
EXPECT_TRUE
(
LogIsVisible
(
WARNING
));
}
TEST_F
(
LogIsVisibleTest
,
AlwaysReturnsFalseIfVerbosityIsError
)
{
GMOCK_FLAG
(
verbose
)
=
kErrorVerbosity
;
EXPECT_FALSE
(
LogIsVisible
(
INFO
));
EXPECT_FALSE
(
LogIsVisible
(
WARNING
));
}
TEST_F
(
LogIsVisibleTest
,
WorksWhenVerbosityIsWarning
)
{
GMOCK_FLAG
(
verbose
)
=
kWarningVerbosity
;
EXPECT_FALSE
(
LogIsVisible
(
INFO
));
EXPECT_TRUE
(
LogIsVisible
(
WARNING
));
}
// TODO(wan@google.com): find a way to re-enable these tests.
#if 0
...
...
test/gmock-printers_test.cc
View file @
9413f2ff
...
...
@@ -485,75 +485,58 @@ TEST(PrintPointerTest, MemberFunctionPointer) {
// Tests printing C arrays.
// One-dimensional array.
void
ArrayHelper1
(
int
(
&
a
)[
5
])
{
// NOLINT
EXPECT_EQ
(
"{ 1, 2, 3, 4, 5 }"
,
Print
(
a
));
// The difference between this and Print() is that it ensures that the
// argument is a reference to an array.
template
<
typename
T
,
size_t
N
>
string
PrintArrayHelper
(
T
(
&
a
)[
N
])
{
return
Print
(
a
);
}
// One-dimensional array.
TEST
(
PrintArrayTest
,
OneDimensionalArray
)
{
int
a
[
5
]
=
{
1
,
2
,
3
,
4
,
5
};
ArrayHelper1
(
a
);
EXPECT_EQ
(
"{ 1, 2, 3, 4, 5 }"
,
PrintArrayHelper
(
a
)
);
}
// Two-dimensional array.
void
ArrayHelper2
(
int
(
&
a
)[
2
][
5
])
{
// NOLINT
EXPECT_EQ
(
"{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }"
,
Print
(
a
));
}
TEST
(
PrintArrayTest
,
TwoDimensionalArray
)
{
int
a
[
2
][
5
]
=
{
{
1
,
2
,
3
,
4
,
5
},
{
6
,
7
,
8
,
9
,
0
}
};
ArrayHelper2
(
a
);
EXPECT_EQ
(
"{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }"
,
PrintArrayHelper
(
a
)
);
}
// Array of const elements.
void
ArrayHelper3
(
const
bool
(
&
a
)[
1
])
{
// NOLINT
EXPECT_EQ
(
"{ false }"
,
Print
(
a
));
}
TEST
(
PrintArrayTest
,
ConstArray
)
{
const
bool
a
[
1
]
=
{
false
};
ArrayHelper3
(
a
);
EXPECT_EQ
(
"{ false }"
,
PrintArrayHelper
(
a
)
);
}
// Char array.
void
ArrayHelper4
(
char
(
&
a
)[
3
])
{
// NOLINT
EXPECT_EQ
(
PrintPointer
(
a
)
+
" pointing to
\"
Hi
\"
"
,
Print
(
a
));
}
TEST
(
PrintArrayTest
,
CharArray
)
{
char
a
[
3
]
=
"Hi"
;
ArrayHelper4
(
a
);
// Array a contains '\0' in the middle and doesn't end with '\0'.
char
a
[
3
]
=
{
'H'
,
'\0'
,
'i'
};
EXPECT_EQ
(
"
\"
H
\\
0i
\"
"
,
PrintArrayHelper
(
a
));
}
// Const char array.
void
ArrayHelper5
(
const
char
(
&
a
)[
3
])
{
// NOLINT
EXPECT_EQ
(
Print
(
a
),
PrintPointer
(
a
)
+
" pointing to
\"
Hi
\"
"
);
}
TEST
(
PrintArrayTest
,
ConstCharArray
)
{
const
char
a
[
3
]
=
"
Hi"
;
ArrayHelper5
(
a
);
const
char
a
[
4
]
=
"
\0
Hi"
;
EXPECT_EQ
(
"
\"\\
0Hi
\\
0
\"
"
,
PrintArrayHelper
(
a
)
);
}
// Array of objects.
TEST
(
PrintArrayTest
,
ObjectArray
)
{
string
a
[
3
]
=
{
"Hi"
,
"Hello"
,
"Ni hao"
};
EXPECT_EQ
(
"{
\"
Hi
\"
,
\"
Hello
\"
,
\"
Ni hao
\"
}"
,
Print
(
a
));
EXPECT_EQ
(
"{
\"
Hi
\"
,
\"
Hello
\"
,
\"
Ni hao
\"
}"
,
Print
ArrayHelper
(
a
));
}
// Array with many elements.
TEST
(
PrintArrayTest
,
BigArray
)
{
int
a
[
100
]
=
{
1
,
2
,
3
};
EXPECT_EQ
(
"{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }"
,
Print
(
a
));
Print
ArrayHelper
(
a
));
}
// Tests printing ::string and ::std::string.
...
...
@@ -995,6 +978,11 @@ TEST(PrintToStringTest, WorksForReference) {
UniversalPrinter
<
const
int
&>::
PrintToString
(
n
));
}
TEST
(
PrintToStringTest
,
WorksForArray
)
{
int
n
[
3
]
=
{
1
,
2
,
3
};
EXPECT_EQ
(
"{ 1, 2, 3 }"
,
UniversalPrinter
<
int
[
3
]
>::
PrintToString
(
n
));
}
TEST
(
UniversalTersePrintTest
,
WorksForNonReference
)
{
::
std
::
stringstream
ss
;
UniversalTersePrint
(
123
,
&
ss
);
...
...
test/gmock-spec-builders_test.cc
View file @
9413f2ff
...
...
@@ -1612,6 +1612,53 @@ TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) {
#endif // 0
// A helper class that generates a failure when printed. We use it to
// ensure that Google Mock doesn't print a value (even to an internal
// buffer) when it is not supposed to do so.
class
PrintMeNot
{};
void
PrintTo
(
PrintMeNot
/* dummy */
,
::
std
::
ostream
*
/* os */
)
{
ADD_FAILURE
()
<<
"Google Mock is printing a value that shouldn't be "
<<
"printed even to an internal buffer."
;
}
class
LogTestHelper
{
public
:
MOCK_METHOD1
(
Foo
,
PrintMeNot
(
PrintMeNot
));
};
class
GMockLogTest
:
public
::
testing
::
Test
{
protected
:
virtual
void
SetUp
()
{
original_verbose_
=
GMOCK_FLAG
(
verbose
);
}
virtual
void
TearDown
()
{
GMOCK_FLAG
(
verbose
)
=
original_verbose_
;
}
LogTestHelper
helper_
;
string
original_verbose_
;
};
TEST_F
(
GMockLogTest
,
DoesNotPrintGoodCallInternallyIfVerbosityIsWarning
)
{
GMOCK_FLAG
(
verbose
)
=
kWarningVerbosity
;
EXPECT_CALL
(
helper_
,
Foo
(
_
))
.
WillOnce
(
Return
(
PrintMeNot
()));
helper_
.
Foo
(
PrintMeNot
());
// This is an expected call.
}
TEST_F
(
GMockLogTest
,
DoesNotPrintGoodCallInternallyIfVerbosityIsError
)
{
GMOCK_FLAG
(
verbose
)
=
kErrorVerbosity
;
EXPECT_CALL
(
helper_
,
Foo
(
_
))
.
WillOnce
(
Return
(
PrintMeNot
()));
helper_
.
Foo
(
PrintMeNot
());
// This is an expected call.
}
TEST_F
(
GMockLogTest
,
DoesNotPrintWarningInternallyIfVerbosityIsError
)
{
GMOCK_FLAG
(
verbose
)
=
kErrorVerbosity
;
ON_CALL
(
helper_
,
Foo
(
_
))
.
WillByDefault
(
Return
(
PrintMeNot
()));
helper_
.
Foo
(
PrintMeNot
());
// This should generate a warning.
}
// Tests Mock::AllowLeak().
TEST
(
AllowLeakTest
,
AllowsLeakingUnusedMockObject
)
{
MockA
*
a
=
new
MockA
;
Mock
::
AllowLeak
(
a
);
...
...
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