Skip to content

Commit

Permalink
pythongh-119050: Add XML support to libregrtest refleak checker
Browse files Browse the repository at this point in the history
regrtest test runner: Add XML support to the refleak checker
(-R option).

* run_unittest() now stores XML elements as string, rather than
  objects, in support.junit_xml_list.
* runtest_refleak() now saves/restores XML strings before/after
  checking for reference leaks. Save XML into a temporary file.
  • Loading branch information
vstinner committed May 18, 2024
1 parent 74072a3 commit 30ee228
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 25 deletions.
9 changes: 0 additions & 9 deletions Lib/test/libregrtest/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,15 +520,6 @@ def _parse_args(args, **kwargs):
"--huntrleaks without -jN option",
file=sys.stderr)

if ns.huntrleaks and ns.xmlpath:
# The XML data is written into a file outside runtest_refleak(), so
# it looks like a leak but it's not. Simply disable XML output when
# hunting for reference leaks (gh-83434).
ns.xmlpath = None
print("WARNING: Disable --junit-xml because it's incompatible "
"with --huntrleaks",
file=sys.stderr)

if ns.forever:
# --forever implies --failfast
ns.failfast = True
Expand Down
37 changes: 34 additions & 3 deletions Lib/test/libregrtest/refleak.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import sys
import warnings
from inspect import isabstract
Expand All @@ -23,6 +24,32 @@ def _get_dump(cls):
cls._abc_negative_cache, cls._abc_negative_cache_version)


def save_support_xml(filename):
if support.junit_xml_list is None:
return

with open(filename, 'x', encoding='ascii') as fp:
for elem in support.junit_xml_list:
print(elem, file=fp)
support.junit_xml_list = None


def restore_support_xml(filename):
try:
fp = open(filename, 'r', encoding='ascii')
except FileNotFoundError:
return

xml_list = []
with fp:
for line in fp:
line = line.rstrip()
xml_list.append(line)
os.unlink(filename)

support.junit_xml_list = xml_list


def runtest_refleak(test_name, test_func,
hunt_refleak: HuntRefleak,
quiet: bool):
Expand Down Expand Up @@ -95,18 +122,20 @@ def get_pooled_int(value):
numbers = numbers[:warmups] + ':' + numbers[warmups:]
print(numbers, file=sys.stderr, flush=True)

results = None
xml_filename = 'refleak-xml.tmp'
result = None
dash_R_cleanup(fs, ps, pic, zdc, abcs)
support.gc_collect()

for i in rep_range:
current = refleak_helper._hunting_for_refleaks
refleak_helper._hunting_for_refleaks = True
try:
results = test_func()
result = test_func()
finally:
refleak_helper._hunting_for_refleaks = current

save_support_xml(xml_filename)
dash_R_cleanup(fs, ps, pic, zdc, abcs)
support.gc_collect()

Expand Down Expand Up @@ -145,6 +174,8 @@ def get_pooled_int(value):
fd_before = fd_after
interned_before = interned_after

restore_support_xml(xml_filename)

if not quiet:
print(file=sys.stderr)

Expand Down Expand Up @@ -189,7 +220,7 @@ def check_fd_deltas(deltas):
failed = True
else:
print(' (this is fine)', file=sys.stderr, flush=True)
return (failed, results)
return (failed, result)


def dash_R_cleanup(fs, ps, pic, zdc, abcs):
Expand Down
9 changes: 5 additions & 4 deletions Lib/test/libregrtest/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ def _run_suite(suite):
result = runner.run(suite)

if support.junit_xml_list is not None:
support.junit_xml_list.append(result.get_xml_element())
import xml.etree.ElementTree as ET
xml_elem = result.get_xml_element()
xml_str = ET.tostring(xml_elem).decode('ascii')
support.junit_xml_list.append(xml_str)

if not result.testsRun and not result.skipped and not result.errors:
raise support.TestDidNotRun
Expand Down Expand Up @@ -280,9 +283,7 @@ def _runtest(result: TestResult, runtests: RunTests) -> None:

xml_list = support.junit_xml_list
if xml_list:
import xml.etree.ElementTree as ET
result.xml_data = [ET.tostring(x).decode('us-ascii')
for x in xml_list]
result.xml_data = xml_list
finally:
if use_timeout:
faulthandler.cancel_dump_traceback_later()
Expand Down
9 changes: 0 additions & 9 deletions Lib/test/test_regrtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,15 +473,6 @@ def test_verbose3_huntrleaks(self):
self.assertEqual(regrtest.hunt_refleak.runs, 10)
self.assertFalse(regrtest.output_on_failure)

def test_xml_huntrleaks(self):
args = ['-R', '3:12', '--junit-xml', 'output.xml']
with support.captured_stderr():
regrtest = self.create_regrtest(args)
self.assertIsNotNone(regrtest.hunt_refleak)
self.assertEqual(regrtest.hunt_refleak.warmups, 3)
self.assertEqual(regrtest.hunt_refleak.runs, 12)
self.assertIsNone(regrtest.junit_filename)


@dataclasses.dataclass(slots=True)
class Rerun:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
regrtest test runner: Add XML support to the refleak checker (-R option).
Patch by Victor Stinner.

0 comments on commit 30ee228

Please sign in to comment.