Commit d2aff607 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

[2.7] bpo-30283: Backport test_regrtest from master to 2.7 (#1513)

* bpo-30283: regrtest: add --testdir option

* bpo-30283: Backport _testcapi.raise_signal()

Function used by test_regrtest to simulate an interrupted unit test.

* bpo-30283: Backport test_regrtest from master
parent c8a77d33
...@@ -60,6 +60,8 @@ Special runs ...@@ -60,6 +60,8 @@ Special runs
-- call gc.set_threshold(THRESHOLD) -- call gc.set_threshold(THRESHOLD)
-F/--forever -- run the specified tests in a loop, until an error happens -F/--forever -- run the specified tests in a loop, until an error happens
-P/--pgo -- enable Profile Guided Optimization training -P/--pgo -- enable Profile Guided Optimization training
--testdir -- execute test files in the specified directory
(instead of the Python stdlib test suite)
Additional Option Details: Additional Option Details:
...@@ -276,7 +278,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -276,7 +278,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo', 'multiprocess=', 'slaveargs=', 'forever', 'header', 'pgo',
'failfast', 'match=']) 'failfast', 'match=', 'testdir='])
except getopt.error, msg: except getopt.error, msg:
usage(2, msg) usage(2, msg)
...@@ -285,6 +287,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -285,6 +287,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
random_seed = random.randrange(10000000) random_seed = random.randrange(10000000)
if use_resources is None: if use_resources is None:
use_resources = [] use_resources = []
slaveargs = None
for o, a in opts: for o, a in opts:
if o in ('-h', '--help'): if o in ('-h', '--help'):
usage(0) usage(0)
...@@ -367,16 +370,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -367,16 +370,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
elif o == '--header': elif o == '--header':
header = True header = True
elif o == '--slaveargs': elif o == '--slaveargs':
args, kwargs = json.loads(a) slaveargs = a
try:
result = runtest(*args, **kwargs)
except BaseException, e:
result = INTERRUPTED, e.__class__.__name__
print # Force a newline (just in case)
print json.dumps(result)
sys.exit(0)
elif o in ('-P', '--pgo'): elif o in ('-P', '--pgo'):
pgo = True pgo = True
elif o in ('--testdir'):
testdir = a
else: else:
print >>sys.stderr, ("No handler for option {}. Please " print >>sys.stderr, ("No handler for option {}. Please "
"report this as a bug at http://bugs.python.org.").format(o) "report this as a bug at http://bugs.python.org.").format(o)
...@@ -390,6 +388,25 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -390,6 +388,25 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
if failfast and not (verbose or verbose3): if failfast and not (verbose or verbose3):
usage("-G/--failfast needs either -v or -W") usage("-G/--failfast needs either -v or -W")
if testdir:
testdir = os.path.abspath(testdir)
# Prepend test directory to sys.path, so runtest() will be able
# to locate tests
sys.path.insert(0, testdir)
if slaveargs is not None:
args, kwargs = json.loads(slaveargs)
if testdir:
kwargs['testdir'] = testdir
try:
result = runtest(*args, **kwargs)
except BaseException, e:
result = INTERRUPTED, e.__class__.__name__
print # Force a newline (just in case)
print json.dumps(result)
sys.exit(0)
good = [] good = []
bad = [] bad = []
skipped = [] skipped = []
...@@ -544,7 +561,10 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -544,7 +561,10 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
output.put((None, None, None, None)) output.put((None, None, None, None))
return return
# -E is needed by some tests, e.g. test_import # -E is needed by some tests, e.g. test_import
popen = Popen(base_cmd + ['--slaveargs', json.dumps(args_tuple)], args = base_cmd + ['--slaveargs', json.dumps(args_tuple)]
if testdir:
args.extend(('--testdir', testdir))
popen = Popen(args,
stdout=PIPE, stderr=PIPE, stdout=PIPE, stderr=PIPE,
universal_newlines=True, universal_newlines=True,
close_fds=(os.name != 'nt')) close_fds=(os.name != 'nt'))
...@@ -616,18 +636,20 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -616,18 +636,20 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
if trace: if trace:
# If we're tracing code coverage, then we don't exit with status # If we're tracing code coverage, then we don't exit with status
# if on a false return value from main. # if on a false return value from main.
tracer.runctx('runtest(test, verbose, quiet)', tracer.runctx('runtest(test, verbose, quiet, testdir=testdir)',
globals=globals(), locals=vars()) globals=globals(), locals=vars())
else: else:
try: try:
result = runtest(test, verbose, quiet, huntrleaks, None, pgo, result = runtest(test, verbose, quiet, huntrleaks, None, pgo,
failfast=failfast, failfast=failfast,
match_tests=match_tests) match_tests=match_tests,
testdir=testdir)
accumulate_result(test, result) accumulate_result(test, result)
if verbose3 and result[0] == FAILED: if verbose3 and result[0] == FAILED:
if not pgo: if not pgo:
print "Re-running test %r in verbose mode" % test print "Re-running test %r in verbose mode" % test
runtest(test, True, quiet, huntrleaks, None, pgo) runtest(test, True, quiet, huntrleaks, None, pgo,
testdir=testdir)
except KeyboardInterrupt: except KeyboardInterrupt:
interrupted = True interrupted = True
break break
...@@ -695,7 +717,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, ...@@ -695,7 +717,8 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
sys.stdout.flush() sys.stdout.flush()
try: try:
test_support.verbose = True test_support.verbose = True
ok = runtest(test, True, quiet, huntrleaks, None, pgo) ok = runtest(test, True, quiet, huntrleaks, None, pgo,
testdir=testdir)
except KeyboardInterrupt: except KeyboardInterrupt:
# print a newline separate from the ^C # print a newline separate from the ^C
print print
...@@ -757,7 +780,7 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): ...@@ -757,7 +780,7 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
def runtest(test, verbose, quiet, def runtest(test, verbose, quiet,
huntrleaks=False, use_resources=None, pgo=False, huntrleaks=False, use_resources=None, pgo=False,
failfast=False, match_tests=None): failfast=False, match_tests=None, testdir=None):
"""Run a single test. """Run a single test.
test -- the name of the test test -- the name of the test
...@@ -786,7 +809,7 @@ def runtest(test, verbose, quiet, ...@@ -786,7 +809,7 @@ def runtest(test, verbose, quiet,
test_support.match_tests = match_tests test_support.match_tests = match_tests
if failfast: if failfast:
test_support.failfast = True test_support.failfast = True
return runtest_inner(test, verbose, quiet, huntrleaks, pgo) return runtest_inner(test, verbose, quiet, huntrleaks, pgo, testdir)
finally: finally:
cleanup_test_droppings(test, verbose) cleanup_test_droppings(test, verbose)
...@@ -947,7 +970,7 @@ class saved_test_environment: ...@@ -947,7 +970,7 @@ class saved_test_environment:
return False return False
def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False): def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False, testdir=None):
test_support.unload(test) test_support.unload(test)
if verbose: if verbose:
capture_stdout = None capture_stdout = None
...@@ -961,7 +984,7 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False): ...@@ -961,7 +984,7 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False):
try: try:
if capture_stdout: if capture_stdout:
sys.stdout = capture_stdout sys.stdout = capture_stdout
if test.startswith('test.'): if test.startswith('test.') or testdir:
abstest = test abstest = test
else: else:
# Always import it from the test package # Always import it from the test package
...@@ -970,7 +993,10 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False): ...@@ -970,7 +993,10 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False):
with saved_test_environment(test, verbose, quiet, pgo) as environment: with saved_test_environment(test, verbose, quiet, pgo) as environment:
start_time = time.time() start_time = time.time()
the_package = __import__(abstest, globals(), locals(), []) the_package = __import__(abstest, globals(), locals(), [])
if abstest.startswith('test.'):
the_module = getattr(the_package, test) the_module = getattr(the_package, test)
else:
the_module = the_package
# Old tests run to completion simply as a side-effect of # Old tests run to completion simply as a side-effect of
# being imported. For tests based on unittest or doctest, # being imported. For tests based on unittest or doctest,
# explicitly invoke their test_main() function (if it exists). # explicitly invoke their test_main() function (if it exists).
......
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "structmember.h" #include "structmember.h"
#include "datetime.h" #include "datetime.h"
#include "marshal.h" #include "marshal.h"
#include <signal.h>
#ifdef WITH_THREAD #ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
...@@ -2481,6 +2482,24 @@ pymarshal_read_object_from_file(PyObject* self, PyObject *args) ...@@ -2481,6 +2482,24 @@ pymarshal_read_object_from_file(PyObject* self, PyObject *args)
return Py_BuildValue("Nl", obj, pos); return Py_BuildValue("Nl", obj, pos);
} }
static PyObject*
test_raise_signal(PyObject* self, PyObject *args)
{
int signum, err;
if (PyArg_ParseTuple(args, "i:raise_signal", &signum) < 0)
return NULL;
err = raise(signum);
if (err)
return PyErr_SetFromErrno(PyExc_OSError);
if (PyErr_CheckSignals() < 0)
return NULL;
Py_RETURN_NONE;
}
static PyMethodDef TestMethods[] = { static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS}, {"raise_exception", raise_exception, METH_VARARGS},
...@@ -2593,6 +2612,7 @@ static PyMethodDef TestMethods[] = { ...@@ -2593,6 +2612,7 @@ static PyMethodDef TestMethods[] = {
pymarshal_read_last_object_from_file, METH_VARARGS}, pymarshal_read_last_object_from_file, METH_VARARGS},
{"pymarshal_read_object_from_file", {"pymarshal_read_object_from_file",
pymarshal_read_object_from_file, METH_VARARGS}, pymarshal_read_object_from_file, METH_VARARGS},
{"raise_signal", (PyCFunction)test_raise_signal, METH_VARARGS},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment