summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-03-06 20:05:23 +0000
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-03-06 20:05:23 +0000
commitb0fe69fcbfaa44ae05f6f2429d9c4bbb326b5ea5 (patch)
treece6c72890e27b3215259bedcf7ddb9e28eff4544
parentc85c0c20322a1f36113cf4d6282908e16ca32669 (diff)
downloadgoogletest-b0fe69fcbfaa44ae05f6f2429d9c4bbb326b5ea5.tar.gz
Implements --gtest_throw_on_failure for using gtest with other testing frameworks.
git-svn-id: http://googletest.googlecode.com/svn/trunk@199 861a406c-534a-0410-8894-cb66d6ee9925
-rw-r--r--Makefile.am16
-rw-r--r--include/gtest/gtest.h21
-rw-r--r--scons/SConscript2
-rw-r--r--src/gtest-internal-inl.h4
-rw-r--r--src/gtest.cc67
-rwxr-xr-xtest/gtest_break_on_failure_unittest.py23
-rw-r--r--test/gtest_break_on_failure_unittest_.cc1
-rwxr-xr-xtest/gtest_env_var_test.py1
-rw-r--r--test/gtest_env_var_test_.cc5
-rw-r--r--test/gtest_throw_on_failure_ex_test.cc92
-rwxr-xr-xtest/gtest_throw_on_failure_test.py171
-rw-r--r--test/gtest_throw_on_failure_test_.cc56
-rw-r--r--test/gtest_unittest.cc71
13 files changed, 501 insertions, 29 deletions
diff --git a/Makefile.am b/Makefile.am
index 2a465dd..fc182d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,6 @@ EXTRA_DIST = \
scons/SConscript \
scripts/fuse_gtest_files.py \
scripts/gen_gtest_pred_impl.py \
- src/gtest-all.cc \
test/gtest_all_test.cc
# MSVC project files
@@ -263,6 +262,13 @@ check_PROGRAMS += test/gtest-test-part_test
test_gtest_test_part_test_SOURCES = test/gtest-test-part_test.cc
test_gtest_test_part_test_LDADD = lib/libgtest_main.la
+TESTS += test/gtest_throw_on_failure_ex_test
+check_PROGRAMS += test/gtest_throw_on_failure_ex_test
+test_gtest_throw_on_failure_ex_test_SOURCES = \
+ test/gtest_throw_on_failure_ex_test.cc \
+ src/gtest-all.cc
+test_gtest_throw_on_failure_ex_test_CXXFLAGS = $(AM_CXXFLAGS) -fexceptions
+
TESTS += test/gtest-typed-test_test
check_PROGRAMS += test/gtest-typed-test_test
test_gtest_typed_test_test_SOURCES = test/gtest-typed-test_test.cc \
@@ -327,6 +333,14 @@ EXTRA_DIST += test/gtest_output_test_golden_lin.txt \
test/gtest_output_test_golden_win.txt
TESTS += test/gtest_output_test.py
+check_PROGRAMS += test/gtest_throw_on_failure_test_
+test_gtest_throw_on_failure_test__SOURCES = \
+ test/gtest_throw_on_failure_test_.cc \
+ src/gtest-all.cc
+test_gtest_throw_on_failure_test__CXXFLAGS = $(AM_CXXFLAGS) -fno-exceptions
+check_SCRIPTS += test/gtest_throw_on_failure_test.py
+TESTS += test/gtest_throw_on_failure_test.py
+
check_PROGRAMS += test/gtest_uninitialized_test_
test_gtest_uninitialized_test__SOURCES = test/gtest_uninitialized_test_.cc
test_gtest_uninitialized_test__LDADD = lib/libgtest.la
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index 7fecb92..9b72b63 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -101,20 +101,20 @@ GTEST_DECLARE_bool_(also_run_disabled_tests);
// This flag brings the debugger on an assertion failure.
GTEST_DECLARE_bool_(break_on_failure);
-// This flag controls whether Google Test catches all test-thrown exceptions
-// and logs them as failures.
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
GTEST_DECLARE_bool_(catch_exceptions);
-// This flag enables using colors in terminal output. Available values are
-// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
// to let Google Test decide.
GTEST_DECLARE_string_(color);
-// This flag sets up the filter to select by name using a glob pattern
+// This flag sets up the filter to select by name using a glob pattern
// the tests to run. If the filter is not given all tests are executed.
GTEST_DECLARE_string_(filter);
-// This flag causes the Google Test to list tests. None of the tests listed
+// This flag causes the Google Test to list tests. None of the tests listed
// are actually run if the flag is provided.
GTEST_DECLARE_bool_(list_tests);
@@ -122,11 +122,11 @@ GTEST_DECLARE_bool_(list_tests);
// in addition to its normal textual output.
GTEST_DECLARE_string_(output);
-// This flags control whether Google Test prints the elapsed time for each
+// This flags control whether Google Test prints the elapsed time for each
// test.
GTEST_DECLARE_bool_(print_time);
-// This flag sets how many times the tests are repeated. The default value
+// This flag sets how many times the tests are repeated. The default value
// is 1. If the value is -1 the tests are repeating forever.
GTEST_DECLARE_int32_(repeat);
@@ -138,6 +138,11 @@ GTEST_DECLARE_bool_(show_internal_stack_frames);
// printed in a failure message.
GTEST_DECLARE_int32_(stack_trace_depth);
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
// The upper limit for valid stack trace depths.
const int kMaxStackTraceDepth = 100;
diff --git a/scons/SConscript b/scons/SConscript
index b7dafc7..8ca7fab 100644
--- a/scons/SConscript
+++ b/scons/SConscript
@@ -214,6 +214,8 @@ GtestBinary(env_with_exceptions,
# - gtest_break_on_failure_unittest_
# - gtest_filter_unittest_
# - gtest_list_tests_unittest_
+# - gtest_throw_on_failure_ex_test
+# - gtest_throw_on_failure_test_
# - gtest_xml_outfile1_test_
# - gtest_xml_outfile2_test_
# - gtest_xml_output_unittest_
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index eadcf95..de5124d 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -84,6 +84,7 @@ const char kListTestsFlag[] = "list_tests";
const char kOutputFlag[] = "output";
const char kPrintTimeFlag[] = "print_time";
const char kRepeatFlag[] = "repeat";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
// This class saves the values of all Google Test flags in its c'tor, and
// restores them in its d'tor.
@@ -103,6 +104,7 @@ class GTestFlagSaver {
output_ = GTEST_FLAG(output);
print_time_ = GTEST_FLAG(print_time);
repeat_ = GTEST_FLAG(repeat);
+ throw_on_failure_ = GTEST_FLAG(throw_on_failure);
}
// The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
@@ -119,6 +121,7 @@ class GTestFlagSaver {
GTEST_FLAG(output) = output_;
GTEST_FLAG(print_time) = print_time_;
GTEST_FLAG(repeat) = repeat_;
+ GTEST_FLAG(throw_on_failure) = throw_on_failure_;
}
private:
// Fields for saving the original values of flags.
@@ -135,6 +138,7 @@ class GTestFlagSaver {
bool print_time_;
bool pretty_;
internal::Int32 repeat_;
+ bool throw_on_failure_;
} GTEST_ATTRIBUTE_UNUSED_;
// Converts a Unicode code point to a narrow string in UTF-8 encoding.
diff --git a/src/gtest.cc b/src/gtest.cc
index f86a2a3..61a3484 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -111,6 +111,10 @@
#endif // GTEST_OS_LINUX
+#if GTEST_HAS_EXCEPTIONS
+#include <stdexcept>
+#endif
+
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
@@ -231,6 +235,13 @@ GTEST_DEFINE_bool_(
"True iff " GTEST_NAME_ " should include internal stack frames when "
"printing test failure stack traces.");
+GTEST_DEFINE_bool_(
+ throw_on_failure,
+ internal::BoolFromGTestEnv("throw_on_failure", false),
+ "When this flag is specified, a failed assertion will throw an exception "
+ "if exceptions are enabled or exit the program with a non-zero code "
+ "otherwise.");
+
namespace internal {
// GTestIsInitialized() returns true iff the user has initialized
@@ -2438,14 +2449,20 @@ static const char * TestPartResultTypeToString(TestPartResultType type) {
return "Unknown result type";
}
+// Prints a TestPartResult to a String.
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result) {
+ return (Message()
+ << internal::FormatFileLocation(test_part_result.file_name(),
+ test_part_result.line_number())
+ << " " << TestPartResultTypeToString(test_part_result.type())
+ << test_part_result.message()).GetString();
+}
+
// Prints a TestPartResult.
static void PrintTestPartResult(
- const TestPartResult & test_part_result) {
- printf("%s %s%s\n",
- internal::FormatFileLocation(test_part_result.file_name(),
- test_part_result.line_number()).c_str(),
- TestPartResultTypeToString(test_part_result.type()),
- test_part_result.message());
+ const TestPartResult& test_part_result) {
+ printf("%s\n", PrintTestPartResultToString(test_part_result).c_str());
fflush(stdout);
}
@@ -3240,6 +3257,19 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
return env;
}
+#if GTEST_HAS_EXCEPTIONS
+// A failed Google Test assertion will throw an exception of this type
+// when exceptions are enabled. We derive it from std::runtime_error,
+// which is for errors presumably detectable only at run time. Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure)
+ : runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif
+
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
@@ -3276,11 +3306,23 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type,
impl_->GetTestPartResultReporterForCurrentThread()->
ReportTestPartResult(result);
- // If this is a failure and the user wants the debugger to break on
- // failures ...
- if (result_type != TPRT_SUCCESS && GTEST_FLAG(break_on_failure)) {
- // ... then we generate a seg fault.
- *static_cast<int*>(NULL) = 1;
+ if (result_type != TPRT_SUCCESS) {
+ // gunit_break_on_failure takes precedence over
+ // gunit_throw_on_failure. This allows a user to set the latter
+ // in the code (perhaps in order to use Google Test assertions
+ // with another testing framework) and specify the former on the
+ // command line for debugging.
+ if (GTEST_FLAG(break_on_failure)) {
+ *static_cast<int*>(NULL) = 1;
+ } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+ throw GoogleTestFailureException(result);
+#else
+ // We cannot call abort() as it generates a pop-up in debug mode
+ // that cannot be suppressed in VC 7.1 or below.
+ exit(1);
+#endif
+ }
}
}
@@ -4078,7 +4120,8 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
- ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat))
+ ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag, &GTEST_FLAG(throw_on_failure))
) {
// Yes. Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being
diff --git a/test/gtest_break_on_failure_unittest.py b/test/gtest_break_on_failure_unittest.py
index a295ac4..9c2855f 100755
--- a/test/gtest_break_on_failure_unittest.py
+++ b/test/gtest_break_on_failure_unittest.py
@@ -42,7 +42,6 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import gtest_test_utils
import os
-import signal
import sys
import unittest
@@ -55,13 +54,17 @@ BREAK_ON_FAILURE_ENV_VAR = 'GTEST_BREAK_ON_FAILURE'
# The command line flag for enabling/disabling the break-on-failure mode.
BREAK_ON_FAILURE_FLAG = 'gtest_break_on_failure'
+# The environment variable for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE_ENV_VAR = 'GTEST_THROW_ON_FAILURE'
+
# Path to the gtest_break_on_failure_unittest_ program.
EXE_PATH = os.path.join(gtest_test_utils.GetBuildDir(),
- 'gtest_break_on_failure_unittest_');
+ 'gtest_break_on_failure_unittest_')
# Utilities.
+
def SetEnvVar(env_var, value):
"""Sets an environment variable to a given value; unsets it when the
given value is None.
@@ -74,8 +77,7 @@ def SetEnvVar(env_var, value):
def Run(command):
- """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise.
- """
+ """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
p = gtest_test_utils.Subprocess(command)
if p.terminated_by_signal:
@@ -84,7 +86,8 @@ def Run(command):
return 0
-# The unit test.
+# The tests.
+
class GTestBreakOnFailureUnitTest(unittest.TestCase):
"""Tests using the GTEST_BREAK_ON_FAILURE environment variable or
@@ -180,6 +183,16 @@ class GTestBreakOnFailureUnitTest(unittest.TestCase):
flag_value='1',
expect_seg_fault=1)
+ def testBreakOnFailureOverridesThrowOnFailure(self):
+ """Tests that gtest_break_on_failure overrides gtest_throw_on_failure."""
+
+ SetEnvVar(THROW_ON_FAILURE_ENV_VAR, '1')
+ try:
+ self.RunAndVerify(env_var_value=None,
+ flag_value='1',
+ expect_seg_fault=1)
+ finally:
+ SetEnvVar(THROW_ON_FAILURE_ENV_VAR, None)
if __name__ == '__main__':
gtest_test_utils.Main()
diff --git a/test/gtest_break_on_failure_unittest_.cc b/test/gtest_break_on_failure_unittest_.cc
index 26b5bd3..10a1203 100644
--- a/test/gtest_break_on_failure_unittest_.cc
+++ b/test/gtest_break_on_failure_unittest_.cc
@@ -54,7 +54,6 @@ TEST(Foo, Bar) {
} // namespace
-
int main(int argc, char **argv) {
#if GTEST_OS_WINDOWS
// Suppresses display of the Windows error dialog upon encountering
diff --git a/test/gtest_env_var_test.py b/test/gtest_env_var_test.py
index 67a2249..c5acc5c 100755
--- a/test/gtest_env_var_test.py
+++ b/test/gtest_env_var_test.py
@@ -103,6 +103,7 @@ def TestEnvVarAffectsFlag(command):
TestFlag(command, 'output', 'tmp/foo.xml', '')
TestFlag(command, 'print_time', '1', '0')
TestFlag(command, 'repeat', '999', '1')
+ TestFlag(command, 'throw_on_failure', '1', '0')
if IS_WINDOWS:
TestFlag(command, 'catch_exceptions', '1', '0')
diff --git a/test/gtest_env_var_test_.cc b/test/gtest_env_var_test_.cc
index dd820e4..f7c78fc 100644
--- a/test/gtest_env_var_test_.cc
+++ b/test/gtest_env_var_test_.cc
@@ -101,6 +101,11 @@ void PrintFlag(const char* flag) {
return;
}
+ if (strcmp(flag, "throw_on_failure") == 0) {
+ cout << GTEST_FLAG(throw_on_failure);
+ return;
+ }
+
cout << "Invalid flag name " << flag
<< ". Valid names are break_on_failure, color, filter, etc.\n";
exit(1);
diff --git a/test/gtest_throw_on_failure_ex_test.cc b/test/gtest_throw_on_failure_ex_test.cc
new file mode 100644
index 0000000..8bf9dc9
--- /dev/null
+++ b/test/gtest_throw_on_failure_ex_test.cc
@@ -0,0 +1,92 @@
+// Copyright 2009, 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 Google Test's throw-on-failure mode with exceptions enabled.
+
+#include <gtest/gtest.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdexcept>
+
+// Prints the given failure message and exits the program with
+// non-zero. We use this instead of a Google Test assertion to
+// indicate a failure, as the latter is been tested and cannot be
+// relied on.
+void Fail(const char* msg) {
+ printf("FAILURE: %s\n", msg);
+ fflush(stdout);
+ exit(1);
+}
+
+// Tests that an assertion failure throws a subclass of
+// std::runtime_error.
+void TestFailureThrowsRuntimeError() {
+ testing::GTEST_FLAG(throw_on_failure) = true;
+
+ // A successful assertion shouldn't throw.
+ try {
+ EXPECT_EQ(3, 3);
+ } catch(...) {
+ Fail("A successful assertion wrongfully threw.");
+ }
+
+ // A failed assertion should throw a subclass of std::runtime_error.
+ try {
+ EXPECT_EQ(2, 3) << "Expected failure";
+ } catch(const std::runtime_error& e) {
+ if (strstr(e.what(), "Expected failure") != NULL)
+ return;
+
+ printf("%s",
+ "A failed assertion did throw an exception of the right type, "
+ "but the message is incorrect. Instead of containing \"Expected "
+ "failure\", it is:\n");
+ Fail(e.what());
+ } catch(...) {
+ Fail("A failed assertion threw the wrong type of exception.");
+ }
+ Fail("A failed assertion should've thrown but didn't.");
+}
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+
+ // We want to ensure that people can use Google Test assertions in
+ // other testing frameworks, as long as they initialize Google Test
+ // properly and set the thrown-on-failure mode. Therefore, we don't
+ // use Google Test's constructs for defining and running tests
+ // (e.g. TEST and RUN_ALL_TESTS) here.
+
+ TestFailureThrowsRuntimeError();
+ return 0;
+}
diff --git a/test/gtest_throw_on_failure_test.py b/test/gtest_throw_on_failure_test.py
new file mode 100755
index 0000000..091e933
--- /dev/null
+++ b/test/gtest_throw_on_failure_test.py
@@ -0,0 +1,171 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2009, 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.
+
+"""Tests Google Test's throw-on-failure mode with exceptions disabled.
+
+This script invokes gtest_throw_on_failure_test_ (a program written with
+Google Test) with different environments and command line flags.
+"""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import gtest_test_utils
+import os
+import unittest
+
+
+# Constants.
+
+# The command line flag for enabling/disabling the throw-on-failure mode.
+THROW_ON_FAILURE = 'gtest_throw_on_failure'
+
+# Path to the gtest_throw_on_failure_test_ program, compiled with
+# exceptions disabled.
+EXE_PATH = os.path.join(gtest_test_utils.GetBuildDir(),
+ 'gtest_throw_on_failure_test_')
+
+
+# Utilities.
+
+
+def SetEnvVar(env_var, value):
+ """Sets an environment variable to a given value; unsets it when the
+ given value is None.
+ """
+
+ env_var = env_var.upper()
+ if value is not None:
+ os.environ[env_var] = value
+ elif env_var in os.environ:
+ del os.environ[env_var]
+
+
+def Run(command):
+ """Runs a command; returns True/False if its exit code is/isn't 0."""
+
+ print 'Running "%s". . .' % ' '.join(command)
+ return gtest_test_utils.Subprocess(command).exit_code == 0
+
+
+# The tests. TODO(wan@google.com): refactor the class to share common
+# logic with code in gtest_break_on_failure_unittest.py.
+class ThrowOnFailureTest(unittest.TestCase):
+ """Tests the throw-on-failure mode."""
+
+ def RunAndVerify(self, env_var_value, flag_value, should_fail):
+ """Runs gtest_throw_on_failure_test_ and verifies that it does
+ (or does not) exit with a non-zero code.
+
+ Args:
+ env_var_value: value of the GTEST_BREAK_ON_FAILURE environment
+ variable; None if the variable should be unset.
+ flag_value: value of the --gtest_break_on_failure flag;
+ None if the flag should not be present.
+ should_fail: True iff the program is expected to fail.
+ """
+
+ SetEnvVar(THROW_ON_FAILURE, env_var_value)
+
+ if env_var_value is None:
+ env_var_value_msg = ' is not set'
+ else:
+ env_var_value_msg = '=' + env_var_value
+
+ if flag_value is None:
+ flag = ''
+ elif flag_value == '0':
+ flag = '--%s=0' % THROW_ON_FAILURE
+ else:
+ flag = '--%s' % THROW_ON_FAILURE
+
+ command = [EXE_PATH]
+ if flag:
+ command.append(flag)
+
+ if should_fail:
+ should_or_not = 'should'
+ else:
+ should_or_not = 'should not'
+
+ failed = not Run(command)
+
+ SetEnvVar(THROW_ON_FAILURE, None)
+
+ msg = ('when %s%s, an assertion failure in "%s" %s cause a non-zero '
+ 'exit code.' %
+ (THROW_ON_FAILURE, env_var_value_msg, ' '.join(command),
+ should_or_not))
+ self.assert_(failed == should_fail, msg)
+
+ def testDefaultBehavior(self):
+ """Tests the behavior of the default mode."""
+
+ self.RunAndVerify(env_var_value=None, flag_value=None, should_fail=False)
+
+ def testThrowOnFailureEnvVar(self):
+ """Tests using the GTEST_THROW_ON_FAILURE environment variable."""
+
+ self.RunAndVerify(env_var_value='0',
+ flag_value=None,
+ should_fail=False)
+ self.RunAndVerify(env_var_value='1',
+ flag_value=None,
+ should_fail=True)
+
+ def testThrowOnFailureFlag(self):
+ """Tests using the --gtest_throw_on_failure flag."""
+
+ self.RunAndVerify(env_var_value=None,
+ flag_value='0',
+ should_fail=False)
+ self.RunAndVerify(env_var_value=None,
+ flag_value='1',
+ should_fail=True)
+
+ def testThrowOnFailureFlagOverridesEnvVar(self):
+ """Tests that --gtest_throw_on_failure overrides GTEST_THROW_ON_FAILURE."""
+
+ self.RunAndVerify(env_var_value='0',
+ flag_value='0',
+ should_fail=False)
+ self.RunAndVerify(env_var_value='0',
+ flag_value='1',
+ should_fail=True)
+ self.RunAndVerify(env_var_value='1',
+ flag_value='0',
+ should_fail=False)
+ self.RunAndVerify(env_var_value='1',
+ flag_value='1',
+ should_fail=True)
+
+
+if __name__ == '__main__':
+ gtest_test_utils.Main()
diff --git a/test/gtest_throw_on_failure_test_.cc b/test/gtest_throw_on_failure_test_.cc
new file mode 100644
index 0000000..88fbd5a
--- /dev/null
+++ b/test/gtest_throw_on_failure_test_.cc
@@ -0,0 +1,56 @@
+// Copyright 2009, 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 Google Test's throw-on-failure mode with exceptions disabled.
+//
+// This program must be compiled with exceptions disabled. It will be
+// invoked by gtest_throw_on_failure_test.py, and is expected to exit
+// with non-zero in the throw-on-failure mode or 0 otherwise.
+
+#include <gtest/gtest.h>
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+
+ // We want to ensure that people can use Google Test assertions in
+ // other testing frameworks, as long as they initialize Google Test
+ // properly and set the thrown-on-failure mode. Therefore, we don't
+ // use Google Test's constructs for defining and running tests
+ // (e.g. TEST and RUN_ALL_TESTS) here.
+
+ // In the throw-on-failure mode with exceptions disabled, this
+ // assertion will cause the program to exit with a non-zero code.
+ EXPECT_EQ(2, 3);
+
+ // When not in the throw-on-failure mode, the control will reach
+ // here.
+ return 0;
+}
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index 8dabcc9..9a731ee 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -48,7 +48,8 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
|| testing::GTEST_FLAG(print_time)
|| testing::GTEST_FLAG(repeat) > 0
|| testing::GTEST_FLAG(show_internal_stack_frames)
- || testing::GTEST_FLAG(stack_trace_depth) > 0;
+ || testing::GTEST_FLAG(stack_trace_depth) > 0
+ || testing::GTEST_FLAG(throw_on_failure);
EXPECT_TRUE(dummy || !dummy); // Suppresses warning that dummy is unused.
}
@@ -115,6 +116,7 @@ using testing::GTEST_FLAG(print_time);
using testing::GTEST_FLAG(repeat);
using testing::GTEST_FLAG(show_internal_stack_frames);
using testing::GTEST_FLAG(stack_trace_depth);
+using testing::GTEST_FLAG(throw_on_failure);
using testing::IsNotSubstring;
using testing::IsSubstring;
using testing::Message;
@@ -1203,6 +1205,7 @@ class GTestFlagSaverTest : public Test {
GTEST_FLAG(output) = "";
GTEST_FLAG(print_time) = false;
GTEST_FLAG(repeat) = 1;
+ GTEST_FLAG(throw_on_failure) = false;
}
// Restores the Google Test flags that the tests have modified. This will
@@ -1225,6 +1228,7 @@ class GTestFlagSaverTest : public Test {
EXPECT_STREQ("", GTEST_FLAG(output).c_str());
EXPECT_FALSE(GTEST_FLAG(print_time));
EXPECT_EQ(1, GTEST_FLAG(repeat));
+ EXPECT_FALSE(GTEST_FLAG(throw_on_failure));
GTEST_FLAG(also_run_disabled_tests) = true;
GTEST_FLAG(break_on_failure) = true;
@@ -1236,6 +1240,7 @@ class GTestFlagSaverTest : public Test {
GTEST_FLAG(output) = "xml:foo.xml";
GTEST_FLAG(print_time) = true;
GTEST_FLAG(repeat) = 100;
+ GTEST_FLAG(throw_on_failure) = true;
}
private:
// For saving Google Test flags during this test case.
@@ -4320,7 +4325,8 @@ struct Flags {
list_tests(false),
output(""),
print_time(false),
- repeat(1) {}
+ repeat(1),
+ throw_on_failure(false) {}
// Factory methods.
@@ -4396,6 +4402,14 @@ struct Flags {
return flags;
}
+ // Creates a Flags struct where the gtest_throw_on_failure flag has
+ // the given value.
+ static Flags ThrowOnFailure(bool throw_on_failure) {
+ Flags flags;
+ flags.throw_on_failure = throw_on_failure;
+ return flags;
+ }
+
// These fields store the flag values.
bool also_run_disabled_tests;
bool break_on_failure;
@@ -4406,6 +4420,7 @@ struct Flags {
const char* output;
bool print_time;
Int32 repeat;
+ bool throw_on_failure;
};
// Fixture for testing InitGoogleTest().
@@ -4422,6 +4437,7 @@ class InitGoogleTestTest : public Test {
GTEST_FLAG(output) = "";
GTEST_FLAG(print_time) = false;
GTEST_FLAG(repeat) = 1;
+ GTEST_FLAG(throw_on_failure) = false;
}
// Asserts that two narrow or wide string arrays are equal.
@@ -4447,6 +4463,7 @@ class InitGoogleTestTest : public Test {
EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str());
EXPECT_EQ(expected.print_time, GTEST_FLAG(print_time));
EXPECT_EQ(expected.repeat, GTEST_FLAG(repeat));
+ EXPECT_EQ(expected.throw_on_failure, GTEST_FLAG(throw_on_failure));
}
// Parses a command line (specified by argc1 and argv1), then
@@ -4993,6 +5010,56 @@ TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFalse) {
GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(false));
}
+
+// Tests parsing --gtest_throw_on_failure.
+TEST_F(InitGoogleTestTest, ThrowOnFailureNoDef) {
+ const char* argv[] = {
+ "foo.exe",
+ "--gtest_throw_on_failure",
+ NULL
+};
+
+ const char* argv2[] = {
+ "foo.exe",
+ NULL
+ };
+
+ GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true));
+}
+
+// Tests parsing --gtest_throw_on_failure=0.
+TEST_F(InitGoogleTestTest, ThrowOnFailureFalse_0) {
+ const char* argv[] = {
+ "foo.exe",
+ "--gtest_throw_on_failure=0",
+ NULL
+ };
+
+ const char* argv2[] = {
+ "foo.exe",
+ NULL
+ };
+
+ GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(false));
+}
+
+// Tests parsing a --gtest_throw_on_failure flag that has a "true"
+// definition.
+TEST_F(InitGoogleTestTest, ThrowOnFailureTrue) {
+ const char* argv[] = {
+ "foo.exe",
+ "--gtest_throw_on_failure=1",
+ NULL
+ };
+
+ const char* argv2[] = {
+ "foo.exe",
+ NULL
+ };
+
+ GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true));
+}
+
#if GTEST_OS_WINDOWS
// Tests parsing wide strings.
TEST_F(InitGoogleTestTest, WideStrings) {