[pypy-svn] r58322 - in pypy/build/testrunner: . test
pedronis at codespeak.net
pedronis at codespeak.net
Mon Sep 22 17:51:06 CEST 2008
Author: pedronis
Date: Mon Sep 22 17:51:04 2008
New Revision: 58322
Modified:
pypy/build/testrunner/runner.py
pypy/build/testrunner/test/test_runner.py
Log:
(iko, pedronis)
- support parallel runs
- configurability hack through python code overriding the run parameters instance
Modified: pypy/build/testrunner/runner.py
==============================================================================
--- pypy/build/testrunner/runner.py (original)
+++ pypy/build/testrunner/runner.py Mon Sep 22 17:51:04 2008
@@ -1,4 +1,4 @@
-import sys, os, signal
+import sys, os, signal, thread, Queue
import py
from py.compat import subprocess, optparse
@@ -17,12 +17,7 @@
return name
return 'signal %d' % (n,)
-def execute_test(cwd, test, out, logfname, interp=None, test_driver=None):
- if interp is None:
- interp = [os.path.abspath(sys.executable)]
- if test_driver is None:
- test_driver = [os.path.abspath(os.path.join('py', 'bin', 'py.test'))]
-
+def execute_test(cwd, test, out, logfname, interp, test_driver):
args = interp+test_driver
args += ['--resultlog=%s' % logfname, test]
@@ -32,59 +27,124 @@
return exitcode
+def worker(num, n, run_param, testdirs, result_queue):
+ sessdir = run_param.sessdir
+ root = run_param.root
+ test_driver = run_param.test_driver
+ interp = run_param.interp
+ # xxx cfg thread start
+ while 1:
+ try:
+ test = testdirs.pop(0)
+ except IndexError:
+ result_queue.put(None) # done
+ return
+ basename = py.path.local(test).purebasename
+ logfname = sessdir.join("%d-%s-pytest-log" % (num, basename))
+ one_output = sessdir.join("%d-%s-output" % (num, basename))
+ num += n
-def execute_tests(cwd, testdirs, logfile, out, test_driver=None):
- sessdir = py.path.local.make_numbered_dir(prefix='usession-testrunner-', keep=4)
- c = 0
- failure = False
-
- for test in testdirs:
- basename = py.path.local(test).purebasename
- logfname = sessdir.join("%d-%s-pytest-log" % (c, basename))
- one_output = sessdir.join("%d-%s-output" % (c, basename))
- c += 1
- exitcode = execute_test(cwd, test, one_output, logfname,
- test_driver=test_driver)
- if c > 1:
- out.write(79*'_'+'\n')
+ exitcode = execute_test(root, test, one_output, logfname,
+ interp, test_driver)
+
+ # xxx cfg cleanup after testdir
+
output = one_output.read()
- out.write(output)
if logfname.check(file=1):
logdata = logfname.read()
- logfile.write(logdata)
+ else:
+ logdata = ""
+
if exitcode:
failure = True
if exitcode != 1:
pass # xxx unexpected exit cases
+ else:
+ failure = False
- return failure
+ result_queue.put((failure, logdata, output))
+
+
+
+def start_workers(n, run_param, testdirs):
+ result_queue = Queue.Queue()
+ for i in range(n):
+ thread.start_new_thread(worker, (i, n, run_param, testdirs,
+ result_queue))
+ return result_queue
+
+
+def execute_tests(run_param, testdirs, logfile, out):
+ sessdir = py.path.local.make_numbered_dir(prefix='usession-testrunner-',
+ keep=4)
+ run_param.sessdir = sessdir
+
+ N = run_param.parallel_runs
+ failure = False
+
+ result_queue =start_workers(N, run_param, testdirs)
+
+ done = 0
+ first_ever = True
+ while True:
+ res = result_queue.get()
+ if res is None:
+ done += 1
+ if done == N:
+ break
+ continue
+
+ somefailed, logdata, output = res
+ failure = failure or somefailed
+
+ if first_ever:
+ first_ever = False
+ else:
+ out.write(79*'_'+'\n')
+
+ out.write(output)
+ if logdata:
+ logfile.write(logdata)
+ return failure
-def is_test_py_file(p):
- name = p.basename
- return name.startswith('test_') and name.endswith('.py')
-
-def collect_one_testdir(testdirs, root, reldir, tests):
- testdirs.append(reldir)
- return
-
-def collect_testdirs(testdirs, p, root=None):
- if root is None:
- root = p
- reldir = p.relto(root)
- entries = [p1 for p1 in p.listdir() if p1.check(dotfile=0)]
+class RunParam(object):
+ interp = [os.path.abspath(sys.executable)]
+ test_driver = [os.path.abspath(os.path.join('py', 'bin', 'py.test'))]
+ parallel_runs = 1
+
+ def __init__(self, root):
+ self.root = root
+ self.self = self
+
+ def is_test_py_file(self, p):
+ name = p.basename
+ return name.startswith('test_') and name.endswith('.py')
+
+ def collect_one_testdir(self, testdirs, reldir, tests):
+ testdirs.append(reldir)
+ return
+
+ def collect_testdirs(self, testdirs, p=None):
+ if p is None:
+ p = self.root
+
+ reldir = p.relto(self.root)
+ entries = [p1 for p1 in p.listdir() if p1.check(dotfile=0)]
+
+ if p != self.root:
+ for p1 in entries:
+ if self.is_test_py_file(p1):
+ self.collect_one_testdir(testdirs, reldir,
+ [t for t in entries
+ if self.is_test_py_file(t)])
+ return
- if p != root:
for p1 in entries:
- if is_test_py_file(p1):
- collect_one_testdir(testdirs, root, reldir,
- [t for t in entries if is_test_py_file(t)])
- return
-
- for p1 in entries:
- if p1.check(dir=1, link=0):
- collect_testdirs(testdirs, p1, root=root)
+ if p1.check(dir=1, link=0):
+ self.collect_testdirs(testdirs, p1)
+
if __name__ == '__main__':
@@ -93,10 +153,15 @@
help="accumulated machine-readable logfile")
parser.add_option("--output", dest="output", default='-',
help="plain test output (default: stdout)")
- parser.add_option("--config", dest="config", default=None,
+ parser.add_option("--config", dest="config", default=[],
+ action="append",
help="configuration python file (optional)")
parser.add_option("--root", dest="root", default=".",
help="root directory for the run")
+ parser.add_option("--parallel-runs", dest="parallel_runs", default=0,
+ type="int",
+ help="number of parallel test runs")
+
opts, args = parser.parse_args()
if opts.logfile is None:
@@ -112,10 +177,22 @@
root = py.path.local(opts.root)
testdirs = []
+
+
+ run_param = RunParam(root)
+ # the config files are python files whose run overrides the content
+ # of the run_param instance namespace
+ # in that code function overriding method should not take self
+ # though a self and self.__class__ are available if needed
+ for config_py_file in opts.config:
+ execfile(config_py_file, run_param.__dict__)
- collect_testdirs(testdirs, root)
+ run_param.collect_testdirs(testdirs)
- res = execute_tests(root, testdirs, logfile, out)
+ if opts.parallel_runs:
+ run_param.parallel_runs = opts.parallel_runs
+
+ res = execute_tests(run_param, testdirs, logfile, out)
if res:
sys.exit(1)
Modified: pypy/build/testrunner/test/test_runner.py
==============================================================================
--- pypy/build/testrunner/test/test_runner.py (original)
+++ pypy/build/testrunner/test/test_runner.py Mon Sep 22 17:51:04 2008
@@ -18,18 +18,6 @@
def teardown_class(cls):
runner.run = cls.real_run[0]
- def test_basic(self):
- res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE')
-
- expected = [os.path.abspath(sys.executable),
- os.path.abspath(os.path.join('py', 'bin', 'py.test')),
- '--resultlog=LOGFILE',
- 'test_one']
-
- assert self.called == (expected, '/wd', 'out')
- assert res == 0
-
-
def test_explicit(self):
res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE',
interp=['INTERP', 'IARG'],
@@ -46,12 +34,16 @@
def test_error(self):
self.exitcode[:] = [1]
- res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE')
+ res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE',
+ interp=['INTERP', 'IARG'],
+ test_driver=['driver', 'darg'])
assert res == 1
self.exitcode[:] = [-signal.SIGSEGV]
- res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE')
+ res = runner.execute_test('/wd', 'test_one', 'out', 'LOGFILE',
+ interp=['INTERP', 'IARG'],
+ test_driver=['driver', 'darg'])
assert res == -signal.SIGSEGV
@@ -71,7 +63,9 @@
def test_collect_testdirs_simple(self):
res = []
- runner.collect_testdirs(res, self.udir)
+ run_param = runner.RunParam(self.udir)
+
+ run_param.collect_testdirs(res)
assert res == ['test_normal']
@@ -81,9 +75,12 @@
log = cStringIO.StringIO()
out = cStringIO.StringIO()
+
+ param = runner.RunParam(self.udir)
+ param.test_driver = test_driver
+ param.parallel_runs = 3
- res = runner.execute_tests(self.udir, ['test_normal'], log, out,
- test_driver=test_driver)
+ res = runner.execute_tests(param, ['test_normal'], log, out)
assert res
@@ -102,3 +99,7 @@
assert noutcomes == 107
assert nfailures == 6
+
+ # xxx test with more than one dir
+
+ # xxx test for main logic
More information about the Pypy-commit
mailing list