##// END OF EJS Templates
Make RPM spec in contrib more aligned with the one from Fedora...
Make RPM spec in contrib more aligned with the one from Fedora This is mostly syntactical changes which make the real differences more obvious when looking at a diff. contrib/mergetools.rc is now also installed and enabled by default.

File last commit:

r8843:eb7b247a default
r8942:51038bb5 default
Show More
run-tests.py
804 lines | 26.2 KiB | text/x-python | PythonLexer
Stephen Darnell
Add a pure python version of run-tests....
r2110 #!/usr/bin/env python
#
# run-tests.py - Run a set of tests on Mercurial
#
# Copyright 2006 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Stephen Darnell
Add a pure python version of run-tests....
r2110
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 # Modifying this script is tricky because it has many modes:
# - serial (default) vs parallel (-jN, N > 1)
# - no coverage (default) vs coverage (-c, -C, -s)
# - temp install (default) vs specific hg script (--with-hg, --local)
# - tests are a mix of shell scripts and Python scripts
#
# If you change this script, it is recommended that you ensure you
# haven't broken it by running it in various modes with a representative
# sample of test scripts. For example:
Dirkjan Ochtman
kill trailing whitespace
r8843 #
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 # 1) serial, no coverage, temp install:
# ./run-tests.py test-s*
# 2) serial, no coverage, local hg:
# ./run-tests.py --local test-s*
# 3) serial, coverage, temp install:
# ./run-tests.py -c test-s*
# 4) serial, coverage, local hg:
# ./run-tests.py -c --local test-s* # unsupported
# 5) parallel, no coverage, temp install:
# ./run-tests.py -j2 test-s*
# 6) parallel, no coverage, local hg:
# ./run-tests.py -j2 --local test-s*
# 7) parallel, coverage, temp install:
# ./run-tests.py -j2 -c test-s* # currently broken
# 8) parallel, coverage, local install
# ./run-tests.py -j2 -c --local test-s* # unsupported (and broken)
#
# (You could use any subset of the tests: test-s* happens to match
# enough that it's worth doing parallel runs, few enough that it
# completes fairly quickly, includes both shell and Python scripts, and
# includes some scripts that run daemon processes.)
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 import difflib
import errno
import optparse
import os
Martin Geisler
util: always use subprocess
r8280 import subprocess
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 import shutil
import signal
import sys
Stephen Darnell
Add a pure python version of run-tests....
r2110 import tempfile
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 import time
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
util: always use subprocess
r8280 closefds = os.name == 'posix'
def Popen4(cmd, bufsize=-1):
p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
close_fds=closefds,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
p.fromchild = p.stdout
p.tochild = p.stdin
p.childerr = p.stderr
return p
Thomas Arendsen Hein
Use skipped: instead of hghave: for skipping tests, use this in test-merge-types
r5685 # reserved exit code to skip test (used by hghave)
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 SKIPPED_STATUS = 80
Thomas Arendsen Hein
Use skipped: instead of hghave: for skipping tests, use this in test-merge-types
r5685 SKIPPED_PREFIX = 'skipped: '
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 FAILED_PREFIX = 'hghave check failed: '
Martin Geisler
run-tests: upper-case global PYTHON variable
r8096 PYTHON = sys.executable
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 requiredtools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
Stephen Darnell
Add a pure python version of run-tests....
r2110
Thomas Arendsen Hein
run-tests.py: Allow environment variables to set jobs/timeout/port.
r6366 defaults = {
'jobs': ('HGTEST_JOBS', 1),
'timeout': ('HGTEST_TIMEOUT', 180),
'port': ('HGTEST_PORT', 20059),
}
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def parseargs():
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser = optparse.OptionParser("%prog [options] [tests]")
parser.add_option("-C", "--annotate", action="store_true",
help="output files annotated with coverage")
parser.add_option("--child", type="int",
help="run as child process, summary to given fd")
parser.add_option("-c", "--cover", action="store_true",
help="print a test coverage report")
parser.add_option("-f", "--first", action="store_true",
help="exit on the first test failure")
parser.add_option("-i", "--interactive", action="store_true",
help="prompt to accept changed output")
parser.add_option("-j", "--jobs", type="int",
help="number of jobs to run in parallel"
" (default: $%s or %d)" % defaults['jobs'])
parser.add_option("--keep-tmpdir", action="store_true",
help="keep temporary directory after running tests"
" (best used with --tmpdir)")
parser.add_option("-R", "--restart", action="store_true",
help="restart at last error")
parser.add_option("-p", "--port", type="int",
help="port on which servers should listen"
" (default: $%s or %d)" % defaults['port'])
parser.add_option("-r", "--retest", action="store_true",
help="retest failed tests")
parser.add_option("-s", "--cover_stdlib", action="store_true",
help="print a test coverage report inc. standard libraries")
parser.add_option("-t", "--timeout", type="int",
help="kill errant tests after TIMEOUT seconds"
" (default: $%s or %d)" % defaults['timeout'])
parser.add_option("--tmpdir", type="string",
help="run tests in the given temporary directory")
parser.add_option("-v", "--verbose", action="store_true",
help="output verbose messages")
parser.add_option("-n", "--nodiff", action="store_true",
help="skip showing test changes")
parser.add_option("--with-hg", type="string",
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 metavar="HG",
help="test using specified hg script rather than a "
"temporary installation")
parser.add_option("--local", action="store_true",
help="shortcut for --with-hg=<testdir>/../hg")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("--pure", action="store_true",
help="use pure Python code instead of C extensions")
Stephen Darnell
Add a pure python version of run-tests....
r2110
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 for option, default in defaults.items():
defaults[option] = int(os.environ.get(*default))
parser.set_defaults(**defaults)
(options, args) = parser.parse_args()
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if options.with_hg:
if not (os.path.isfile(options.with_hg) and
os.access(options.with_hg, os.X_OK)):
parser.error('--with-hg must specify an executable hg script')
if not os.path.basename(options.with_hg) == 'hg':
sys.stderr.write('warning: --with-hg should specify an hg script')
if options.local:
testdir = os.path.dirname(os.path.realpath(sys.argv[0]))
hgbin = os.path.join(os.path.dirname(testdir), 'hg')
if not os.access(hgbin, os.X_OK):
parser.error('--local specified, but %r not found or not executable'
% hgbin)
options.with_hg = hgbin
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 options.anycoverage = (options.cover or
options.cover_stdlib or
options.annotate)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if options.anycoverage and options.with_hg:
# I'm not sure if this is a fundamental limitation or just a
# bug. But I don't want to waste people's time and energy doing
# test runs that don't give the results they want.
parser.error("sorry, coverage options do not work when --with-hg "
"or --local specified")
global vlog
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if options.verbose:
Greg Ward
run-tests: show PID if running in parallel mode with -v....
r8671 if options.jobs > 1 or options.child is not None:
pid = "[%d]" % os.getpid()
else:
pid = None
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 def vlog(*msg):
Greg Ward
run-tests: show PID if running in parallel mode with -v....
r8671 if pid:
print pid,
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 for m in msg:
print m,
print
else:
vlog = lambda *msg: None
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091
if options.jobs < 1:
print >> sys.stderr, 'ERROR: -j/--jobs must be positive'
sys.exit(1)
if options.interactive and options.jobs > 1:
print '(--interactive overrides --jobs)'
options.jobs = 1
return (options, args)
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Patrick Mezard
Make run-tests.py --interactive work on Windows
r5800 def rename(src, dst):
"""Like os.rename(), trade atomicity and opened files friendliness
for existing destination support.
"""
shutil.copy(src, dst)
os.remove(src)
Vadim Gelfer
run-tests.py: fix handling of newlines....
r2247 def splitnewlines(text):
'''like str.splitlines, but only split on newlines.
keep line endings.'''
i = 0
lines = []
while True:
n = text.find('\n', i)
if n == -1:
last = text[i:]
if last:
lines.append(last)
return lines
lines.append(text[i:n+1])
i = n + 1
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def parsehghaveoutput(lines):
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 '''Parse hghave log lines.
Return tuple of lists (missing, failed):
* the missing/unknown features
* the features for which existence check failed'''
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 missing = []
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 failed = []
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 for line in lines:
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 if line.startswith(SKIPPED_PREFIX):
line = line.splitlines()[0]
missing.append(line[len(SKIPPED_PREFIX):])
elif line.startswith(FAILED_PREFIX):
line = line.splitlines()[0]
failed.append(line[len(FAILED_PREFIX):])
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 return missing, failed
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def showdiff(expected, output):
Stephen Darnell
Add a pure python version of run-tests....
r2110 for line in difflib.unified_diff(expected, output,
Thomas Arendsen Hein
Fix diff header (line endings) for failed test output in run-tests.py.
r2409 "Expected output", "Test output"):
Vadim Gelfer
run-tests.py: fix handling of newlines....
r2247 sys.stdout.write(line)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def findprogram(program):
Stephen Darnell
Add a pure python version of run-tests....
r2110 """Search PATH for a executable program"""
for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
name = os.path.join(p, program)
if os.access(name, os.X_OK):
return name
return None
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def checktools():
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 # Before we go any further, check for pre-requisite tools
# stuff from coreutils (cat, rm, etc) are not tested
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 for p in requiredtools:
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 if os.name == 'nt':
p += '.exe'
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 found = findprogram(p)
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 if found:
vlog("# Found prerequisite", p, "at", found)
else:
print "WARNING: Did not find prerequisite tool: "+p
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def cleanup(options):
Peter Arrenbrecht
tests: add --keep-tmp to run-tests.py to debug test environment...
r6208 if not options.keep_tmpdir:
Greg Ward
run-tests: show PID if running in parallel mode with -v....
r8671 vlog("# Cleaning up HGTMP", HGTMP)
Peter Arrenbrecht
tests: add --keep-tmp to run-tests.py to debug test environment...
r6208 shutil.rmtree(HGTMP, True)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def usecorrectpython():
Vadim Gelfer
run-tests.py: make tests use same python interpreter as test harness....
r2570 # some tests run python interpreter. they must use same
# interpreter we use or bad things will happen.
exedir, exename = os.path.split(sys.executable)
if exename == 'python':
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 path = findprogram('python')
Vadim Gelfer
run-tests.py: make tests use same python interpreter as test harness....
r2570 if os.path.dirname(path) == exedir:
return
vlog('# Making python executable in test path use correct Python')
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 mypython = os.path.join(BINDIR, 'python')
Vadim Gelfer
run-tests.py: make tests use same python interpreter as test harness....
r2570 try:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 os.symlink(sys.executable, mypython)
Vadim Gelfer
run-tests.py: make tests use same python interpreter as test harness....
r2570 except AttributeError:
# windows fallback
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 shutil.copyfile(sys.executable, mypython)
shutil.copymode(sys.executable, mypython)
Thomas Arendsen Hein
Whitespace/Tab cleanup
r3223
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def installhg(options):
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 vlog("# Performing temporary installation of HG")
installerrs = os.path.join("tests", "install.err")
Martin Geisler
run-tests: add --pure flag for using pure Python modules
r7723 pure = options.pure and "--pure" or ""
Stephen Darnell
Add a pure python version of run-tests....
r2110
Brendan Cully
Make run-tests.py work when invoked outside of tests....
r5267 # Run installer in hg root
os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '..'))
Martin Geisler
run-tests: add --pure flag for using pure Python modules
r7723 cmd = ('%s setup.py %s clean --all'
Benoit Boissinot
run-tests.py: use --prefix instead of --home...
r7139 ' install --force --prefix="%s" --install-lib="%s"'
Alexis S. L. Carvalho
run-tests.py: pass --install-scripts to setup.py...
r5189 ' --install-scripts="%s" >%s 2>&1'
Martin Geisler
run-tests: add --pure flag for using pure Python modules
r7723 % (sys.executable, pure, INST, PYTHONDIR, BINDIR, installerrs))
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 vlog("# Running", cmd)
if os.system(cmd) == 0:
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.verbose:
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 os.remove(installerrs)
else:
f = open(installerrs)
for line in f:
print line,
f.close()
sys.exit(1)
os.chdir(TESTDIR)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 usecorrectpython()
Vadim Gelfer
run-tests.py: make tests use same python interpreter as test harness....
r2570
Thomas Arendsen Hein
Use dummy diffstat in tests and remove older diffstat workaround....
r7172 vlog("# Installing dummy diffstat")
f = open(os.path.join(BINDIR, 'diffstat'), 'w')
f.write('#!' + sys.executable + '\n'
'import sys\n'
'files = 0\n'
'for line in sys.stdin:\n'
' if line.startswith("diff "):\n'
' files += 1\n'
'sys.stdout.write("files patched: %d\\n" % files)\n')
f.close()
os.chmod(os.path.join(BINDIR, 'diffstat'), 0700)
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if options.anycoverage:
Stephen Darnell
Add code coverage to the python version of run-tests (inc. annotation)...
r2144 vlog("# Installing coverage wrapper")
os.environ['COVERAGE_FILE'] = COVERAGE_FILE
if os.path.exists(COVERAGE_FILE):
os.unlink(COVERAGE_FILE)
# Create a wrapper script to invoke hg via coverage.py
Vadim Gelfer
run-tests.py: remove trailing white space
r2146 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
Stephen Darnell
Add code coverage to the python version of run-tests (inc. annotation)...
r2144 f = open(os.path.join(BINDIR, 'hg'), 'w')
f.write('#!' + sys.executable + '\n')
Thomas Arendsen Hein
Cleanup of whitespace, indentation and line continuation.
r4633 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620 '"%s", "-x", "-p", "%s"] + sys.argv[1:])\n' %
Thomas Arendsen Hein
Cleanup of whitespace, indentation and line continuation.
r4633 (os.path.join(TESTDIR, 'coverage.py'),
os.path.join(BINDIR, '_hg.py')))
Stephen Darnell
Add code coverage to the python version of run-tests (inc. annotation)...
r2144 f.close()
os.chmod(os.path.join(BINDIR, 'hg'), 0700)
Greg Ward
run-tests: move _hgpath() up so it's not in the middle of the main program.
r8092
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def outputcoverage(options):
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620
vlog('# Producing coverage report')
os.chdir(PYTHONDIR)
def covrun(*args):
start = sys.executable, os.path.join(TESTDIR, 'coverage.py')
cmd = '"%s" "%s" %s' % (start[0], start[1], ' '.join(args))
vlog('# Running: %s' % cmd)
os.system(cmd)
Vadim Gelfer
make indentation of coverage code in run-tests.py nicer.
r2145 omit = [BINDIR, TESTDIR, PYTHONDIR]
if not options.cover_stdlib:
# Exclude as system paths (ignoring empty strings seen on win)
Vadim Gelfer
run-tests.py: remove trailing white space
r2146 omit += [x for x in sys.path if x != '']
Vadim Gelfer
make indentation of coverage code in run-tests.py nicer.
r2145 omit = ','.join(omit)
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620
covrun('-c') # combine from parallel processes
Dirkjan Ochtman
tests: delete parallel coverage files after combining
r8696 for fn in os.listdir(TESTDIR):
if fn.startswith('.coverage.'):
os.unlink(os.path.join(TESTDIR, fn))
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620 covrun('-i', '-r', '"--omit=%s"' % omit) # report
Vadim Gelfer
make indentation of coverage code in run-tests.py nicer.
r2145 if options.annotate:
adir = os.path.join(TESTDIR, 'annotated')
if not os.path.isdir(adir):
os.mkdir(adir)
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
Stephen Darnell
Add code coverage to the python version of run-tests (inc. annotation)...
r2144
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 class Timeout(Exception):
pass
def alarmed(signum, frame):
raise Timeout
Simon Heimberg
run-tests: fix error when timeout occurs
r8116 def run(cmd, options):
Stephen Darnell
Add a pure python version of run-tests....
r2110 """Run command in a sub-process, capturing the output (stdout and stderr).
Return the exist code, and output."""
# TODO: Use subprocess.Popen if we're running on Python 2.4
Frank Wierzbicki
tests: use same popen strategy for jython as for nt
r7792 if os.name == 'nt' or sys.platform.startswith('java'):
Stephen Darnell
Add a pure python version of run-tests....
r2110 tochild, fromchild = os.popen4(cmd)
tochild.close()
output = fromchild.read()
ret = fromchild.close()
if ret == None:
ret = 0
else:
Mads Kiilerich
run-tests.py: avoid using popen2.Popen4 - use subprocess instead...
r7813 proc = Popen4(cmd)
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 try:
output = ''
proc.tochild.close()
output = proc.fromchild.read()
ret = proc.wait()
Patrick Mezard
run-tests: extract correct status when script terminates with exit
r4880 if os.WIFEXITED(ret):
ret = os.WEXITSTATUS(ret)
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 except Timeout:
vlog('# Process %d timed out - killing it' % proc.pid)
os.kill(proc.pid, signal.SIGTERM)
ret = proc.wait()
if ret == 0:
ret = signal.SIGTERM << 8
Thomas Arendsen Hein
Add message to test output if a test is aborted due to a timeout....
r5078 output += ("\n### Abort: timeout after %d seconds.\n"
% options.timeout)
Vadim Gelfer
run-tests.py: fix handling of newlines....
r2247 return ret, splitnewlines(output)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 def runone(options, test, skips, fails):
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 '''tristate output:
None -> skipped
True -> passed
False -> failed'''
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 def skip(msg):
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.verbose:
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 skips.append((test, msg))
else:
print "\nSkipping %s: %s" % (test, msg)
return None
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 def fail(msg):
fails.append((test, msg))
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.nodiff:
Matt Mackall
run-tests: allow turning off diff display
r7343 print "\nERROR: %s %s" % (test, msg)
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 return None
Stephen Darnell
Add a pure python version of run-tests....
r2110 vlog("# Test", test)
Thomas Arendsen Hein
Clear contents of global hgrc for tests before running each test....
r2989 # create a fresh hgrc
hgrc = file(HGRCPATH, 'w+')
Alexis S. L. Carvalho
run-tests.py: set ui.slash = True...
r4529 hgrc.write('[ui]\n')
hgrc.write('slash = True\n')
Alexis S. L. Carvalho
run-tests.py: add a default --date "0 0" argument to commit et al...
r5524 hgrc.write('[defaults]\n')
hgrc.write('backout = -d "0 0"\n')
hgrc.write('commit = -d "0 0"\n')
hgrc.write('tag = -d "0 0"\n')
Thomas Arendsen Hein
Clear contents of global hgrc for tests before running each test....
r2989 hgrc.close()
Stephen Darnell
Add a pure python version of run-tests....
r2110 err = os.path.join(TESTDIR, test+".err")
ref = os.path.join(TESTDIR, test+".out")
Alexis S. L. Carvalho
run-tests.py: small cleanup
r4320 testpath = os.path.join(TESTDIR, test)
Stephen Darnell
Add a pure python version of run-tests....
r2110
if os.path.exists(err):
os.remove(err) # Remove any previous output files
# Make a tmp subdirectory to work in
tmpd = os.path.join(HGTMP, test)
os.mkdir(tmpd)
os.chdir(tmpd)
Alexis S. L. Carvalho
run-tests.py: use coverage.py with "#!/usr/bin/env python" tests
r4321 try:
tf = open(testpath)
firstline = tf.readline().rstrip()
tf.close()
except:
firstline = ''
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 lctest = test.lower()
Stephen Darnell
Add a pure python version of run-tests....
r2110
Alexis S. L. Carvalho
run-tests.py: use coverage.py with "#!/usr/bin/env python" tests
r4321 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
Martin Geisler
run-tests: upper-case global PYTHON variable
r8096 cmd = '%s "%s"' % (PYTHON, testpath)
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 elif lctest.endswith('.bat'):
# do not run batch scripts on non-windows
if os.name != 'nt':
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 return skip("batch script")
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 # To reliably get the error code from batch files on WinXP,
# the "cmd /c call" prefix is needed. Grrr
Alexis S. L. Carvalho
run-tests.py: small cleanup
r4320 cmd = 'cmd /c call "%s"' % testpath
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 else:
# do not run shell scripts on windows
if os.name == 'nt':
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 return skip("shell script")
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 # do not try to run non-executable programs
Benoit Boissinot
run-tests.py: report missing file as an error
r7144 if not os.path.exists(testpath):
return fail("does not exist")
elif not os.access(testpath, os.X_OK):
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 return skip("not executable")
Alexis S. L. Carvalho
run-tests.py: small cleanup
r4320 cmd = '"%s"' % testpath
Stephen Darnell
Add a pure python version of run-tests....
r2110
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 if options.timeout > 0:
signal.alarm(options.timeout)
Stephen Darnell
Add a pure python version of run-tests....
r2110 vlog("# Running", cmd)
Simon Heimberg
run-tests: fix error when timeout occurs
r8116 ret, out = run(cmd, options)
Stephen Darnell
Add a pure python version of run-tests....
r2110 vlog("# Ret was:", ret)
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 if options.timeout > 0:
signal.alarm(0)
Matt Mackall
run-tests: allow turning off diff display
r7343 mark = '.'
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 skipped = (ret == SKIPPED_STATUS)
Vadim Gelfer
run-tests.py must print changed test output no matter what exit code is.
r2213 # If reference output file exists, check test output against it
if os.path.exists(ref):
f = open(ref, "r")
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 refout = splitnewlines(f.read())
Vadim Gelfer
run-tests.py must print changed test output no matter what exit code is.
r2213 f.close()
Vadim Gelfer
run-tests.py: print diff if reference output not existing.
r2246 else:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 refout = []
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 if skipped:
Matt Mackall
run-tests: allow turning off diff display
r7343 mark = 's'
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 missing, failed = parsehghaveoutput(out)
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 if not missing:
missing = ['irrelevant']
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 if failed:
fail("hghave failed checking for %s" % failed[-1])
skipped = False
else:
skip(missing[-1])
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 elif out != refout:
Matt Mackall
run-tests: allow turning off diff display
r7343 mark = '!'
Thomas Arendsen Hein
run-tests.py: Only one fail message when output changed and error code....
r6383 if ret:
fail("output changed and returned error code %d" % ret)
else:
fail("output changed")
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.nodiff:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 showdiff(refout, out)
Thomas Arendsen Hein
run-tests.py: Only one fail message when output changed and error code....
r6383 ret = 1
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 elif ret:
Matt Mackall
run-tests: allow turning off diff display
r7343 mark = '!'
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 fail("returned error code %d" % ret)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.verbose:
Matt Mackall
run-tests: allow turning off diff display
r7343 sys.stdout.write(mark)
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 sys.stdout.flush()
Thomas Arendsen Hein
Remove trailing spaces
r5081 if ret != 0 and not skipped:
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 # Save errors to a file for diagnosis
Vadim Gelfer
run-tests.py: fix handling of newlines....
r2247 f = open(err, "wb")
Stephen Darnell
Add a pure python version of run-tests....
r2110 for line in out:
f.write(line)
f.close()
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 # Kill off any leftover daemon processes
try:
fp = file(DAEMON_PIDS)
for line in fp:
try:
pid = int(line)
except ValueError:
continue
try:
os.kill(pid, 0)
vlog('# Killing daemon process %d' % pid)
os.kill(pid, signal.SIGTERM)
time.sleep(0.25)
os.kill(pid, 0)
vlog('# Daemon process %d is stuck - really killing it' % pid)
os.kill(pid, signal.SIGKILL)
except OSError, err:
if err.errno != errno.ESRCH:
raise
fp.close()
os.unlink(DAEMON_PIDS)
except IOError:
pass
Stephen Darnell
Add a pure python version of run-tests....
r2110 os.chdir(TESTDIR)
Peter Arrenbrecht
tests: add --keep-tmp to run-tests.py to debug test environment...
r6208 if not options.keep_tmpdir:
Thomas Arendsen Hein
Replaced tab in run-tests.py
r6209 shutil.rmtree(tmpd, True)
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 if skipped:
return None
Stephen Darnell
Add a pure python version of run-tests....
r2110 return ret == 0
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 _hgpath = None
def _gethgpath():
"""Return the path to the mercurial package that is actually found by
the current Python interpreter."""
global _hgpath
if _hgpath is not None:
return _hgpath
cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
pipe = os.popen(cmd % PYTHON)
try:
_hgpath = pipe.read().strip()
finally:
pipe.close()
return _hgpath
def _checkhglib(verb):
"""Ensure that the 'mercurial' package imported by python is
Greg Ward
run-tests: fix _checkhglib() so it's correct when using --with-hg....
r8673 the one we expect it to be. If not, print a warning to stderr."""
expecthg = os.path.join(PYTHONDIR, 'mercurial')
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 actualhg = _gethgpath()
if actualhg != expecthg:
Greg Ward
run-tests: fix _checkhglib() so it's correct when using --with-hg....
r8673 sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
' (expected %s)\n'
% (verb, actualhg, expecthg))
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672
def runchildren(options, tests):
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if INST:
Benoit Boissinot
run-tests: fix -jN broken by 60a9e3cf0cf4
r8107 installhg(options)
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 _checkhglib("Testing")
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
optcopy = dict(options.__dict__)
optcopy['jobs'] = 1
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if optcopy['with_hg'] is None:
optcopy['with_hg'] = os.path.join(BINDIR, "hg")
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 opts = []
for opt, value in optcopy.iteritems():
name = '--' + opt.replace('_', '-')
if value is True:
opts.append(name)
elif value is not None:
opts.append(name + '=' + str(value))
tests.reverse()
jobs = [[] for j in xrange(options.jobs)]
while tests:
Simon Heimberg
run-tests: cosmetics
r8161 for job in jobs:
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 if not tests: break
Simon Heimberg
run-tests: cosmetics
r8161 job.append(tests.pop())
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 fps = {}
Simon Heimberg
run-tests: cosmetics
r8161 for j, job in enumerate(jobs):
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 if not job:
continue
rfd, wfd = os.pipe()
childopts = ['--child=%d' % wfd, '--port=%d' % (options.port + j * 3)]
Martin Geisler
run-tests: upper-case global PYTHON variable
r8096 cmdline = [PYTHON, sys.argv[0]] + opts + childopts + job
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 vlog(' '.join(cmdline))
fps[os.spawnvp(os.P_NOWAIT, cmdline[0], cmdline)] = os.fdopen(rfd, 'r')
os.close(wfd)
failures = 0
tested, skipped, failed = 0, 0, 0
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 skips = []
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 fails = []
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 while fps:
pid, status = os.wait()
fp = fps.pop(pid)
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 l = fp.read().splitlines()
test, skip, fail = map(int, l[:3])
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 split = -fail or len(l)
for s in l[3:split]:
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 skips.append(s.split(" ", 1))
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 for s in l[split:]:
fails.append(s.split(" ", 1))
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 tested += test
skipped += skip
failed += fail
vlog('pid %d exited, status %d' % (pid, status))
failures |= status
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 print
for s in skips:
print "Skipped %s: %s" % (s[0], s[1])
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 for s in fails:
print "Failed %s: %s" % (s[0], s[1])
Dirkjan Ochtman
imported patch test-check
r6982
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 _checkhglib("Tested")
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 print "# Ran %d tests, %d skipped, %d failed." % (
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 tested, skipped, failed)
sys.exit(failures != 0)
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 def runtests(options, tests):
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 global DAEMON_PIDS, HGRCPATH
DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
Benoit Boissinot
catch KeyboardInterrupt in run-tests
r2258 try:
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if INST:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 installhg(options)
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 _checkhglib("Testing")
Dirkjan Ochtman
imported patch test-check
r6982
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 if options.timeout > 0:
try:
signal.signal(signal.SIGALRM, alarmed)
Greg Ward
run-tests: clarify timeout log message.
r8651 vlog('# Running each test with %d second timeout' %
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 options.timeout)
except AttributeError:
print 'WARNING: cannot run tests with timeouts'
options.timeout = 0
Matt Mackall
tests: add -R switch...
r3625 tested = 0
Benoit Boissinot
catch KeyboardInterrupt in run-tests
r2258 failed = 0
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 skipped = 0
Stephen Darnell
Add a pure python version of run-tests....
r2110
Matt Mackall
tests: add -R switch...
r3625 if options.restart:
orig = list(tests)
while tests:
if os.path.exists(tests[0] + ".err"):
break
tests.pop(0)
if not tests:
print "running all tests"
tests = orig
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 skips = []
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 fails = []
Matt Mackall
tests: add -R switch...
r3625 for test in tests:
if options.retest and not os.path.exists(test + ".err"):
skipped += 1
continue
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 ret = runone(options, test, skips, fails)
Matt Mackall
tests: add -R switch...
r3625 if ret is None:
skipped += 1
elif not ret:
Matt Mackall
tests: add -i switch...
r3626 if options.interactive:
print "Accept this change? [n] ",
answer = sys.stdin.readline().strip()
if answer.lower() in "y yes".split():
Patrick Mezard
Make run-tests.py --interactive work on Windows
r5800 rename(test + ".err", test + ".out")
Matt Mackall
tests: add -i switch...
r3626 tested += 1
Matt Mackall
tests: teach -i about fails list
r6343 fails.pop()
Matt Mackall
tests: add -i switch...
r3626 continue
Matt Mackall
tests: add -R switch...
r3625 failed += 1
if options.first:
break
tested += 1
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 if options.child:
fp = os.fdopen(options.child, 'w')
fp.write('%d\n%d\n%d\n' % (tested, skipped, failed))
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 for s in skips:
Thomas Arendsen Hein
Removed tabs and trailing whitespace in python files
r5760 fp.write("%s %s\n" % s)
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 for s in fails:
fp.write("%s %s\n" % s)
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 fp.close()
else:
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 print
for s in skips:
print "Skipped %s: %s" % s
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244 for s in fails:
print "Failed %s: %s" % s
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 _checkhglib("Tested")
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 print "# Ran %d tests, %d skipped, %d failed." % (
Bryan O'Sullivan
Allow tests to run in parallel.
r5384 tested, skipped, failed)
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if options.anycoverage:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 outputcoverage(options)
Benoit Boissinot
catch KeyboardInterrupt in run-tests
r2258 except KeyboardInterrupt:
failed = True
print "\ninterrupted!"
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
if failed:
sys.exit(1)
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 def main():
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 (options, args) = parseargs()
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 if not options.child:
os.umask(022)
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 checktools()
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 # Reset some environment variables to well-known values so that
# the tests produce repeatable output.
os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
os.environ['TZ'] = 'GMT'
os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
os.environ['CDPATH'] = ''
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
TESTDIR = os.environ["TESTDIR"] = os.getcwd()
HGTMP = os.environ['HGTMP'] = os.path.realpath(tempfile.mkdtemp('', 'hgtests.',
options.tmpdir))
DAEMON_PIDS = None
HGRCPATH = None
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
os.environ["HGMERGE"] = "internal:merge"
os.environ["HGUSER"] = "test"
os.environ["HGENCODING"] = "ascii"
os.environ["HGENCODINGMODE"] = "strict"
os.environ["HGPORT"] = str(options.port)
os.environ["HGPORT1"] = str(options.port + 1)
os.environ["HGPORT2"] = str(options.port + 2)
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 if options.with_hg:
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 INST = None
BINDIR = os.path.dirname(os.path.realpath(options.with_hg))
# This looks redundant with how Python initializes sys.path from
# the location of the script being executed. Needed because the
# "hg" specified by --with-hg is not the only Python script
# executed in the test suite that needs to import 'mercurial'
# ... which means it's not really redundant at all.
PYTHONDIR = BINDIR
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 else:
INST = os.path.join(HGTMP, "install")
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 BINDIR = os.environ["BINDIR"] = os.path.join(INST, "bin")
PYTHONDIR = os.path.join(INST, "lib", "python")
os.environ["BINDIR"] = BINDIR
os.environ["PYTHON"] = PYTHON
if not options.child:
path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
os.environ["PATH"] = os.pathsep.join(path)
Brendan Cully
Unbreak run-tests support for out-of-tree extensions
r8724 # 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
pypath = [PYTHONDIR, TESTDIR]
Greg Ward
run-tests: don't replace PYTHONPATH, just augment it....
r8687 # 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.)
Brendan Cully
Unbreak run-tests support for out-of-tree extensions
r8724 oldpypath = os.environ.get('PYTHONPATH')
if oldpypath:
pypath.append(oldpypath)
os.environ['PYTHONPATH'] = os.pathsep.join(pypath)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 if len(args) == 0:
args = os.listdir(".")
args.sort()
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 tests = []
for test in args:
if (test.startswith("test-") and '~' not in test and
('.' not in test or test.endswith('.py') or
test.endswith('.bat'))):
tests.append(test)
Simon Heimberg
runtest: do not start testing when there is no test
r8592 if not tests:
print "# Ran 0 tests, 0 skipped, 0 failed."
return
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094
vlog("# Using TESTDIR", TESTDIR)
vlog("# Using HGTMP", HGTMP)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 vlog("# Using PATH", os.environ["PATH"])
vlog("# Using PYTHONPATH", os.environ["PYTHONPATH"])
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 try:
if len(tests) > 1 and options.jobs > 1:
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 runchildren(options, tests)
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 else:
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 runtests(options, tests)
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 finally:
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 cleanup(options)
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 main()