]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-119050: Add XML support to libregrtest refleak checker (#119148)
authorVictor Stinner <vstinner@python.org>
Mon, 20 May 2024 21:05:39 +0000 (17:05 -0400)
committerGitHub <noreply@github.com>
Mon, 20 May 2024 21:05:39 +0000 (17:05 -0400)
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.

Lib/test/libregrtest/cmdline.py
Lib/test/libregrtest/refleak.py
Lib/test/libregrtest/single.py
Lib/test/test_regrtest.py
Misc/NEWS.d/next/Tests/2024-05-18-10-59-27.gh-issue-119050.g4qiH7.rst [new file with mode: 0644]

index 3e7428c4ad37979f378cb75c5a6598e9db613ad2..d4dac77b250ad6877a8a03eb14b5541a96d1c314 100644 (file)
@@ -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
index bb57ffd75636cb3d5d3407fa8438e9b5b89ec4d2..85a5cb72083264daa1e8401de1f844aef347e6f8 100644 (file)
@@ -1,3 +1,4 @@
+import os
 import sys
 import warnings
 from inspect import isabstract
@@ -23,6 +24,30 @@ except ImportError:
                 cls._abc_negative_cache, cls._abc_negative_cache_version)
 
 
+def save_support_xml(filename):
+    if support.junit_xml_list is None:
+        return
+
+    import pickle
+    with open(filename, 'xb') as fp:
+        pickle.dump(support.junit_xml_list, fp)
+    support.junit_xml_list = None
+
+
+def restore_support_xml(filename):
+    try:
+        fp = open(filename, 'rb')
+    except FileNotFoundError:
+        return
+
+    import pickle
+    with fp:
+        xml_list = pickle.load(fp)
+    os.unlink(filename)
+
+    support.junit_xml_list = xml_list
+
+
 def runtest_refleak(test_name, test_func,
                     hunt_refleak: HuntRefleak,
                     quiet: bool):
@@ -95,7 +120,8 @@ def runtest_refleak(test_name, test_func,
         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()
 
@@ -103,10 +129,11 @@ def runtest_refleak(test_name, test_func,
         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()
 
@@ -145,6 +172,8 @@ def runtest_refleak(test_name, test_func,
         fd_before = fd_after
         interned_before = interned_after
 
+        restore_support_xml(xml_filename)
+
     if not quiet:
         print(file=sys.stderr)
 
@@ -189,7 +218,7 @@ def runtest_refleak(test_name, test_func,
                 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):
index fc2f2716ad4ce05473c6493e8828ecfeda65b83b..adc8f1f455579fa56830521e33af1dd88cd42420 100644 (file)
@@ -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
@@ -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()
index 809abd7e92d65fd58ba5fa8eee9ce3f82bbe0f70..17eff617a56aa42d6781c84c7fcaf6172c689f2a 100644 (file)
@@ -473,15 +473,6 @@ class ParseArgsTestCase(unittest.TestCase):
         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:
diff --git a/Misc/NEWS.d/next/Tests/2024-05-18-10-59-27.gh-issue-119050.g4qiH7.rst b/Misc/NEWS.d/next/Tests/2024-05-18-10-59-27.gh-issue-119050.g4qiH7.rst
new file mode 100644 (file)
index 0000000..cfc70c1
--- /dev/null
@@ -0,0 +1,2 @@
+regrtest test runner: Add XML support to the refleak checker (-R option).
+Patch by Victor Stinner.