Skip to content

Commit b78950d

Browse files
committed
pythongh-109162: Refactor libregrtest.RunTests
* Rename dash_R() runtest_refleak(). The function now gets huntrleaks and quiet arguments, instead of 'ns' argument. * Add attributes to Regrtest and RunTests: * verbose * quiet * huntrleaks * test_dir * Add HuntRefleak class.
1 parent b4131a1 commit b78950d

File tree

5 files changed

+88
-60
lines changed

5 files changed

+88
-60
lines changed

Lib/test/libregrtest/main.py

+32-25
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from test.libregrtest.cmdline import _parse_args, Namespace
1313
from test.libregrtest.runtest import (
1414
findtests, split_test_packages, run_single_test, abs_module_name,
15-
PROGRESS_MIN_TIME, State, RunTests, TestResult,
15+
PROGRESS_MIN_TIME, State, RunTests, TestResult, HuntRefleak,
1616
FilterTuple, FilterDict, TestList)
1717
from test.libregrtest.setup import setup_tests, setup_test_dir
1818
from test.libregrtest.pgo import setup_pgo_tests
@@ -92,6 +92,14 @@ def __init__(self, ns: Namespace):
9292
self.pgo_extended: bool = ns.pgo_extended
9393
self.output_on_failure: bool = ns.verbose3
9494
self.timeout: float | None = ns.timeout
95+
self.verbose: bool = ns.verbose
96+
self.quiet: bool = ns.quiet
97+
if ns.huntrleaks:
98+
self.hunt_refleak: HuntRefleak = HuntRefleak(*ns.huntrleaks)
99+
else:
100+
self.hunt_refleak = None
101+
self.test_dir: str | None = ns.testdir
102+
self.junit_filename: str | None = ns.xmlpath
95103

96104
# tests
97105
self.tests = []
@@ -200,8 +208,7 @@ def log(self, line=''):
200208
print(line, flush=True)
201209

202210
def display_progress(self, test_index, text):
203-
quiet = self.ns.quiet
204-
if quiet:
211+
if self.quiet:
205212
return
206213

207214
# "[ 51/405/1] test_tcl passed"
@@ -214,7 +221,6 @@ def display_progress(self, test_index, text):
214221
def find_tests(self):
215222
ns = self.ns
216223
single = ns.single
217-
test_dir = ns.testdir
218224

219225
if single:
220226
self.next_single_filename = os.path.join(self.tmp_dir, 'pynexttest')
@@ -250,7 +256,8 @@ def find_tests(self):
250256
exclude_tests.add(arg)
251257
ns.args = []
252258

253-
alltests = findtests(testdir=test_dir, exclude=exclude_tests)
259+
alltests = findtests(testdir=self.test_dir,
260+
exclude=exclude_tests)
254261

255262
if not self.fromfile:
256263
self.selected = self.tests or ns.args
@@ -298,14 +305,12 @@ def _list_cases(self, suite):
298305
print(test.id())
299306

300307
def list_cases(self):
301-
ns = self.ns
302-
test_dir = ns.testdir
303308
support.verbose = False
304309
support.set_match_tests(self.match_tests, self.ignore_tests)
305310

306311
skipped = []
307312
for test_name in self.selected:
308-
module_name = abs_module_name(test_name, test_dir)
313+
module_name = abs_module_name(test_name, self.test_dir)
309314
try:
310315
suite = unittest.defaultTestLoader.loadTestsFromName(module_name)
311316
self._list_cases(suite)
@@ -331,7 +336,6 @@ def get_rerun_match(self, rerun_list) -> FilterDict:
331336
def _rerun_failed_tests(self, need_rerun, runtests: RunTests):
332337
# Configure the runner to re-run tests
333338
ns = self.ns
334-
ns.verbose = True
335339
if ns.use_mp is None:
336340
ns.use_mp = 1
337341

