1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#!/usr/bin/env python 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Copyright 2006, Google Inc. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# All rights reserved. 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Redistribution and use in source and binary forms, with or without 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# modification, are permitted provided that the following conditions are 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# met: 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# * Redistributions of source code must retain the above copyright 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# notice, this list of conditions and the following disclaimer. 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# * Redistributions in binary form must reproduce the above 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# copyright notice, this list of conditions and the following disclaimer 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# in the documentation and/or other materials provided with the 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# distribution. 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# * Neither the name of Google Inc. nor the names of its 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# contributors may be used to endorse or promote products derived from 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# this software without specific prior written permission. 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch"""Unit test utilities for Google C++ Testing Framework.""" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch__author__ = 'wan@google.com (Zhanyong Wan)' 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport atexit 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport os 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport shutil 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport sys 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport tempfile 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochimport unittest 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch_test_module = unittest 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Suppresses the 'Import not at the top of the file' lint complaint. 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# pylint: disable-msg=C6204 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtry: 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch import subprocess 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _SUBPROCESS_MODULE_AVAILABLE = True 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochexcept: 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch import popen2 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _SUBPROCESS_MODULE_AVAILABLE = False 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# pylint: enable-msg=C6204 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT' 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIS_WINDOWS = os.name == 'nt' 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochIS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0] 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Here we expose a class from a particular module, depending on the 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# environment. The comment suppresses the 'Invalid variable name' lint 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# complaint. 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTestCase = _test_module.TestCase # pylint: disable-msg=C6409 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# Initially maps a flag to its default value. After 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch# _ParseAndStripGTestFlags() is called, maps a flag to its actual value. 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick_flag_map = {'source_dir': os.path.dirname(sys.argv[0]), 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'build_dir': os.path.dirname(sys.argv[0])} 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch_gtest_flags_are_parsed = False 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef _ParseAndStripGTestFlags(argv): 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Parses and strips Google Test flags from argv. This is idempotent.""" 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # Suppresses the lint complaint about a global variable since we need it 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # here to maintain module-wide state. 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch global _gtest_flags_are_parsed # pylint: disable-msg=W0603 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if _gtest_flags_are_parsed: 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _gtest_flags_are_parsed = True 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for flag in _flag_map: 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # The environment variable overrides the default value. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if flag.upper() in os.environ: 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _flag_map[flag] = os.environ[flag.upper()] 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # The command line flag overrides the environment variable. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i = 1 # Skips the program name. 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while i < len(argv): 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefix = '--' + flag + '=' 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if argv[i].startswith(prefix): 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _flag_map[flag] = argv[i][len(prefix):] 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch del argv[i] 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # We don't increment i in case we just found a --gtest_* flag 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # and removed it from argv. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i += 1 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetFlag(flag): 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns the value of the given flag.""" 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # In case GetFlag() is called before Main(), we always call 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # are parsed. 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _ParseAndStripGTestFlags(sys.argv) 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return _flag_map[flag] 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetSourceDir(): 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns the absolute path of the directory where the .py files are.""" 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return os.path.abspath(GetFlag('source_dir')) 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetBuildDir(): 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns the absolute path of the directory where the test binaries are.""" 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return os.path.abspath(GetFlag('build_dir')) 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch_temp_dir = None 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef _RemoveTempDir(): 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if _temp_dir: 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutil.rmtree(_temp_dir, ignore_errors=True) 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochatexit.register(_RemoveTempDir) 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetTempDir(): 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns a directory for temporary files.""" 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch global _temp_dir 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if not _temp_dir: 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _temp_dir = tempfile.mkdtemp() 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return _temp_dir 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetTestExecutablePath(executable_name, build_dir=None): 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns the absolute path of the test binary given its name. 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch The function will print a message and abort the program if the resulting file 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch doesn't exist. 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Args: 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch executable_name: name of the test binary that the test script runs. 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch build_dir: directory where to look for executables, by default 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch the result of GetBuildDir(). 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Returns: 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch The absolute path of the test binary. 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """ 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path = os.path.abspath(os.path.join(build_dir or GetBuildDir(), 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch executable_name)) 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IS_WINDOWS or IS_CYGWIN) and not path.endswith('.exe'): 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path += '.exe' 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if not os.path.exists(path): 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch message = ( 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 'Unable to find the test binary. Please make sure to provide path\n' 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'to the binary via the --build_dir flag or the BUILD_DIR\n' 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'environment variable.') 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch print >> sys.stderr, message 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sys.exit(1) 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return path 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef GetExitStatus(exit_code): 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Returns the argument to exit(), or -1 if exit() wasn't called. 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Args: 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch exit_code: the result value of os.system(command). 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """ 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if os.name == 'nt': 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # the argument to exit() directly. 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return exit_code 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # On Unix, os.WEXITSTATUS() must be used to extract the exit status 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # from the result of os.system(). 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if os.WIFEXITED(exit_code): 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return os.WEXITSTATUS(exit_code) 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Subprocess: 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch def __init__(self, command, working_dir=None, capture_stderr=True, env=None): 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Changes into a specified directory, if provided, and executes a command. 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Restores the old directory afterwards. 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Args: 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command: The command to run, in the form of sys.argv. 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch working_dir: The directory to change into. 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch capture_stderr: Determines whether to capture stderr in the output member 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch or to discard it. 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch env: Dictionary with environment to pass to the subprocess. 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Returns: 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch An object that represents outcome of the executed process. It has the 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch following attributes: 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch terminated_by_signal True iff the child process has been terminated 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch by a signal. 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signal Sygnal that terminated the child process. 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch exited True iff the child process exited normally. 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch exit_code The code with which the child process exited. 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output Child process's stdout and stderr output 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch combined in a string. 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """ 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # The subprocess module is the preferrable way of running programs 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # since it is available and behaves consistently on all platforms, 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # including Windows. But it is only available starting in python 2.4. 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # In earlier python versions, we revert to the popen2 module, which is 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # available in python 2.0 and later but doesn't provide required 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # functionality (Popen4) under Windows. This allows us to support Mac 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # OS X 10.4 Tiger, which has python 2.3 installed. 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if _SUBPROCESS_MODULE_AVAILABLE: 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if capture_stderr: 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stderr = subprocess.STDOUT 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stderr = subprocess.PIPE 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch p = subprocess.Popen(command, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stdout=subprocess.PIPE, stderr=stderr, 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cwd=working_dir, universal_newlines=True, env=env) 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # communicate returns a tuple with the file obect for the child's 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # output. 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.output = p.communicate()[0] 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self._return_code = p.returncode 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_dir = os.getcwd() 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch def _ReplaceEnvDict(dest, src): 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # Changes made by os.environ.clear are not inheritable by child 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # processes until Python 2.6. To produce inheritable changes we have 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # to delete environment items with the del statement. 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for key in dest: 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch del dest[key] 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dest.update(src) 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # When 'env' is not None, backup the environment variables and replace 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # them with the passed 'env'. When 'env' is None, we simply use the 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # current 'os.environ' for compatibility with the subprocess.Popen 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # semantics used above. 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if env is not None: 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_environ = os.environ.copy() 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _ReplaceEnvDict(os.environ, env) 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch try: 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if working_dir is not None: 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch os.chdir(working_dir) 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if capture_stderr: 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch p = popen2.Popen4(command) 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch p = popen2.Popen3(command) 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch p.tochild.close() 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.output = p.fromchild.read() 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ret_code = p.wait() 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch finally: 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch os.chdir(old_dir) 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # Restore the old environment variables 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # if they were replaced. 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if env is not None: 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _ReplaceEnvDict(os.environ, old_environ) 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # Converts ret_code to match the semantics of 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # subprocess.Popen.returncode. 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if os.WIFSIGNALED(ret_code): 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self._return_code = -os.WTERMSIG(ret_code) 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: # os.WIFEXITED(ret_code) should return True here. 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self._return_code = os.WEXITSTATUS(ret_code) 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if self._return_code < 0: 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.terminated_by_signal = True 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.exited = False 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.signal = -self._return_code 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else: 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.terminated_by_signal = False 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.exited = True 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch self.exit_code = self._return_code 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdef Main(): 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch """Runs the unit test.""" 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # We must call _ParseAndStripGTestFlags() before calling 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # unittest.main(). Otherwise the latter will be confused by the 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # --gtest_* flags. 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _ParseAndStripGTestFlags(sys.argv) 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # The tested binaries should not be writing XML output files unless the 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # script explicitly instructs them to. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # TODO(vladl@google.com): Move this into Subprocess when we implement 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch # passing environment into it as a parameter. 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if GTEST_OUTPUT_VAR_NAME in os.environ: 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch del os.environ[GTEST_OUTPUT_VAR_NAME] 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch _test_module.main() 306