#
# run_tests.py - run the tests in the regression test suite.
#
'''usage: python run_tests.py [--url=<base-url>] [--fs-type=<fs-type>]
[--verbose] [--cleanup]
<abs_srcdir> <abs_builddir>
<prog ...>
The optional base-url, fs-type, verbose, and cleanup options, and
the first four parameters are passed unchanged to the TestHarness
constuctor. All other parameters are names of test programs.
'''
import os, sys
import getopt
try:
my_getopt = getopt.gnu_getopt
except AttributeError:
my_getopt = getopt.getopt
class TestHarness:
'''Test harness for Subversion tests.
'''
def __init__(self, abs_srcdir, abs_builddir, logfile,
base_url=None, fs_type=None, verbose=None, cleanup=None):
'''Construct a TestHarness instance.
ABS_SRCDIR and ABS_BUILDDIR are the source and build directories.
LOGFILE is the name of the log file.
BASE_URL is the base url for DAV tests.
FS_TYPE is the FS type for repository creation.
'''
self.srcdir = abs_srcdir
self.builddir = abs_builddir
self.logfile = logfile
self.base_url = base_url
self.fs_type = fs_type
self.verbose = verbose
self.cleanup = cleanup
self.log = None
def run(self, list):
'Run all test programs given in LIST.'
self._open_log('w')
failed = 0
for prog in list:
failed = self._run_test(prog) or failed
self._open_log('r')
log_lines = self.log.readlines()
skipped = filter(lambda x: x[:6] == 'SKIP: ', log_lines)
if failed:
print 'At least one test FAILED, checking ' + self.logfile
map(sys.stdout.write, filter(lambda x: x[:6] in ('FAIL: ', 'XPASS:'),
log_lines))
if skipped:
print 'At least one test was SKIPPED, checking ' + self.logfile
map(sys.stdout.write, skipped)
self._close_log()
return failed
def _open_log(self, mode):
'Open the log file with the required MODE.'
self._close_log()
self.log = open(self.logfile, mode)
def _close_log(self):
'Close the log file.'
if not self.log is None:
self.log.close()
self.log = None
def _run_test(self, prog):
'Run a single test.'
def quote(arg):
if sys.platform == 'win32':
return '"' + arg + '"'
else:
return arg
progdir, progbase = os.path.split(prog)
# Using write here because we don't want even a trailing space
sys.stdout.write('Running all tests in ' + progbase + '...')
print >> self.log, 'START: ' + progbase
if progbase[-3:] == '.py':
progname = sys.executable
cmdline = [quote(progname),
quote(os.path.join(self.srcdir, prog))]
if self.verbose is not None:
cmdline.append('--verbose')
if self.cleanup is not None:
cmdline.append('--cleanup')
if self.base_url is not None:
cmdline.append(quote('--url=' + self.base_url))
if self.fs_type is not None:
cmdline.append(quote('--fs-type=' + self.fs_type))
elif os.access(prog, os.X_OK):
progname = './' + progbase
cmdline = [quote(progname),
quote('--srcdir=' + os.path.join(self.srcdir, progdir))]
if self.verbose is not None:
cmdline.append('--verbose')
if self.cleanup is not None:
cmdline.append('--cleanup')
if self.fs_type is not None:
cmdline.append(quote('--fs-type=' + self.fs_type))
else:
print 'Don\'t know what to do about ' + progbase
sys.exit(1)
old_cwd = os.getcwd()
try:
os.chdir(progdir)
failed = self._run_prog(progname, cmdline)
except:
os.chdir(old_cwd)
raise
else:
os.chdir(old_cwd)
if failed:
print 'FAILURE'
else:
print 'success'
print >> self.log, 'END: ' + progbase + '\n'
return failed
def _run_prog(self, progname, cmdline):
'Execute COMMAND, redirecting standard output and error to the log file.'
def restore_streams(stdout, stderr):
os.dup2(stdout, 1)
os.dup2(stderr, 2)
os.close(stdout)
os.close(stderr)
sys.stdout.flush()
sys.stderr.flush()
self.log.flush()
old_stdout = os.dup(1)
old_stderr = os.dup(2)
try:
os.dup2(self.log.fileno(), 1)
os.dup2(self.log.fileno(), 2)
rv = os.spawnv(os.P_WAIT, progname, cmdline)
except:
restore_streams(old_stdout, old_stderr)
raise
else:
restore_streams(old_stdout, old_stderr)
return rv
def main():
try:
opts, args = my_getopt(sys.argv[1:], 'u:f:vc',
['url=', 'fs-type=', 'verbose', 'cleanup'])
except getopt.GetoptError:
args = []
if len(args) < 3:
print __doc__
sys.exit(2)
base_url, fs_type, verbose, cleanup = None, None, None, None
for opt, val in opts:
if opt in ('-u', '--url'):
base_url = val
elif opt in ('-f', '--fs-type'):
fs_type = val
elif opt in ('-v', '--verbose'):
verbose = 1
elif opt in ('-c', '--cleanup'):
cleanup = 1
else:
raise getopt.GetoptError
th = TestHarness(args[0], args[1],
os.path.abspath('tests.log'),
base_url, fs_type, verbose, cleanup)
failed = th.run(args[2:])
if failed:
sys.exit(1)
# Run main if not imported as a module
if __name__ == '__main__':
main()
syntax highlighted by Code2HTML, v. 0.9.1