summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtest/gtest_break_on_failure_unittest.py11
-rwxr-xr-xtest/gtest_env_var_test.py10
-rwxr-xr-xtest/gtest_filter_unittest.py61
-rwxr-xr-xtest/gtest_output_test.py46
-rwxr-xr-xtest/gtest_shuffle_test.py14
-rwxr-xr-xtest/gtest_test_utils.py50
6 files changed, 133 insertions, 59 deletions
diff --git a/test/gtest_break_on_failure_unittest.py b/test/gtest_break_on_failure_unittest.py
index 218d371..c819183 100755
--- a/test/gtest_break_on_failure_unittest.py
+++ b/test/gtest_break_on_failure_unittest.py
@@ -69,21 +69,24 @@ EXE_PATH = gtest_test_utils.GetTestExecutablePath(
# Utilities.
+environ = os.environ.copy()
+
+
def SetEnvVar(env_var, value):
"""Sets an environment variable to a given value; unsets it when the
given value is None.
"""
if value is not None:
- os.environ[env_var] = value
- elif env_var in os.environ:
- del os.environ[env_var]
+ environ[env_var] = value
+ elif env_var in environ:
+ del environ[env_var]
def Run(command):
"""Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
- p = gtest_test_utils.Subprocess(command)
+ p = gtest_test_utils.Subprocess(command, env=environ)
if p.terminated_by_signal:
return 1
else:
diff --git a/test/gtest_env_var_test.py b/test/gtest_env_var_test.py
index f8250d4..bcc0bfd 100755
--- a/test/gtest_env_var_test.py
+++ b/test/gtest_env_var_test.py
@@ -42,6 +42,8 @@ IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_env_var_test_')
+environ = os.environ.copy()
+
def AssertEq(expected, actual):
if expected != actual:
@@ -54,9 +56,9 @@ def SetEnvVar(env_var, value):
"""Sets the env variable to 'value'; unsets it when 'value' is None."""
if value is not None:
- os.environ[env_var] = value
- elif env_var in os.environ:
- del os.environ[env_var]
+ environ[env_var] = value
+ elif env_var in environ:
+ del environ[env_var]
def GetFlag(flag):
@@ -65,7 +67,7 @@ def GetFlag(flag):
args = [COMMAND]
if flag is not None:
args += [flag]
- return gtest_test_utils.Subprocess(args).output
+ return gtest_test_utils.Subprocess(args, env=environ).output
def TestFlag(flag, test_val, default_val):
diff --git a/test/gtest_filter_unittest.py b/test/gtest_filter_unittest.py
index a94a521..89171e0 100755
--- a/test/gtest_filter_unittest.py
+++ b/test/gtest_filter_unittest.py
@@ -45,11 +45,42 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import os
import re
import sets
+import sys
+
import gtest_test_utils
# Constants.
-IS_WINDOWS = os.name == 'nt'
+# Checks if this platform can pass empty environment variables to child
+# processes. We set an env variable to an empty string and invoke a python
+# script in a subprocess to print whether the variable is STILL in
+# os.environ. We then use 'eval' to parse the child's output so that an
+# exception is thrown if the input is anything other than 'True' nor 'False'.
+os.environ['EMPTY_VAR'] = ''
+child = gtest_test_utils.Subprocess(
+ [sys.executable, '-c', 'import os; print \'EMPTY_VAR\' in os.environ'])
+CAN_PASS_EMPTY_ENV = eval(child.output)
+
+
+# Check if this platform can unset environment variables in child processes.
+# We set an env variable to a non-empty string, unset it, and invoke
+# a python script in a subprocess to print whether the variable
+# is NO LONGER in os.environ.
+# We use 'eval' to parse the child's output so that an exception
+# is thrown if the input is neither 'True' nor 'False'.
+os.environ['UNSET_VAR'] = 'X'
+del os.environ['UNSET_VAR']
+child = gtest_test_utils.Subprocess(
+ [sys.executable, '-c', 'import os; print \'UNSET_VAR\' not in os.environ'])
+CAN_UNSET_ENV = eval(child.output)
+
+
+# Checks if we should test with an empty filter. This doesn't
+# make sense on platforms that cannot pass empty env variables (Win32)
+# and on platforms that cannot unset variables (since we cannot tell
+# the difference between "" and NULL -- Borland and Solaris < 5.10)
+CAN_TEST_EMPTY_FILTER = (CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV)
+
# The environment variable for specifying the test filters.
FILTER_ENV_VAR = 'GTEST_FILTER'
@@ -119,26 +150,29 @@ param_tests_present = None
# Utilities.
+environ = os.environ.copy()
+
def SetEnvVar(env_var, value):
"""Sets the env variable to 'value'; unsets it when 'value' is None."""
if value is not None:
- os.environ[env_var] = value
- elif env_var in os.environ:
- del os.environ[env_var]
+ environ[env_var] = value
+ elif env_var in environ:
+ del environ[env_var]
def RunAndReturnOutput(args = None):
"""Runs the test program and returns its output."""
- return gtest_test_utils.Subprocess([COMMAND] + (args or [])).output
+ return gtest_test_utils.Subprocess([COMMAND] + (args or []),
+ env=environ).output
def RunAndExtractTestList(args = None):
"""Runs the test program and returns its exit code and a list of tests run."""
- p = gtest_test_utils.Subprocess([COMMAND] + (args or []))
+ p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
tests_run = []
test_case = ''
test = ''
@@ -157,15 +191,12 @@ def RunAndExtractTestList(args = None):
def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
"""Runs the given function and arguments in a modified environment."""
try:
- original_env = os.environ.copy()
- os.environ.update(extra_env)
+ original_env = environ.copy()
+ environ.update(extra_env)
return function(*args, **kwargs)
finally:
- for key in extra_env.iterkeys():
- if key in original_env:
- os.environ[key] = original_env[key]
- else:
- del os.environ[key]
+ environ.clear()
+ environ.update(original_env)
def RunWithSharding(total_shards, shard_index, command):
@@ -223,7 +254,7 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
# we can still test the case when the variable is not supplied (i.e.,
# gtest_filter is None).
# pylint: disable-msg=C6403
- if not IS_WINDOWS or gtest_filter != '':
+ if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
SetEnvVar(FILTER_ENV_VAR, gtest_filter)
tests_run = RunAndExtractTestList()[0]
SetEnvVar(FILTER_ENV_VAR, None)
@@ -265,7 +296,7 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
# we can still test the case when the variable is not supplied (i.e.,
# gtest_filter is None).
# pylint: disable-msg=C6403
- if not IS_WINDOWS or gtest_filter != '':
+ if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
SetEnvVar(FILTER_ENV_VAR, gtest_filter)
partition = []
for i in range(0, total_shards):
diff --git a/test/gtest_output_test.py b/test/gtest_output_test.py
index 8d9a40b..a0aa64f 100755
--- a/test/gtest_output_test.py
+++ b/test/gtest_output_test.py
@@ -48,6 +48,7 @@ import gtest_test_utils
# The flag for generating the golden file
GENGOLDEN_FLAG = '--gengolden'
+CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
IS_WINDOWS = os.name == 'nt'
@@ -123,6 +124,20 @@ def RemoveTime(output):
return re.sub(r'\(\d+ ms', '(? ms', output)
+def RemoveTypeInfoDetails(test_output):
+ """Removes compiler-specific type info from Google Test program's output.
+
+ Args:
+ test_output: the output of a Google Test program.
+
+ Returns:
+ output with type information normalized to canonical form.
+ """
+
+ # some compilers output the name of type 'unsigned int' as 'unsigned'
+ return re.sub(r'unsigned int', 'unsigned', test_output)
+
+
def RemoveTestCounts(output):
"""Removes test counts from a Google Test program's output."""
@@ -184,16 +199,9 @@ def GetShellCommandOutput(env_cmd):
# Spawns cmd in a sub-process, and gets its standard I/O file objects.
# Set and save the environment properly.
- old_env_vars = dict(os.environ)
- os.environ.update(env_cmd[0])
- p = gtest_test_utils.Subprocess(env_cmd[1])
-
- # Changes made by os.environ.clear are not inheritable by child processes
- # until Python 2.6. To produce inheritable changes we have to delete
- # environment items with the del statement.
- for key in os.environ.keys():
- del os.environ[key]
- os.environ.update(old_env_vars)
+ environ = os.environ.copy()
+ environ.update(env_cmd[0])
+ p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
return p.output
@@ -209,8 +217,10 @@ def GetCommandOutput(env_cmd):
"""
# Disables exception pop-ups on Windows.
- os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
- return NormalizeOutput(GetShellCommandOutput(env_cmd))
+ environ, cmdline = env_cmd
+ environ = dict(environ) # Ensures we are modifying a copy.
+ environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
+ return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
def GetOutputOfAllCommands():
@@ -262,11 +272,17 @@ class GTestOutputTest(gtest_test_utils.TestCase):
# We want the test to pass regardless of certain features being
# supported or not.
+
+ # We still have to remove type name specifics in all cases.
+ normalized_actual = RemoveTypeInfoDetails(output)
+ normalized_golden = RemoveTypeInfoDetails(golden)
+
if CAN_GENERATE_GOLDEN_FILE:
- self.assert_(golden == output)
+ self.assert_(normalized_golden == normalized_actual)
else:
- normalized_actual = RemoveTestCounts(output)
- normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(golden))
+ normalized_actual = RemoveTestCounts(normalized_actual)
+ normalized_golden = RemoveTestCounts(self.RemoveUnsupportedTests(
+ normalized_golden))
# This code is very handy when debugging golden file differences:
if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
diff --git a/test/gtest_shuffle_test.py b/test/gtest_shuffle_test.py
index a870a01..30d0303 100755
--- a/test/gtest_shuffle_test.py
+++ b/test/gtest_shuffle_test.py
@@ -78,16 +78,10 @@ def RandomSeedFlag(n):
def RunAndReturnOutput(extra_env, args):
"""Runs the test program and returns its output."""
- try:
- original_env = os.environ.copy()
- os.environ.update(extra_env)
- return gtest_test_utils.Subprocess([COMMAND] + args).output
- finally:
- for key in extra_env.iterkeys():
- if key in original_env:
- os.environ[key] = original_env[key]
- else:
- del os.environ[key]
+ environ_copy = os.environ.copy()
+ environ_copy.update(extra_env)
+
+ return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
def GetTestsForAllIterations(extra_env, args):
diff --git a/test/gtest_test_utils.py b/test/gtest_test_utils.py
index 19b5b22..e0f5973 100755
--- a/test/gtest_test_utils.py
+++ b/test/gtest_test_utils.py
@@ -194,23 +194,28 @@ def GetExitStatus(exit_code):
class Subprocess:
- def __init__(self, command, working_dir=None, capture_stderr=True):
+ def __init__(self, command, working_dir=None, capture_stderr=True, env=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.
+
+ Restores the old directory afterwards.
Args:
command: The command to run, in the form of sys.argv.
working_dir: The directory to change into.
capture_stderr: Determines whether to capture stderr in the output member
or to discard it.
+ env: Dictionary with environment to pass to the subprocess.
+
+ Returns:
+ An object that represents outcome of the executed process. It has the
+ following attributes:
+ terminated_by_signal 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 process exited.
+ output Child process's stdout and stderr output
+ combined in a string.
"""
# The subprocess module is the preferrable way of running programs
@@ -228,13 +233,30 @@ class Subprocess:
p = subprocess.Popen(command,
stdout=subprocess.PIPE, stderr=stderr,
- cwd=working_dir, universal_newlines=True)
+ cwd=working_dir, universal_newlines=True, env=env)
# communicate returns a tuple with the file obect for the child's
# output.
self.output = p.communicate()[0]
self._return_code = p.returncode
else:
old_dir = os.getcwd()
+
+ def _ReplaceEnvDict(dest, src):
+ # Changes made by os.environ.clear are not inheritable by child
+ # processes until Python 2.6. To produce inheritable changes we have
+ # to delete environment items with the del statement.
+ for key in dest:
+ del dest[key]
+ dest.update(src)
+
+ # When 'env' is not None, backup the environment variables and replace
+ # them with the passed 'env'. When 'env' is None, we simply use the
+ # current 'os.environ' for compatibility with the subprocess.Popen
+ # semantics used above.
+ if env is not None:
+ old_environ = os.environ.copy()
+ _ReplaceEnvDict(os.environ, env)
+
try:
if working_dir is not None:
os.chdir(working_dir)
@@ -247,6 +269,12 @@ class Subprocess:
ret_code = p.wait()
finally:
os.chdir(old_dir)
+
+ # Restore the old environment variables
+ # if they were replaced.
+ if env is not None:
+ _ReplaceEnvDict(os.environ, old_environ)
+
# Converts ret_code to match the semantics of
# subprocess.Popen.returncode.
if os.WIFSIGNALED(ret_code):