From 40e72a8a837b47cbfe2e695068c1845073ab2630 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 6 Mar 2009 20:05:23 +0000 Subject: Implements --gtest_throw_on_failure for using gtest with other testing frameworks. --- Makefile.am | 16 ++- include/gtest/gtest.h | 21 ++-- scons/SConscript | 2 + src/gtest-internal-inl.h | 4 + src/gtest.cc | 67 +++++++++--- test/gtest_break_on_failure_unittest.py | 23 ++++- test/gtest_break_on_failure_unittest_.cc | 1 - test/gtest_env_var_test.py | 1 + test/gtest_env_var_test_.cc | 5 + test/gtest_throw_on_failure_ex_test.cc | 92 +++++++++++++++++ test/gtest_throw_on_failure_test.py | 171 +++++++++++++++++++++++++++++++ test/gtest_throw_on_failure_test_.cc | 56 ++++++++++ test/gtest_unittest.cc | 71 ++++++++++++- 13 files changed, 501 insertions(+), 29 deletions(-) create mode 100644 test/gtest_throw_on_failure_ex_test.cc create mode 100755 test/gtest_throw_on_failure_test.py create mode 100644 test/gtest_throw_on_failure_test_.cc 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 +#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(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(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, >EST_FLAG(list_tests)) || ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || - ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_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 + +#include +#include +#include +#include + +// 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 + +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) { -- cgit v0.12