@@ -349,6 +353,7 @@ def _rerun_failed_tests(self, need_rerun, runtests: RunTests):
349353
runtests = runtests.copy(
350354
tests=tuple(tests),
351355
rerun=True,
356+
verbose=True,
352357
forever=False,
353358
fail_fast=False,
354359
match_tests_dict=match_tests_dict,
@@ -379,7 +384,6 @@ def rerun_failed_tests(self, need_rerun, runtests: RunTests):
379384

380385
def display_result(self, runtests):
381386
pgo = runtests.pgo
382-
quiet = self.ns.quiet
383387
print_slow = self.ns.print_slow
384388

385389
# If running the test suite for PGO then no one cares about results.
@@ -398,7 +402,7 @@ def display_result(self, runtests):
398402
print(count(len(omitted), "test"), "omitted:")
399403
printlist(omitted)
400404

401-
if self.good and not quiet:
405+
if self.good and not self.quiet:
402406
print()
403407
if (not self.bad
404408
and not self.skipped
@@ -425,12 +429,12 @@ def display_result(self, runtests):
425429
count(len(self.environment_changed), "test")))
426430
printlist(self.environment_changed)
427431

428-
if self.skipped and not quiet:
432+
if self.skipped and not self.quiet:
429433
print()
430434
print(count(len(self.skipped), "test"), "skipped:")
431435
printlist(self.skipped)
432436

433-
if self.resource_denied and not quiet:
437+
if self.resource_denied and not self.quiet:
434438
print()
435439
print(count(len(self.resource_denied), "test"), "skipped (resource denied):")
436440
printlist(self.resource_denied)
@@ -684,7 +688,7 @@ def display_summary(self):
684688
print(f"Result: {result}")
685689

686690
def save_xml_result(self):
687-
if not self.ns.xmlpath and not self.testsuite_xml:
691+
if not self.junit_filename and not self.testsuite_xml:
688692
return
689693

690694
import xml.etree.ElementTree as ET
@@ -703,7 +707,7 @@ def save_xml_result(self):
703707
for k, v in totals.items():
704708
root.set(k, str(v))
705709

706-
xmlpath = os.path.join(os_helper.SAVEDCWD, self.ns.xmlpath)
710+
xmlpath = os.path.join(os_helper.SAVEDCWD, self.junit_filename)
707711
with open(xmlpath, 'wb') as f:
708712
for s in ET.tostringlist(root):
709713
f.write(s)
@@ -785,7 +789,7 @@ def main(self, tests: TestList | None = None):
785789
ns = self.ns
786790
self.tests = tests
787791

788-
if ns.xmlpath:
792+
if self.junit_filename:
789793
support.junit_xml_list = self.testsuite_xml = []
790794

791795
strip_py_suffix(ns.args)
@@ -844,16 +848,14 @@ def get_exitcode(self):
844848
return exitcode
845849

846850
def action_run_tests(self):
847-
if self.ns.huntrleaks:
848-
warmup, repetitions, _ = self.ns.huntrleaks
849-
if warmup < 3:
850-
msg = ("WARNING: Running tests with --huntrleaks/-R and less than "
851-
"3 warmup repetitions can give false positives!")
852-
print(msg, file=sys.stdout, flush=True)
851+
if self.hunt_refleak and self.hunt_refleak.warmups < 3:
852+
msg = ("WARNING: Running tests with --huntrleaks/-R and "
853+
"less than 3 warmup repetitions can give false positives!")
854+
print(msg, file=sys.stdout, flush=True)
853855

854856
# For a partial run, we do not need to clutter the output.
855857
if (self.want_header
856-
or not(self.pgo or self.ns.quiet or self.ns.single
858+
or not(self.pgo or self.quiet or self.ns.single
857859
or self.tests or self.ns.args)):
858860
self.display_header()
859861

@@ -869,7 +871,12 @@ def action_run_tests(self):
869871
pgo=self.pgo,
870872
pgo_extended=self.pgo_extended,
871873
output_on_failure=self.output_on_failure,
872-
timeout=self.timeout)
874+
timeout=self.timeout,
875+
verbose=self.verbose,
876+
quiet=self.quiet,
877+
hunt_refleak=self.hunt_refleak,
878+
test_dir=self.test_dir,
879+
junit_filename=self.junit_filename)
873880

