From 95536ab53bba952d748f6c1535ba9a3b2ff7e294 Mon Sep 17 00:00:00 2001 From: vladlosev Date: Wed, 26 Nov 2008 20:02:45 +0000 Subject: Fixed gtest_break_on_failure_unittest on Ubuntu 8.04 and Windows --- test/gtest_break_on_failure_unittest.py | 18 ++++--- test/gtest_break_on_failure_unittest_.cc | 8 +++ test/gtest_test_utils.py | 87 ++++++++++++++++++++++++-------- test/gtest_xml_outfiles_test.py | 9 ++-- test/gtest_xml_output_unittest.py | 24 ++++----- 5 files changed, 101 insertions(+), 45 deletions(-) (limited to 'test') diff --git a/test/gtest_break_on_failure_unittest.py b/test/gtest_break_on_failure_unittest.py index 88716c9c..a295ac40 100755 --- a/test/gtest_break_on_failure_unittest.py +++ b/test/gtest_break_on_failure_unittest.py @@ -77,8 +77,11 @@ def Run(command): """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise. """ - exit_code = os.system(command) - return os.WIFSIGNALED(exit_code) + p = gtest_test_utils.Subprocess(command) + if p.terminated_by_signal: + return 1 + else: + return 0 # The unit test. @@ -112,11 +115,13 @@ class GTestBreakOnFailureUnitTest(unittest.TestCase): if flag_value is None: flag = '' elif flag_value == '0': - flag = ' --%s=0' % BREAK_ON_FAILURE_FLAG + flag = '--%s=0' % BREAK_ON_FAILURE_FLAG else: - flag = ' --%s' % BREAK_ON_FAILURE_FLAG + flag = '--%s' % BREAK_ON_FAILURE_FLAG - command = EXE_PATH + flag + command = [EXE_PATH] + if flag: + command.append(flag) if expect_seg_fault: should_or_not = 'should' @@ -128,7 +133,8 @@ class GTestBreakOnFailureUnitTest(unittest.TestCase): SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, None) msg = ('when %s%s, an assertion failure in "%s" %s cause a seg-fault.' % - (BREAK_ON_FAILURE_ENV_VAR, env_var_value_msg, command, should_or_not)) + (BREAK_ON_FAILURE_ENV_VAR, env_var_value_msg, ' '.join(command), + should_or_not)) self.assert_(has_seg_fault == expect_seg_fault, msg) def testDefaultBehavior(self): diff --git a/test/gtest_break_on_failure_unittest_.cc b/test/gtest_break_on_failure_unittest_.cc index f272fdd5..84c4a2ee 100644 --- a/test/gtest_break_on_failure_unittest_.cc +++ b/test/gtest_break_on_failure_unittest_.cc @@ -41,6 +41,9 @@ #include +#ifdef GTEST_OS_WINDOWS +#include +#endif namespace { @@ -53,6 +56,11 @@ TEST(Foo, Bar) { int main(int argc, char **argv) { +#ifdef GTEST_OS_WINDOWS + // Suppresses display of the Windows error dialog upon encountering + // a general protection fault (segment violation). + SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS); +#endif testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/gtest_test_utils.py b/test/gtest_test_utils.py index a3f0138e..8ee99c08 100755 --- a/test/gtest_test_utils.py +++ b/test/gtest_test_utils.py @@ -37,6 +37,13 @@ import os import sys import unittest +try: + import subprocess + _SUBPROCESS_MODULE_AVAILABLE = True +except: + import popen2 + _SUBPROCESS_MODULE_AVAILABLE = False + # Initially maps a flag to its default value. After # _ParseAndStripGTestFlags() is called, maps a flag to its actual @@ -116,29 +123,65 @@ def GetExitStatus(exit_code): return -1 -def RunCommandSuppressOutput(command, working_dir=None): - """Changes into a specified directory, if provided, and executes a command. - Restores the old directory afterwards. - - Args: - command: A command to run. - working_dir: A directory to change into. - """ - - old_dir = None - try: - if working_dir is not None: +class Subprocess: + def __init__(this, command, working_dir=None): + """Changes into a specified directory, if provided, and executes a command. + Restores the old directory afterwards. Execution results are returned + via the following attributes: + terminated_by_sygnal True iff the child process has been terminated + by a signal. + signal Sygnal that terminated the child process. + exited True iff the child process exited normally. + exit_code The code with which the child proces exited. + output Child process's stdout and stderr output + combined in a string. + + Args: + command: A command to run. + working_dir: A directory to change into. + """ + + # The subprocess module is the preferrable way of running programs + # since it is available and behaves consistently on all platforms, + # including Windows. But it is only available starting in python 2.4. + # In earlier python versions, we revert to the popen2 module, which is + # available in python 2.0 and later but doesn't provide required + # functionality (Popen4) under Windows. This allows us to support Mac + # OS X 10.4 Tiger, which has python 2.3 installed. + if _SUBPROCESS_MODULE_AVAILABLE: + p = subprocess.Popen(command, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + cwd=working_dir, universal_newlines=True) + # communicate returns a tuple with the file obect for the child's + # output. + this.output = p.communicate()[0] + this._return_code = p.returncode + else: old_dir = os.getcwd() - os.chdir(working_dir) - f = os.popen(command, 'r') - f.read() - ret_code = f.close() - finally: - if old_dir is not None: - os.chdir(old_dir) - if ret_code is None: - ret_code = 0 - return ret_code + try: + if working_dir is not None: + os.chdir(working_dir) + p = popen2.Popen4(command) + p.tochild.close() + this.output = p.fromchild.read() + ret_code = p.wait() + finally: + os.chdir(old_dir) + # Converts ret_code to match the semantics of + # subprocess.Popen.returncode. + if os.WIFSIGNALED(ret_code): + this._return_code = -os.WTERMSIG(ret_code) + else: # os.WIFEXITED(ret_code) should return True here. + this._return_code = os.WEXITSTATUS(ret_code) + + if this._return_code < 0: + this.terminated_by_signal = True + this.exited = False + this.signal = -this._return_code + else: + this.terminated_by_signal = False + this.exited = True + this.exit_code = this._return_code def Main(): diff --git a/test/gtest_xml_outfiles_test.py b/test/gtest_xml_outfiles_test.py index d5d7266a..4ebc15ef 100755 --- a/test/gtest_xml_outfiles_test.py +++ b/test/gtest_xml_outfiles_test.py @@ -100,11 +100,10 @@ class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase): def _TestOutFile(self, test_name, expected_xml): gtest_prog_path = os.path.join(gtest_test_utils.GetBuildDir(), test_name) - command = "%s --gtest_output=xml:%s" % (gtest_prog_path, self.output_dir_) - status = gtest_test_utils.RunCommandSuppressOutput( - command, - working_dir=tempfile.mkdtemp()) - self.assertEquals(0, gtest_test_utils.GetExitStatus(status)) + command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_] + p = gtest_test_utils.Subprocess(command, working_dir=tempfile.mkdtemp()) + self.assert_(p.exited) + self.assertEquals(0, p.exit_code) # TODO(wan@google.com): libtool causes the built test binary to be # named lt-gtest_xml_outfiles_test_ instead of diff --git a/test/gtest_xml_output_unittest.py b/test/gtest_xml_output_unittest.py index c5f9f57f..5e0b220b 100755 --- a/test/gtest_xml_output_unittest.py +++ b/test/gtest_xml_output_unittest.py @@ -131,10 +131,11 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase): if e.errno != errno.ENOENT: raise - status = gtest_test_utils.RunCommandSuppressOutput( - "%s %s=xml" % (gtest_prog_path, GTEST_OUTPUT_FLAG), - working_dir=temp_dir) - self.assertEquals(0, gtest_test_utils.GetExitStatus(status)) + p = gtest_test_utils.Subprocess( + [gtest_prog_path, "%s=xml" % GTEST_OUTPUT_FLAG], + working_dir=temp_dir) + self.assert_(p.exited) + self.assertEquals(0, p.exit_code) self.assert_(os.path.isfile(output_file)) @@ -150,18 +151,17 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase): gtest_prog_path = os.path.join(gtest_test_utils.GetBuildDir(), gtest_prog_name) - command = ("%s %s=xml:%s" % (gtest_prog_path, GTEST_OUTPUT_FLAG, xml_path)) - status = gtest_test_utils.RunCommandSuppressOutput(command) - if os.WIFSIGNALED(status): - signal = os.WTERMSIG(status) + command = [gtest_prog_path, "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path)] + p = gtest_test_utils.Subprocess(command) + if p.terminated_by_signal: self.assert_(False, - "%s was killed by signal %d" % (gtest_prog_name, signal)) + "%s was killed by signal %d" % (gtest_prog_name, p.signal)) else: - exit_code = gtest_test_utils.GetExitStatus(status) - self.assertEquals(expected_exit_code, exit_code, + self.assert_(p.exited) + self.assertEquals(expected_exit_code, p.exit_code, "'%s' exited with code %s, which doesn't match " "the expected exit code %s." - % (command, exit_code, expected_exit_code)) + % (command, p.exit_code, expected_exit_code)) expected = minidom.parseString(expected_xml) actual = minidom.parse(xml_path) -- cgit v1.2.3