Skip some tests that require a subinterpreter launched with -E or -I when the

interpreter under test is being run in an environment that requires the use of
environment variables such as PYTHONHOME in order to function at all.

Adds a test.script_helper.interpreter_requires_environment() function
to be used with @unittest.skipIf on stdlib test methods requiring this.
This commit is contained in:
Gregory P. Smith 2015-02-04 01:04:31 -08:00
commit 8f2fae1e7d
4 changed files with 82 additions and 2 deletions

View File

@ -15,6 +15,41 @@ import zipfile
from importlib.util import source_from_cache
from test.support import make_legacy_pyc, strip_python_stderr, temp_dir
# Cached result of the expensive test performed in the function below.
__cached_interp_requires_environment = None
def interpreter_requires_environment():
"""
Returns True if our sys.executable interpreter requires environment
variables in order to be able to run at all.
This is designed to be used with @unittest.skipIf() to annotate tests
that need to use an assert_python*() function to launch an isolated
mode (-I) or no environment mode (-E) sub-interpreter process.
A normal build & test does not run into this situation but it can happen
when trying to run the standard library test suite from an interpreter that
doesn't have an obvious home with Python's current home finding logic.
Setting PYTHONHOME is one way to get most of the testsuite to run in that
situation. PYTHONPATH or PYTHONUSERSITE are other common envirnonment
variables that might impact whether or not the interpreter can start.
"""
global __cached_interp_requires_environment
if __cached_interp_requires_environment is None:
# Try running an interpreter with -E to see if it works or not.
try:
subprocess.check_call([sys.executable, '-E',
'-c', 'import sys; sys.exit(0)'])
except subprocess.CalledProcessError:
__cached_interp_requires_environment = True
else:
__cached_interp_requires_environment = False
return __cached_interp_requires_environment
# Executing the interpreter in a subprocess
def _assert_python(expected_success, *args, **env_vars):
if '__isolated' in env_vars:

View File

@ -8,6 +8,7 @@ import shutil
import sys
import subprocess
import tempfile
from test import script_helper
from test.script_helper import (spawn_python, kill_python, assert_python_ok,
assert_python_failure)
@ -439,7 +440,8 @@ class CmdLineTest(unittest.TestCase):
self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
self.assertEqual(b'', out)
@unittest.skipIf(script_helper.interpreter_requires_environment(),
'Cannot run -I tests when PYTHON env vars are required.')
def test_isolatedmode(self):
self.verify_valid_flag('-I')
self.verify_valid_flag('-IEs')

View File

@ -1,7 +1,10 @@
"""Unittests for test.script_helper. Who tests the test helper?"""
import subprocess
import sys
from test import script_helper
import unittest
from unittest import mock
class TestScriptHelper(unittest.TestCase):
@ -31,5 +34,43 @@ class TestScriptHelper(unittest.TestCase):
msg='unexpected command line.')
class TestScriptHelperEnvironment(unittest.TestCase):
"""Code coverage for interpreter_requires_environment()."""
def setUp(self):
self.assertTrue(
hasattr(script_helper, '__cached_interp_requires_environment'))
# Reset the private cached state.
script_helper.__dict__['__cached_interp_requires_environment'] = None
def tearDown(self):
# Reset the private cached state.
script_helper.__dict__['__cached_interp_requires_environment'] = None
@mock.patch('subprocess.check_call')
def test_interpreter_requires_environment_true(self, mock_check_call):
mock_check_call.side_effect = subprocess.CalledProcessError('', '')
self.assertTrue(script_helper.interpreter_requires_environment())
self.assertTrue(script_helper.interpreter_requires_environment())
self.assertEqual(1, mock_check_call.call_count)
@mock.patch('subprocess.check_call')
def test_interpreter_requires_environment_false(self, mock_check_call):
# The mocked subprocess.check_call fakes a no-error process.
script_helper.interpreter_requires_environment()
self.assertFalse(script_helper.interpreter_requires_environment())
self.assertEqual(1, mock_check_call.call_count)
@mock.patch('subprocess.check_call')
def test_interpreter_requires_environment_details(self, mock_check_call):
script_helper.interpreter_requires_environment()
self.assertFalse(script_helper.interpreter_requires_environment())
self.assertFalse(script_helper.interpreter_requires_environment())
self.assertEqual(1, mock_check_call.call_count)
check_call_command = mock_check_call.call_args[0][0]
self.assertEqual(sys.executable, check_call_command[0])
self.assertIn('-E', check_call_command)
if __name__ == '__main__':
unittest.main()

View File

@ -5,7 +5,7 @@ import tracemalloc
import unittest
from unittest.mock import patch
from test.script_helper import assert_python_ok, assert_python_failure
from test import support
from test import script_helper, support
try:
import threading
except ImportError:
@ -755,6 +755,8 @@ class TestCommandLine(unittest.TestCase):
stdout = stdout.rstrip()
self.assertEqual(stdout, b'False')
@unittest.skipIf(script_helper.interpreter_requires_environment(),
'Cannot run -E tests when PYTHON env vars are required.')
def test_env_var_ignored_with_E(self):
"""PYTHON* environment variables must be ignored when -E is present."""
code = 'import tracemalloc; print(tracemalloc.is_tracing())'