874881
setup_tests(runtests, self.ns)
875882

@@ -892,7 +899,7 @@ def _main(self):
892899
if self.want_wait:
893900
input("Press any key to continue...")
894901

895-
setup_test_dir(self.ns.testdir)
902+
setup_test_dir(self.test_dir)
896903
self.find_tests()
897904

898905
exitcode = 0

Lib/test/libregrtest/refleak.py

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from inspect import isabstract
55
from test import support
66
from test.support import os_helper
7+
from test.libregrtest.runtest import HuntRefleak
78
from test.libregrtest.utils import clear_caches
89

910
try:
@@ -19,7 +20,9 @@ def _get_dump(cls):
1920
cls._abc_negative_cache, cls._abc_negative_cache_version)
2021

2122

22-
def dash_R(ns, test_name, test_func):
23+
def runtest_refleak(test_name, test_func,
24+
hunt_refleak: HuntRefleak,
25+
quiet: bool):
2326
"""Run a test multiple times, looking for reference leaks.
2427
2528
Returns:
@@ -62,9 +65,11 @@ def dash_R(ns, test_name, test_func):
6265
def get_pooled_int(value):
6366
return int_pool.setdefault(value, value)
6467

65-
nwarmup, ntracked, fname = ns.huntrleaks
66-
fname = os.path.join(os_helper.SAVEDCWD, fname)
67-
repcount = nwarmup + ntracked
68+
warmups = hunt_refleak.warmups
69+
runs = hunt_refleak.runs
70+
filename = hunt_refleak.filename
71+
filename = os.path.join(os_helper.SAVEDCWD, filename)
72+
repcount = warmups + runs
6873

6974
# Pre-allocate to ensure that the loop doesn't allocate anything new
7075
rep_range = list(range(repcount))
@@ -78,7 +83,7 @@ def get_pooled_int(value):
7883
# initialize variables to make pyflakes quiet
7984
rc_before = alloc_before = fd_before = interned_before = 0
8085

81-
if not ns.quiet:
86+
if not quiet:
8287
print("beginning", repcount, "repetitions", file=sys.stderr)
8388
print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr,
8489
flush=True)
@@ -102,7 +107,7 @@ def get_pooled_int(value):
102107
rc_after = gettotalrefcount() - interned_after * 2
103108
fd_after = fd_count()
104109

105-
if not ns.quiet:
110+
if not quiet:
106111
print('.', end='', file=sys.stderr, flush=True)
107112

108113
rc_deltas[i] = get_pooled_int(rc_after - rc_before)
@@ -114,7 +119,7 @@ def get_pooled_int(value):
114119
fd_before = fd_after
115120
interned_before = interned_after
116121

117-
if not ns.quiet:
122+
if not quiet:
118123
print(file=sys.stderr)
119124

120125
# These checkers return False on success, True on failure
@@ -143,12 +148,12 @@ def check_fd_deltas(deltas):
143148
(fd_deltas, 'file descriptors', check_fd_deltas)
144149
]:
145150
# ignore warmup runs
146-
deltas = deltas[nwarmup:]
151+
deltas = deltas[warmups:]
147152
if checker(deltas):
148153
msg = '%s leaked %s %s, sum=%s' % (
149154
test_name, deltas, item_name, sum(deltas))
150155
print(msg, file=sys.stderr, flush=True)
151-
with open(fname, "a", encoding="utf-8") as refrep:
156+
with open(filename, "a", encoding="utf-8") as refrep:
152157
print(msg, file=refrep)
153158
refrep.flush()
154159
failed = True

0 commit comments

Comments
 (0)