Skip to content

Commit

Permalink
pythongh-109162: Refactor libregrtest.runtest (python#109172)
Browse files Browse the repository at this point in the history
* Rename runtest() to run_single_test().
* Pass runtests to run_single_test().
* Add type annotation to Regrtest attributes. Add missing attributes
  to Namespace.
* Add attributes to Regrtest and RunTests:

  * fail_fast
  * ignore_tests
  * match_tests
  * output_on_failure
  * pgo
  * pgo_extended
  * timeout

* Get pgo from 'runtests', rather than from 'ns'.
* Remove WorkerJob.match_tests.
* setup_support() now gets pgo_extended from runtests.
* save_env(): change parameter order, pass test_name first.
* Add setup_test_dir() function.
* Pass runtests to setup_tests().
  • Loading branch information
vstinner committed Sep 9, 2023
1 parent 057bc72 commit e9e2ca7
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 104 deletions.
6 changes: 6 additions & 0 deletions Lib/test/libregrtest/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def __init__(self, **kwargs) -> None:
self.verbose = 0
self.quiet = False
self.exclude = False
self.cleanup = False
self.wait = False
self.list_cases = False
self.list_tests = False
self.single = False
self.randomize = False
self.fromfile = None
Expand All @@ -171,6 +175,8 @@ def __init__(self, **kwargs) -> None:
self.pgo = False
self.pgo_extended = False
self.worker_json = None
self.start = None
self.timeout = None

super().__init__(**kwargs)

Expand Down
91 changes: 53 additions & 38 deletions Lib/test/libregrtest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
import unittest
from test.libregrtest.cmdline import _parse_args, Namespace
from test.libregrtest.runtest import (
findtests, split_test_packages, runtest, abs_module_name,
findtests, split_test_packages, run_single_test, abs_module_name,
PROGRESS_MIN_TIME, State, RunTests, TestResult,
FilterTuple, FilterDict, TestList)
from test.libregrtest.setup import setup_tests
from test.libregrtest.setup import setup_tests, setup_test_dir
from test.libregrtest.pgo import setup_pgo_tests
from test.libregrtest.utils import (strip_py_suffix, count, format_duration,
printlist, get_build_info)
Expand Down Expand Up @@ -64,11 +64,11 @@ def __init__(self, ns: Namespace):
self.ns: Namespace = ns

# Actions
self.want_header = ns.header
self.want_list_tests = ns.list_tests
self.want_list_cases = ns.list_cases
self.want_wait = ns.wait
self.want_cleanup = ns.cleanup
self.want_header: bool = ns.header
self.want_list_tests: bool = ns.list_tests
self.want_list_cases: bool = ns.list_cases
self.want_wait: bool = ns.wait
self.want_cleanup: bool = ns.cleanup

# Select tests
if ns.match_tests:
Expand All @@ -79,14 +79,19 @@ def __init__(self, ns: Namespace):
self.ignore_tests: FilterTuple = tuple(ns.ignore_tests)
else:
self.ignore_tests = None
self.exclude = ns.exclude
self.fromfile = ns.fromfile
self.starting_test = ns.start
self.exclude: bool = ns.exclude
self.fromfile: str | None = ns.fromfile
self.starting_test: str | None = ns.start

# Options to run tests
self.forever = ns.forever
self.randomize = ns.randomize
self.random_seed = ns.random_seed
self.fail_fast: bool = ns.failfast
self.forever: bool = ns.forever
self.randomize: bool = ns.randomize
self.random_seed: int | None = ns.random_seed
self.pgo: bool = ns.pgo
self.pgo_extended: bool = ns.pgo_extended
self.output_on_failure: bool = ns.verbose3
self.timeout: float | None = ns.timeout

# tests
self.tests = []
Expand Down Expand Up @@ -196,21 +201,19 @@ def log(self, line=''):

def display_progress(self, test_index, text):
quiet = self.ns.quiet
pgo = self.ns.pgo
if quiet:
return

# "[ 51/405/1] test_tcl passed"
line = f"{test_index:{self.test_count_width}}{self.test_count_text}"
fails = len(self.bad) + len(self.environment_changed)
if fails and not pgo:
if fails and not self.pgo:
line = f"{line}/{fails}"
self.log(f"[{line}] {text}")

def find_tests(self):
ns = self.ns
single = ns.single
pgo = ns.pgo
test_dir = ns.testdir

if single:
Expand All @@ -237,7 +240,7 @@ def find_tests(self):

strip_py_suffix(self.tests)

if pgo:
if self.pgo:
# add default PGO tests if no tests are specified
setup_pgo_tests(ns)

Expand Down Expand Up @@ -329,8 +332,6 @@ def _rerun_failed_tests(self, need_rerun, runtests: RunTests):
# Configure the runner to re-run tests
ns = self.ns
ns.verbose = True
ns.failfast = False
ns.verbose3 = False
if ns.use_mp is None:
ns.use_mp = 1

Expand All @@ -345,12 +346,16 @@ def _rerun_failed_tests(self, need_rerun, runtests: RunTests):

# Re-run failed tests
self.log(f"Re-running {len(tests)} failed tests in verbose mode in subprocesses")
runtests = runtests.copy(tests=tuple(tests),
match_tests_dict=match_tests_dict,
rerun=True,
forever=False)
runtests = runtests.copy(
tests=tuple(tests),
rerun=True,
forever=False,
fail_fast=False,
match_tests_dict=match_tests_dict,
output_on_failure=False)
self.set_tests(runtests)
self._run_tests_mp(runtests)
return runtests

def rerun_failed_tests(self, need_rerun, runtests: RunTests):
if self.ns.python:
Expand All @@ -364,16 +369,16 @@ def rerun_failed_tests(self, need_rerun, runtests: RunTests):
self.first_state = self.get_tests_state()

print()
self._rerun_failed_tests(need_rerun, runtests)
rerun_runtests = self._rerun_failed_tests(need_rerun, runtests)

if self.bad:
print(count(len(self.bad), 'test'), "failed again:")
printlist(self.bad)

self.display_result()
self.display_result(rerun_runtests)

def display_result(self):
pgo = self.ns.pgo
def display_result(self, runtests):
pgo = runtests.pgo
quiet = self.ns.quiet
print_slow = self.ns.print_slow

Expand Down Expand Up @@ -444,12 +449,12 @@ def run_test(self, test_name: str, runtests: RunTests, tracer):
if tracer is not None:
# If we're tracing code coverage, then we don't exit with status
# if on a false return value from main.
cmd = ('result = runtest(self.ns, test_name)')
cmd = ('result = run_single_test(test_name, runtests, self.ns)')
ns = dict(locals())
tracer.runctx(cmd, globals=globals(), locals=ns)
result = ns['result']
else:
result = runtest(self.ns, test_name)
result = run_single_test(test_name, runtests, self.ns)

self.accumulate_result(result)

Expand All @@ -458,9 +463,7 @@ def run_test(self, test_name: str, runtests: RunTests, tracer):
def run_tests_sequentially(self, runtests):
ns = self.ns
coverage = ns.trace
fail_fast = ns.failfast
fail_env_changed = ns.fail_env_changed
timeout = ns.timeout

if coverage:
import trace
Expand All @@ -471,8 +474,8 @@ def run_tests_sequentially(self, runtests):
save_modules = sys.modules.keys()

msg = "Run tests sequentially"
if timeout:
msg += " (timeout: %s)" % format_duration(timeout)
if runtests.timeout:
msg += " (timeout: %s)" % format_duration(runtests.timeout)
self.log(msg)

previous_test = None
Expand All @@ -492,7 +495,7 @@ def run_tests_sequentially(self, runtests):
if module not in save_modules and module.startswith("test."):
support.unload(module)

if result.must_stop(fail_fast, fail_env_changed):
if result.must_stop(self.fail_fast, fail_env_changed):
break

previous_test = str(result)
Expand Down Expand Up @@ -850,16 +853,28 @@ def action_run_tests(self):

# For a partial run, we do not need to clutter the output.
if (self.want_header
or not(self.ns.pgo or self.ns.quiet or self.ns.single
or not(self.pgo or self.ns.quiet or self.ns.single
or self.tests or self.ns.args)):
self.display_header()

if self.randomize:
print("Using random seed", self.random_seed)

runtests = RunTests(tuple(self.selected), forever=self.forever)
runtests = RunTests(
tuple(self.selected),
fail_fast=self.fail_fast,
match_tests=self.match_tests,
ignore_tests=self.ignore_tests,
forever=self.forever,
pgo=self.pgo,
pgo_extended=self.pgo_extended,
output_on_failure=self.output_on_failure,
timeout=self.timeout)

setup_tests(runtests, self.ns)

tracer = self.run_tests(runtests)
self.display_result()
self.display_result(runtests)

need_rerun = self.need_rerun
if self.ns.rerun and need_rerun:
Expand All @@ -877,7 +892,7 @@ def _main(self):
if self.want_wait:
input("Press any key to continue...")

setup_tests(self.ns)
setup_test_dir(self.ns.testdir)
self.find_tests()

exitcode = 0
Expand Down

0 comments on commit e9e2ca7

Please sign in to comment.