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:
commit
8f2fae1e7d
|
@ -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:
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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())'
|
||||
|
|
Loading…
Reference in New Issue