media/webrtc/trunk/testing/gtest/test/gtest_test_utils.py

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rwxr-xr-x

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

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

mercurial