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 33This script invokes googletest-catch-exceptions-test_ and 34googletest-catch-exceptions-ex-test_ (programs written with 35Google Test) and verifies their output. 36""" 37 38from googletest.test import gtest_test_utils 39 40# Constants. 41FLAG_PREFIX = '--gtest_' 42LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests' 43NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0' 44FILTER_FLAG = FLAG_PREFIX + 'filter' 45 46# Path to the googletest-catch-exceptions-ex-test_ binary, compiled with 47# exceptions enabled. 48EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath( 49 'googletest-catch-exceptions-ex-test_' 50) 51 52# Path to the googletest-catch-exceptions-test_ binary, compiled with 53# exceptions disabled. 54EXE_PATH = gtest_test_utils.GetTestExecutablePath( 55 'googletest-catch-exceptions-no-ex-test_' 56) 57 58environ = gtest_test_utils.environ 59SetEnvVar = gtest_test_utils.SetEnvVar 60 61# Tests in this file run a Google-Test-based test program and expect it 62# to terminate prematurely. Therefore they are incompatible with 63# the premature-exit-file protocol by design. Unset the 64# premature-exit filepath to prevent Google Test from creating 65# the file. 66SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None) 67 68TEST_LIST = gtest_test_utils.Subprocess( 69 [EXE_PATH, LIST_TESTS_FLAG], env=environ 70).output 71 72SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST 73 74if SUPPORTS_SEH_EXCEPTIONS: 75 BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH], env=environ).output 76 77EX_BINARY_OUTPUT = gtest_test_utils.Subprocess( 78 [EX_EXE_PATH], env=environ 79).output 80 81 82# The tests. 83if SUPPORTS_SEH_EXCEPTIONS: 84 85 class CatchSehExceptionsTest(gtest_test_utils.TestCase): 86 """Tests exception-catching behavior.""" 87 88 def TestSehExceptions(self, test_output): 89 self.assertIn( 90 ( 91 'SEH exception with code 0x2a thrown ' 92 "in the test fixture's constructor" 93 ), 94 test_output, 95 ) 96 self.assertIn( 97 ( 98 'SEH exception with code 0x2a thrown ' 99 "in the test fixture's destructor" 100 ), 101 test_output, 102 ) 103 self.assertIn( 104 'SEH exception with code 0x2a thrown in SetUpTestSuite()', test_output 105 ) 106 self.assertIn( 107 'SEH exception with code 0x2a thrown in TearDownTestSuite()', 108 test_output, 109 ) 110 self.assertIn( 111 'SEH exception with code 0x2a thrown in SetUp()', test_output 112 ) 113 self.assertIn( 114 'SEH exception with code 0x2a thrown in TearDown()', test_output 115 ) 116 self.assertIn( 117 'SEH exception with code 0x2a thrown in the test body', test_output 118 ) 119 120 def testCatchesSehExceptionsWithCxxExceptionsEnabled(self): 121 self.TestSehExceptions(EX_BINARY_OUTPUT) 122 123 def testCatchesSehExceptionsWithCxxExceptionsDisabled(self): 124 self.TestSehExceptions(BINARY_OUTPUT) 125 126 127class CatchCxxExceptionsTest(gtest_test_utils.TestCase): 128 """Tests C++ exception-catching behavior. 129 130 Tests in this test case verify that: 131 * C++ exceptions are caught and logged as C++ (not SEH) exceptions 132 * Exception thrown affect the remainder of the test work flow in the 133 expected manner. 134 """ 135 136 def testCatchesCxxExceptionsInFixtureConstructor(self): 137 self.assertTrue( 138 'C++ exception with description ' 139 '"Standard C++ exception" thrown ' 140 "in the test fixture's constructor" 141 in EX_BINARY_OUTPUT, 142 EX_BINARY_OUTPUT, 143 ) 144 self.assertTrue( 145 'unexpected' not in EX_BINARY_OUTPUT, 146 ( 147 'This failure belongs in this test only if ' 148 '"CxxExceptionInConstructorTest" (no quotes) ' 149 'appears on the same line as words "called unexpectedly"' 150 ), 151 ) 152 153 if ( 154 'CxxExceptionInDestructorTest.ThrowsExceptionInDestructor' 155 in EX_BINARY_OUTPUT 156 ): 157 158 def testCatchesCxxExceptionsInFixtureDestructor(self): 159 self.assertTrue( 160 'C++ exception with description ' 161 '"Standard C++ exception" thrown ' 162 "in the test fixture's destructor" 163 in EX_BINARY_OUTPUT, 164 EX_BINARY_OUTPUT, 165 ) 166 self.assertTrue( 167 'CxxExceptionInDestructorTest::TearDownTestSuite() ' 168 'called as expected.' 169 in EX_BINARY_OUTPUT, 170 EX_BINARY_OUTPUT, 171 ) 172 173 def testCatchesCxxExceptionsInSetUpTestCase(self): 174 self.assertTrue( 175 'C++ exception with description "Standard C++ exception"' 176 ' thrown in SetUpTestSuite()' 177 in EX_BINARY_OUTPUT, 178 EX_BINARY_OUTPUT, 179 ) 180 self.assertTrue( 181 'CxxExceptionInConstructorTest::TearDownTestSuite() called as expected.' 182 in EX_BINARY_OUTPUT, 183 EX_BINARY_OUTPUT, 184 ) 185 self.assertFalse( 186 'CxxExceptionInSetUpTestSuiteTest constructor called as expected.' 187 in EX_BINARY_OUTPUT, 188 EX_BINARY_OUTPUT, 189 ) 190 self.assertFalse( 191 'CxxExceptionInSetUpTestSuiteTest destructor called as expected.' 192 in EX_BINARY_OUTPUT, 193 EX_BINARY_OUTPUT, 194 ) 195 self.assertFalse( 196 'CxxExceptionInSetUpTestSuiteTest::SetUp() called as expected.' 197 in EX_BINARY_OUTPUT, 198 EX_BINARY_OUTPUT, 199 ) 200 self.assertFalse( 201 'CxxExceptionInSetUpTestSuiteTest::TearDown() called as expected.' 202 in EX_BINARY_OUTPUT, 203 EX_BINARY_OUTPUT, 204 ) 205 self.assertFalse( 206 'CxxExceptionInSetUpTestSuiteTest test body called as expected.' 207 in EX_BINARY_OUTPUT, 208 EX_BINARY_OUTPUT, 209 ) 210 211 def testCatchesCxxExceptionsInTearDownTestCase(self): 212 self.assertTrue( 213 'C++ exception with description "Standard C++ exception"' 214 ' thrown in TearDownTestSuite()' 215 in EX_BINARY_OUTPUT, 216 EX_BINARY_OUTPUT, 217 ) 218 219 def testCatchesCxxExceptionsInSetUp(self): 220 self.assertTrue( 221 'C++ exception with description "Standard C++ exception"' 222 ' thrown in SetUp()' 223 in EX_BINARY_OUTPUT, 224 EX_BINARY_OUTPUT, 225 ) 226 self.assertTrue( 227 'CxxExceptionInSetUpTest::TearDownTestSuite() called as expected.' 228 in EX_BINARY_OUTPUT, 229 EX_BINARY_OUTPUT, 230 ) 231 self.assertTrue( 232 'CxxExceptionInSetUpTest destructor called as expected.' 233 in EX_BINARY_OUTPUT, 234 EX_BINARY_OUTPUT, 235 ) 236 self.assertTrue( 237 'CxxExceptionInSetUpTest::TearDown() called as expected.' 238 in EX_BINARY_OUTPUT, 239 EX_BINARY_OUTPUT, 240 ) 241 self.assertTrue( 242 'unexpected' not in EX_BINARY_OUTPUT, 243 ( 244 'This failure belongs in this test only if ' 245 '"CxxExceptionInSetUpTest" (no quotes) ' 246 'appears on the same line as words "called unexpectedly"' 247 ), 248 ) 249 250 def testCatchesCxxExceptionsInTearDown(self): 251 self.assertTrue( 252 'C++ exception with description "Standard C++ exception"' 253 ' thrown in TearDown()' 254 in EX_BINARY_OUTPUT, 255 EX_BINARY_OUTPUT, 256 ) 257 self.assertTrue( 258 'CxxExceptionInTearDownTest::TearDownTestSuite() called as expected.' 259 in EX_BINARY_OUTPUT, 260 EX_BINARY_OUTPUT, 261 ) 262 self.assertTrue( 263 'CxxExceptionInTearDownTest destructor called as expected.' 264 in EX_BINARY_OUTPUT, 265 EX_BINARY_OUTPUT, 266 ) 267 268 def testCatchesCxxExceptionsInTestBody(self): 269 self.assertTrue( 270 'C++ exception with description "Standard C++ exception"' 271 ' thrown in the test body' 272 in EX_BINARY_OUTPUT, 273 EX_BINARY_OUTPUT, 274 ) 275 self.assertTrue( 276 'CxxExceptionInTestBodyTest::TearDownTestSuite() called as expected.' 277 in EX_BINARY_OUTPUT, 278 EX_BINARY_OUTPUT, 279 ) 280 self.assertTrue( 281 'CxxExceptionInTestBodyTest destructor called as expected.' 282 in EX_BINARY_OUTPUT, 283 EX_BINARY_OUTPUT, 284 ) 285 self.assertTrue( 286 'CxxExceptionInTestBodyTest::TearDown() called as expected.' 287 in EX_BINARY_OUTPUT, 288 EX_BINARY_OUTPUT, 289 ) 290 291 def testCatchesNonStdCxxExceptions(self): 292 self.assertTrue( 293 'Unknown C++ exception thrown in the test body' in EX_BINARY_OUTPUT, 294 EX_BINARY_OUTPUT, 295 ) 296 297 def testUnhandledCxxExceptionsAbortTheProgram(self): 298 # Filters out SEH exception tests on Windows. Unhandled SEH exceptions 299 # cause tests to show pop-up windows there. 300 filter_out_seh_tests_flag = FILTER_FLAG + '=-*Seh*' 301 # By default, Google Test doesn't catch the exceptions. 302 uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess( 303 [EX_EXE_PATH, NO_CATCH_EXCEPTIONS_FLAG, filter_out_seh_tests_flag], 304 env=environ, 305 ).output 306 307 self.assertIn( 308 'Unhandled C++ exception terminating the program', 309 uncaught_exceptions_ex_binary_output, 310 ) 311 self.assertNotIn('unexpected', uncaught_exceptions_ex_binary_output) 312 313 314if __name__ == '__main__': 315 gtest_test_utils.Main() 316