summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_generators.py
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-05-08 16:12:35 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-05-08 16:12:35 (GMT)
commit04e70d19e7a5ab0cea7d3d231606180226e16f06 (patch)
treea1956f14fe0e89e656fd2161178dad0e25ff4b14 /Lib/test/test_generators.py
parent070cb3c9bed3fbdbda42c257e05d46adcbeb784e (diff)
downloadcpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.zip
cpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.tar.gz
cpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.tar.bz2
Issue #17807: Generators can now be finalized even when they are part of a reference cycle.
Diffstat (limited to 'Lib/test/test_generators.py')
-rw-r--r--Lib/test/test_generators.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index edf3443..4e92117 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -1,3 +1,55 @@
+import gc
+import sys
+import unittest
+import weakref
+
+from test import support
+
+
+class FinalizationTest(unittest.TestCase):
+
+ def test_frame_resurrect(self):
+ # A generator frame can be resurrected by a generator's finalization.
+ def gen():
+ nonlocal frame
+ try:
+ yield
+ finally:
+ frame = sys._getframe()
+
+ g = gen()
+ wr = weakref.ref(g)
+ next(g)
+ del g
+ support.gc_collect()
+ self.assertIs(wr(), None)
+ self.assertTrue(frame)
+ del frame
+ support.gc_collect()
+
+ def test_refcycle(self):
+ # A generator caught in a refcycle gets finalized anyway.
+ old_garbage = gc.garbage[:]
+ finalized = False
+ def gen():
+ nonlocal finalized
+ try:
+ g = yield
+ yield 1
+ finally:
+ finalized = True
+
+ g = gen()
+ next(g)
+ g.send(g)
+ self.assertGreater(sys.getrefcount(g), 2)
+ self.assertFalse(finalized)
+ del g
+ support.gc_collect()
+ self.assertTrue(finalized)
+ self.assertEqual(gc.garbage, old_garbage)
+
+
tutorial_tests = """
Let's try a simple generator:
@@ -1880,6 +1932,7 @@ __test__ = {"tut": tutorial_tests,
# so this works as expected in both ways of running regrtest.
def test_main(verbose=None):
from test import support, test_generators
+ support.run_unittest(__name__)
support.run_doctest(test_generators, verbose)
# This part isn't needed for regrtest, but for running the test directly.