]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-139951: Tests on tuple GC tracking (GH-140575) (#140701)
authorMikhail Efimov <efimov.mikhail@gmail.com>
Wed, 29 Oct 2025 07:17:49 +0000 (10:17 +0300)
committerGitHub <noreply@github.com>
Wed, 29 Oct 2025 07:17:49 +0000 (07:17 +0000)
Lib/test/test_capi/test_tuple.py
Lib/test/test_tuple.py

index 7c07bc64e247c50fa86c3aa3462f6d9d2c3ca523..be6c91558312066b93902e9870eb72cbcd510b44 100644 (file)
@@ -14,6 +14,12 @@ class TupleSubclass(tuple):
 
 
 class CAPITest(unittest.TestCase):
+    def _not_tracked(self, t):
+        self.assertFalse(gc.is_tracked(t), t)
+
+    def _tracked(self, t):
+        self.assertTrue(gc.is_tracked(t), t)
+
     def test_check(self):
         # Test PyTuple_Check()
         check = _testlimitedcapi.tuple_check
@@ -52,11 +58,14 @@ class CAPITest(unittest.TestCase):
         self.assertEqual(tup1, ())
         self.assertEqual(size(tup1), 0)
         self.assertIs(type(tup1), tuple)
+        self._not_tracked(tup1)
+
         tup2 = tuple_new(1)
         self.assertIs(type(tup2), tuple)
         self.assertEqual(size(tup2), 1)
         self.assertIsNot(tup2, tup1)
         self.assertTrue(checknull(tup2, 0))
+        self._tracked(tup2)
 
         self.assertRaises(SystemError, tuple_new, -1)
         self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
@@ -70,6 +79,10 @@ class CAPITest(unittest.TestCase):
         self.assertEqual(pack(1, [1]), ([1],))
         self.assertEqual(pack(2, [1], [2]), ([1], [2]))
 
+        self._tracked(pack(1, [1]))
+        self._tracked(pack(2, [1], b'abc'))
+        self._not_tracked(pack(2, 42, b'abc'))
+
         self.assertRaises(SystemError, pack, PY_SSIZE_T_MIN)
         self.assertRaises(SystemError, pack, -1)
         self.assertRaises(MemoryError, pack, PY_SSIZE_T_MAX)
index 9ce80c5e8ea0093e00176c3c7078e0ad3123d4c3..e533392b8cae94aa62e8bab0ecab55f0739bb6c4 100644 (file)
@@ -290,12 +290,18 @@ class TupleTest(seq_tests.CommonTest):
         self.assertEqual(repr(a0), "()")
         self.assertEqual(repr(a2), "(0, 1, 2)")
 
+    # Checks that t is not tracked without any GC collections.
+    def _not_tracked_instantly(self, t):
+        self.assertFalse(gc.is_tracked(t), t)
+
+    # Checks that t is not tracked after GC collection.
     def _not_tracked(self, t):
         # Nested tuples can take several collections to untrack
         gc.collect()
         gc.collect()
         self.assertFalse(gc.is_tracked(t), t)
 
+    # Checks that t continues to be tracked even after GC collection.
     def _tracked(self, t):
         self.assertTrue(gc.is_tracked(t), t)
         gc.collect()
@@ -307,13 +313,19 @@ class TupleTest(seq_tests.CommonTest):
         # Test GC-optimization of tuple literals
         x, y, z = 1.5, "a", []
 
-        self._not_tracked(())
-        self._not_tracked((1,))
-        self._not_tracked((1, 2))
-        self._not_tracked((1, 2, "a"))
-        self._not_tracked((1, 2, (None, True, False, ()), int))
-        self._not_tracked((object(),))
+        # We check that those objects aren't tracked at all.
+        # It's essential for the GC performance, see gh-139951.
+        self._not_tracked_instantly(())
+        self._not_tracked_instantly((1,))
+        self._not_tracked_instantly((1, 2))
+        self._not_tracked_instantly((1, 2, "a"))
+        self._not_tracked_instantly((1, 2) * 5)
+        self._not_tracked_instantly((12, 10**10, 'a_' * 100))
+        self._not_tracked_instantly((object(),))
+
         self._not_tracked(((1, x), y, (2, 3)))
+        self._not_tracked((1, 2, (None, True, False, ()), int))
+        self._not_tracked((object(), ()))
 
         # Tuples with mutable elements are always tracked, even if those
         # elements are not tracked right now.
@@ -343,6 +355,12 @@ class TupleTest(seq_tests.CommonTest):
         self._tracked(tp(tuple([obj]) for obj in [x, y, z]))
         self._tracked(tuple(tp([obj]) for obj in [x, y, z]))
 
+        t = tp([1, x, y, z])
+        self.assertEqual(type(t), tp)
+        self._tracked(t)
+        self.assertEqual(type(t[:]), tuple)
+        self._tracked(t[:])
+
     @support.cpython_only
     def test_track_dynamic(self):
         # Test GC-optimization of dynamically constructed tuples.