1*481dde66SAndroid Build Coastguard Worker# Copyright 2006, Google Inc. 2*481dde66SAndroid Build Coastguard Worker# All rights reserved. 3*481dde66SAndroid Build Coastguard Worker# 4*481dde66SAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without 5*481dde66SAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are 6*481dde66SAndroid Build Coastguard Worker# met: 7*481dde66SAndroid Build Coastguard Worker# 8*481dde66SAndroid Build Coastguard Worker# * Redistributions of source code must retain the above copyright 9*481dde66SAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer. 10*481dde66SAndroid Build Coastguard Worker# * Redistributions in binary form must reproduce the above 11*481dde66SAndroid Build Coastguard Worker# copyright notice, this list of conditions and the following disclaimer 12*481dde66SAndroid Build Coastguard Worker# in the documentation and/or other materials provided with the 13*481dde66SAndroid Build Coastguard Worker# distribution. 14*481dde66SAndroid Build Coastguard Worker# * Neither the name of Google Inc. nor the names of its 15*481dde66SAndroid Build Coastguard Worker# contributors may be used to endorse or promote products derived from 16*481dde66SAndroid Build Coastguard Worker# this software without specific prior written permission. 17*481dde66SAndroid Build Coastguard Worker# 18*481dde66SAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19*481dde66SAndroid Build Coastguard Worker# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20*481dde66SAndroid Build Coastguard Worker# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21*481dde66SAndroid Build Coastguard Worker# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22*481dde66SAndroid Build Coastguard Worker# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23*481dde66SAndroid Build Coastguard Worker# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24*481dde66SAndroid Build Coastguard Worker# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25*481dde66SAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26*481dde66SAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27*481dde66SAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28*481dde66SAndroid Build Coastguard Worker# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*481dde66SAndroid Build Coastguard Worker 30*481dde66SAndroid Build Coastguard Worker"""Unit test utilities for Google C++ Testing and Mocking Framework.""" 31*481dde66SAndroid Build Coastguard Worker# Suppresses the 'Import not at the top of the file' lint complaint. 32*481dde66SAndroid Build Coastguard Worker# pylint: disable=g-import-not-at-top 33*481dde66SAndroid Build Coastguard Worker 34*481dde66SAndroid Build Coastguard Workerimport os 35*481dde66SAndroid Build Coastguard Workerimport subprocess 36*481dde66SAndroid Build Coastguard Workerimport sys 37*481dde66SAndroid Build Coastguard Worker 38*481dde66SAndroid Build Coastguard WorkerIS_WINDOWS = os.name == 'nt' 39*481dde66SAndroid Build Coastguard WorkerIS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0] 40*481dde66SAndroid Build Coastguard WorkerIS_OS2 = os.name == 'os2' 41*481dde66SAndroid Build Coastguard Worker 42*481dde66SAndroid Build Coastguard Workerimport atexit 43*481dde66SAndroid Build Coastguard Workerimport shutil 44*481dde66SAndroid Build Coastguard Workerimport tempfile 45*481dde66SAndroid Build Coastguard Workerimport unittest as _test_module 46*481dde66SAndroid Build Coastguard Worker# pylint: enable=g-import-not-at-top 47*481dde66SAndroid Build Coastguard Worker 48*481dde66SAndroid Build Coastguard WorkerGTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT' 49*481dde66SAndroid Build Coastguard Worker 50*481dde66SAndroid Build Coastguard Worker# The environment variable for specifying the path to the premature-exit file. 51*481dde66SAndroid Build Coastguard WorkerPREMATURE_EXIT_FILE_ENV_VAR = 'TEST_PREMATURE_EXIT_FILE' 52*481dde66SAndroid Build Coastguard Worker 53*481dde66SAndroid Build Coastguard Workerenviron = os.environ.copy() 54*481dde66SAndroid Build Coastguard Worker 55*481dde66SAndroid Build Coastguard Worker 56*481dde66SAndroid Build Coastguard Workerdef SetEnvVar(env_var, value): 57*481dde66SAndroid Build Coastguard Worker """Sets/unsets an environment variable to a given value.""" 58*481dde66SAndroid Build Coastguard Worker 59*481dde66SAndroid Build Coastguard Worker if value is not None: 60*481dde66SAndroid Build Coastguard Worker environ[env_var] = value 61*481dde66SAndroid Build Coastguard Worker elif env_var in environ: 62*481dde66SAndroid Build Coastguard Worker del environ[env_var] 63*481dde66SAndroid Build Coastguard Worker 64*481dde66SAndroid Build Coastguard Worker 65*481dde66SAndroid Build Coastguard Worker# Here we expose a class from a particular module, depending on the 66*481dde66SAndroid Build Coastguard Worker# environment. 67*481dde66SAndroid Build Coastguard WorkerTestCase = _test_module.TestCase 68*481dde66SAndroid Build Coastguard Worker 69*481dde66SAndroid Build Coastguard Worker# Initially maps a flag to its default value. After 70*481dde66SAndroid Build Coastguard Worker# _ParseAndStripGTestFlags() is called, maps a flag to its actual value. 71*481dde66SAndroid Build Coastguard Worker_flag_map = { 72*481dde66SAndroid Build Coastguard Worker 'source_dir': os.path.dirname(sys.argv[0]), 73*481dde66SAndroid Build Coastguard Worker 'build_dir': os.path.dirname(sys.argv[0]), 74*481dde66SAndroid Build Coastguard Worker} 75*481dde66SAndroid Build Coastguard Worker_gtest_flags_are_parsed = False 76*481dde66SAndroid Build Coastguard Worker 77*481dde66SAndroid Build Coastguard Worker 78*481dde66SAndroid Build Coastguard Workerdef _ParseAndStripGTestFlags(argv): 79*481dde66SAndroid Build Coastguard Worker """Parses and strips Google Test flags from argv. This is idempotent.""" 80*481dde66SAndroid Build Coastguard Worker 81*481dde66SAndroid Build Coastguard Worker global _gtest_flags_are_parsed 82*481dde66SAndroid Build Coastguard Worker if _gtest_flags_are_parsed: 83*481dde66SAndroid Build Coastguard Worker return 84*481dde66SAndroid Build Coastguard Worker 85*481dde66SAndroid Build Coastguard Worker _gtest_flags_are_parsed = True 86*481dde66SAndroid Build Coastguard Worker for flag in _flag_map: 87*481dde66SAndroid Build Coastguard Worker # The environment variable overrides the default value. 88*481dde66SAndroid Build Coastguard Worker if flag.upper() in os.environ: 89*481dde66SAndroid Build Coastguard Worker _flag_map[flag] = os.environ[flag.upper()] 90*481dde66SAndroid Build Coastguard Worker 91*481dde66SAndroid Build Coastguard Worker # The command line flag overrides the environment variable. 92*481dde66SAndroid Build Coastguard Worker i = 1 # Skips the program name. 93*481dde66SAndroid Build Coastguard Worker while i < len(argv): 94*481dde66SAndroid Build Coastguard Worker prefix = '--' + flag + '=' 95*481dde66SAndroid Build Coastguard Worker if argv[i].startswith(prefix): 96*481dde66SAndroid Build Coastguard Worker _flag_map[flag] = argv[i][len(prefix) :] 97*481dde66SAndroid Build Coastguard Worker del argv[i] 98*481dde66SAndroid Build Coastguard Worker break 99*481dde66SAndroid Build Coastguard Worker else: 100*481dde66SAndroid Build Coastguard Worker # We don't increment i in case we just found a --gtest_* flag 101*481dde66SAndroid Build Coastguard Worker # and removed it from argv. 102*481dde66SAndroid Build Coastguard Worker i += 1 103*481dde66SAndroid Build Coastguard Worker 104*481dde66SAndroid Build Coastguard Worker 105*481dde66SAndroid Build Coastguard Workerdef GetFlag(flag): 106*481dde66SAndroid Build Coastguard Worker """Returns the value of the given flag.""" 107*481dde66SAndroid Build Coastguard Worker 108*481dde66SAndroid Build Coastguard Worker # In case GetFlag() is called before Main(), we always call 109*481dde66SAndroid Build Coastguard Worker # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags 110*481dde66SAndroid Build Coastguard Worker # are parsed. 111*481dde66SAndroid Build Coastguard Worker _ParseAndStripGTestFlags(sys.argv) 112*481dde66SAndroid Build Coastguard Worker 113*481dde66SAndroid Build Coastguard Worker return _flag_map[flag] 114*481dde66SAndroid Build Coastguard Worker 115*481dde66SAndroid Build Coastguard Worker 116*481dde66SAndroid Build Coastguard Workerdef GetSourceDir(): 117*481dde66SAndroid Build Coastguard Worker """Returns the absolute path of the directory where the .py files are.""" 118*481dde66SAndroid Build Coastguard Worker 119*481dde66SAndroid Build Coastguard Worker return os.path.abspath(GetFlag('source_dir')) 120*481dde66SAndroid Build Coastguard Worker 121*481dde66SAndroid Build Coastguard Worker 122*481dde66SAndroid Build Coastguard Workerdef GetBuildDir(): 123*481dde66SAndroid Build Coastguard Worker """Returns the absolute path of the directory where the test binaries are.""" 124*481dde66SAndroid Build Coastguard Worker 125*481dde66SAndroid Build Coastguard Worker return os.path.abspath(GetFlag('build_dir')) 126*481dde66SAndroid Build Coastguard Worker 127*481dde66SAndroid Build Coastguard Worker 128*481dde66SAndroid Build Coastguard Worker_temp_dir = None 129*481dde66SAndroid Build Coastguard Worker 130*481dde66SAndroid Build Coastguard Workerdef _RemoveTempDir(): 131*481dde66SAndroid Build Coastguard Worker if _temp_dir: 132*481dde66SAndroid Build Coastguard Worker shutil.rmtree(_temp_dir, ignore_errors=True) 133*481dde66SAndroid Build Coastguard Worker 134*481dde66SAndroid Build Coastguard Workeratexit.register(_RemoveTempDir) 135*481dde66SAndroid Build Coastguard Worker 136*481dde66SAndroid Build Coastguard Worker 137*481dde66SAndroid Build Coastguard Workerdef GetTempDir(): 138*481dde66SAndroid Build Coastguard Worker global _temp_dir 139*481dde66SAndroid Build Coastguard Worker if not _temp_dir: 140*481dde66SAndroid Build Coastguard Worker _temp_dir = tempfile.mkdtemp() 141*481dde66SAndroid Build Coastguard Worker return _temp_dir 142*481dde66SAndroid Build Coastguard Worker 143*481dde66SAndroid Build Coastguard Worker 144*481dde66SAndroid Build Coastguard Workerdef GetTestExecutablePath(executable_name, build_dir=None): 145*481dde66SAndroid Build Coastguard Worker """Returns the absolute path of the test binary given its name. 146*481dde66SAndroid Build Coastguard Worker 147*481dde66SAndroid Build Coastguard Worker The function will print a message and abort the program if the resulting file 148*481dde66SAndroid Build Coastguard Worker doesn't exist. 149*481dde66SAndroid Build Coastguard Worker 150*481dde66SAndroid Build Coastguard Worker Args: 151*481dde66SAndroid Build Coastguard Worker executable_name: name of the test binary that the test script runs. 152*481dde66SAndroid Build Coastguard Worker build_dir: directory where to look for executables, by default the 153*481dde66SAndroid Build Coastguard Worker result of GetBuildDir(). 154*481dde66SAndroid Build Coastguard Worker 155*481dde66SAndroid Build Coastguard Worker Returns: 156*481dde66SAndroid Build Coastguard Worker The absolute path of the test binary. 157*481dde66SAndroid Build Coastguard Worker """ 158*481dde66SAndroid Build Coastguard Worker 159*481dde66SAndroid Build Coastguard Worker path = os.path.abspath( 160*481dde66SAndroid Build Coastguard Worker os.path.join(build_dir or GetBuildDir(), executable_name) 161*481dde66SAndroid Build Coastguard Worker ) 162*481dde66SAndroid Build Coastguard Worker if (IS_WINDOWS or IS_CYGWIN or IS_OS2) and not path.endswith('.exe'): 163*481dde66SAndroid Build Coastguard Worker path += '.exe' 164*481dde66SAndroid Build Coastguard Worker 165*481dde66SAndroid Build Coastguard Worker if not os.path.exists(path): 166*481dde66SAndroid Build Coastguard Worker message = ( 167*481dde66SAndroid Build Coastguard Worker 'Unable to find the test binary "%s". Please make sure to provide\n' 168*481dde66SAndroid Build Coastguard Worker 'a path to the binary via the --build_dir flag or the BUILD_DIR\n' 169*481dde66SAndroid Build Coastguard Worker 'environment variable.' % path 170*481dde66SAndroid Build Coastguard Worker ) 171*481dde66SAndroid Build Coastguard Worker print(message, file=sys.stderr) 172*481dde66SAndroid Build Coastguard Worker sys.exit(1) 173*481dde66SAndroid Build Coastguard Worker 174*481dde66SAndroid Build Coastguard Worker return path 175*481dde66SAndroid Build Coastguard Worker 176*481dde66SAndroid Build Coastguard Worker 177*481dde66SAndroid Build Coastguard Workerdef GetExitStatus(exit_code): 178*481dde66SAndroid Build Coastguard Worker """Returns the argument to exit(), or -1 if exit() wasn't called. 179*481dde66SAndroid Build Coastguard Worker 180*481dde66SAndroid Build Coastguard Worker Args: 181*481dde66SAndroid Build Coastguard Worker exit_code: the result value of os.system(command). 182*481dde66SAndroid Build Coastguard Worker """ 183*481dde66SAndroid Build Coastguard Worker 184*481dde66SAndroid Build Coastguard Worker if os.name == 'nt': 185*481dde66SAndroid Build Coastguard Worker # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns 186*481dde66SAndroid Build Coastguard Worker # the argument to exit() directly. 187*481dde66SAndroid Build Coastguard Worker return exit_code 188*481dde66SAndroid Build Coastguard Worker else: 189*481dde66SAndroid Build Coastguard Worker # On Unix, os.WEXITSTATUS() must be used to extract the exit status 190*481dde66SAndroid Build Coastguard Worker # from the result of os.system(). 191*481dde66SAndroid Build Coastguard Worker if os.WIFEXITED(exit_code): 192*481dde66SAndroid Build Coastguard Worker return os.WEXITSTATUS(exit_code) 193*481dde66SAndroid Build Coastguard Worker else: 194*481dde66SAndroid Build Coastguard Worker return -1 195*481dde66SAndroid Build Coastguard Worker 196*481dde66SAndroid Build Coastguard Worker 197*481dde66SAndroid Build Coastguard Workerclass Subprocess: 198*481dde66SAndroid Build Coastguard Worker 199*481dde66SAndroid Build Coastguard Worker def __init__(self, command, working_dir=None, capture_stderr=True, env=None): 200*481dde66SAndroid Build Coastguard Worker """Changes into a specified directory, if provided, and executes a command. 201*481dde66SAndroid Build Coastguard Worker 202*481dde66SAndroid Build Coastguard Worker Restores the old directory afterwards. 203*481dde66SAndroid Build Coastguard Worker 204*481dde66SAndroid Build Coastguard Worker Args: 205*481dde66SAndroid Build Coastguard Worker command: The command to run, in the form of sys.argv. 206*481dde66SAndroid Build Coastguard Worker working_dir: The directory to change into. 207*481dde66SAndroid Build Coastguard Worker capture_stderr: Determines whether to capture stderr in the output member 208*481dde66SAndroid Build Coastguard Worker or to discard it. 209*481dde66SAndroid Build Coastguard Worker env: Dictionary with environment to pass to the subprocess. 210*481dde66SAndroid Build Coastguard Worker 211*481dde66SAndroid Build Coastguard Worker Returns: 212*481dde66SAndroid Build Coastguard Worker An object that represents outcome of the executed process. It has the 213*481dde66SAndroid Build Coastguard Worker following attributes: 214*481dde66SAndroid Build Coastguard Worker terminated_by_signal True if and only if the child process has been 215*481dde66SAndroid Build Coastguard Worker terminated by a signal. 216*481dde66SAndroid Build Coastguard Worker exited True if and only if the child process exited 217*481dde66SAndroid Build Coastguard Worker normally. 218*481dde66SAndroid Build Coastguard Worker exit_code The code with which the child process exited. 219*481dde66SAndroid Build Coastguard Worker output Child process's stdout and stderr output 220*481dde66SAndroid Build Coastguard Worker combined in a string. 221*481dde66SAndroid Build Coastguard Worker """ 222*481dde66SAndroid Build Coastguard Worker 223*481dde66SAndroid Build Coastguard Worker if capture_stderr: 224*481dde66SAndroid Build Coastguard Worker stderr = subprocess.STDOUT 225*481dde66SAndroid Build Coastguard Worker else: 226*481dde66SAndroid Build Coastguard Worker stderr = subprocess.PIPE 227*481dde66SAndroid Build Coastguard Worker 228*481dde66SAndroid Build Coastguard Worker p = subprocess.Popen( 229*481dde66SAndroid Build Coastguard Worker command, 230*481dde66SAndroid Build Coastguard Worker stdout=subprocess.PIPE, 231*481dde66SAndroid Build Coastguard Worker stderr=stderr, 232*481dde66SAndroid Build Coastguard Worker cwd=working_dir, 233*481dde66SAndroid Build Coastguard Worker universal_newlines=True, 234*481dde66SAndroid Build Coastguard Worker env=env, 235*481dde66SAndroid Build Coastguard Worker ) 236*481dde66SAndroid Build Coastguard Worker # communicate returns a tuple with the file object for the child's 237*481dde66SAndroid Build Coastguard Worker # output. 238*481dde66SAndroid Build Coastguard Worker self.output = p.communicate()[0] 239*481dde66SAndroid Build Coastguard Worker self._return_code = p.returncode 240*481dde66SAndroid Build Coastguard Worker 241*481dde66SAndroid Build Coastguard Worker if bool(self._return_code & 0x80000000): 242*481dde66SAndroid Build Coastguard Worker self.terminated_by_signal = True 243*481dde66SAndroid Build Coastguard Worker self.exited = False 244*481dde66SAndroid Build Coastguard Worker else: 245*481dde66SAndroid Build Coastguard Worker self.terminated_by_signal = False 246*481dde66SAndroid Build Coastguard Worker self.exited = True 247*481dde66SAndroid Build Coastguard Worker self.exit_code = self._return_code 248*481dde66SAndroid Build Coastguard Worker 249*481dde66SAndroid Build Coastguard Worker 250*481dde66SAndroid Build Coastguard Workerdef Main(): 251*481dde66SAndroid Build Coastguard Worker """Runs the unit test.""" 252*481dde66SAndroid Build Coastguard Worker 253*481dde66SAndroid Build Coastguard Worker # We must call _ParseAndStripGTestFlags() before calling 254*481dde66SAndroid Build Coastguard Worker # unittest.main(). Otherwise the latter will be confused by the 255*481dde66SAndroid Build Coastguard Worker # --gtest_* flags. 256*481dde66SAndroid Build Coastguard Worker _ParseAndStripGTestFlags(sys.argv) 257*481dde66SAndroid Build Coastguard Worker # The tested binaries should not be writing XML output files unless the 258*481dde66SAndroid Build Coastguard Worker # script explicitly instructs them to. 259*481dde66SAndroid Build Coastguard Worker if GTEST_OUTPUT_VAR_NAME in os.environ: 260*481dde66SAndroid Build Coastguard Worker del os.environ[GTEST_OUTPUT_VAR_NAME] 261*481dde66SAndroid Build Coastguard Worker 262*481dde66SAndroid Build Coastguard Worker _test_module.main() 263