From c9c178fdb1af01e441a6c83f3a21a67e5dd9f17d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 25 Feb 2022 00:03:20 +0100 Subject: [PATCH] bpo-1635741: test_embed cheks that Python does not leak (GH-31555) --- Lib/test/test_cmd_line.py | 2 +- Lib/test/test_embed.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 352109ed4b2ff1..1521b5b50ca249 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -118,7 +118,7 @@ def run_python(*args): self.assertEqual(out.rstrip(), b'{}') self.assertEqual(err, b'') # "-X showrefcount" shows the refcount, but only in debug builds - rc, out, err = run_python('-X', 'showrefcount', '-c', code) + rc, out, err = run_python('-I', '-X', 'showrefcount', '-c', code) self.assertEqual(out.rstrip(), b"{'showrefcount': True}") if Py_DEBUG: # bpo-46417: Tolerate negative reference count which can occur diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 15c6b05916f34d..e376331063d861 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1641,6 +1641,27 @@ def test_frozenmain(self): """).lstrip() self.assertEqual(out, expected) + @unittest.skipUnless(hasattr(sys, 'gettotalrefcount'), + '-X showrefcount requires a Python debug build') + def test_no_memleak(self): + # bpo-1635741: Python must release all memory at exit + cmd = [sys.executable, "-I", "-X", "showrefcount", "-c", "pass"] + proc = subprocess.run(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + self.assertEqual(proc.returncode, 0) + out = proc.stdout.rstrip() + match = re.match(r'^\[(-?\d+) refs, (-?\d+) blocks\]', out) + if not match: + self.fail(f"unexpected output: {out!a}") + refs = int(match.group(1)) + blocks = int(match.group(2)) + # bpo-46417: Tolerate negative reference count which can occur because + # of bugs in C extensions. It is only wrong if it's greater than 0. + self.assertLessEqual(refs, 0, out) + self.assertEqual(blocks, 0, out) + class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase): # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr():