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.
--- 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)