[PATCH 046 of 179 tests-refactor] run-tests: move TESTDIR out of a global
Gregory Szorc
gregory.szorc at gmail.com
Fri May 2 13:38:03 CDT 2014
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1397974524 25200
# Sat Apr 19 23:15:24 2014 -0700
# Branch stable
# Node ID e45a84e5b9eb089060cfbe21b9470fd72fdaff95
# Parent 5717b806b4e8d500931b0143ce4c598c341e6a88
run-tests: move TESTDIR out of a global
This patch starts the process of removing global variables from
run-tests.py. The goal of this is to make it easier to run tests
differently without having to concern yourself with global state.
diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -425,17 +425,17 @@ def usecorrectpython():
(exename, pyexename, exedir))
path = os.environ['PATH'].split(os.pathsep)
while exedir in path:
path.remove(exedir)
os.environ['PATH'] = os.pathsep.join([exedir] + path)
if not findprogram(pyexename):
print "WARNING: Cannot find %s in search path" % pyexename
-def installhg(options):
+def installhg(runner, options):
vlog("# Performing temporary installation of HG")
installerrs = os.path.join("tests", "install.err")
compiler = ''
if options.compiler:
compiler = '--compiler ' + options.compiler
pure = options.pure and "--pure" or ""
py3 = ''
if sys.version_info[0] == 3:
@@ -465,17 +465,17 @@ def installhg(options):
if not options.verbose:
os.remove(installerrs)
else:
f = open(installerrs)
for line in f:
print line,
f.close()
sys.exit(1)
- os.chdir(TESTDIR)
+ os.chdir(runner.testdir)
usecorrectpython()
if options.py3k_warnings and not options.anycoverage:
vlog("# Updating hg command to enable Py3k Warnings switch")
f = open(os.path.join(BINDIR, 'hg'), 'r')
lines = [line.rstrip() for line in f]
lines[0] += ' -3'
@@ -497,67 +497,68 @@ def installhg(options):
'"%~dp0python" "%~dp0hg" %*')
f = open(hgbat, 'wb')
f.write(data)
f.close()
else:
print 'WARNING: cannot fix hg.bat reference to python.exe'
if options.anycoverage:
- custom = os.path.join(TESTDIR, 'sitecustomize.py')
+ custom = os.path.join(runner.testdir, 'sitecustomize.py')
target = os.path.join(PYTHONDIR, 'sitecustomize.py')
vlog('# Installing coverage trigger to %s' % target)
shutil.copyfile(custom, target)
- rc = os.path.join(TESTDIR, '.coveragerc')
+ rc = os.path.join(runner.testdir, '.coveragerc')
vlog('# Installing coverage rc to %s' % rc)
os.environ['COVERAGE_PROCESS_START'] = rc
fn = os.path.join(INST, '..', '.coverage')
os.environ['COVERAGE_FILE'] = fn
def outputtimes(options):
vlog('# Producing time report')
times.sort(key=lambda t: (t[1], t[0]), reverse=True)
cols = '%7.3f %s'
print '\n%-7s %s' % ('Time', 'Test')
for test, timetaken in times:
print cols % (timetaken, test)
-def outputcoverage(options):
+def outputcoverage(runner, options):
vlog('# Producing coverage report')
os.chdir(PYTHONDIR)
def covrun(*args):
cmd = 'coverage %s' % ' '.join(args)
vlog('# Running: %s' % cmd)
os.system(cmd)
covrun('-c')
- omit = ','.join(os.path.join(x, '*') for x in [BINDIR, TESTDIR])
+ omit = ','.join(os.path.join(x, '*') for x in [BINDIR, runner.testdir])
covrun('-i', '-r', '"--omit=%s"' % omit) # report
if options.htmlcov:
- htmldir = os.path.join(TESTDIR, 'htmlcov')
+ htmldir = os.path.join(runner.testdir, 'htmlcov')
covrun('-i', '-b', '"--directory=%s"' % htmldir, '"--omit=%s"' % omit)
if options.annotate:
- adir = os.path.join(TESTDIR, 'annotated')
+ adir = os.path.join(runner.testdir, 'annotated')
if not os.path.isdir(adir):
os.mkdir(adir)
covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
class Test(object):
"""Encapsulates a single, runnable test.
Test instances can be run multiple times via run(). However, multiple
runs cannot be run concurrently.
"""
def __init__(self, testdir, test, options, count, refpath):
path = os.path.join(testdir, test)
errpath = os.path.join(testdir, '%s.err' % test)
+ self._testdir = testdir
self._test = test
self._path = path
self._options = options
self._count = count
self._daemonpids = []
self._refpath = refpath
self._errpath = errpath
@@ -840,17 +841,17 @@ class TTest(Test):
# Similarly, with --debug, output is None.
if exitcode == SKIPPED_STATUS or output is None:
return exitcode, output
return self._processoutput(exitcode, output, salt, after, expected)
def _hghave(self, reqs, testtmp):
# TODO do something smarter when all other uses of hghave are gone.
- tdir = TESTDIR.replace('\\', '/')
+ tdir = self._testdir.replace('\\', '/')
proc = Popen4('%s -c "%s/hghave %s"' %
(self._options.shell, tdir, ' '.join(reqs)),
testtmp, 0)
stdout, stderr = proc.communicate()
ret = proc.wait()
if wifexited(ret):
ret = os.WEXITSTATUS(ret)
if ret == 2:
@@ -1077,35 +1078,35 @@ class TTest(Test):
if el.endswith(" (re)\n"):
return TTest.rematch(el[:-6], l)
if el.endswith(" (glob)\n"):
return TTest.globmatch(el[:-8], l)
if os.altsep and l.replace('\\', '/') == el:
return '+glob'
return False
-def gettest(testdir, test, options, count):
+def gettest(runner, test, options, count):
"""Obtain a Test by looking at its filename.
Returns a Test instance. The Test may not be runnable if it doesn't map
to a known type.
"""
lctest = test.lower()
- refpath = os.path.join(testdir, test)
+ refpath = os.path.join(runner.testdir, test)
- runner = Test
+ testcls = Test
for ext, cls, out in testtypes:
if lctest.endswith(ext):
- runner = cls
- refpath = os.path.join(testdir, test + out)
+ testcls = cls
+ refpath = os.path.join(runner.testdir, test + out)
break
- return runner(testdir, test, options, count, refpath)
+ return testcls(runner.testdir, test, options, count, refpath)
wifexited = getattr(os, "WIFEXITED", lambda x: False)
def run(cmd, wd, options, replacements, env):
"""Run command in a sub-process, capturing the output (stdout and stderr).
Return a tuple (exitcode, output). output is None in debug mode."""
# TODO: Use subprocess.Popen if we're running on Python 2.4
if options.debug:
proc = subprocess.Popen(cmd, shell=True, cwd=wd, env=env)
@@ -1184,17 +1185,17 @@ def scheduletests(runner, options, tests
jobs = options.jobs
done = queue.Queue()
running = 0
count = 0
global abort
def job(test, count):
try:
- t = gettest(TESTDIR, test, options, count)
+ t = gettest(runner, test, options, count)
done.put(t.run())
del t # For side-effects.
except KeyboardInterrupt:
pass
except: # re-raises
done.put(('!', test, 'run-test raised an error, see traceback'))
raise
@@ -1218,17 +1219,17 @@ def scheduletests(runner, options, tests
running += 1
count += 1
except KeyboardInterrupt:
abort = True
def runtests(runner, options, tests):
try:
if INST:
- installhg(options)
+ installhg(runner, options)
_checkhglib("Testing")
else:
usecorrectpython()
if options.restart:
orig = list(tests)
while tests:
if os.path.exists(tests[0] + ".err"):
@@ -1258,17 +1259,17 @@ def runtests(runner, options, tests):
print "# Ran %d tests, %d skipped, %d warned, %d failed." % (
tested, skipped + ignored, warned, failed)
if results['!']:
print 'python hash seed:', os.environ['PYTHONHASHSEED']
if options.time:
outputtimes(options)
if options.anycoverage:
- outputcoverage(options)
+ outputcoverage(runner, options)
except KeyboardInterrupt:
failed = True
print "\ninterrupted!"
if failed:
return 1
if warned:
return 80
@@ -1276,16 +1277,18 @@ def runtests(runner, options, tests):
testtypes = [('.py', PythonTest, '.out'),
('.t', TTest, '')]
class TestRunner(object):
"""Holds context for executing tests.
Tests rely on a lot of state. This object holds it for them.
"""
+ def __init__(self):
+ self.testdir = None
def main(args, parser=None):
runner = TestRunner()
parser = parser or getparser()
(options, args) = parseargs(args, parser)
os.umask(022)
@@ -1323,18 +1326,18 @@ def main(args, parser=None):
return val
tests.sort(key=sortkey)
if 'PYTHONHASHSEED' not in os.environ:
# use a random python hash seed all the time
# we do the randomness ourself to know what seed is used
os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
- global TESTDIR, HGTMP, INST, BINDIR, TMPBINDIR, PYTHONDIR, COVERAGE_FILE
- TESTDIR = os.environ["TESTDIR"] = os.getcwd()
+ global HGTMP, INST, BINDIR, TMPBINDIR, PYTHONDIR, COVERAGE_FILE
+ runner.testdir = os.environ['TESTDIR'] = os.getcwd()
if options.tmpdir:
options.keep_tmpdir = True
tmpdir = options.tmpdir
if os.path.exists(tmpdir):
# Meaning of tmpdir has changed since 1.3: we used to create
# HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if
# tmpdir already exists.
print "error: temp dir %r already exists" % tmpdir
@@ -1380,29 +1383,30 @@ def main(args, parser=None):
if TMPBINDIR != BINDIR:
path = [TMPBINDIR] + path
os.environ["PATH"] = os.pathsep.join(path)
# Include TESTDIR in PYTHONPATH so that out-of-tree extensions
# can run .../tests/run-tests.py test-foo where test-foo
# adds an extension to HGRC. Also include run-test.py directory to import
# modules like heredoctest.
- pypath = [PYTHONDIR, TESTDIR, os.path.abspath(os.path.dirname(__file__))]
+ pypath = [PYTHONDIR, runner.testdir,
+ os.path.abspath(os.path.dirname(__file__))]
# We have to augment PYTHONPATH, rather than simply replacing
# it, in case external libraries are only available via current
# PYTHONPATH. (In particular, the Subversion bindings on OS X
# are in /opt/subversion.)
oldpypath = os.environ.get(IMPL_PATH)
if oldpypath:
pypath.append(oldpypath)
os.environ[IMPL_PATH] = os.pathsep.join(pypath)
- COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
+ COVERAGE_FILE = os.path.join(runner.testdir, ".coverage")
- vlog("# Using TESTDIR", TESTDIR)
+ vlog("# Using TESTDIR", runner.testdir)
vlog("# Using HGTMP", HGTMP)
vlog("# Using PATH", os.environ["PATH"])
vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
try:
return runtests(runner, options, tests) or 0
finally:
time.sleep(.1)
More information about the Mercurial-devel
mailing list