##// END OF EJS Templates
tests: add run-tests --changed option for running tests changed in revisions...
tests: add run-tests --changed option for running tests changed in revisions Convenient when polishing patches and changing details of how they change test output. This will probably break in weird ways for revsets with special quoting ... but it is good enough for run-tests. Usage example: yes | ./run-tests.py -li --changed qparent

File last commit:

r20821:3d1d16b1 default
r20821:3d1d16b1 default
Show More
run-tests.py
1302 lines | 44.0 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
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
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
Greg Ward
run-tests: give each child its own tmp dir (issue1911)...
r9899 # 8) parallel, coverage, local install:
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 # ./run-tests.py -j2 -c --local test-s* # unsupported (and broken)
Greg Ward
run-tests: give each child its own tmp dir (issue1911)...
r9899 # 9) parallel, custom tmp dir:
# ./run-tests.py -j2 --tmpdir /tmp/myhgtests
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 #
# (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.)
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 from distutils import version
Vadim Gelfer
tests: add timeouts, make run-tests.py clean up dead daemon processes...
r2571 import difflib
import errno
import optparse
import os
Nicolas Dumazet
pylint, pyflakes: remove unused or duplicate imports
r10905 import shutil
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 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
Pierre-Yves David
test: display used python hash seed...
r18616 import random
Matt Mackall
tests: basic support for unified tests
r11741 import re
Matt Mackall
run-tests: add locking on results struct
r14000 import threading
Patrick Mezard
run-tests: do not duplicate killdaemons() code
r17464 import killdaemons as killmod
Bryan O'Sullivan
run-tests: support running tests in parallel on windows...
r18057 import Queue as queue
Stephen Darnell
Add a pure python version of run-tests....
r2110
Matt Mackall
run-tests: do chdir for tests under a lock for thread safety
r14019 processlock = threading.Lock()
Brendan Cully
run-tests: lock popen wait/poll...
r19413
Brendan Cully
run-tests: replace popen locking with a noop _cleanup handler on py24...
r19415 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
# http://bugs.python.org/issue1731717 for details. We shouldn't be producing
# zombies but it's pretty harmless even if we do.
Simon Heimberg
run-tests: better check for python version...
r20219 if sys.version_info < (2, 5):
Brendan Cully
run-tests: replace popen locking with a noop _cleanup handler on py24...
r19415 subprocess._cleanup = lambda: None
Matt Mackall
run-tests: do chdir for tests under a lock for thread safety
r14019
Martin Geisler
util: always use subprocess
r8280 closefds = os.name == 'posix'
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 def Popen4(cmd, wd, timeout, env=None):
Matt Mackall
run-tests: do chdir for tests under a lock for thread safety
r14019 processlock.acquire()
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
Martin Geisler
util: always use subprocess
r8280 close_fds=closefds,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
Matt Mackall
run-tests: do chdir for tests under a lock for thread safety
r14019 processlock.release()
Martin Geisler
util: always use subprocess
r8280 p.fromchild = p.stdout
p.tochild = p.stdin
p.childerr = p.stderr
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001
Patrick Mezard
run-tests: ignore timeout when Popen.terminate is unavailable...
r14337 p.timeout = False
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001 if timeout:
def t():
start = time.time()
while time.time() - start < timeout and p.returncode is None:
Matt Mackall
tests: shorten post-test sleeps...
r16346 time.sleep(.1)
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001 p.timeout = True
if p.returncode is None:
Thomas Arendsen Hein
run-tests: fallback to SIGTERM if subprocess.Popen does not have terminate()
r14821 terminate(p)
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001 threading.Thread(target=t).start()
Martin Geisler
util: always use subprocess
r8280 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: '
Mads Kiilerich
run-tests: convert windows paths to unix
r15448 PYTHON = sys.executable.replace('\\', '/')
Ronny Pfannschmidt
tests: adapt the test runner to work with jython
r10758 IMPL_PATH = 'PYTHONPATH'
if 'java' in sys.platform:
IMPL_PATH = 'JYTHONPATH'
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881
Bryan O'Sullivan
run-tests: check for the correct python when starting
r18049 requiredtools = [os.path.basename(sys.executable), "diff", "grep", "unzip",
"gunzip", "bunzip2", "sed"]
Sean Farley
run-tests: remove files that we potentially create outside of $TMPDIR
r20019 createdfiles = []
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),
Mads Kiilerich
tests: let run-tests.py default to use 'sh' in $PATH instead of '/bin/sh'...
r15941 'shell': ('HGTEST_SHELL', 'sh'),
Thomas Arendsen Hein
run-tests.py: Allow environment variables to set jobs/timeout/port.
r6366 }
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 def parselistfiles(files, listtype, warn=True):
entries = dict()
for filename in files:
try:
path = os.path.expanduser(os.path.expandvars(filename))
f = open(path, "r")
except IOError, err:
if err.errno != errno.ENOENT:
raise
if warn:
print "warning: no such %s file: %s" % (listtype, filename)
continue
for line in f.readlines():
line = line.split('#', 1)[0].strip()
if line:
entries[line] = filename
f.close()
return entries
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]")
Matt Mackall
run-tests: sort options
r11039
# keep these sorted
parser.add_option("--blacklist", action="append",
help="skip tests listed in the specified blacklist file")
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 parser.add_option("--whitelist", action="append",
help="always run tests listed in the specified whitelist file")
Mads Kiilerich
tests: add run-tests --changed option for running tests changed in revisions...
r20821 parser.add_option("--changed", type="string",
help="run tests that are changed in parent rev or working directory")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-C", "--annotate", action="store_true",
help="output files annotated with coverage")
parser.add_option("-c", "--cover", action="store_true",
help="print a test coverage report")
Matt Mackall
run-tests: sort options
r11039 parser.add_option("-d", "--debug", action="store_true",
help="debug mode: write output of test scripts to console"
" rather than capturing and diff'ing it (disables timeout)")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-f", "--first", action="store_true",
help="exit on the first test failure")
Markus Zapke-Gründemann
tests: add htmlcov option
r15859 parser.add_option("-H", "--htmlcov", action="store_true",
help="create an HTML report of the coverage of the files")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 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",
Greg Ward
run-tests: make --tmpdir option more useful....
r9706 help="keep temporary directory after running tests")
Matt Mackall
run-tests: sort options
r11039 parser.add_option("-k", "--keywords",
help="run tests matching keywords")
parser.add_option("-l", "--local", action="store_true",
help="shortcut for --with-hg=<testdir>/../hg")
Matt Mackall
run-tests: add --loop support...
r19283 parser.add_option("--loop", action="store_true",
help="loop tests repeatedly")
Matt Mackall
run-tests: sort options
r11039 parser.add_option("-n", "--nodiff", action="store_true",
help="skip showing test changes")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-p", "--port", type="int",
help="port on which servers should listen"
" (default: $%s or %d)" % defaults['port'])
Bryan O'Sullivan
run-tests: add a --compiler option...
r17966 parser.add_option("--compiler", type="string",
help="compiler to build with")
Matt Mackall
run-tests: sort options
r11039 parser.add_option("--pure", action="store_true",
help="use pure Python code instead of C extensions")
parser.add_option("-R", "--restart", action="store_true",
help="restart at last error")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-r", "--retest", action="store_true",
help="retest failed tests")
Matt Mackall
run-tests: add --noskips option
r9580 parser.add_option("-S", "--noskips", action="store_true",
help="don't report skip tests verbosely")
Martin Geisler
run-tests: add --shell command line flag...
r14202 parser.add_option("--shell", type="string",
help="shell to use (default: $%s or %s)" % defaults['shell'])
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-t", "--timeout", type="int",
help="kill errant tests after TIMEOUT seconds"
" (default: $%s or %d)" % defaults['timeout'])
Siddharth Agarwal
run-tests: add --time option to log times for each test...
r17921 parser.add_option("--time", action="store_true",
help="time how long each test takes")
Matt Mackall
run-tests: sort options
r11039 parser.add_option("--tmpdir", type="string",
help="run tests in the given temporary directory"
" (implies --keep-tmpdir)")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.add_option("-v", "--verbose", action="store_true",
help="output verbose messages")
Matt Mackall
run-tests: add --view switch to use external diff viewer
r11040 parser.add_option("--view", type="string",
help="external diff viewer")
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 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")
Alejandro Santos
tests: add -3 switch to run-tests.py
r9028 parser.add_option("-3", "--py3k-warnings", action="store_true",
help="enable Py3k warnings on Python 2.6+")
Augie Fackler
run-tests: add flag to provide extra hgrc options for test runs
r14134 parser.add_option('--extra-config-opt', action="append",
help='set the given config opt in the test hgrc')
Mads Kiilerich
run-tests: introduce --random for running tests in random error...
r19057 parser.add_option('--random', action="store_true",
help='run tests in random order')
Stephen Darnell
Add a pure python version of run-tests....
r2110
Martin Geisler
run-tests: use type of default to convert environment variable...
r14201 for option, (envvar, default) in defaults.items():
defaults[option] = type(default)(os.environ.get(envvar, default))
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 parser.set_defaults(**defaults)
(options, args) = parser.parse_args()
Ronny Pfannschmidt
tests: adapt the test runner to work with jython
r10758 # jython is always pure
Ronny Pfannschmidt
run-tests: force to test pure on pypy as well
r10766 if 'java' in sys.platform or '__pypy__' in sys.modules:
Ronny Pfannschmidt
Fix run-tests.py -jX after 2ed667a9dfcb
r10765 options.pure = True
Ronny Pfannschmidt
tests: adapt the test runner to work with jython
r10758
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if options.with_hg:
Mads Kiilerich
run-tests: expand user in --with-hg...
r15942 options.with_hg = os.path.expanduser(options.with_hg)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 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':
Thomas Arendsen Hein
run-tests: print a newline after all warnings
r14359 sys.stderr.write('warning: --with-hg should specify an hg script\n')
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 if options.local:
testdir = os.path.dirname(os.path.realpath(sys.argv[0]))
hgbin = os.path.join(os.path.dirname(testdir), 'hg')
Mads Kiilerich
tests: don't require 'hg' without extension on windows...
r16538 if os.name != 'nt' and not os.access(hgbin, os.X_OK):
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 parser.error('--local specified, but %r not found or not executable'
% hgbin)
options.with_hg = hgbin
Markus Zapke-Gründemann
tests: add htmlcov option
r15859 options.anycoverage = options.cover or options.annotate or options.htmlcov
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 if options.anycoverage:
try:
import coverage
covver = version.StrictVersion(coverage.__version__).version
if covver < (3, 3):
parser.error('coverage options require coverage 3.3 or later')
except ImportError:
parser.error('coverage options now require the coverage package')
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 if options.anycoverage and options.local:
# this needs some path mangling somewhere, I guess
parser.error("sorry, coverage options do not work when --local "
"is specified")
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674
Matt Mackall
run-tests: make vlog a proper function
r19250 global verbose
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if options.verbose:
Matt Mackall
run-tests: drop options.child and users
r19279 verbose = ''
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091
Nicolas Dumazet
run-tests: expand --tmpdir and create it if needed
r9394 if options.tmpdir:
options.tmpdir = os.path.expanduser(options.tmpdir)
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091 if options.jobs < 1:
Martin Geisler
run-tests: standardize on --foo instead of -f/--foo...
r9408 parser.error('--jobs must be positive')
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 if options.interactive and options.debug:
parser.error("-i/--interactive and -d/--debug are incompatible")
if options.debug:
if options.timeout != defaults['timeout']:
sys.stderr.write(
'warning: --timeout option ignored with --debug\n')
options.timeout = 0
Alejandro Santos
tests: add -3 switch to run-tests.py
r9028 if options.py3k_warnings:
if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
Martin Geisler
run-tests: standardize on --foo instead of -f/--foo...
r9408 parser.error('--py3k-warnings can only be used on Python 2.6+')
Nicolas Dumazet
run-tests: add a "--blacklist target" option to skip predefined test lists...
r9959 if options.blacklist:
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 options.blacklist = parselistfiles(options.blacklist, 'blacklist')
if options.whitelist:
Matt Mackall
run-tests: drop options.child and users
r19279 options.whitelisted = parselistfiles(options.whitelist, 'whitelist')
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 else:
options.whitelisted = {}
Greg Ward
run-tests: factor out parse_args(). Clarify use of globals a bit.
r8091
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)
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
Mads Kiilerich
run-tests.py: Show paths to failing tests, .err and .out...
r10088 def showdiff(expected, output, ref, err):
Idan Kamara
run-tests: print a new line before writing the diff
r14062 print
Mads Kiilerich
run-tests.py: Show paths to failing tests, .err and .out...
r10088 for line in difflib.unified_diff(expected, output, ref, err):
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
Matt Mackall
run-tests: make vlog a proper function
r19250 verbose = False
def vlog(*msg):
if verbose is not False:
iolock.acquire()
if verbose:
print verbose,
for m in msg:
print m,
print
sys.stdout.flush()
iolock.release()
Matt Mackall
run-tests: add a log function
r19251 def log(*msg):
iolock.acquire()
if verbose:
print verbose,
for m in msg:
print m,
print
sys.stdout.flush()
iolock.release()
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)
Patrick Mezard
run-tests: fix python executable detection and copy on Windows
r14335 if os.name == 'nt' or os.access(name, os.X_OK):
Stephen Darnell
Add a pure python version of run-tests....
r2110 return name
return None
Matt Mackall
run-tests: pull hgrc creation out as function
r19242 def createhgrc(path, options):
# create a fresh hgrc
Simon Heimberg
run-tests: open hgrc file only for writing...
r19299 hgrc = open(path, 'w')
Matt Mackall
run-tests: pull hgrc creation out as function
r19242 hgrc.write('[ui]\n')
hgrc.write('slash = True\n')
hgrc.write('interactive = False\n')
hgrc.write('[defaults]\n')
hgrc.write('backout = -d "0 0"\n')
hgrc.write('commit = -d "0 0"\n')
David Soria Parra
shelve: add a shelve extension to save/restore working changes...
r19854 hgrc.write('shelve = --date "0 0"\n')
Matt Mackall
run-tests: pull hgrc creation out as function
r19242 hgrc.write('tag = -d "0 0"\n')
if options.extra_config_opt:
for opt in options.extra_config_opt:
section, key = opt.split('.', 1)
assert '=' in key, ('extra config opt %s must '
'have an = for assignment' % opt)
hgrc.write('[%s]\n%s\n' % (section, key))
hgrc.close()
Matt Mackall
run-tests: use count to calculate port to use...
r19275 def createenv(options, testtmp, threadtmp, port):
Matt Mackall
run-tests: move environment creation to a separate function
r19269 env = os.environ.copy()
env['TESTTMP'] = testtmp
env['HOME'] = testtmp
Matt Mackall
run-tests: use count to calculate port to use...
r19275 env["HGPORT"] = str(port)
env["HGPORT1"] = str(port + 1)
env["HGPORT2"] = str(port + 2)
Matt Mackall
run-tests: introduce threadtmp directory
r19274 env["HGRCPATH"] = os.path.join(threadtmp, '.hgrc')
env["DAEMON_PIDS"] = os.path.join(threadtmp, 'daemon.pids')
Matt Mackall
run-tests: move more variables to env
r19272 env["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
env["HGMERGE"] = "internal:merge"
env["HGUSER"] = "test"
env["HGENCODING"] = "ascii"
env["HGENCODINGMODE"] = "strict"
Matt Mackall
run-tests: move environment creation to a separate function
r19269
Matt Mackall
run-tests: move most of remaining environment tweaks
r19270 # Reset some environment variables to well-known values so that
# the tests produce repeatable output.
env['LANG'] = env['LC_ALL'] = env['LANGUAGE'] = 'C'
env['TZ'] = 'GMT'
env["EMAIL"] = "Foo Bar <foo.bar@example.com>"
env['COLUMNS'] = '80'
env['TERM'] = 'xterm'
Matt Mackall
run-tests: simplify env deletion
r19271 for k in ('HG HGPROF CDPATH GREP_OPTIONS http_proxy no_proxy ' +
'NO_PROXY').split():
if k in env:
del env[k]
Matt Mackall
run-tests: move most of remaining environment tweaks
r19270
# unset env related to hooks
for k in env.keys():
if k.startswith('HG_'):
del env[k]
Matt Mackall
run-tests: move environment creation to a separate function
r19269 return env
Matt Mackall
run-tests: pull hgrc creation out as function
r19242
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:
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 if os.name == 'nt' and not p.endswith('.exe'):
Stephen Darnell
Tidyups for run-tests.py inc. try/finally cleanup and allow tests to be specified on command line
r2133 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
Thomas Arendsen Hein
run-tests: fallback to SIGTERM if subprocess.Popen does not have terminate()
r14821 def terminate(proc):
"""Terminate subprocess (with fallback for Python versions < 2.6)"""
vlog('# Terminating process %d' % proc.pid)
try:
Augie Fackler
tests: use getattr instead of hasattr
r14971 getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))()
Thomas Arendsen Hein
run-tests: fallback to SIGTERM if subprocess.Popen does not have terminate()
r14821 except OSError:
pass
Matt Mackall
run-tests: use env dict to kill daemons
r19263 def killdaemons(pidfile):
return killmod.killdaemons(pidfile, tryhard=False, remove=True,
Patrick Mezard
run-tests: do not duplicate killdaemons() code
r17464 logfn=vlog)
Brendan Cully
run-tests: kill daemons on ^C with -j....
r10336
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)
Sean Farley
run-tests: remove files that we potentially create outside of $TMPDIR
r20019 for f in createdfiles:
try:
os.remove(f)
except OSError:
pass
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.
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 pyexename = sys.platform == 'win32' and 'python.exe' or 'python'
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 if getattr(os, 'symlink', None):
Bryan O'Sullivan
run-tests: fix whitespace nonsense
r18061 vlog("# Making python executable in test path a symlink to '%s'" %
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 sys.executable)
Siddharth Agarwal
run-tests.py: work when --with-hg is set to system hg...
r20541 mypython = os.path.join(TMPBINDIR, pyexename)
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 try:
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 if os.readlink(mypython) == sys.executable:
return
os.unlink(mypython)
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 except OSError, err:
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 if err.errno != errno.ENOENT:
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 raise
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 if findprogram(pyexename) != sys.executable:
try:
os.symlink(sys.executable, mypython)
Sean Farley
run-tests: remove files that we potentially create outside of $TMPDIR
r20019 createdfiles.append(mypython)
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 except OSError, err:
# child processes may race, which is harmless
if err.errno != errno.EEXIST:
raise
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 else:
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 exedir, exename = os.path.split(sys.executable)
vlog("# Modifying search path to find %s as %s in '%s'" %
(exename, pyexename, exedir))
Bryan O'Sullivan
run-tests: on windows, put correct python at front of PATH...
r18059 path = os.environ['PATH'].split(os.pathsep)
while exedir in path:
path.remove(exedir)
os.environ['PATH'] = os.pathsep.join([exedir] + path)
Mads Kiilerich
run-tests.py: fix handling of symlink to the right python...
r18244 if not findprogram(pyexename):
print "WARNING: Cannot find %s in search path" % pyexename
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")
Bryan O'Sullivan
run-tests: add a --compiler option...
r17966 compiler = ''
if options.compiler:
compiler = '--compiler ' + options.compiler
Martin Geisler
run-tests: add --pure flag for using pure Python modules
r7723 pure = options.pure and "--pure" or ""
Augie Fackler
run-tests: if run by python3, execute setup.py with --c2to3
r19758 py3 = ''
if sys.version_info[0] == 3:
py3 = '--c2to3'
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
Greg Ward
run-tests: use os.path.realpath() to find hg's setup.py....
r8943 script = os.path.realpath(sys.argv[0])
hgroot = os.path.dirname(os.path.dirname(script))
os.chdir(hgroot)
Patrick Mezard
run-tests: work around a distutils bug triggered by 0a8a43b4ca75
r9905 nohome = '--home=""'
if os.name == 'nt':
# The --home="" trick works only on OS where os.sep == '/'
# because of a distutils convert_path() fast-path. Avoid it at
# least on Windows for now, deal with .pydistutils.cfg bugs
# when they happen.
nohome = ''
Augie Fackler
run-tests: if run by python3, execute setup.py with --c2to3
r19758 cmd = ('%(exe)s setup.py %(py3)s %(pure)s clean --all'
Bryan O'Sullivan
run-tests: add a --compiler option...
r17966 ' build %(compiler)s --build-base="%(base)s"'
Bryan O'Sullivan
run-tests: make build command line less intimidating...
r17965 ' install --force --prefix="%(prefix)s" --install-lib="%(libdir)s"'
' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
Augie Fackler
run-tests: move from dict() construction to {} literals...
r20680 % {'exe': sys.executable, 'py3': py3, 'pure': pure,
'compiler': compiler, 'base': os.path.join(HGTMP, "build"),
'prefix': INST, 'libdir': PYTHONDIR, 'bindir': BINDIR,
'nohome': nohome, 'logfile': 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
Alejandro Santos
tests: add -3 switch to run-tests.py
r9028 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'
f.close()
f = open(os.path.join(BINDIR, 'hg'), 'w')
for line in lines:
f.write(line + '\n')
f.close()
Patrick Mezard
run-tests: fix hg.bat python reference...
r14336 hgbat = os.path.join(BINDIR, 'hg.bat')
if os.path.isfile(hgbat):
# hg.bat expects to be put in bin/scripts while run-tests.py
# installation layout put it in bin/ directly. Fix it
f = open(hgbat, 'rb')
data = f.read()
f.close()
if '"%~dp0..\python" "%~dp0hg" %*' in data:
data = data.replace('"%~dp0..\python" "%~dp0hg" %*',
'"%~dp0python" "%~dp0hg" %*')
f = open(hgbat, 'wb')
f.write(data)
f.close()
else:
print 'WARNING: cannot fix hg.bat reference to python.exe'
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if options.anycoverage:
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 custom = os.path.join(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')
vlog('# Installing coverage rc to %s' % rc)
os.environ['COVERAGE_PROCESS_START'] = rc
fn = os.path.join(INST, '..', '.coverage')
os.environ['COVERAGE_FILE'] = fn
Greg Ward
run-tests: move _hgpath() up so it's not in the middle of the main program.
r8092
Siddharth Agarwal
run-tests: add --time option to log times for each test...
r17921 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)
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):
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 cmd = 'coverage %s' % ' '.join(args)
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620 vlog('# Running: %s' % cmd)
os.system(cmd)
Dirkjan Ochtman
tests: use external coverage, mandate newer version...
r10648 covrun('-c')
Matt Mackall
run-tests: use a list comprehension instead of map
r15858 omit = ','.join(os.path.join(x, '*') for x in [BINDIR, TESTDIR])
Dirkjan Ochtman
tests: make coverage run in parallel mode, clean up coverage code
r8620 covrun('-i', '-r', '"--omit=%s"' % omit) # report
Markus Zapke-Gründemann
tests: add htmlcov option
r15859 if options.htmlcov:
htmldir = os.path.join(TESTDIR, 'htmlcov')
covrun('-i', '-b', '"--directory=%s"' % htmldir, '"--omit=%s"' % omit)
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
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 def pytest(test, wd, options, replacements, env):
Matt Mackall
tests: move script execution in runner helpers
r11740 py3kswitch = options.py3k_warnings and ' -3' or ''
cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
vlog("# Running", cmd)
Matt Mackall
run-tests: backout 4f32747879d1 line endings change...
r19460 if os.name == 'nt':
replacements.append((r'\r\n', '\n'))
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 return run(cmd, wd, options, replacements, env)
Matt Mackall
tests: move script execution in runner helpers
r11740
Mads Kiilerich
tests: use (esc) markup for string-escape...
r12941 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
escapemap.update({'\\': '\\\\', '\r': r'\r'})
def escapef(m):
return escapemap[m.group(0)]
def stringescape(s):
return escapesub(escapef, s)
Matt Mackall
run-tests: pull out unified matching funcs
r15414 def rematch(el, l):
try:
Mads Kiilerich
run-tests: alternative way of handling \r on Windows...
r17777 # use \Z to ensure that the regex matches to the end of the string
Matt Mackall
run-tests: backout 4f32747879d1 line endings change...
r19460 if os.name == 'nt':
return re.match(el + r'\r?\n\Z', l)
Mads Kiilerich
run-tests: alternative way of handling \r on Windows...
r17777 return re.match(el + r'\n\Z', l)
Matt Mackall
run-tests: pull out unified matching funcs
r15414 except re.error:
# el is an invalid regex
return False
def globmatch(el, l):
Mads Kiilerich
tests: make (glob) on windows accept \ instead of /...
r15447 # The only supported special characters are * and ? plus / which also
# matches \ on windows. Escaping of these caracters is supported.
Simon Heimberg
tests: quickly check if the glob line already matches the output...
r18680 if el + '\n' == l:
Simon Heimberg
run-tests: test for os.altsep instead of os.name when checking \ for /...
r19419 if os.altsep:
Simon Heimberg
tests: inform on Windows about unnecessary glob lines...
r18681 # matching on "/" is not needed for this line
Simon Heimberg
run-tests: print more information on unnecessary glob matching...
r20274 return '-glob'
Simon Heimberg
tests: quickly check if the glob line already matches the output...
r18680 return True
Matt Mackall
run-tests: pull out unified matching funcs
r15414 i, n = 0, len(el)
res = ''
while i < n:
c = el[i]
i += 1
Mads Kiilerich
tests: make (glob) on windows accept \ instead of /...
r15447 if c == '\\' and el[i] in '*?\\/':
Matt Mackall
run-tests: pull out unified matching funcs
r15414 res += el[i - 1:i + 1]
i += 1
elif c == '*':
res += '.*'
elif c == '?':
res += '.'
Simon Heimberg
run-tests: test for os.altsep instead of os.name when checking \ for /...
r19419 elif c == '/' and os.altsep:
Mads Kiilerich
tests: make (glob) on windows accept \ instead of /...
r15447 res += '[/\\\\]'
Matt Mackall
run-tests: pull out unified matching funcs
r15414 else:
res += re.escape(c)
return rematch(res, l)
Matt Mackall
run-tests: pull out line matching function
r15415 def linematch(el, l):
if el == l: # perfect match (fast)
return True
Mads Kiilerich
run-tests: make it possible to combine (esc) with (glob) and (re)...
r17778 if el:
if el.endswith(" (esc)\n"):
el = el[:-7].decode('string-escape') + '\n'
Matt Mackall
run-tests: backout 4f32747879d1 line endings change...
r19460 if el == l or os.name == 'nt' and el[:-1] + '\r\n' == l:
return True
Simon Heimberg
run-tests: test each line matching function on its own...
r20272 if el.endswith(" (re)\n"):
return rematch(el[:-6], l)
if el.endswith(" (glob)\n"):
return globmatch(el[:-8], l)
Simon Heimberg
run-tests: suggest to append glob when only path sep does not match...
r20273 if os.altsep and l.replace('\\', '/') == el:
return '+glob'
Matt Mackall
run-tests: pull out line matching function
r15415 return False
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 def tsttest(test, wd, options, replacements, env):
Matt Mackall
tests: add some comments to the unified test code
r15413 # We generate a shell script which outputs unique markers to line
# up script results with our source. These markers include input
# line number and the last return code
Matt Mackall
tests: basic support for unified tests
r11741 salt = "SALT" + str(time.time())
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 def addsalt(line, inpython):
if inpython:
script.append('%s %d 0\n' % (salt, line))
else:
script.append('echo %s %s $?\n' % (salt, line))
Matt Mackall
tests: basic support for unified tests
r11741
Matt Mackall
tests: add some comments to the unified test code
r15413 # After we run the shell script, we re-unify the script output
# with non-active parts of the source, with synchronization by our
# SALT line number markers. The after table contains the
# non-active components, ordered by line number
after = {}
Matt Mackall
tests: basic support for unified tests
r11741 pos = prepos = -1
Matt Mackall
tests: add some comments to the unified test code
r15413
# Expected shellscript output
Matt Mackall
tests: basic support for unified tests
r11741 expected = {}
Matt Mackall
tests: add some comments to the unified test code
r15413
# We keep track of whether or not we're in a Python block so we
# can generate the surrounding doctest magic
Matt Mackall
tests: rewrite inline Python support...
r15412 inpython = False
Matt Mackall
tests: add some comments to the unified test code
r15413
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 # True or False when in a true or false conditional section
skipping = None
def hghave(reqs):
# TODO: do something smarter when all other uses of hghave is gone
Adrian Buehlmann
tests/run-tests: avoid C:/ in arguments...
r16897 tdir = TESTDIR.replace('\\', '/')
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 proc = Popen4('%s -c "%s/hghave %s"' %
Mads Kiilerich
tests: use the right directory for running hghave from run-tests.py
r16906 (options.shell, tdir, ' '.join(reqs)), wd, 0)
Mads Kiilerich
tests: make hghave and run-tests exit on unknown feature requirements
r18229 stdout, stderr = proc.communicate()
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 ret = proc.wait()
if wifexited(ret):
ret = os.WEXITSTATUS(ret)
Mads Kiilerich
tests: make hghave and run-tests exit on unknown feature requirements
r18229 if ret == 2:
print stdout
sys.exit(1)
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 return ret == 0
Matt Mackall
run-tests: minor cleanups
r15416 f = open(test)
t = f.readlines()
f.close()
script = []
Mads Kiilerich
tests: add 'set -x' to the .t sh scripts in run-tests.py debug mode...
r15940 if options.debug:
script.append('set -x\n')
Mads Kiilerich
tests: use an alias to make msys 'pwd' return paths with forward slashes
r15569 if os.getenv('MSYSTEM'):
script.append('alias pwd="pwd -W"\n')
Simon Heimberg
run-tests: do not fail on empty tsttest file...
r18565 n = 0
Matt Mackall
tests: rewrite inline Python support...
r15412 for n, l in enumerate(t):
Mads Kiilerich
tests: handle .t files without trailing LF...
r12934 if not l.endswith('\n'):
l += '\n'
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 if l.startswith('#if'):
if skipping is not None:
after.setdefault(pos, []).append(' !!! nested #if\n')
skipping = not hghave(l.split()[1:])
after.setdefault(pos, []).append(l)
elif l.startswith('#else'):
if skipping is None:
after.setdefault(pos, []).append(' !!! missing #if\n')
skipping = not skipping
after.setdefault(pos, []).append(l)
elif l.startswith('#endif'):
if skipping is None:
after.setdefault(pos, []).append(' !!! missing #if\n')
skipping = None
after.setdefault(pos, []).append(l)
elif skipping:
after.setdefault(pos, []).append(l)
elif l.startswith(' >>> '): # python inlines
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 after.setdefault(pos, []).append(l)
prepos = pos
pos = n
Matt Mackall
tests: rewrite inline Python support...
r15412 if not inpython:
# we've just entered a Python block, add the header
inpython = True
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 addsalt(prepos, False) # make sure we report the exit code
Matt Mackall
tests: rewrite inline Python support...
r15412 script.append('%s -m heredoctest <<EOF\n' % PYTHON)
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 addsalt(n, True)
script.append(l[2:])
Adrian Buehlmann
run-tests: don't add python lines to expected dict...
r16841 elif l.startswith(' ... '): # python inlines
Matt Mackall
tests: rewrite inline Python support...
r15412 after.setdefault(prepos, []).append(l)
script.append(l[2:])
elif l.startswith(' $ '): # commands
if inpython:
script.append("EOF\n")
inpython = False
Matt Mackall
tests: basic support for unified tests
r11741 after.setdefault(pos, []).append(l)
prepos = pos
pos = n
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 addsalt(n, False)
Mads Kiilerich
tests: make .t tests stop immediately if a cd fails...
r16905 cmd = l[4:].split()
if len(cmd) == 2 and cmd[0] == 'cd':
l = ' $ cd %s || exit 1\n' % cmd[1]
Matt Mackall
tests: basic support for unified tests
r11741 script.append(l[4:])
elif l.startswith(' > '): # continuations
after.setdefault(prepos, []).append(l)
script.append(l[4:])
elif l.startswith(' '): # results
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 # queue up a list of expected results
expected.setdefault(pos, []).append(l[2:])
Matt Mackall
tests: basic support for unified tests
r11741 else:
Matt Mackall
tests: rewrite inline Python support...
r15412 if inpython:
script.append("EOF\n")
inpython = False
Matt Mackall
tests: basic support for unified tests
r11741 # non-command/result - queue up for merged output
after.setdefault(pos, []).append(l)
Matt Mackall
tests: add some comments to the unified test code
r15413 if inpython:
script.append("EOF\n")
Mads Kiilerich
tests: introduce c-style conditional sections in .t tests...
r16842 if skipping is not None:
after.setdefault(pos, []).append(' !!! missing #endif\n')
Matt Mackall
run-tests: replace inline python handling with more native scheme...
r15434 addsalt(n + 1, False)
Matt Mackall
tests: add exit codes to unified tests
r12316
Matt Mackall
run-tests: minor cleanups
r15416 # Write out the script and execute it
Mads Kiilerich
run-tests: place the .t shell script next to $TESTTMP and with a useful name...
r19871 name = wd + '.sh'
f = open(name, 'w')
for l in script:
f.write(l)
f.close()
Matt Mackall
tests: basic support for unified tests
r11741
Mads Kiilerich
run-tests: place the .t shell script next to $TESTTMP and with a useful name...
r19871 cmd = '%s "%s"' % (options.shell, name)
vlog("# Running", cmd)
exitcode, output = run(cmd, wd, options, replacements, env)
# do not merge output if skipped, return hghave message instead
# similarly, with --debug, output is None
if exitcode == SKIPPED_STATUS or output is None:
return exitcode, output
Matt Mackall
tests: basic support for unified tests
r11741
Matt Mackall
tests: add some comments to the unified test code
r15413 # Merge the script output back into a unified test
Simon Heimberg
run-tests: fixed warn detection on failures with too many output...
r20601 warnonly = 1 # 1: not yet, 2: yes, 3: for sure not
if exitcode != 0: # failure has been reported
warnonly = 3 # set to "for sure not"
Matt Mackall
tests: basic support for unified tests
r11741 pos = -1
postout = []
Mads Kiilerich
run-tests: drop unused enumerate
r17739 for l in output:
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 lout, lcmd = l, None
if salt in l:
lout, lcmd = l.split(salt, 1)
if lout:
Mads Kiilerich
run-tests: use more explicit criteria for detecting no-eol...
r17741 if not lout.endswith('\n'):
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 lout += ' (no-eol)\n'
Matt Mackall
tests: add some comments to the unified test code
r15413 # find the expected output at the current position
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 el = None
if pos in expected and expected[pos]:
el = expected[pos].pop(0)
Simon Heimberg
run-tests: suggest to append glob when only path sep does not match...
r20273 r = linematch(el, lout)
if isinstance(r, str):
if r == '+glob':
lout = el[:-1] + ' (glob)\n'
Simon Heimberg
run-tests: fixed warn detection on detecting warn only for lines...
r20600 r = '' # warn only this line
Simon Heimberg
run-tests: print more information on unnecessary glob matching...
r20274 elif r == '-glob':
Simon Heimberg
run-tests: unnecessary globs also count as warnings...
r20510 lout = ''.join(el.rsplit(' (glob)', 1))
Simon Heimberg
run-tests: fixed warn detection on detecting warn only for lines...
r20600 r = '' # warn only this line
Simon Heimberg
run-tests: print more information on unnecessary glob matching...
r20274 else:
log('\ninfo, unknown linematch result: %r\n' % r)
r = False
Simon Heimberg
run-tests: suggest to append glob when only path sep does not match...
r20273 if r:
Matt Mackall
run-tests: pull out line matching function
r15415 postout.append(" " + el)
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 else:
Mads Kiilerich
tests: use (esc) markup for string-escape...
r12941 if needescape(lout):
lout = stringescape(lout.rstrip('\n')) + " (esc)\n"
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 postout.append(" " + lout) # let diff deal with it
Simon Heimberg
run-tests: fixed warn detection on detecting warn only for lines...
r20600 if r != '': # if line failed
Simon Heimberg
run-tests: fixed warn detection on failures with too many output...
r20601 warnonly = 3 # set to "for sure not"
elif warnonly == 1: # is "not yet" (and line is warn only)
warnonly = 2 # set to "yes" do warn
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940
if lcmd:
Matt Mackall
tests: add exit codes to unified tests
r12316 # add on last return code
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 ret = int(lcmd.split()[1])
Matt Mackall
tests: add exit codes to unified tests
r12316 if ret != 0:
postout.append(" [%s]\n" % ret)
Matt Mackall
tests: basic support for unified tests
r11741 if pos in after:
Matt Mackall
tests: add some comments to the unified test code
r15413 # merge in non-active test bits
Matt Mackall
tests: basic support for unified tests
r11741 postout += after.pop(pos)
Mads Kiilerich
tests: (no-eol) markup for command output without trailing LF...
r12940 pos = int(lcmd.split()[0])
Matt Mackall
tests: basic support for unified tests
r11741
if pos in after:
postout += after.pop(pos)
Simon Heimberg
run-tests: fixed warn detection on failures with too many output...
r20601 if warnonly == 2:
exitcode = False # set exitcode to warned
Matt Mackall
tests: basic support for unified tests
r11741 return exitcode, postout
Simon Heimberg
run-tests: only call WIFEXITED on systems it exists...
r13348 wifexited = getattr(os, "WIFEXITED", lambda x: False)
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 def run(cmd, wd, options, replacements, env):
Stephen Darnell
Add a pure python version of run-tests....
r2110 """Run command in a sub-process, capturing the output (stdout and stderr).
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 Return a tuple (exitcode, output). output is None in debug mode."""
Stephen Darnell
Add a pure python version of run-tests....
r2110 # TODO: Use subprocess.Popen if we're running on Python 2.4
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 if options.debug:
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 proc = subprocess.Popen(cmd, shell=True, cwd=wd, env=env)
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 ret = proc.wait()
return (ret, None)
Matt Mackall
run-tests: add env dict to isolate test environment
r19262 proc = Popen4(cmd, wd, options.timeout, env)
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 def cleanup():
Thomas Arendsen Hein
run-tests: fallback to SIGTERM if subprocess.Popen does not have terminate()
r14821 terminate(proc)
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 ret = proc.wait()
if ret == 0:
ret = signal.SIGTERM << 8
Matt Mackall
run-tests: use env dict to kill daemons
r19263 killdaemons(env['DAEMON_PIDS'])
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 return ret
output = ''
proc.tochild.close()
Brendan Cully
run-tests: kill daemons on ^C with -j....
r10336
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 try:
output = proc.fromchild.read()
except KeyboardInterrupt:
vlog('# Handling keyboard interrupt')
cleanup()
raise
Brendan Cully
run-tests: kill daemons on ^C with -j....
r10336
Brendan Cully
run-tests: lock popen wait/poll...
r19413 ret = proc.wait()
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 if wifexited(ret):
ret = os.WEXITSTATUS(ret)
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 if proc.timeout:
ret = 'timeout'
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001
Patrick Mezard
run-tests: use the common test path on Windows and Java...
r14338 if ret:
Matt Mackall
run-tests: use env dict to kill daemons
r19263 killdaemons(env['DAEMON_PIDS'])
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001
Matt Mackall
run-tests: add abort flag...
r19273 if abort:
raise KeyboardInterrupt()
Mads Kiilerich
tests: replace test tmp directory with $TESTTMP in test output...
r12639 for s, r in replacements:
Martin Geisler
run-tests: use regex when searching for $HGPORT in test output...
r12895 output = re.sub(s, r, output)
Mads Kiilerich
run-tests: allow test output lines to be terminated with \r in addition to \n...
r17742 return ret, output.splitlines(True)
Stephen Darnell
Add a pure python version of run-tests....
r2110
Matt Mackall
run-tests: introduce threadtmp directory
r19274 def runone(options, test, count):
Matt Mackall
run-tests: change return code of runone
r19248 '''returns a result element: (code, test, msg)'''
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 def skip(msg):
Matt Mackall
run-tests: change return code of runone
r19248 if options.verbose:
Matt Mackall
run-tests: add a log function
r19251 log("\nSkipping %s: %s" % (testpath, msg))
Matt Mackall
run-tests: change return code of runone
r19248 return 's', test, msg
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470
Matt Mackall
run-tests: move interactive handling into runone
r13988 def fail(msg, ret):
Simon Heimberg
run-tests: add possibility for test-runners to report a "warned" test result...
r20508 warned = ret is False
Greg Ward
run-tests: reduce global variables set by parse_args().
r8095 if not options.nodiff:
Simon Heimberg
run-tests: add possibility for test-runners to report a "warned" test result...
r20508 log("\n%s: %s %s" % (warned and 'Warning' or 'ERROR', test, msg))
Patrick Mezard
run-tests: fix --interactive (after 994ad067ac6e)...
r13999 if (not ret and options.interactive
and os.path.exists(testpath + ".err")):
Matt Mackall
run-tests: fix some missing i/o locks
r14003 iolock.acquire()
Matt Mackall
run-tests: move interactive handling into runone
r13988 print "Accept this change? [n] ",
answer = sys.stdin.readline().strip()
Matt Mackall
run-tests: fix some missing i/o locks
r14003 iolock.release()
Matt Mackall
run-tests: move interactive handling into runone
r13988 if answer.lower() in "y yes".split():
if test.endswith(".t"):
Patrick Mezard
run-tests: fix --interactive (after 994ad067ac6e)...
r13999 rename(testpath + ".err", testpath)
Matt Mackall
run-tests: move interactive handling into runone
r13988 else:
Patrick Mezard
run-tests: fix --interactive (after 994ad067ac6e)...
r13999 rename(testpath + ".err", testpath + ".out")
Matt Mackall
run-tests: unify marks and result codes
r19249 return '.', test, ''
Simon Heimberg
run-tests: add possibility for test-runners to report a "warned" test result...
r20508 return warned and '~' or '!', test, msg
Matt Mackall
run-tests: use a results dict
r13994
def success():
Matt Mackall
run-tests: unify marks and result codes
r19249 return '.', test, ''
Matt Mackall
run-tests: use a results dict
r13994
def ignore(msg):
Matt Mackall
run-tests: change return code of runone
r19248 return 'i', test, msg
Benoit Boissinot
run-tests.py: add a summary of failed tests at the end
r6244
Matt Mackall
run-tests: regroup nested functions
r19244 def describe(ret):
if ret < 0:
return 'killed by signal %d' % -ret
return 'returned error code %d' % ret
Matt Mackall
run-tests: regroup some variable initialization
r19245 testpath = os.path.join(TESTDIR, test)
err = os.path.join(TESTDIR, test + ".err")
lctest = test.lower()
Matt Mackall
run-tests: fix a path existence check
r19246 if not os.path.exists(testpath):
Matt Mackall
run-tests: change return code of runone
r19248 return skip("doesn't exist")
Matt Mackall
run-tests: move existence/name format check into runone
r13989
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 if not (options.whitelisted and test in options.whitelisted):
if options.blacklist and test in options.blacklist:
Matt Mackall
run-tests: change return code of runone
r19248 return skip("blacklisted")
Matt Mackall
run-tests: move blacklist and retest filtering to runone
r13993
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 if options.retest and not os.path.exists(test + ".err"):
simon@laptop-tosh
run-tests: ignoring tests works again...
r19311 return ignore("not retesting")
Matt Mackall
run-tests: move blacklist and retest filtering to runone
r13993
Augie Fackler
run-tests: allow whitelisting tests that should always run...
r14493 if options.keywords:
fp = open(test)
t = fp.read().lower() + test.lower()
fp.close()
for k in options.keywords.lower().split():
if k in t:
break
else:
simon@laptop-tosh
run-tests: ignoring tests works again...
r19311 return ignore("doesn't match keyword")
Matt Mackall
run-tests: move keyword checking into runone
r13991
Simon Heimberg
run-tests: only check the common criteria once per test
r19527 if not lctest.startswith("test-"):
return skip("not a test file")
Matt Mackall
run-tests: make a table of test types
r19239 for ext, func, out in testtypes:
Simon Heimberg
run-tests: only check the common criteria once per test
r19527 if lctest.endswith(ext):
Matt Mackall
run-tests: make a table of test types
r19239 runner = func
ref = os.path.join(TESTDIR, test + out)
break
Vadim Gelfer
run-tests.py: skip tests that should not run....
r2710 else:
Mads Kiilerich
run-tests: remove dead code for supporting old test scripts
r17801 return skip("unknown test type")
Stephen Darnell
Add a pure python version of run-tests....
r2110
Matt Mackall
run-tests: regroup some initialization checks
r19247 vlog("# Test", test)
if os.path.exists(err):
os.remove(err) # Remove any previous output files
Mads Kiilerich
run-tests.py: skipped tests shouldn't change working directory
r10406 # Make a tmp subdirectory to work in
Matt Mackall
run-tests: introduce threadtmp directory
r19274 threadtmp = os.path.join(HGTMP, "child%d" % count)
testtmp = os.path.join(threadtmp, os.path.basename(test))
os.mkdir(threadtmp)
Matt Mackall
run-tests: regroup temp dir creation
r19243 os.mkdir(testtmp)
Idan Kamara
tests: set HOME to the test temp dir (issue2707)
r13764
Matt Mackall
run-tests: use count to calculate port to use...
r19275 port = options.port + count * 3
Mads Kiilerich
tests: ignore \r on windows
r15449 replacements = [
Matt Mackall
run-tests: use count to calculate port to use...
r19275 (r':%s\b' % port, ':$HGPORT'),
(r':%s\b' % (port + 1), ':$HGPORT1'),
(r':%s\b' % (port + 2), ':$HGPORT2'),
Mads Kiilerich
tests: ignore \r on windows
r15449 ]
if os.name == 'nt':
Mads Kiilerich
run-tests: make $TESTTMP matching case-insensitive on windows
r15451 replacements.append(
(''.join(c.isalpha() and '[%s%s]' % (c.lower(), c.upper()) or
c in '/\\' and r'[/\\]' or
c.isdigit() and c or
'\\' + c
for c in testtmp), '$TESTTMP'))
else:
replacements.append((re.escape(testtmp), '$TESTTMP'))
Mads Kiilerich
tests: ignore \r on windows
r15449
Matt Mackall
run-tests: use count to calculate port to use...
r19275 env = createenv(options, testtmp, threadtmp, port)
Matt Mackall
run-tests: move HGRCPATH to env
r19268 createhgrc(env['HGRCPATH'], options)
Matt Mackall
run-tests: always gather runtimes
r19302 starttime = time.time()
Simon Heimberg
run-tests: report interrupted tests...
r19300 try:
ret, out = runner(testpath, testtmp, options, replacements, env)
except KeyboardInterrupt:
Matt Mackall
run-tests: always gather runtimes
r19302 endtime = time.time()
Matt Mackall
run-tests: simplify interrupted message
r19304 log('INTERRUPTED: %s (after %d seconds)' % (test, endtime - starttime))
Simon Heimberg
run-tests: report interrupted tests...
r19300 raise
Matt Mackall
run-tests: always gather runtimes
r19302 endtime = time.time()
times.append((test, endtime - starttime))
Stephen Darnell
Add a pure python version of run-tests....
r2110 vlog("# Ret was:", ret)
Matt Mackall
run-tests: use env dict to kill daemons
r19263 killdaemons(env['DAEMON_PIDS'])
Mads Kiilerich
tests: kill daemons early, making breaking at "Accept" prompt safe
r18051
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 skipped = (ret == SKIPPED_STATUS)
Matt Mackall
run-tests: add --view switch to use external diff viewer
r11040
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 # If we're not in --debug mode and reference output file exists,
# check test output against it.
if options.debug:
Martin Geisler
code style: prefer 'is' and 'is not' tests with singletons
r13031 refout = None # to match "out is None"
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 elif os.path.exists(ref):
Vadim Gelfer
run-tests.py must print changed test output no matter what exit code is.
r2213 f = open(ref, "r")
Mads Kiilerich
run-tests: allow test output lines to be terminated with \r in addition to \n...
r17742 refout = f.read().splitlines(True)
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 = []
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707
Matt Mackall
run-tests: add --view switch to use external diff viewer
r11040 if (ret != 0 or out != refout) and not skipped and not options.debug:
# Save errors to a file for diagnosis
f = open(err, "wb")
for line in out:
f.write(line)
f.close()
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 if skipped:
Greg Ward
run-tests: add "debug" mode: don't capture child output, just show it....
r9707 if out is None: # debug mode: nothing to parse
missing = ['unknown']
failed = None
else:
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:
Matt Mackall
run-tests: change return code of runone
r19248 result = fail("hghave failed checking for %s" % failed[-1], ret)
Nicolas Dumazet
run-tests: detect when hghave fails to check for a feature and fail test...
r8060 skipped = False
else:
Matt Mackall
run-tests: change return code of runone
r19248 result = skip(missing[-1])
Matt Mackall
run-tests: switch timeout handling from alarm to helper thread...
r14001 elif ret == 'timeout':
Matt Mackall
run-tests: change return code of runone
r19248 result = fail("timed out", ret)
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 elif out != refout:
Patrick Mezard
run-tests: display diff before prompting with --interactive
r14006 if not options.nodiff:
Matt Mackall
run-tests: add a lock for console I/O
r14002 iolock.acquire()
Matt Mackall
run-tests: add --view switch to use external diff viewer
r11040 if options.view:
os.system("%s %s %s" % (options.view, ref, err))
else:
showdiff(refout, out, ref, err)
Matt Mackall
run-tests: add a lock for console I/O
r14002 iolock.release()
Patrick Mezard
run-tests: display diff before prompting with --interactive
r14006 if ret:
Matt Mackall
run-tests: change return code of runone
r19248 result = fail("output changed and " + describe(ret), ret)
Patrick Mezard
run-tests: display diff before prompting with --interactive
r14006 else:
Matt Mackall
run-tests: change return code of runone
r19248 result = fail("output changed", ret)
Patrick Mezard
Add hghave utility and run-tests.py support....
r4881 elif ret:
Matt Mackall
run-tests: change return code of runone
r19248 result = fail(describe(ret), ret)
Idan Kamara
run-tests: don't count test as succeeded if it failed...
r14037 else:
Matt Mackall
run-tests: change return code of runone
r19248 result = success()
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: add a lock for console I/O
r14002 iolock.acquire()
Matt Mackall
run-tests: unify marks and result codes
r19249 sys.stdout.write(result[0])
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470 sys.stdout.flush()
Matt Mackall
run-tests: add a lock for console I/O
r14002 iolock.release()
Matt Mackall
tests: tidy up reporting of skipped tests...
r5470
Peter Arrenbrecht
tests: add --keep-tmp to run-tests.py to debug test environment...
r6208 if not options.keep_tmpdir:
Matt Mackall
run-tests: introduce threadtmp directory
r19274 shutil.rmtree(threadtmp, True)
Matt Mackall
run-tests: change return code of runone
r19248 return result
Stephen Darnell
Add a pure python version of run-tests....
r2110
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
Augie Fackler
run-tests: find mercurial path with syntax valid on both py2 and py3
r19759 cmd = '%s -c "import mercurial; print (mercurial.__path__[0])"'
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 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()
Idan Kamara
run-tests: compare absolute paths in _checkhglib
r14263 if os.path.abspath(actualhg) != os.path.abspath(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
Simon Heimberg
run-tests: introduce 'warned' as test result...
r20506 results = {'.':[], '!':[], '~': [], 's':[], 'i':[]}
Siddharth Agarwal
run-tests: add --time option to log times for each test...
r17921 times = []
Matt Mackall
run-tests: add a lock for console I/O
r14002 iolock = threading.Lock()
Matt Mackall
run-tests: add abort flag...
r19273 abort = False
Matt Mackall
run-tests: add locking on results struct
r14000
Matt Mackall
run-tests: introduce thread scheduler
r19276 def scheduletests(options, tests):
jobs = options.jobs
done = queue.Queue()
running = 0
count = 0
global abort
def job(test, count):
try:
done.put(runone(options, test, count))
except KeyboardInterrupt:
pass
Simon Heimberg
run-tests: report tests as failed when run-test raises an error...
r20258 except: # re-raises
done.put(('!', test, 'run-test raised an error, see traceback'))
raise
Matt Mackall
run-tests: change return code of runone
r19248
Matt Mackall
run-tests: introduce thread scheduler
r19276 try:
while tests or running:
if not done.empty() or running == jobs or not tests:
try:
code, test, msg = done.get(True, 1)
results[code].append((test, msg))
if options.first and code not in '.si':
break
except queue.Empty:
continue
running -= 1
if tests and not running == jobs:
test = tests.pop(0)
Matt Mackall
run-tests: add --loop support...
r19283 if options.loop:
tests.append(test)
Simon Heimberg
run-tests: set the thread name to the test name for info on error...
r20259 t = threading.Thread(target=job, name=test, args=(test, count))
Matt Mackall
run-tests: introduce thread scheduler
r19276 t.start()
running += 1
count += 1
except KeyboardInterrupt:
abort = True
Matt Mackall
run-tests: move test loop into a helper function
r13995
Greg Ward
run-tests: factor out _checkhglib() to check import path of 'mercurial'....
r8672 def runtests(options, tests):
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")
Bryan O'Sullivan
run-tests: use correct python when run with --local
r18048 else:
usecorrectpython()
Dirkjan Ochtman
imported patch test-check
r6982
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
run-tests: introduce thread scheduler
r19276 scheduletests(options, tests)
Matt Mackall
tests: add -R switch...
r3625
Matt Mackall
run-tests: unify marks and result codes
r19249 failed = len(results['!'])
Simon Heimberg
run-tests: introduce 'warned' as test result...
r20506 warned = len(results['~'])
tested = len(results['.']) + failed + warned
Matt Mackall
run-tests: use a results dict
r13994 skipped = len(results['s'])
ignored = len(results['i'])
Matt Mackall
run-tests: drop options.child and users
r19279 print
Matt Mackall
run-tests: make --noskips work
r19294 if not options.noskips:
for s in results['s']:
print "Skipped %s: %s" % s
Simon Heimberg
run-tests: introduce 'warned' as test result...
r20506 for s in results['~']:
print "Warned %s: %s" % s
Matt Mackall
run-tests: drop options.child and users
r19279 for s in results['!']:
print "Failed %s: %s" % s
_checkhglib("Tested")
Simon Heimberg
run-tests: introduce 'warned' as test result...
r20506 print "# Ran %d tests, %d skipped, %d warned, %d failed." % (
tested, skipped + ignored, warned, failed)
Mads Kiilerich
tests: python hash seed is only relevant after failures - otherwise keep quiet
r20046 if results['!']:
print 'python hash seed:', os.environ['PYTHONHASHSEED']
Matt Mackall
run-tests: drop options.child and users
r19279 if options.time:
outputtimes(options)
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
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
Matt Mackall
run-tests: drop options.child and users
r19279 print "\ninterrupted!"
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Matt Mackall
run-tests: use a results dict
r13994 if failed:
Simon Heimberg
run-tests: handle sys.exit in main function
r20505 return 1
Simon Heimberg
run-tests: separate exit code when no failed tests but warned ones...
r20507 if warned:
return 80
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Matt Mackall
run-tests: make a table of test types
r19239 testtypes = [('.py', pytest, '.out'),
('.t', tsttest, '')]
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()
Matt Mackall
run-tests: drop options.child and users
r19279 os.umask(022)
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Matt Mackall
run-tests: drop options.child and users
r19279 checktools()
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Mads Kiilerich
tests: small refactoring of run-tests' handling of tests list
r20793 if not args:
Mads Kiilerich
tests: add run-tests --changed option for running tests changed in revisions...
r20821 if options.changed:
proc = Popen4('hg st --rev "%s" -man0 .' % options.changed,
None, 0)
stdout, stderr = proc.communicate()
args = stdout.strip('\0').split('\0')
else:
args = os.listdir(".")
Benoit Boissinot
run-tests.py: do not install hg when the tests do no exist
r12677
Mads Kiilerich
tests: small refactoring of run-tests' handling of tests list
r20793 tests = [t for t in args
if t.startswith("test-")
and (t.endswith(".py") or t.endswith(".t"))]
Benoit Boissinot
run-tests.py: do not install hg when the tests do no exist
r12677
Mads Kiilerich
run-tests: introduce --random for running tests in random error...
r19057 if options.random:
random.shuffle(tests)
Matt Mackall
run-tests: schedule largest tests first
r19277 else:
Matt Mackall
run-tests: sort certain slow tests earlier by keyword...
r19281 # keywords for slow tests
slow = 'svn gendoc check-code-hg'.split()
def sortkey(f):
# run largest tests first, as they tend to take the longest
simon@laptop-tosh
run-tests: sort missing files first instead of raising an error...
r19315 try:
val = -os.stat(f).st_size
except OSError, e:
if e.errno != errno.ENOENT:
raise
return -1e9 # file does not exist, tell early
Matt Mackall
run-tests: sort certain slow tests earlier by keyword...
r19281 for kw in slow:
if kw in f:
val *= 10
return val
tests.sort(key=sortkey)
Mads Kiilerich
run-tests: introduce --random for running tests in random error...
r19057
Pierre-Yves David
test: display used python hash seed...
r18616 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))
Greg Ward
run-tests: move bits of main program so it's all at the bottom.
r8093
Siddharth Agarwal
run-tests.py: work when --with-hg is set to system hg...
r20541 global TESTDIR, HGTMP, INST, BINDIR, TMPBINDIR, PYTHONDIR, COVERAGE_FILE
Adrian Buehlmann
tests/run-tests: avoid C:/ in arguments...
r16897 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
Greg Ward
run-tests: make --tmpdir option more useful....
r9706 if options.tmpdir:
Matt Mackall
run-tests: drop options.child and users
r19279 options.keep_tmpdir = True
Greg Ward
run-tests: make --tmpdir option more useful....
r9706 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.
sys.exit("error: temp dir %r already exists" % tmpdir)
# Automatically removing tmpdir sounds convenient, but could
# really annoy anyone in the habit of using "--tmpdir=/tmp"
# or "--tmpdir=$HOME".
#vlog("# Removing temp dir", tmpdir)
#shutil.rmtree(tmpdir)
os.makedirs(tmpdir)
else:
Adrian Buehlmann
tests/run-tests: use $TMP on Windows (issue3490)...
r16890 d = None
if os.name == 'nt':
# without this, we get the default temp dir location, but
# in all lowercase, which causes troubles with paths (issue3490)
d = os.getenv('TMP')
tmpdir = tempfile.mkdtemp('', 'hgtests.', d)
Greg Ward
run-tests: make --tmpdir option more useful....
r9706 HGTMP = os.environ['HGTMP'] = os.path.realpath(tmpdir)
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))
Siddharth Agarwal
run-tests.py: work when --with-hg is set to system hg...
r20541 TMPBINDIR = os.path.join(HGTMP, 'install', 'bin')
os.makedirs(TMPBINDIR)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674
# 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")
Siddharth Agarwal
run-tests.py: work when --with-hg is set to system hg...
r20541 TMPBINDIR = BINDIR
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674 PYTHONDIR = os.path.join(INST, "lib", "python")
os.environ["BINDIR"] = BINDIR
os.environ["PYTHON"] = PYTHON
Matt Mackall
run-tests: drop options.child and users
r19279 path = [BINDIR] + os.environ["PATH"].split(os.pathsep)
Siddharth Agarwal
run-tests.py: work when --with-hg is set to system hg...
r20541 if TMPBINDIR != BINDIR:
path = [TMPBINDIR] + path
Matt Mackall
run-tests: drop options.child and users
r19279 os.environ["PATH"] = os.pathsep.join(path)
Greg Ward
run-tests: redefine --with-hg so it takes the 'hg' script to run....
r8674
Matt Mackall
run-tests: drop options.child and users
r19279 # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
# can run .../tests/run-tests.py test-foo where test-foo
Patrick Mezard
run-tests: fix heredoctest for out-of-tree extensions...
r20513 # 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__))]
Matt Mackall
run-tests: drop options.child and users
r19279 # 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)
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 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"])
Ronny Pfannschmidt
tests: adapt the test runner to work with jython
r10758 vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
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:
Simon Heimberg
run-tests: handle sys.exit in main function
r20505 sys.exit(runtests(options, tests) or 0)
Greg Ward
run-tests: factor out main(); reduce use of globals a bit.
r8094 finally:
Matt Mackall
tests: shorten post-test sleeps...
r16346 time.sleep(.1)
Martin Geisler
run-tests: removed some underscores (coding style)
r8097 cleanup(options)
Bryan O'Sullivan
Allow tests to run in parallel.
r5384
Simon Heimberg
run-tests: loadable as module
r13347 if __name__ == '__main__':
main()