Home | History | Annotate | Download | only in test
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2010 Google Inc.  All Rights Reserved.
      4 #
      5 # Redistribution and use in source and binary forms, with or without
      6 # modification, are permitted provided that the following conditions are
      7 # met:
      8 #
      9 #     * Redistributions of source code must retain the above copyright
     10 # notice, this list of conditions and the following disclaimer.
     11 #     * Redistributions in binary form must reproduce the above
     12 # copyright notice, this list of conditions and the following disclaimer
     13 # in the documentation and/or other materials provided with the
     14 # distribution.
     15 #     * Neither the name of Google Inc. nor the names of its
     16 # contributors may be used to endorse or promote products derived from
     17 # this software without specific prior written permission.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 """Tests Google Test's exception catching behavior.
     32 
     33 This script invokes gtest_catch_exceptions_test_ and
     34 gtest_catch_exceptions_ex_test_ (programs written with
     35 Google Test) and verifies their output.
     36 """
     37 
     38 __author__ = 'vladl (at] google.com (Vlad Losev)'
     39 
     40 import os
     41 
     42 import gtest_test_utils
     43 
     44 # Constants.
     45 FLAG_PREFIX = '--gtest_'
     46 LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
     47 NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0'
     48 FILTER_FLAG = FLAG_PREFIX + 'filter'
     49 
     50 # Path to the gtest_catch_exceptions_ex_test_ binary, compiled with
     51 # exceptions enabled.
     52 EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
     53     'gtest_catch_exceptions_ex_test_')
     54 
     55 # Path to the gtest_catch_exceptions_test_ binary, compiled with
     56 # exceptions disabled.
     57 EXE_PATH = gtest_test_utils.GetTestExecutablePath(
     58     'gtest_catch_exceptions_no_ex_test_')
     59 
     60 environ = gtest_test_utils.environ
     61 SetEnvVar = gtest_test_utils.SetEnvVar
     62 
     63 # Tests in this file run a Google-Test-based test program and expect it
     64 # to terminate prematurely.  Therefore they are incompatible with
     65 # the premature-exit-file protocol by design.  Unset the
     66 # premature-exit filepath to prevent Google Test from creating
     67 # the file.
     68 SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
     69 
     70 TEST_LIST = gtest_test_utils.Subprocess(
     71     [EXE_PATH, LIST_TESTS_FLAG], env=environ).output
     72 
     73 SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
     74 
     75 if SUPPORTS_SEH_EXCEPTIONS:
     76   BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH], env=environ).output
     77 
     78 EX_BINARY_OUTPUT = gtest_test_utils.Subprocess(
     79     [EX_EXE_PATH], env=environ).output
     80 
     81 
     82 # The tests.
     83 if SUPPORTS_SEH_EXCEPTIONS:
     84   # pylint:disable-msg=C6302
     85   class CatchSehExceptionsTest(gtest_test_utils.TestCase):
     86     """Tests exception-catching behavior."""
     87 
     88 
     89     def TestSehExceptions(self, test_output):
     90       self.assert_('SEH exception with code 0x2a thrown '
     91                    'in the test fixture\'s constructor'
     92                    in test_output)
     93       self.assert_('SEH exception with code 0x2a thrown '
     94                    'in the test fixture\'s destructor'
     95                    in test_output)
     96       self.assert_('SEH exception with code 0x2a thrown in SetUpTestCase()'
     97                    in test_output)
     98       self.assert_('SEH exception with code 0x2a thrown in TearDownTestCase()'
     99                    in test_output)
    100       self.assert_('SEH exception with code 0x2a thrown in SetUp()'
    101                    in test_output)
    102       self.assert_('SEH exception with code 0x2a thrown in TearDown()'
    103                    in test_output)
    104       self.assert_('SEH exception with code 0x2a thrown in the test body'
    105                    in test_output)
    106 
    107     def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
    108       self.TestSehExceptions(EX_BINARY_OUTPUT)
    109 
    110     def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
    111       self.TestSehExceptions(BINARY_OUTPUT)
    112 
    113 
    114 class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
    115   """Tests C++ exception-catching behavior.
    116 
    117      Tests in this test case verify that:
    118      * C++ exceptions are caught and logged as C++ (not SEH) exceptions
    119      * Exception thrown affect the remainder of the test work flow in the
    120        expected manner.
    121   """
    122 
    123   def testCatchesCxxExceptionsInFixtureConstructor(self):
    124     self.assert_('C++ exception with description '
    125                  '"Standard C++ exception" thrown '
    126                  'in the test fixture\'s constructor'
    127                  in EX_BINARY_OUTPUT)
    128     self.assert_('unexpected' not in EX_BINARY_OUTPUT,
    129                  'This failure belongs in this test only if '
    130                  '"CxxExceptionInConstructorTest" (no quotes) '
    131                  'appears on the same line as words "called unexpectedly"')
    132 
    133   if ('CxxExceptionInDestructorTest.ThrowsExceptionInDestructor' in
    134       EX_BINARY_OUTPUT):
    135 
    136     def testCatchesCxxExceptionsInFixtureDestructor(self):
    137       self.assert_('C++ exception with description '
    138                    '"Standard C++ exception" thrown '
    139                    'in the test fixture\'s destructor'
    140                    in EX_BINARY_OUTPUT)
    141       self.assert_('CxxExceptionInDestructorTest::TearDownTestCase() '
    142                    'called as expected.'
    143                    in EX_BINARY_OUTPUT)
    144 
    145   def testCatchesCxxExceptionsInSetUpTestCase(self):
    146     self.assert_('C++ exception with description "Standard C++ exception"'
    147                  ' thrown in SetUpTestCase()'
    148                  in EX_BINARY_OUTPUT)
    149     self.assert_('CxxExceptionInConstructorTest::TearDownTestCase() '
    150                  'called as expected.'
    151                  in EX_BINARY_OUTPUT)
    152     self.assert_('CxxExceptionInSetUpTestCaseTest constructor '
    153                  'called as expected.'
    154                  in EX_BINARY_OUTPUT)
    155     self.assert_('CxxExceptionInSetUpTestCaseTest destructor '
    156                  'called as expected.'
    157                  in EX_BINARY_OUTPUT)
    158     self.assert_('CxxExceptionInSetUpTestCaseTest::SetUp() '
    159                  'called as expected.'
    160                  in EX_BINARY_OUTPUT)
    161     self.assert_('CxxExceptionInSetUpTestCaseTest::TearDown() '
    162                  'called as expected.'
    163                  in EX_BINARY_OUTPUT)
    164     self.assert_('CxxExceptionInSetUpTestCaseTest test body '
    165                  'called as expected.'
    166                  in EX_BINARY_OUTPUT)
    167 
    168   def testCatchesCxxExceptionsInTearDownTestCase(self):
    169     self.assert_('C++ exception with description "Standard C++ exception"'
    170                  ' thrown in TearDownTestCase()'
    171                  in EX_BINARY_OUTPUT)
    172 
    173   def testCatchesCxxExceptionsInSetUp(self):
    174     self.assert_('C++ exception with description "Standard C++ exception"'
    175                  ' thrown in SetUp()'
    176                  in EX_BINARY_OUTPUT)
    177     self.assert_('CxxExceptionInSetUpTest::TearDownTestCase() '
    178                  'called as expected.'
    179                  in EX_BINARY_OUTPUT)
    180     self.assert_('CxxExceptionInSetUpTest destructor '
    181                  'called as expected.'
    182                  in EX_BINARY_OUTPUT)
    183     self.assert_('CxxExceptionInSetUpTest::TearDown() '
    184                  'called as expected.'
    185                  in EX_BINARY_OUTPUT)
    186     self.assert_('unexpected' not in EX_BINARY_OUTPUT,
    187                  'This failure belongs in this test only if '
    188                  '"CxxExceptionInSetUpTest" (no quotes) '
    189                  'appears on the same line as words "called unexpectedly"')
    190 
    191   def testCatchesCxxExceptionsInTearDown(self):
    192     self.assert_('C++ exception with description "Standard C++ exception"'
    193                  ' thrown in TearDown()'
    194                  in EX_BINARY_OUTPUT)
    195     self.assert_('CxxExceptionInTearDownTest::TearDownTestCase() '
    196                  'called as expected.'
    197                  in EX_BINARY_OUTPUT)
    198     self.assert_('CxxExceptionInTearDownTest destructor '
    199                  'called as expected.'
    200                  in EX_BINARY_OUTPUT)
    201 
    202   def testCatchesCxxExceptionsInTestBody(self):
    203     self.assert_('C++ exception with description "Standard C++ exception"'
    204                  ' thrown in the test body'
    205                  in EX_BINARY_OUTPUT)
    206     self.assert_('CxxExceptionInTestBodyTest::TearDownTestCase() '
    207                  'called as expected.'
    208                  in EX_BINARY_OUTPUT)
    209     self.assert_('CxxExceptionInTestBodyTest destructor '
    210                  'called as expected.'
    211                  in EX_BINARY_OUTPUT)
    212     self.assert_('CxxExceptionInTestBodyTest::TearDown() '
    213                  'called as expected.'
    214                  in EX_BINARY_OUTPUT)
    215 
    216   def testCatchesNonStdCxxExceptions(self):
    217     self.assert_('Unknown C++ exception thrown in the test body'
    218                  in EX_BINARY_OUTPUT)
    219 
    220   def testUnhandledCxxExceptionsAbortTheProgram(self):
    221     # Filters out SEH exception tests on Windows. Unhandled SEH exceptions
    222     # cause tests to show pop-up windows there.
    223     FITLER_OUT_SEH_TESTS_FLAG = FILTER_FLAG + '=-*Seh*'
    224     # By default, Google Test doesn't catch the exceptions.
    225     uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess(
    226         [EX_EXE_PATH,
    227          NO_CATCH_EXCEPTIONS_FLAG,
    228          FITLER_OUT_SEH_TESTS_FLAG],
    229         env=environ).output
    230 
    231     self.assert_('Unhandled C++ exception terminating the program'
    232                  in uncaught_exceptions_ex_binary_output)
    233     self.assert_('unexpected' not in uncaught_exceptions_ex_binary_output)
    234 
    235 
    236 if __name__ == '__main__':
    237   gtest_test_utils.Main()
    238