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
c306ef2e
Commit
c306ef2e
authored
Sep 06, 2013
by
zhanyong.wan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
supports a protocol for catching tests that prematurely exit
parent
492986a5
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
247 additions
and
22 deletions
+247
-22
CHANGES
CHANGES
+4
-0
CMakeLists.txt
CMakeLists.txt
+2
-0
Makefile.am
Makefile.am
+1
-0
gtest.cc
src/gtest.cc
+57
-3
gtest_break_on_failure_unittest.py
test/gtest_break_on_failure_unittest.py
+9
-15
gtest_catch_exceptions_test.py
test/gtest_catch_exceptions_test.py
+18
-4
gtest_premature_exit_test.cc
test/gtest_premature_exit_test.cc
+141
-0
gtest_test_utils.py
test/gtest_test_utils.py
+15
-0
No files found.
CHANGES
View file @
c306ef2e
...
@@ -2,6 +2,10 @@ Changes for 1.7.0:
...
@@ -2,6 +2,10 @@ Changes for 1.7.0:
* New feature: death tests are supported on OpenBSD and in iOS
* New feature: death tests are supported on OpenBSD and in iOS
simulator now.
simulator now.
* New feature: Google Test now implements a protocol to allow
a test runner to detect that a test program has exited
prematurely and report it as a failure (before it would be
falsely reported as a success if the exit code is 0).
* New feature: Test::RecordProperty() can now be used outside of the
* New feature: Test::RecordProperty() can now be used outside of the
lifespan of a test method, in which case it will be attributed to
lifespan of a test method, in which case it will be attributed to
the current test case or the test program in the XML report.
the current test case or the test program in the XML report.
...
...
CMakeLists.txt
View file @
c306ef2e
...
@@ -124,6 +124,8 @@ if (gtest_build_tests)
...
@@ -124,6 +124,8 @@ if (gtest_build_tests)
test/gtest-param-test2_test.cc
)
test/gtest-param-test2_test.cc
)
cxx_test
(
gtest-port_test gtest_main
)
cxx_test
(
gtest-port_test gtest_main
)
cxx_test
(
gtest_pred_impl_unittest gtest_main
)
cxx_test
(
gtest_pred_impl_unittest gtest_main
)
cxx_test
(
gtest_premature_exit_test gtest
test/gtest_premature_exit_test.cc
)
cxx_test
(
gtest-printers_test gtest_main
)
cxx_test
(
gtest-printers_test gtest_main
)
cxx_test
(
gtest_prod_test gtest_main
cxx_test
(
gtest_prod_test gtest_main
test/production.cc
)
test/production.cc
)
...
...
Makefile.am
View file @
c306ef2e
...
@@ -58,6 +58,7 @@ EXTRA_DIST += \
...
@@ -58,6 +58,7 @@ EXTRA_DIST += \
test
/gtest-param-test_test.cc
\
test
/gtest-param-test_test.cc
\
test
/gtest-param-test_test.h
\
test
/gtest-param-test_test.h
\
test
/gtest-port_test.cc
\
test
/gtest-port_test.cc
\
test
/gtest_premature_exit_test.cc
\
test
/gtest-printers_test.cc
\
test
/gtest-printers_test.cc
\
test
/gtest-test-part_test.cc
\
test
/gtest-test-part_test.cc
\
test
/gtest-tuple_test.cc
\
test
/gtest-tuple_test.cc
\
...
...
src/gtest.cc
View file @
c306ef2e
...
@@ -3523,6 +3523,35 @@ const char* const
...
@@ -3523,6 +3523,35 @@ const char* const
OsStackTraceGetter
::
kElidedFramesMarker
=
OsStackTraceGetter
::
kElidedFramesMarker
=
"... "
GTEST_NAME_
" internal frames ..."
;
"... "
GTEST_NAME_
" internal frames ..."
;
// A helper class that creates the premature-exit file in its
// constructor and deletes the file in its destructor.
class
ScopedPrematureExitFile
{
public
:
explicit
ScopedPrematureExitFile
(
const
char
*
premature_exit_filepath
)
:
premature_exit_filepath_
(
premature_exit_filepath
)
{
// If a path to the premature-exit file is specified...
if
(
premature_exit_filepath
!=
NULL
&&
*
premature_exit_filepath
!=
'\0'
)
{
// create the file with a single "0" character in it. I/O
// errors are ignored as there's nothing better we can do and we
// don't want to fail the test because of this.
FILE
*
pfile
=
posix
::
FOpen
(
premature_exit_filepath
,
"w"
);
fwrite
(
"0"
,
1
,
1
,
pfile
);
fclose
(
pfile
);
}
}
~
ScopedPrematureExitFile
()
{
if
(
premature_exit_filepath_
!=
NULL
&&
*
premature_exit_filepath_
!=
'\0'
)
{
remove
(
premature_exit_filepath_
);
}
}
private
:
const
char
*
const
premature_exit_filepath_
;
GTEST_DISALLOW_COPY_AND_ASSIGN_
(
ScopedPrematureExitFile
);
};
}
// namespace internal
}
// namespace internal
// class TestEventListeners
// class TestEventListeners
...
@@ -3823,14 +3852,39 @@ void UnitTest::RecordProperty(const std::string& key,
...
@@ -3823,14 +3852,39 @@ void UnitTest::RecordProperty(const std::string& key,
// We don't protect this under mutex_, as we only support calling it
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
// from the main thread.
int
UnitTest
::
Run
()
{
int
UnitTest
::
Run
()
{
const
bool
in_death_test_child_process
=
internal
::
GTEST_FLAG
(
internal_run_death_test
).
length
()
>
0
;
// Google Test implements this protocol for catching that a test
// program exits before returning control to Google Test:
//
// 1. Upon start, Google Test creates a file whose absolute path
// is specified by the environment variable
// TEST_PREMATURE_EXIT_FILE.
// 2. When Google Test has finished its work, it deletes the file.
//
// This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
// running a Google-Test-based test program and check the existence
// of the file at the end of the test execution to see if it has
// exited prematurely.
// If we are in the child process of a death test, don't
// create/delete the premature exit file, as doing so is unnecessary
// and will confuse the parent process. Otherwise, create/delete
// the file upon entering/leaving this function. If the program
// somehow exits before this function has a chance to return, the
// premature-exit file will be left undeleted, causing a test runner
// that understands the premature-exit-file protocol to report the
// test as having failed.
const
internal
::
ScopedPrematureExitFile
premature_exit_file
(
in_death_test_child_process
?
NULL
:
internal
::
posix
::
GetEnv
(
"TEST_PREMATURE_EXIT_FILE"
));
// Captures the value of GTEST_FLAG(catch_exceptions). This value will be
// Captures the value of GTEST_FLAG(catch_exceptions). This value will be
// used for the duration of the program.
// used for the duration of the program.
impl
()
->
set_catch_exceptions
(
GTEST_FLAG
(
catch_exceptions
));
impl
()
->
set_catch_exceptions
(
GTEST_FLAG
(
catch_exceptions
));
#if GTEST_HAS_SEH
#if GTEST_HAS_SEH
const
bool
in_death_test_child_process
=
internal
::
GTEST_FLAG
(
internal_run_death_test
).
length
()
>
0
;
// Either the user wants Google Test to catch exceptions thrown by the
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// tests or this is executing in the context of death test child
// process. In either case the user does not want to see pop-up dialogs
// process. In either case the user does not want to see pop-up dialogs
...
...
test/gtest_break_on_failure_unittest.py
View file @
c306ef2e
...
@@ -66,21 +66,15 @@ EXE_PATH = gtest_test_utils.GetTestExecutablePath(
...
@@ -66,21 +66,15 @@ EXE_PATH = gtest_test_utils.GetTestExecutablePath(
'gtest_break_on_failure_unittest_'
)
'gtest_break_on_failure_unittest_'
)
# Utilities.
environ
=
gtest_test_utils
.
environ
SetEnvVar
=
gtest_test_utils
.
SetEnvVar
environ
=
os
.
environ
.
copy
()
# Tests in this file run a Google-Test-based test program and expect it
# to terminate prematurely. Therefore they are incompatible with
# the premature-exit-file protocol by design. Unset the
def
SetEnvVar
(
env_var
,
value
):
# premature-exit filepath to prevent Google Test from creating
"""Sets an environment variable to a given value; unsets it when the
# the file.
given value is None.
SetEnvVar
(
gtest_test_utils
.
PREMATURE_EXIT_FILE_ENV_VAR
,
None
)
"""
if
value
is
not
None
:
environ
[
env_var
]
=
value
elif
env_var
in
environ
:
del
environ
[
env_var
]
def
Run
(
command
):
def
Run
(
command
):
...
...
test/gtest_catch_exceptions_test.py
View file @
c306ef2e
...
@@ -57,14 +57,27 @@ EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
...
@@ -57,14 +57,27 @@ EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
EXE_PATH
=
gtest_test_utils
.
GetTestExecutablePath
(
EXE_PATH
=
gtest_test_utils
.
GetTestExecutablePath
(
'gtest_catch_exceptions_no_ex_test_'
)
'gtest_catch_exceptions_no_ex_test_'
)
TEST_LIST
=
gtest_test_utils
.
Subprocess
([
EXE_PATH
,
LIST_TESTS_FLAG
])
.
output
environ
=
gtest_test_utils
.
environ
SetEnvVar
=
gtest_test_utils
.
SetEnvVar
# Tests in this file run a Google-Test-based test program and expect it
# to terminate prematurely. Therefore they are incompatible with
# the premature-exit-file protocol by design. Unset the
# premature-exit filepath to prevent Google Test from creating
# the file.
SetEnvVar
(
gtest_test_utils
.
PREMATURE_EXIT_FILE_ENV_VAR
,
None
)
TEST_LIST
=
gtest_test_utils
.
Subprocess
(
[
EXE_PATH
,
LIST_TESTS_FLAG
],
env
=
environ
)
.
output
SUPPORTS_SEH_EXCEPTIONS
=
'ThrowsSehException'
in
TEST_LIST
SUPPORTS_SEH_EXCEPTIONS
=
'ThrowsSehException'
in
TEST_LIST
if
SUPPORTS_SEH_EXCEPTIONS
:
if
SUPPORTS_SEH_EXCEPTIONS
:
BINARY_OUTPUT
=
gtest_test_utils
.
Subprocess
([
EXE_PATH
])
.
output
BINARY_OUTPUT
=
gtest_test_utils
.
Subprocess
([
EXE_PATH
],
env
=
environ
)
.
output
EX_BINARY_OUTPUT
=
gtest_test_utils
.
Subprocess
(
[
EX_EXE_PATH
],
env
=
environ
)
.
output
EX_BINARY_OUTPUT
=
gtest_test_utils
.
Subprocess
([
EX_EXE_PATH
])
.
output
# The tests.
# The tests.
if
SUPPORTS_SEH_EXCEPTIONS
:
if
SUPPORTS_SEH_EXCEPTIONS
:
...
@@ -212,7 +225,8 @@ class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
...
@@ -212,7 +225,8 @@ class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
uncaught_exceptions_ex_binary_output
=
gtest_test_utils
.
Subprocess
(
uncaught_exceptions_ex_binary_output
=
gtest_test_utils
.
Subprocess
(
[
EX_EXE_PATH
,
[
EX_EXE_PATH
,
NO_CATCH_EXCEPTIONS_FLAG
,
NO_CATCH_EXCEPTIONS_FLAG
,
FITLER_OUT_SEH_TESTS_FLAG
])
.
output
FITLER_OUT_SEH_TESTS_FLAG
],
env
=
environ
)
.
output
self
.
assert_
(
'Unhandled C++ exception terminating the program'
self
.
assert_
(
'Unhandled C++ exception terminating the program'
in
uncaught_exceptions_ex_binary_output
)
in
uncaught_exceptions_ex_binary_output
)
...
...
test/gtest_premature_exit_test.cc
0 → 100644
View file @
c306ef2e
// Copyright 2013, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Tests that Google Test manipulates the premature-exit-detection
// file correctly.
#include <stdio.h>
#include "gtest/gtest.h"
using
::
testing
::
InitGoogleTest
;
using
::
testing
::
Test
;
using
::
testing
::
internal
::
posix
::
GetEnv
;
using
::
testing
::
internal
::
posix
::
Stat
;
using
::
testing
::
internal
::
posix
::
StatStruct
;
namespace
{
// Is the TEST_PREMATURE_EXIT_FILE environment variable expected to be
// set?
const
bool
kTestPrematureExitFileEnvVarShouldBeSet
=
false
;
class
PrematureExitTest
:
public
Test
{
public
:
// Returns true iff the given file exists.
static
bool
FileExists
(
const
char
*
filepath
)
{
StatStruct
stat
;
return
Stat
(
filepath
,
&
stat
)
==
0
;
}
protected
:
PrematureExitTest
()
{
premature_exit_file_path_
=
GetEnv
(
"TEST_PREMATURE_EXIT_FILE"
);
// Normalize NULL to "" for ease of handling.
if
(
premature_exit_file_path_
==
NULL
)
{
premature_exit_file_path_
=
""
;
}
}
// Returns true iff the premature-exit file exists.
bool
PrematureExitFileExists
()
const
{
return
FileExists
(
premature_exit_file_path_
);
}
const
char
*
premature_exit_file_path_
;
};
typedef
PrematureExitTest
PrematureExitDeathTest
;
// Tests that:
// - the premature-exit file exists during the execution of a
// death test (EXPECT_DEATH*), and
// - a death test doesn't interfere with the main test process's
// handling of the premature-exit file.
TEST_F
(
PrematureExitDeathTest
,
FileExistsDuringExecutionOfDeathTest
)
{
if
(
*
premature_exit_file_path_
==
'\0'
)
{
return
;
}
EXPECT_DEATH_IF_SUPPORTED
({
// If the file exists, crash the process such that the main test
// process will catch the (expected) crash and report a success;
// otherwise don't crash, which will cause the main test process
// to report that the death test has failed.
if
(
PrematureExitFileExists
())
{
exit
(
1
);
}
},
""
);
}
// Tests that TEST_PREMATURE_EXIT_FILE is set where it's expected to
// be set.
TEST_F
(
PrematureExitTest
,
TestPrematureExitFileEnvVarIsSet
)
{
if
(
kTestPrematureExitFileEnvVarShouldBeSet
)
{
const
char
*
const
filepath
=
GetEnv
(
"TEST_PREMATURE_EXIT_FILE"
);
ASSERT_TRUE
(
filepath
!=
NULL
);
ASSERT_NE
(
*
filepath
,
'\0'
);
}
}
// Tests that the premature-exit file exists during the execution of a
// normal (non-death) test.
TEST_F
(
PrematureExitTest
,
PrematureExitFileExistsDuringTestExecution
)
{
if
(
*
premature_exit_file_path_
==
'\0'
)
{
return
;
}
EXPECT_TRUE
(
PrematureExitFileExists
())
<<
" file "
<<
premature_exit_file_path_
<<
" should exist during test execution, but doesn't."
;
}
}
// namespace
int
main
(
int
argc
,
char
**
argv
)
{
InitGoogleTest
(
&
argc
,
argv
);
const
int
exit_code
=
RUN_ALL_TESTS
();
// Test that the premature-exit file is deleted upon return from
// RUN_ALL_TESTS().
const
char
*
const
filepath
=
GetEnv
(
"TEST_PREMATURE_EXIT_FILE"
);
if
(
filepath
!=
NULL
&&
*
filepath
!=
'\0'
)
{
if
(
PrematureExitTest
::
FileExists
(
filepath
))
{
printf
(
"File %s shouldn't exist after the test program finishes, but does."
,
filepath
);
return
1
;
}
}
return
exit_code
;
}
test/gtest_test_utils.py
View file @
c306ef2e
...
@@ -56,6 +56,21 @@ GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
...
@@ -56,6 +56,21 @@ GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
IS_WINDOWS
=
os
.
name
==
'nt'
IS_WINDOWS
=
os
.
name
==
'nt'
IS_CYGWIN
=
os
.
name
==
'posix'
and
'CYGWIN'
in
os
.
uname
()[
0
]
IS_CYGWIN
=
os
.
name
==
'posix'
and
'CYGWIN'
in
os
.
uname
()[
0
]
# The environment variable for specifying the path to the premature-exit file.
PREMATURE_EXIT_FILE_ENV_VAR
=
'TEST_PREMATURE_EXIT_FILE'
environ
=
os
.
environ
.
copy
()
def
SetEnvVar
(
env_var
,
value
):
"""Sets/unsets an environment variable to a given value."""
if
value
is
not
None
:
environ
[
env_var
]
=
value
elif
env_var
in
environ
:
del
environ
[
env_var
]
# Here we expose a class from a particular module, depending on the
# Here we expose a class from a particular module, depending on the
# environment. The comment suppresses the 'Invalid variable name' lint
# environment. The comment suppresses the 'Invalid variable name' lint
# complaint.
# complaint.
...
...
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