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
50f4deb1
Commit
50f4deb1
authored
Oct 18, 2010
by
vladlosev
Browse files
Modifies handling of C++ exceptions in death tests to treat exceptions escaping them as failures.
parent
2c810105
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
160 additions
and
15 deletions
+160
-15
CMakeLists.txt
CMakeLists.txt
+7
-0
include/gtest/internal/gtest-death-test-internal.h
include/gtest/internal/gtest-death-test-internal.h
+32
-3
src/gtest-death-test.cc
src/gtest-death-test.cc
+23
-10
test/gtest-death-test_ex_test.cc
test/gtest-death-test_ex_test.cc
+93
-0
test/gtest-death-test_test.cc
test/gtest-death-test_test.cc
+5
-2
No files found.
CMakeLists.txt
View file @
50f4deb1
...
@@ -147,6 +147,13 @@ if (gtest_build_tests)
...
@@ -147,6 +147,13 @@ if (gtest_build_tests)
cxx_library
(
gtest_main_no_rtti
"
${
cxx_no_rtti
}
"
cxx_library
(
gtest_main_no_rtti
"
${
cxx_no_rtti
}
"
src/gtest-all.cc src/gtest_main.cc
)
src/gtest-all.cc src/gtest_main.cc
)
cxx_test_with_flags
(
gtest-death-test_ex_nocatch_test
"
${
cxx_exception
}
-DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
gtest test/gtest-death-test_ex_test.cc
)
cxx_test_with_flags
(
gtest-death-test_ex_catch_test
"
${
cxx_exception
}
-DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
gtest test/gtest-death-test_ex_test.cc
)
cxx_test_with_flags
(
gtest_no_rtti_unittest
"
${
cxx_no_rtti
}
"
cxx_test_with_flags
(
gtest_no_rtti_unittest
"
${
cxx_no_rtti
}
"
gtest_main_no_rtti test/gtest_unittest.cc
)
gtest_main_no_rtti test/gtest_unittest.cc
)
...
...
include/gtest/internal/gtest-death-test-internal.h
View file @
50f4deb1
...
@@ -39,6 +39,8 @@
...
@@ -39,6 +39,8 @@
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-internal.h"
#include <stdio.h>
namespace
testing
{
namespace
testing
{
namespace
internal
{
namespace
internal
{
...
@@ -96,8 +98,12 @@ class GTEST_API_ DeathTest {
...
@@ -96,8 +98,12 @@ class GTEST_API_ DeathTest {
// test, then wait for it to complete.
// test, then wait for it to complete.
enum
TestRole
{
OVERSEE_TEST
,
EXECUTE_TEST
};
enum
TestRole
{
OVERSEE_TEST
,
EXECUTE_TEST
};
// An enumeration of the two reasons that a test might be aborted.
// An enumeration of the three reasons that a test might be aborted.
enum
AbortReason
{
TEST_ENCOUNTERED_RETURN_STATEMENT
,
TEST_DID_NOT_DIE
};
enum
AbortReason
{
TEST_ENCOUNTERED_RETURN_STATEMENT
,
TEST_THREW_EXCEPTION
,
TEST_DID_NOT_DIE
};
// Assumes one of the above roles.
// Assumes one of the above roles.
virtual
TestRole
AssumeRole
()
=
0
;
virtual
TestRole
AssumeRole
()
=
0
;
...
@@ -149,6 +155,29 @@ class DefaultDeathTestFactory : public DeathTestFactory {
...
@@ -149,6 +155,29 @@ class DefaultDeathTestFactory : public DeathTestFactory {
// by a signal, or exited normally with a nonzero exit code.
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_
bool
ExitedUnsuccessfully
(
int
exit_status
);
GTEST_API_
bool
ExitedUnsuccessfully
(
int
exit_status
);
// Traps C++ exceptions escaping statement and reports them as test
// failures. Note that trapping SEH exceptions is not implemented here.
#if GTEST_HAS_EXCEPTIONS
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} catch (const ::std::exception& gtest_exception) { \
fprintf(\
stderr, \
"\n%s: Caught std::exception-derived exception escaping the " \
"death test statement. Exception message: %s\n", \
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
gtest_exception.what()); \
fflush(stderr); \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
} catch (...) { \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
}
#else
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
#endif
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
// ASSERT_EXIT*, and EXPECT_EXIT*.
#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
...
@@ -172,7 +201,7 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
...
@@ -172,7 +201,7 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
gtest_sentinel(gtest_dt); \
GTEST_
SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statemen
t); \
GTEST_
EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_d
t); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
break; \
} \
} \
...
...
src/gtest-death-test.cc
View file @
50f4deb1
...
@@ -182,15 +182,19 @@ static String DeathTestThreadWarning(size_t thread_count) {
...
@@ -182,15 +182,19 @@ static String DeathTestThreadWarning(size_t thread_count) {
// Flag characters for reporting a death test that did not die.
// Flag characters for reporting a death test that did not die.
static
const
char
kDeathTestLived
=
'L'
;
static
const
char
kDeathTestLived
=
'L'
;
static
const
char
kDeathTestReturned
=
'R'
;
static
const
char
kDeathTestReturned
=
'R'
;
static
const
char
kDeathTestThrew
=
'T'
;
static
const
char
kDeathTestInternalError
=
'I'
;
static
const
char
kDeathTestInternalError
=
'I'
;
// An enumeration describing all of the possible ways that a death test
// An enumeration describing all of the possible ways that a death test can
// can conclude. DIED means that the process died while executing the
// conclude. DIED means that the process died while executing the test
// test code; LIVED means that process lived beyond the end of the test
// code; LIVED means that process lived beyond the end of the test code;
// code; and RETURNED means that the test statement attempted a "return,"
// RETURNED means that the test statement attempted to execute a return
// which is not allowed. IN_PROGRESS means the test has not yet
// statement, which is not allowed; THREW means that the test statement
// concluded.
// returned control by throwing an exception. IN_PROGRESS means the test
enum
DeathTestOutcome
{
IN_PROGRESS
,
DIED
,
LIVED
,
RETURNED
};
// has not yet concluded.
// TODO(vladl@google.com): Unify names and possibly values for
// AbortReason, DeathTestOutcome, and flag characters above.
enum
DeathTestOutcome
{
IN_PROGRESS
,
DIED
,
LIVED
,
RETURNED
,
THREW
};
// Routine for aborting the program which is safe to call from an
// Routine for aborting the program which is safe to call from an
// exec-style death test child process, in which case the error
// exec-style death test child process, in which case the error
...
@@ -388,6 +392,9 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
...
@@ -388,6 +392,9 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
case
kDeathTestReturned
:
case
kDeathTestReturned
:
set_outcome
(
RETURNED
);
set_outcome
(
RETURNED
);
break
;
break
;
case
kDeathTestThrew
:
set_outcome
(
THREW
);
break
;
case
kDeathTestLived
:
case
kDeathTestLived
:
set_outcome
(
LIVED
);
set_outcome
(
LIVED
);
break
;
break
;
...
@@ -416,7 +423,9 @@ void DeathTestImpl::Abort(AbortReason reason) {
...
@@ -416,7 +423,9 @@ void DeathTestImpl::Abort(AbortReason reason) {
// it finds any data in our pipe. So, here we write a single flag byte
// it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit.
// to the pipe, then exit.
const
char
status_ch
=
const
char
status_ch
=
reason
==
TEST_DID_NOT_DIE
?
kDeathTestLived
:
kDeathTestReturned
;
reason
==
TEST_DID_NOT_DIE
?
kDeathTestLived
:
reason
==
TEST_THREW_EXCEPTION
?
kDeathTestThrew
:
kDeathTestReturned
;
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
posix
::
Write
(
write_fd
(),
&
status_ch
,
1
));
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
posix
::
Write
(
write_fd
(),
&
status_ch
,
1
));
// We are leaking the descriptor here because on some platforms (i.e.,
// We are leaking the descriptor here because on some platforms (i.e.,
// when built as Windows DLL), destructors of global objects will still
// when built as Windows DLL), destructors of global objects will still
...
@@ -434,8 +443,8 @@ void DeathTestImpl::Abort(AbortReason reason) {
...
@@ -434,8 +443,8 @@ void DeathTestImpl::Abort(AbortReason reason) {
//
//
// Private data members:
// Private data members:
// outcome: An enumeration describing how the death test
// outcome: An enumeration describing how the death test
// concluded: DIED, LIVED, or RETURNED. The death test
fails
// concluded: DIED, LIVED,
THREW,
or RETURNED. The death test
// in the latter t
wo
cases.
//
fails
in the latter t
hree
cases.
// status: The exit status of the child process. On *nix, it is in the
// status: The exit status of the child process. On *nix, it is in the
// in the format specified by wait(2). On Windows, this is the
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
// value supplied to the ExitProcess() API or a numeric code
...
@@ -466,6 +475,10 @@ bool DeathTestImpl::Passed(bool status_ok) {
...
@@ -466,6 +475,10 @@ bool DeathTestImpl::Passed(bool status_ok) {
buffer
<<
" Result: failed to die.
\n
"
buffer
<<
" Result: failed to die.
\n
"
<<
" Error msg: "
<<
error_message
;
<<
" Error msg: "
<<
error_message
;
break
;
break
;
case
THREW
:
buffer
<<
" Result: threw an exception.
\n
"
<<
" Error msg: "
<<
error_message
;
break
;
case
RETURNED
:
case
RETURNED
:
buffer
<<
" Result: illegal return in test statement.
\n
"
buffer
<<
" Result: illegal return in test statement.
\n
"
<<
" Error msg: "
<<
error_message
;
<<
" Error msg: "
<<
error_message
;
...
...
test/gtest-death-test_ex_test.cc
0 → 100644
View file @
50f4deb1
// Copyright 2010, 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: vladl@google.com (Vlad Losev)
//
// Tests that verify interaction of exceptions and death tests.
#include "gtest/gtest-death-test.h"
#include "gtest/gtest.h"
#if GTEST_HAS_DEATH_TEST
#if GTEST_HAS_SEH
#include <windows.h> // For RaiseException().
#endif
#include "gtest/gtest-spi.h"
#if GTEST_HAS_EXCEPTIONS
#include <exception> // For std::exception.
// Tests that death tests report thrown exceptions as failures and that the
// exceptions do not escape death test macros.
TEST
(
CxxExceptionDeathTest
,
ExceptionIsFailure
)
{
try
{
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
1
,
""
),
"threw an exception"
);
}
catch
(...)
{
// NOLINT
FAIL
()
<<
"An exception escaped a death test macro invocation "
<<
"with catch_exceptions "
<<
(
testing
::
GTEST_FLAG
(
catch_exceptions
)
?
"enabled"
:
"disabled"
);
}
}
class
TestException
:
public
std
::
exception
{
public:
virtual
const
char
*
what
()
const
throw
()
{
return
"exceptional message"
;
}
};
TEST
(
CxxExceptionDeathTest
,
PrintsMessageForStdExceptions
)
{
// Verifies that the exception message is quoted in the failure text.
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
TestException
(),
""
),
"exceptional message"
);
// Verifies that the location is mentioned in the failure text.
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
throw
TestException
(),
""
),
"gtest-death-test_ex_test.cc"
);
}
#endif // GTEST_HAS_EXCEPTIONS
#if GTEST_HAS_SEH
// Tests that enabling interception of SEH exceptions with the
// catch_exceptions flag does not interfere with SEH exceptions being
// treated as death by death tests.
TEST
(
SehExceptionDeasTest
,
CatchExceptionsDoesNotInterfere
)
{
EXPECT_DEATH
(
RaiseException
(
42
,
0x0
,
0
,
NULL
),
""
)
<<
"with catch_exceptions "
<<
(
testing
::
GTEST_FLAG
(
catch_exceptions
)
?
"enabled"
:
"disabled"
);
}
#endif
#endif // GTEST_HAS_DEATH_TEST
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
testing
::
GTEST_FLAG
(
catch_exceptions
)
=
GTEST_ENABLE_CATCH_EXCEPTIONS_
!=
0
;
return
RUN_ALL_TESTS
();
}
test/gtest-death-test_test.cc
View file @
50f4deb1
...
@@ -538,15 +538,18 @@ TEST_F(TestForDeathTest, SingleEvaluation) {
...
@@ -538,15 +538,18 @@ TEST_F(TestForDeathTest, SingleEvaluation) {
}
}
// Tests that run-away death tests are reported as failures.
// Tests that run-away death tests are reported as failures.
TEST_F
(
TestForDeathTest
,
Runaway
)
{
TEST_F
(
TestForDeathTest
,
Runaway
IsFailure
)
{
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
static_cast
<
void
>
(
0
),
"Foo"
),
EXPECT_NONFATAL_FAILURE
(
EXPECT_DEATH
(
static_cast
<
void
>
(
0
),
"Foo"
),
"failed to die."
);
"failed to die."
);
}
// Tests that death tests report executing 'return' in the statement as
// failure.
TEST_F
(
TestForDeathTest
,
ReturnIsFailure
)
{
EXPECT_FATAL_FAILURE
(
ASSERT_DEATH
(
return
,
"Bar"
),
EXPECT_FATAL_FAILURE
(
ASSERT_DEATH
(
return
,
"Bar"
),
"illegal return in test statement."
);
"illegal return in test statement."
);
}
}
// Tests that EXPECT_DEBUG_DEATH works as expected,
// Tests that EXPECT_DEBUG_DEATH works as expected,
// that is, in debug mode, it:
// that is, in debug mode, it:
// 1. Asserts on death.
// 1. Asserts on death.
...
...
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