bpo-12383: Refactor subprocess test_empty_env (#1874)
authorGregory P. Smith <greg@krypto.org>
Tue, 30 May 2017 21:40:37 +0000 (14:40 -0700)
committerGitHub <noreply@github.com>
Tue, 30 May 2017 21:40:37 +0000 (14:40 -0700)
Bugfix: This test wasn't being run because it was skipping based on the
presence of Py_ENABLE_SHARED rather than its value.  It is always present
on POSIX systems but defaults to 0.

Refactoring: Move the environment variables that can be ignored into a
function.  Parse the list from the child process and filter out the ones
to exclude in the parent before checking that the rest is empty.

Feature: Adds always present environment variables to ignore when
running in a Gentoo sandbox so that the test can pass there.

Lib/test/test_subprocess.py

index be9e7834d9b368a5cf5f8dd4c643c19bed54b3d6..cf6ee9cb638288c59a71698d3f1f4340bde0f9f6 100644 (file)
@@ -630,21 +630,29 @@ class ProcessTestCase(BaseTestCase):
     # Python
     @unittest.skipIf(sys.platform == 'win32',
                      'cannot test an empty env on Windows')
-    @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') is not None,
-                     'the python library cannot be loaded '
-                     'with an empty environment')
+    @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1,
+                     'The Python shared library cannot be loaded '
+                     'with an empty environment.')
     def test_empty_env(self):
+        """Verify that env={} is as empty as possible."""
+
+        def is_env_var_to_ignore(var_name):
+            """Determine if an environment variable is under our control."""
+            # This excludes some __CF_* and VERSIONER_* keys MacOS insists
+            # on adding even when the environment in exec is empty.
+            # Gentoo sandboxes also force LD_PRELOAD and SANDBOX_* to exist.
+            return ('VERSIONER' in k or '__CF' in k or  # MacOS
+                    k == 'LD_PRELOAD' or k.startswith('SANDBOX'))  # Gentoo
+
         with subprocess.Popen([sys.executable, "-c",
-                               'import os; '
-                               'print(list(os.environ.keys()))'],
-                              stdout=subprocess.PIPE,
-                              env={}) as p:
+                               'import os; print(list(os.environ.keys()))'],
+                              stdout=subprocess.PIPE, env={}) as p:
             stdout, stderr = p.communicate()
-            self.assertIn(stdout.strip(),
-                (b"[]",
-                 # Mac OS X adds __CF_USER_TEXT_ENCODING variable to an empty
-                 # environment
-                 b"['__CF_USER_TEXT_ENCODING']"))
+            child_env_names = eval(stdout.strip())
+            self.assertIsInstance(child_env_names, list)
+            child_env_names = [k for k in child_env_names
+                               if not is_env_var_to_ignore(k)]
+            self.assertEqual(child_env_names, [])
 
     def test_communicate_stdin(self):
         p = subprocess.Popen([sys.executable, "-c",