Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
e7bb5ede
Commit
e7bb5ede
authored
May 05, 2009
by
zhanyong.wan
Browse files
Improves the error message for leaked mocks to include the test name (by Zhanyong Wan).
parent
125783fb
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
74 additions
and
16 deletions
+74
-16
include/gmock/internal/gmock-port.h
include/gmock/internal/gmock-port.h
+4
-4
src/gmock-spec-builders.cc
src/gmock-spec-builders.cc
+18
-2
test/gmock_output_test.py
test/gmock_output_test.py
+39
-9
test/gmock_output_test_.cc
test/gmock_output_test_.cc
+11
-0
test/gmock_output_test_golden.txt
test/gmock_output_test_golden.txt
+2
-1
No files found.
include/gmock/internal/gmock-port.h
View file @
e7bb5ede
...
...
@@ -166,16 +166,16 @@ inline To down_cast(From* f) { // so we only accept pointers
return
static_cast
<
To
>
(
f
);
}
// The GMOCK_COMPILE_ASSERT macro can be used to verify that a compile time
// The GMOCK_COMPILE_ASSERT
_
macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
// GMOCK_COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// GMOCK_COMPILE_ASSERT
_
(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// GMOCK_COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
// GMOCK_COMPILE_ASSERT
_
(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
...
...
src/gmock-spec-builders.cc
View file @
e7bb5ede
...
...
@@ -168,6 +168,8 @@ struct MockObjectState {
// invoked on this mock object.
const
char
*
first_used_file
;
int
first_used_line
;
::
std
::
string
first_used_test_case
;
::
std
::
string
first_used_test
;
bool
leakable
;
// true iff it's OK to leak the object.
FunctionMockers
function_mockers
;
// All registered methods of the object.
};
...
...
@@ -203,8 +205,13 @@ class MockObjectRegistry {
const
MockObjectState
&
state
=
it
->
second
;
internal
::
FormatFileLocation
(
state
.
first_used_file
,
state
.
first_used_line
,
&
cout
);
cout
<<
" ERROR: this mock object should be deleted but never is. "
<<
"Its address is @"
<<
it
->
first
<<
"."
;
cout
<<
" ERROR: this mock object"
;
if
(
state
.
first_used_test
!=
""
)
{
cout
<<
" (used in test "
<<
state
.
first_used_test_case
<<
"."
<<
state
.
first_used_test
<<
")"
;
}
cout
<<
" should be deleted but never is. Its address is @"
<<
it
->
first
<<
"."
;
leaked_count
++
;
}
if
(
leaked_count
>
0
)
{
...
...
@@ -357,6 +364,15 @@ void Mock::RegisterUseByOnCallOrExpectCall(
if
(
state
.
first_used_file
==
NULL
)
{
state
.
first_used_file
=
file
;
state
.
first_used_line
=
line
;
const
TestInfo
*
const
test_info
=
UnitTest
::
GetInstance
()
->
current_test_info
();
if
(
test_info
!=
NULL
)
{
// TODO(wan@google.com): record the test case name when the
// ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
// TearDownTestCase().
state
.
first_used_test_case
=
test_info
->
test_case_name
();
state
.
first_used_test
=
test_info
->
name
();
}
}
}
...
...
test/gmock_output_test.py
View file @
e7bb5ede
...
...
@@ -64,6 +64,7 @@ GOLDEN_NAME = 'gmock_output_test_golden.txt'
GOLDEN_PATH
=
os
.
path
.
join
(
gmock_test_utils
.
GetSourceDir
(),
GOLDEN_NAME
)
def
ToUnixLineEnding
(
s
):
"""Changes all Windows/Mac line endings in s to UNIX line endings."""
...
...
@@ -109,15 +110,38 @@ def RemoveMemoryAddresses(output):
return
re
.
sub
(
r
'@\w+'
,
'@0x#'
,
output
)
def
NormalizeOutput
(
output
):
"""Normalizes output (the output of gmock_output_test_.exe)."""
def
RemoveTestNamesOfLeakedMocks
(
output
):
"""Removes the test names of leaked mock objects from the test output."""
return
re
.
sub
(
r
'\(used in test .+\) '
,
''
,
output
)
def
GetLeakyTests
(
output
):
"""Returns a list of test names that leak mock objects."""
# findall() returns a list of all matches of the regex in output.
# For example, if '(used in test FooTest.Bar)' is in output, the
# list will contain 'FooTest.Bar'.
return
re
.
findall
(
r
'\(used in test (.+)\)'
,
output
)
def
GetNormalizedOutputAndLeakyTests
(
output
):
"""Normalizes the output of gmock_output_test_.
Args:
output: The test output.
Returns:
A tuple (the normalized test output, the list of test names that have
leaked mocks).
"""
output
=
ToUnixLineEnding
(
output
)
output
=
RemoveReportHeaderAndFooter
(
output
)
output
=
NormalizeErrorMarker
(
output
)
output
=
RemoveLocations
(
output
)
output
=
RemoveMemoryAddresses
(
output
)
return
output
return
(
RemoveTestNamesOfLeakedMocks
(
output
),
GetLeakyTests
(
output
))
def
IterShellCommandOutput
(
cmd
,
stdin_string
=
None
):
...
...
@@ -167,9 +191,8 @@ def GetShellCommandOutput(cmd, stdin_string=None):
return
string
.
join
(
lines
,
''
)
def
GetCommandOutput
(
cmd
):
"""Runs a command and returns its output with all file location
info stripped off.
def
GetNormalizedCommandOutputAndLeakyTests
(
cmd
):
"""Runs a command and returns its normalized output and a list of leaky tests.
Args:
cmd: the shell command.
...
...
@@ -177,22 +200,29 @@ def GetCommandOutput(cmd):
# Disables exception pop-ups on Windows.
os
.
environ
[
'GTEST_CATCH_EXCEPTIONS'
]
=
'1'
return
NormalizeOutput
(
GetShellCommandOutput
(
cmd
,
''
))
return
Get
Normalize
d
Output
AndLeakyTests
(
GetShellCommandOutput
(
cmd
,
''
))
class
GMockOutputTest
(
unittest
.
TestCase
):
def
testOutput
(
self
):
output
=
GetCommandOutput
(
COMMAND
)
(
output
,
leaky_tests
)
=
GetNormalizedCommandOutputAndLeakyTests
(
COMMAND
)
golden_file
=
open
(
GOLDEN_PATH
,
'rb'
)
golden
=
golden_file
.
read
()
golden_file
.
close
()
# The normalized output should match the golden file.
self
.
assertEquals
(
golden
,
output
)
# The raw output should contain 2 leaked mock object errors for
# test GMockOutputTest.CatchesLeakedMocks.
self
.
assertEquals
([
'GMockOutputTest.CatchesLeakedMocks'
,
'GMockOutputTest.CatchesLeakedMocks'
],
leaky_tests
)
if
__name__
==
'__main__'
:
if
sys
.
argv
[
1
:]
==
[
GENGOLDEN_FLAG
]:
output
=
GetCommandOutput
(
COMMAND
)
(
output
,
_
)
=
Get
Normalized
CommandOutput
AndLeakyTests
(
COMMAND
)
golden_file
=
open
(
GOLDEN_PATH
,
'wb'
)
golden_file
.
write
(
output
)
golden_file
.
close
()
...
...
test/gmock_output_test_.cc
View file @
e7bb5ede
...
...
@@ -258,6 +258,16 @@ TEST_F(GMockOutputTest, CatchesLeakedMocks) {
// Both foo1 and foo2 are deliberately leaked.
}
void
TestCatchesLeakedMocksInAdHocTests
()
{
MockFoo
*
foo
=
new
MockFoo
;
// Invokes EXPECT_CALL on foo.
EXPECT_CALL
(
*
foo
,
Bar2
(
_
,
_
));
foo
->
Bar2
(
2
,
1
);
// foo is deliberately leaked.
}
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleMock
(
&
argc
,
argv
);
...
...
@@ -266,5 +276,6 @@ int main(int argc, char **argv) {
testing
::
GMOCK_FLAG
(
catch_leaked_mocks
)
=
true
;
testing
::
GMOCK_FLAG
(
verbose
)
=
"warning"
;
TestCatchesLeakedMocksInAdHocTests
();
return
RUN_ALL_TESTS
();
}
test/gmock_output_test_golden.txt
View file @
e7bb5ede
...
...
@@ -298,4 +298,5 @@ Stack trace:
FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
ERROR: 2 leaked mock objects found at program exit.
FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
ERROR: 3 leaked mock objects found at program exit.
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