mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Close #25373: Fix regrtest --slow with interrupted test
* Fix accumulate_result(): don't use time on interrupted and failed test * Add unit test for interrupted test * Add unit test on --slow with interrupted test, with and without multiprocessing
This commit is contained in:
parent
00a09c05ed
commit
3909e58994
2 changed files with 49 additions and 6 deletions
|
@ -7,10 +7,11 @@ import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
|
from test.libregrtest.cmdline import _parse_args
|
||||||
from test.libregrtest.runtest import (
|
from test.libregrtest.runtest import (
|
||||||
findtests, runtest,
|
findtests, runtest,
|
||||||
STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED)
|
STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED,
|
||||||
from test.libregrtest.cmdline import _parse_args
|
INTERRUPTED, CHILD_ERROR)
|
||||||
from test.libregrtest.setup import setup_tests
|
from test.libregrtest.setup import setup_tests
|
||||||
from test import support
|
from test import support
|
||||||
try:
|
try:
|
||||||
|
@ -87,6 +88,7 @@ class Regrtest:
|
||||||
|
|
||||||
def accumulate_result(self, test, result):
|
def accumulate_result(self, test, result):
|
||||||
ok, test_time = result
|
ok, test_time = result
|
||||||
|
if ok not in (CHILD_ERROR, INTERRUPTED):
|
||||||
self.test_times.append((test_time, test))
|
self.test_times.append((test_time, test))
|
||||||
if ok == PASSED:
|
if ok == PASSED:
|
||||||
self.good.append(test)
|
self.good.append(test)
|
||||||
|
@ -291,10 +293,12 @@ class Regrtest:
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
result = runtest(self.ns, test)
|
result = runtest(self.ns, test)
|
||||||
self.accumulate_result(test, result)
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
self.accumulate_result(test, (INTERRUPTED, None))
|
||||||
self.interrupted = True
|
self.interrupted = True
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
self.accumulate_result(test, result)
|
||||||
|
|
||||||
if self.ns.findleaks:
|
if self.ns.findleaks:
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
|
@ -24,6 +24,16 @@ Py_DEBUG = hasattr(sys, 'getobjects')
|
||||||
ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
|
ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
|
||||||
ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR))
|
ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR))
|
||||||
|
|
||||||
|
TEST_INTERRUPTED = textwrap.dedent("""
|
||||||
|
from signal import SIGINT
|
||||||
|
try:
|
||||||
|
from _testcapi import raise_signal
|
||||||
|
raise_signal(SIGINT)
|
||||||
|
except ImportError:
|
||||||
|
import os
|
||||||
|
os.kill(os.getpid(), SIGINT)
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
class ParseArgsTestCase(unittest.TestCase):
|
class ParseArgsTestCase(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -340,16 +350,19 @@ class BaseTestCase(unittest.TestCase):
|
||||||
return list(match.group(1) for match in parser)
|
return list(match.group(1) for match in parser)
|
||||||
|
|
||||||
def check_executed_tests(self, output, tests, skipped=(), failed=(),
|
def check_executed_tests(self, output, tests, skipped=(), failed=(),
|
||||||
randomize=False):
|
omitted=(), randomize=False):
|
||||||
if isinstance(tests, str):
|
if isinstance(tests, str):
|
||||||
tests = [tests]
|
tests = [tests]
|
||||||
if isinstance(skipped, str):
|
if isinstance(skipped, str):
|
||||||
skipped = [skipped]
|
skipped = [skipped]
|
||||||
if isinstance(failed, str):
|
if isinstance(failed, str):
|
||||||
failed = [failed]
|
failed = [failed]
|
||||||
|
if isinstance(omitted, str):
|
||||||
|
omitted = [omitted]
|
||||||
ntest = len(tests)
|
ntest = len(tests)
|
||||||
nskipped = len(skipped)
|
nskipped = len(skipped)
|
||||||
nfailed = len(failed)
|
nfailed = len(failed)
|
||||||
|
nomitted = len(omitted)
|
||||||
|
|
||||||
executed = self.parse_executed_tests(output)
|
executed = self.parse_executed_tests(output)
|
||||||
if randomize:
|
if randomize:
|
||||||
|
@ -375,7 +388,11 @@ class BaseTestCase(unittest.TestCase):
|
||||||
regex = list_regex('%s test%s failed', failed)
|
regex = list_regex('%s test%s failed', failed)
|
||||||
self.check_line(output, regex)
|
self.check_line(output, regex)
|
||||||
|
|
||||||
good = ntest - nskipped - nfailed
|
if omitted:
|
||||||
|
regex = list_regex('%s test%s omitted', omitted)
|
||||||
|
self.check_line(output, regex)
|
||||||
|
|
||||||
|
good = ntest - nskipped - nfailed - nomitted
|
||||||
if good:
|
if good:
|
||||||
regex = r'%s test%s OK\.$' % (good, plural(good))
|
regex = r'%s test%s OK\.$' % (good, plural(good))
|
||||||
if not skipped and not failed and good > 1:
|
if not skipped and not failed and good > 1:
|
||||||
|
@ -607,6 +624,12 @@ class ArgsTestCase(BaseTestCase):
|
||||||
output = self.run_tests('--fromfile', filename)
|
output = self.run_tests('--fromfile', filename)
|
||||||
self.check_executed_tests(output, tests)
|
self.check_executed_tests(output, tests)
|
||||||
|
|
||||||
|
def test_interrupted(self):
|
||||||
|
code = TEST_INTERRUPTED
|
||||||
|
test = self.create_test("sigint", code=code)
|
||||||
|
output = self.run_tests(test, exitcode=1)
|
||||||
|
self.check_executed_tests(output, test, omitted=test)
|
||||||
|
|
||||||
def test_slow(self):
|
def test_slow(self):
|
||||||
# test --slow
|
# test --slow
|
||||||
tests = [self.create_test() for index in range(3)]
|
tests = [self.create_test() for index in range(3)]
|
||||||
|
@ -617,6 +640,22 @@ class ArgsTestCase(BaseTestCase):
|
||||||
% (self.TESTNAME_REGEX, len(tests)))
|
% (self.TESTNAME_REGEX, len(tests)))
|
||||||
self.check_line(output, regex)
|
self.check_line(output, regex)
|
||||||
|
|
||||||
|
def test_slow_interrupted(self):
|
||||||
|
# Issue #25373: test --slow with an interrupted test
|
||||||
|
code = TEST_INTERRUPTED
|
||||||
|
test = self.create_test("sigint", code=code)
|
||||||
|
|
||||||
|
for multiprocessing in (False, True):
|
||||||
|
if multiprocessing:
|
||||||
|
args = ("--slow", "-j2", test)
|
||||||
|
else:
|
||||||
|
args = ("--slow", test)
|
||||||
|
output = self.run_tests(*args, exitcode=1)
|
||||||
|
self.check_executed_tests(output, test, omitted=test)
|
||||||
|
regex = ('10 slowest tests:\n')
|
||||||
|
self.check_line(output, regex)
|
||||||
|
self.check_line(output, 'Test suite interrupted by signal SIGINT.')
|
||||||
|
|
||||||
def test_coverage(self):
|
def test_coverage(self):
|
||||||
# test --coverage
|
# test --coverage
|
||||||
test = self.create_test()
|
test = self.create_test()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue