tests: more completely restore the environment in syshgenv
authorAdam Simpkins <simpkins@fb.com>
Wed, 28 Jun 2017 12:23:22 -0700
changeset 33126 98e2c78e309c
parent 33125 acfce52518c4
child 33127 0aae80d14fed
tests: more completely restore the environment in syshgenv Update the syshgenv function to attempt to completely restore the original environment, rather than only updating a few specific variables. run_tests.py now generates a shell script that can be used to restore the original environment, and syshgenv sources it. This is a bit more complicated than the previous code, but should do a better job of running the system hg in the correct environment. I've tested it on Linux using python 2.x, but let me know if it causes issues in other environments. I'm not terribly familiar with how the tests get run on Windows, for instance, and how the environment needs to be updated there.
tests/helpers-testrepo.sh
tests/run-tests.py
--- a/tests/helpers-testrepo.sh	Wed Jun 28 13:45:51 2017 -0700
+++ b/tests/helpers-testrepo.sh	Wed Jun 28 12:23:22 2017 -0700
@@ -18,10 +18,7 @@
 # Revert the environment so that running "hg" runs the system hg
 # rather than the test hg installation.
 syshgenv () {
-    PATH="$ORIG_PATH"
-    PYTHONPATH="$ORIG_PYTHONPATH"
-    JYTHONPATH="$ORIG_JYTHONPATH"
-    unset HGRCPATH
+    . "$HGTEST_RESTOREENV"
     HGPLAIN=1
     export HGPLAIN
 }
--- a/tests/run-tests.py	Wed Jun 28 13:45:51 2017 -0700
+++ b/tests/run-tests.py	Wed Jun 28 12:23:22 2017 -0700
@@ -70,6 +70,13 @@
 except ImportError:
     import queue
 
+try:
+    import shlex
+    shellquote = shlex.quote
+except (ImportError, AttributeError):
+    import pipes
+    shellquote = pipes.quote
+
 if os.environ.get('RTUNICODEPEDANTRY', False):
     try:
         reload(sys)
@@ -752,6 +759,7 @@
         This will return a tuple describing the result of the test.
         """
         env = self._getenv()
+        self._genrestoreenv(env)
         self._daemonpids.append(env['DAEMON_PIDS'])
         self._createhgrc(env['HGRCPATH'])
 
@@ -888,6 +896,30 @@
         else:
             return b'127.0.0.1'
 
+    def _genrestoreenv(self, testenv):
+        """Generate a script that can be used by tests to restore the original
+        environment."""
+        # Put the restoreenv script inside self._threadtmp
+        scriptpath = os.path.join(self._threadtmp, b'restoreenv.sh')
+        testenv['HGTEST_RESTOREENV'] = scriptpath
+
+        # Only restore environment variable names that the shell allows
+        # us to export.
+        name_regex = re.compile('[a-zA-Z][a-zA-Z0-9_]*')
+
+        with open(scriptpath, 'w') as envf:
+            for name, value in os.environ.items():
+                if not name_regex.match(name):
+                    # Skip environment variables with unusual names not
+                    # allowed by most shells.
+                    continue
+                envf.write('%s=%s\n' % (name, shellquote(value)))
+
+            for name in testenv:
+                if name in os.environ:
+                    continue
+                envf.write('unset %s\n' % (name,))
+
     def _getenv(self):
         """Obtain environment variables to use during test execution."""
         def defineport(i):
@@ -2274,9 +2306,6 @@
             sepb = _bytespath(os.pathsep)
         else:
             sepb = os.pathsep
-        # save the original path, for tests that need to invoke the
-        # system python
-        osenvironb[b"ORIG_PATH"] = osenvironb[b"PATH"]
         path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb)
         if os.path.islink(__file__):
             # test helper will likely be at the end of the symlink
@@ -2302,7 +2331,6 @@
         # are in /opt/subversion.)
         oldpypath = osenvironb.get(IMPL_PATH)
         if oldpypath:
-            osenvironb['ORIG_' + IMPL_PATH] = oldpypath
             pypath.append(oldpypath)
         osenvironb[IMPL_PATH] = sepb.join(pypath)