xref: /aosp_15_r20/external/googletest/googletest/test/gtest_test_utils.py (revision 481dde660366d6f317d242b6974ef1b20adb843c)
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