blob: 1f0867d379afd82d45c81599500049ad59d246fe [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001import unittest
Brett Cannon7a540732011-02-22 03:04:06 +00002from test.support import (verbose, refcount_test, run_unittest,
Berker Peksagce643912015-05-06 06:33:17 +03003 strip_python_stderr, cpython_only, start_threads,
4 temp_dir)
5from test.support.script_helper import assert_python_ok, make_script
Antoine Pitrou5f454a02013-05-06 21:15:57 +02006
Neil Schemenauer88c761a2001-07-12 13:25:53 +00007import sys
Antoine Pitrou2b0218a2012-09-06 00:59:49 +02008import time
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +00009import gc
Tim Petersead8b7a2004-10-30 23:09:22 +000010import weakref
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +000011
Antoine Pitrou2b0218a2012-09-06 00:59:49 +020012try:
13 import threading
14except ImportError:
15 threading = None
16
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020017try:
18 from _testcapi import with_tp_del
19except ImportError:
20 def with_tp_del(cls):
21 class C(object):
22 def __new__(cls, *args, **kwargs):
23 raise TypeError('requires _testcapi.with_tp_del')
24 return C
25
Guido van Rossumd8faa362007-04-27 19:54:29 +000026### Support code
27###############################################################################
Tim Peters0f81ab62003-04-08 16:39:48 +000028
Tim Petersead8b7a2004-10-30 23:09:22 +000029# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
30# cyclic gc.
31
32# An instance of C1055820 has a self-loop, so becomes cyclic trash when
33# unreachable.
34class C1055820(object):
35 def __init__(self, i):
36 self.i = i
37 self.loop = self
38
39class GC_Detector(object):
40 # Create an instance I. Then gc hasn't happened again so long as
41 # I.gc_happened is false.
42
43 def __init__(self):
44 self.gc_happened = False
45
46 def it_happened(ignored):
47 self.gc_happened = True
48
49 # Create a piece of cyclic trash that triggers it_happened when
50 # gc collects it.
51 self.wr = weakref.ref(C1055820(666), it_happened)
52
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020053@with_tp_del
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000054class Uncollectable(object):
55 """Create a reference cycle with multiple __del__ methods.
56
57 An object in a reference cycle will never have zero references,
58 and so must be garbage collected. If one or more objects in the
59 cycle have __del__ methods, the gc refuses to guess an order,
60 and leaves the cycle uncollected."""
61 def __init__(self, partner=None):
62 if partner is None:
63 self.partner = Uncollectable(partner=self)
64 else:
65 self.partner = partner
Antoine Pitrou796564c2013-07-30 19:59:21 +020066 def __tp_del__(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000067 pass
Tim Petersead8b7a2004-10-30 23:09:22 +000068
Guido van Rossumd8faa362007-04-27 19:54:29 +000069### Tests
70###############################################################################
Tim Petersead8b7a2004-10-30 23:09:22 +000071
Guido van Rossumd8faa362007-04-27 19:54:29 +000072class GCTests(unittest.TestCase):
73 def test_list(self):
74 l = []
75 l.append(l)
76 gc.collect()
77 del l
78 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000079
Guido van Rossumd8faa362007-04-27 19:54:29 +000080 def test_dict(self):
81 d = {}
82 d[1] = d
83 gc.collect()
84 del d
85 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000086
Guido van Rossumd8faa362007-04-27 19:54:29 +000087 def test_tuple(self):
88 # since tuples are immutable we close the loop with a list
89 l = []
90 t = (l,)
91 l.append(t)
92 gc.collect()
93 del t
94 del l
95 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +000096
Guido van Rossumd8faa362007-04-27 19:54:29 +000097 def test_class(self):
98 class A:
99 pass
100 A.a = A
101 gc.collect()
102 del A
103 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000104
Guido van Rossumd8faa362007-04-27 19:54:29 +0000105 def test_newstyleclass(self):
106 class A(object):
107 pass
108 gc.collect()
109 del A
110 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000111
Guido van Rossumd8faa362007-04-27 19:54:29 +0000112 def test_instance(self):
113 class A:
114 pass
115 a = A()
116 a.a = a
117 gc.collect()
118 del a
119 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000120
Guido van Rossumd8faa362007-04-27 19:54:29 +0000121 def test_newinstance(self):
122 class A(object):
123 pass
124 a = A()
125 a.a = a
126 gc.collect()
127 del a
128 self.assertNotEqual(gc.collect(), 0)
129 class B(list):
130 pass
131 class C(B, A):
132 pass
133 a = C()
134 a.a = a
135 gc.collect()
136 del a
137 self.assertNotEqual(gc.collect(), 0)
138 del B, C
139 self.assertNotEqual(gc.collect(), 0)
140 A.a = A()
141 del A
142 self.assertNotEqual(gc.collect(), 0)
143 self.assertEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000144
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145 def test_method(self):
146 # Tricky: self.__init__ is a bound method, it references the instance.
147 class A:
148 def __init__(self):
149 self.init = self.__init__
150 a = A()
151 gc.collect()
152 del a
153 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000154
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200155 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200156 def test_legacy_finalizer(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000157 # A() is uncollectable if it is part of a cycle, make sure it shows up
158 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200159 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000160 class A:
Antoine Pitrou796564c2013-07-30 19:59:21 +0200161 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000162 class B:
163 pass
164 a = A()
165 a.a = a
166 id_a = id(a)
167 b = B()
168 b.b = b
169 gc.collect()
170 del a
171 del b
172 self.assertNotEqual(gc.collect(), 0)
173 for obj in gc.garbage:
174 if id(obj) == id_a:
175 del obj.a
176 break
177 else:
178 self.fail("didn't find obj in garbage (finalizer)")
179 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000180
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200181 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200182 def test_legacy_finalizer_newclass(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000183 # A() is uncollectable if it is part of a cycle, make sure it shows up
184 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200185 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000186 class A(object):
Antoine Pitrou796564c2013-07-30 19:59:21 +0200187 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000188 class B(object):
189 pass
190 a = A()
191 a.a = a
192 id_a = id(a)
193 b = B()
194 b.b = b
195 gc.collect()
196 del a
197 del b
198 self.assertNotEqual(gc.collect(), 0)
199 for obj in gc.garbage:
200 if id(obj) == id_a:
201 del obj.a
202 break
203 else:
204 self.fail("didn't find obj in garbage (finalizer)")
205 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000206
Guido van Rossumd8faa362007-04-27 19:54:29 +0000207 def test_function(self):
208 # Tricky: f -> d -> f, code should call d.clear() after the exec to
209 # break the cycle.
210 d = {}
211 exec("def f(): pass\n", d)
212 gc.collect()
213 del d
214 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000215
Brett Cannon7a540732011-02-22 03:04:06 +0000216 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000217 def test_frame(self):
218 def f():
219 frame = sys._getframe()
220 gc.collect()
221 f()
222 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +0000223
Guido van Rossumd8faa362007-04-27 19:54:29 +0000224 def test_saveall(self):
225 # Verify that cyclic garbage like lists show up in gc.garbage if the
226 # SAVEALL option is enabled.
Tim Petersead8b7a2004-10-30 23:09:22 +0000227
Guido van Rossumd8faa362007-04-27 19:54:29 +0000228 # First make sure we don't save away other stuff that just happens to
229 # be waiting for collection.
230 gc.collect()
231 # if this fails, someone else created immortal trash
232 self.assertEqual(gc.garbage, [])
233
234 L = []
235 L.append(L)
236 id_L = id(L)
237
238 debug = gc.get_debug()
239 gc.set_debug(debug | gc.DEBUG_SAVEALL)
240 del L
241 gc.collect()
242 gc.set_debug(debug)
243
244 self.assertEqual(len(gc.garbage), 1)
245 obj = gc.garbage.pop()
246 self.assertEqual(id(obj), id_L)
247
248 def test_del(self):
249 # __del__ methods can trigger collection, make this to happen
250 thresholds = gc.get_threshold()
251 gc.enable()
252 gc.set_threshold(1)
253
254 class A:
255 def __del__(self):
256 dir(self)
257 a = A()
258 del a
259
260 gc.disable()
261 gc.set_threshold(*thresholds)
262
263 def test_del_newclass(self):
264 # __del__ methods can trigger collection, make this to happen
265 thresholds = gc.get_threshold()
266 gc.enable()
267 gc.set_threshold(1)
268
269 class A(object):
270 def __del__(self):
271 dir(self)
272 a = A()
273 del a
274
275 gc.disable()
276 gc.set_threshold(*thresholds)
277
Christian Heimesa156e092008-02-16 07:38:31 +0000278 # The following two tests are fragile:
279 # They precisely count the number of allocations,
280 # which is highly implementation-dependent.
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200281 # For example, disposed tuples are not freed, but reused.
282 # To minimize variations, though, we first store the get_count() results
283 # and check them at the end.
Brett Cannon7a540732011-02-22 03:04:06 +0000284 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000285 def test_get_count(self):
286 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200287 a, b, c = gc.get_count()
288 x = []
289 d, e, f = gc.get_count()
290 self.assertEqual((b, c), (0, 0))
291 self.assertEqual((e, f), (0, 0))
292 # This is less fragile than asserting that a equals 0.
293 self.assertLess(a, 5)
294 # Between the two calls to get_count(), at least one object was
295 # created (the list).
296 self.assertGreater(d, a)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000297
Brett Cannon7a540732011-02-22 03:04:06 +0000298 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000299 def test_collect_generations(self):
300 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200301 # This object will "trickle" into generation N + 1 after
302 # each call to collect(N)
303 x = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000304 gc.collect(0)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200305 # x is now in gen 1
306 a, b, c = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000307 gc.collect(1)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200308 # x is now in gen 2
309 d, e, f = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000310 gc.collect(2)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200311 # x is now in gen 3
312 g, h, i = gc.get_count()
313 # We don't check a, d, g since their exact values depends on
314 # internal implementation details of the interpreter.
315 self.assertEqual((b, c), (1, 0))
316 self.assertEqual((e, f), (0, 1))
317 self.assertEqual((h, i), (0, 0))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000318
319 def test_trashcan(self):
320 class Ouch:
321 n = 0
322 def __del__(self):
323 Ouch.n = Ouch.n + 1
324 if Ouch.n % 17 == 0:
325 gc.collect()
326
327 # "trashcan" is a hack to prevent stack overflow when deallocating
328 # very deeply nested tuples etc. It works in part by abusing the
329 # type pointer and refcount fields, and that can yield horrible
330 # problems when gc tries to traverse the structures.
331 # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
332 # most likely die via segfault.
333
334 # Note: In 2.3 the possibility for compiling without cyclic gc was
335 # removed, and that in turn allows the trashcan mechanism to work
336 # via much simpler means (e.g., it never abuses the type pointer or
337 # refcount fields anymore). Since it's much less likely to cause a
338 # problem now, the various constants in this expensive (we force a lot
339 # of full collections) test are cut back from the 2.2 version.
340 gc.enable()
341 N = 150
342 for count in range(2):
343 t = []
344 for i in range(N):
345 t = [t, Ouch()]
346 u = []
347 for i in range(N):
348 u = [u, Ouch()]
349 v = {}
350 for i in range(N):
351 v = {1: v, 2: Ouch()}
352 gc.disable()
353
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200354 @unittest.skipUnless(threading, "test meaningless on builds without threads")
355 def test_trashcan_threads(self):
356 # Issue #13992: trashcan mechanism should be thread-safe
357 NESTING = 60
358 N_THREADS = 2
359
360 def sleeper_gen():
361 """A generator that releases the GIL when closed or dealloc'ed."""
362 try:
363 yield
364 finally:
365 time.sleep(0.000001)
366
367 class C(list):
368 # Appending to a list is atomic, which avoids the use of a lock.
369 inits = []
370 dels = []
371 def __init__(self, alist):
372 self[:] = alist
373 C.inits.append(None)
374 def __del__(self):
375 # This __del__ is called by subtype_dealloc().
376 C.dels.append(None)
377 # `g` will release the GIL when garbage-collected. This
378 # helps assert subtype_dealloc's behaviour when threads
379 # switch in the middle of it.
380 g = sleeper_gen()
381 next(g)
382 # Now that __del__ is finished, subtype_dealloc will proceed
383 # to call list_dealloc, which also uses the trashcan mechanism.
384
385 def make_nested():
386 """Create a sufficiently nested container object so that the
387 trashcan mechanism is invoked when deallocating it."""
388 x = C([])
389 for i in range(NESTING):
390 x = [C([x])]
391 del x
392
393 def run_thread():
394 """Exercise make_nested() in a loop."""
395 while not exit:
396 make_nested()
397
398 old_switchinterval = sys.getswitchinterval()
399 sys.setswitchinterval(1e-5)
400 try:
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300401 exit = []
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200402 threads = []
403 for i in range(N_THREADS):
404 t = threading.Thread(target=run_thread)
405 threads.append(t)
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300406 with start_threads(threads, lambda: exit.append(1)):
Serhiy Storchaka9db55002015-03-28 20:38:37 +0200407 time.sleep(1.0)
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200408 finally:
409 sys.setswitchinterval(old_switchinterval)
410 gc.collect()
411 self.assertEqual(len(C.inits), len(C.dels))
412
Guido van Rossumd8faa362007-04-27 19:54:29 +0000413 def test_boom(self):
414 class Boom:
415 def __getattr__(self, someattribute):
416 del self.attr
417 raise AttributeError
418
419 a = Boom()
420 b = Boom()
421 a.attr = b
422 b.attr = a
423
424 gc.collect()
425 garbagelen = len(gc.garbage)
426 del a, b
427 # a<->b are in a trash cycle now. Collection will invoke
428 # Boom.__getattr__ (to see whether a and b have __del__ methods), and
429 # __getattr__ deletes the internal "attr" attributes as a side effect.
430 # That causes the trash cycle to get reclaimed via refcounts falling to
431 # 0, thus mutating the trash graph as a side effect of merely asking
432 # whether __del__ exists. This used to (before 2.3b1) crash Python.
433 # Now __getattr__ isn't called.
434 self.assertEqual(gc.collect(), 4)
435 self.assertEqual(len(gc.garbage), garbagelen)
436
437 def test_boom2(self):
438 class Boom2:
439 def __init__(self):
440 self.x = 0
441
442 def __getattr__(self, someattribute):
443 self.x += 1
444 if self.x > 1:
445 del self.attr
446 raise AttributeError
447
448 a = Boom2()
449 b = Boom2()
450 a.attr = b
451 b.attr = a
452
453 gc.collect()
454 garbagelen = len(gc.garbage)
455 del a, b
456 # Much like test_boom(), except that __getattr__ doesn't break the
457 # cycle until the second time gc checks for __del__. As of 2.3b1,
458 # there isn't a second time, so this simply cleans up the trash cycle.
459 # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
460 # reclaimed this way.
461 self.assertEqual(gc.collect(), 4)
462 self.assertEqual(len(gc.garbage), garbagelen)
463
464 def test_boom_new(self):
465 # boom__new and boom2_new are exactly like boom and boom2, except use
466 # new-style classes.
467
468 class Boom_New(object):
469 def __getattr__(self, someattribute):
470 del self.attr
471 raise AttributeError
472
473 a = Boom_New()
474 b = Boom_New()
475 a.attr = b
476 b.attr = a
477
478 gc.collect()
479 garbagelen = len(gc.garbage)
480 del a, b
481 self.assertEqual(gc.collect(), 4)
482 self.assertEqual(len(gc.garbage), garbagelen)
483
484 def test_boom2_new(self):
485 class Boom2_New(object):
486 def __init__(self):
487 self.x = 0
488
489 def __getattr__(self, someattribute):
490 self.x += 1
491 if self.x > 1:
492 del self.attr
493 raise AttributeError
494
495 a = Boom2_New()
496 b = Boom2_New()
497 a.attr = b
498 b.attr = a
499
500 gc.collect()
501 garbagelen = len(gc.garbage)
502 del a, b
503 self.assertEqual(gc.collect(), 4)
504 self.assertEqual(len(gc.garbage), garbagelen)
505
506 def test_get_referents(self):
507 alist = [1, 3, 5]
508 got = gc.get_referents(alist)
509 got.sort()
510 self.assertEqual(got, alist)
511
512 atuple = tuple(alist)
513 got = gc.get_referents(atuple)
514 got.sort()
515 self.assertEqual(got, alist)
516
517 adict = {1: 3, 5: 7}
518 expected = [1, 3, 5, 7]
519 got = gc.get_referents(adict)
520 got.sort()
521 self.assertEqual(got, expected)
522
523 got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
524 got.sort()
Guido van Rossum805365e2007-05-07 22:24:25 +0000525 self.assertEqual(got, [0, 0] + list(range(5)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000526
527 self.assertEqual(gc.get_referents(1, 'a', 4j), [])
528
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000529 def test_is_tracked(self):
530 # Atomic built-in types are not tracked, user-defined objects and
531 # mutable containers are.
532 # NOTE: types with special optimizations (e.g. tuple) have tests
533 # in their own test files instead.
534 self.assertFalse(gc.is_tracked(None))
535 self.assertFalse(gc.is_tracked(1))
536 self.assertFalse(gc.is_tracked(1.0))
537 self.assertFalse(gc.is_tracked(1.0 + 5.0j))
538 self.assertFalse(gc.is_tracked(True))
539 self.assertFalse(gc.is_tracked(False))
540 self.assertFalse(gc.is_tracked(b"a"))
541 self.assertFalse(gc.is_tracked("a"))
542 self.assertFalse(gc.is_tracked(bytearray(b"a")))
543 self.assertFalse(gc.is_tracked(type))
544 self.assertFalse(gc.is_tracked(int))
545 self.assertFalse(gc.is_tracked(object))
546 self.assertFalse(gc.is_tracked(object()))
547
548 class UserClass:
549 pass
Antoine Pitroua63cc212015-04-13 20:10:06 +0200550
551 class UserInt(int):
552 pass
553
554 # Base class is object; no extra fields.
555 class UserClassSlots:
556 __slots__ = ()
557
558 # Base class is fixed size larger than object; no extra fields.
559 class UserFloatSlots(float):
560 __slots__ = ()
561
562 # Base class is variable size; no extra fields.
563 class UserIntSlots(int):
564 __slots__ = ()
565
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000566 self.assertTrue(gc.is_tracked(gc))
567 self.assertTrue(gc.is_tracked(UserClass))
568 self.assertTrue(gc.is_tracked(UserClass()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200569 self.assertTrue(gc.is_tracked(UserInt()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000570 self.assertTrue(gc.is_tracked([]))
571 self.assertTrue(gc.is_tracked(set()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200572 self.assertFalse(gc.is_tracked(UserClassSlots()))
573 self.assertFalse(gc.is_tracked(UserFloatSlots()))
574 self.assertFalse(gc.is_tracked(UserIntSlots()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000575
Guido van Rossumd8faa362007-04-27 19:54:29 +0000576 def test_bug1055820b(self):
577 # Corresponds to temp2b.py in the bug report.
578
579 ouch = []
580 def callback(ignored):
581 ouch[:] = [wr() for wr in WRs]
582
583 Cs = [C1055820(i) for i in range(2)]
584 WRs = [weakref.ref(c, callback) for c in Cs]
585 c = None
586
587 gc.collect()
588 self.assertEqual(len(ouch), 0)
589 # Make the two instances trash, and collect again. The bug was that
590 # the callback materialized a strong reference to an instance, but gc
591 # cleared the instance's dict anyway.
592 Cs = None
593 gc.collect()
594 self.assertEqual(len(ouch), 2) # else the callbacks didn't run
595 for x in ouch:
596 # If the callback resurrected one of these guys, the instance
597 # would be damaged, with an empty __dict__.
598 self.assertEqual(x, None)
599
Tim Peters5fbc7b12014-05-08 17:42:19 -0500600 def test_bug21435(self):
601 # This is a poor test - its only virtue is that it happened to
602 # segfault on Tim's Windows box before the patch for 21435 was
603 # applied. That's a nasty bug relying on specific pieces of cyclic
604 # trash appearing in exactly the right order in finalize_garbage()'s
605 # input list.
606 # But there's no reliable way to force that order from Python code,
607 # so over time chances are good this test won't really be testing much
608 # of anything anymore. Still, if it blows up, there's _some_
609 # problem ;-)
610 gc.collect()
611
612 class A:
613 pass
614
615 class B:
616 def __init__(self, x):
617 self.x = x
618
619 def __del__(self):
620 self.attr = None
621
622 def do_work():
623 a = A()
624 b = B(A())
625
626 a.attr = b
627 b.attr = a
628
629 do_work()
630 gc.collect() # this blows up (bad C pointer) when it fails
631
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200632 @cpython_only
Antoine Pitrou696e0352010-08-08 22:18:46 +0000633 def test_garbage_at_shutdown(self):
634 import subprocess
635 code = """if 1:
636 import gc
Antoine Pitrou796564c2013-07-30 19:59:21 +0200637 import _testcapi
638 @_testcapi.with_tp_del
Antoine Pitrou696e0352010-08-08 22:18:46 +0000639 class X:
640 def __init__(self, name):
641 self.name = name
642 def __repr__(self):
643 return "<X %%r>" %% self.name
Antoine Pitrou796564c2013-07-30 19:59:21 +0200644 def __tp_del__(self):
Antoine Pitrou696e0352010-08-08 22:18:46 +0000645 pass
646
647 x = X('first')
648 x.x = x
649 x.y = X('second')
650 del x
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000651 gc.set_debug(%s)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000652 """
653 def run_command(code):
Georg Brandl08be72d2010-10-24 15:11:22 +0000654 p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
Antoine Pitrou696e0352010-08-08 22:18:46 +0000655 stdout=subprocess.PIPE,
656 stderr=subprocess.PIPE)
657 stdout, stderr = p.communicate()
Brian Curtin8291af22010-11-01 16:40:17 +0000658 p.stdout.close()
659 p.stderr.close()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000660 self.assertEqual(p.returncode, 0)
661 self.assertEqual(stdout.strip(), b"")
662 return strip_python_stderr(stderr)
663
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000664 stderr = run_command(code % "0")
Georg Brandl08be72d2010-10-24 15:11:22 +0000665 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
666 b"shutdown; use", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000667 self.assertNotIn(b"<X 'first'>", stderr)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000668 # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000669 stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
Georg Brandl08be72d2010-10-24 15:11:22 +0000670 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
671 b"shutdown", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000672 self.assertTrue(
673 (b"[<X 'first'>, <X 'second'>]" in stderr) or
674 (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000675 # With DEBUG_SAVEALL, no additional message should get printed
676 # (because gc.garbage also contains normally reclaimable cyclic
677 # references, and its elements get printed at runtime anyway).
678 stderr = run_command(code % "gc.DEBUG_SAVEALL")
679 self.assertNotIn(b"uncollectable objects at shutdown", stderr)
680
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200681 def test_gc_main_module_at_shutdown(self):
682 # Create a reference cycle through the __main__ module and check
683 # it gets collected at interpreter shutdown.
684 code = """if 1:
685 import weakref
686 class C:
687 def __del__(self):
688 print('__del__ called')
689 l = [C()]
690 l.append(l)
691 """
692 rc, out, err = assert_python_ok('-c', code)
693 self.assertEqual(out.strip(), b'__del__ called')
694
695 def test_gc_ordinary_module_at_shutdown(self):
696 # Same as above, but with a non-__main__ module.
697 with temp_dir() as script_dir:
698 module = """if 1:
699 import weakref
700 class C:
701 def __del__(self):
702 print('__del__ called')
703 l = [C()]
704 l.append(l)
705 """
706 code = """if 1:
707 import sys
708 sys.path.insert(0, %r)
709 import gctest
710 """ % (script_dir,)
711 make_script(script_dir, 'gctest', module)
712 rc, out, err = assert_python_ok('-c', code)
713 self.assertEqual(out.strip(), b'__del__ called')
714
Antoine Pitroud4156c12012-10-30 22:43:19 +0100715 def test_get_stats(self):
716 stats = gc.get_stats()
717 self.assertEqual(len(stats), 3)
718 for st in stats:
719 self.assertIsInstance(st, dict)
720 self.assertEqual(set(st),
721 {"collected", "collections", "uncollectable"})
722 self.assertGreaterEqual(st["collected"], 0)
723 self.assertGreaterEqual(st["collections"], 0)
724 self.assertGreaterEqual(st["uncollectable"], 0)
725 # Check that collection counts are incremented correctly
726 if gc.isenabled():
727 self.addCleanup(gc.enable)
728 gc.disable()
729 old = gc.get_stats()
730 gc.collect(0)
731 new = gc.get_stats()
732 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
733 self.assertEqual(new[1]["collections"], old[1]["collections"])
734 self.assertEqual(new[2]["collections"], old[2]["collections"])
735 gc.collect(2)
736 new = gc.get_stats()
737 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
738 self.assertEqual(new[1]["collections"], old[1]["collections"])
739 self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
740
Antoine Pitrou696e0352010-08-08 22:18:46 +0000741
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000742class GCCallbackTests(unittest.TestCase):
743 def setUp(self):
744 # Save gc state and disable it.
745 self.enabled = gc.isenabled()
746 gc.disable()
747 self.debug = gc.get_debug()
748 gc.set_debug(0)
749 gc.callbacks.append(self.cb1)
750 gc.callbacks.append(self.cb2)
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200751 self.othergarbage = []
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000752
753 def tearDown(self):
754 # Restore gc state
755 del self.visit
756 gc.callbacks.remove(self.cb1)
757 gc.callbacks.remove(self.cb2)
758 gc.set_debug(self.debug)
759 if self.enabled:
760 gc.enable()
761 # destroy any uncollectables
762 gc.collect()
763 for obj in gc.garbage:
764 if isinstance(obj, Uncollectable):
765 obj.partner = None
766 del gc.garbage[:]
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200767 del self.othergarbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000768 gc.collect()
769
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000770 def preclean(self):
771 # Remove all fluff from the system. Invoke this function
772 # manually rather than through self.setUp() for maximum
773 # safety.
774 self.visit = []
775 gc.collect()
776 garbage, gc.garbage[:] = gc.garbage[:], []
777 self.othergarbage.append(garbage)
778 self.visit = []
779
780 def cb1(self, phase, info):
781 self.visit.append((1, phase, dict(info)))
782
783 def cb2(self, phase, info):
784 self.visit.append((2, phase, dict(info)))
785 if phase == "stop" and hasattr(self, "cleanup"):
786 # Clean Uncollectable from garbage
787 uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
788 gc.garbage[:] = [e for e in gc.garbage
789 if not isinstance(e, Uncollectable)]
790 for e in uc:
791 e.partner = None
792
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200793 def test_collect(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000794 self.preclean()
795 gc.collect()
796 # Algorithmically verify the contents of self.visit
797 # because it is long and tortuous.
798
799 # Count the number of visits to each callback
800 n = [v[0] for v in self.visit]
801 n1 = [i for i in n if i == 1]
802 n2 = [i for i in n if i == 2]
803 self.assertEqual(n1, [1]*2)
804 self.assertEqual(n2, [2]*2)
805
806 # Count that we got the right number of start and stop callbacks.
807 n = [v[1] for v in self.visit]
808 n1 = [i for i in n if i == "start"]
809 n2 = [i for i in n if i == "stop"]
810 self.assertEqual(n1, ["start"]*2)
811 self.assertEqual(n2, ["stop"]*2)
812
813 # Check that we got the right info dict for all callbacks
814 for v in self.visit:
815 info = v[2]
816 self.assertTrue("generation" in info)
817 self.assertTrue("collected" in info)
818 self.assertTrue("uncollectable" in info)
819
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200820 def test_collect_generation(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000821 self.preclean()
822 gc.collect(2)
823 for v in self.visit:
824 info = v[2]
825 self.assertEqual(info["generation"], 2)
826
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200827 @cpython_only
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200828 def test_collect_garbage(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000829 self.preclean()
830 # Each of these cause four objects to be garbage: Two
831 # Uncolectables and their instance dicts.
832 Uncollectable()
833 Uncollectable()
834 C1055820(666)
835 gc.collect()
836 for v in self.visit:
837 if v[1] != "stop":
838 continue
839 info = v[2]
840 self.assertEqual(info["collected"], 2)
841 self.assertEqual(info["uncollectable"], 8)
842
843 # We should now have the Uncollectables in gc.garbage
844 self.assertEqual(len(gc.garbage), 4)
845 for e in gc.garbage:
846 self.assertIsInstance(e, Uncollectable)
847
848 # Now, let our callback handle the Uncollectable instances
849 self.cleanup=True
850 self.visit = []
851 gc.garbage[:] = []
852 gc.collect()
853 for v in self.visit:
854 if v[1] != "stop":
855 continue
856 info = v[2]
857 self.assertEqual(info["collected"], 0)
858 self.assertEqual(info["uncollectable"], 4)
859
860 # Uncollectables should be gone
861 self.assertEqual(len(gc.garbage), 0)
862
863
Guido van Rossumd8faa362007-04-27 19:54:29 +0000864class GCTogglingTests(unittest.TestCase):
865 def setUp(self):
866 gc.enable()
867
868 def tearDown(self):
869 gc.disable()
870
871 def test_bug1055820c(self):
872 # Corresponds to temp2c.py in the bug report. This is pretty
873 # elaborate.
874
875 c0 = C1055820(0)
876 # Move c0 into generation 2.
877 gc.collect()
878
879 c1 = C1055820(1)
880 c1.keep_c0_alive = c0
881 del c0.loop # now only c1 keeps c0 alive
882
883 c2 = C1055820(2)
884 c2wr = weakref.ref(c2) # no callback!
885
886 ouch = []
887 def callback(ignored):
Tim Petersead8b7a2004-10-30 23:09:22 +0000888 ouch[:] = [c2wr()]
889
Guido van Rossumd8faa362007-04-27 19:54:29 +0000890 # The callback gets associated with a wr on an object in generation 2.
891 c0wr = weakref.ref(c0, callback)
Tim Petersead8b7a2004-10-30 23:09:22 +0000892
Guido van Rossumd8faa362007-04-27 19:54:29 +0000893 c0 = c1 = c2 = None
Tim Petersead8b7a2004-10-30 23:09:22 +0000894
Guido van Rossumd8faa362007-04-27 19:54:29 +0000895 # What we've set up: c0, c1, and c2 are all trash now. c0 is in
896 # generation 2. The only thing keeping it alive is that c1 points to
897 # it. c1 and c2 are in generation 0, and are in self-loops. There's a
898 # global weakref to c2 (c2wr), but that weakref has no callback.
899 # There's also a global weakref to c0 (c0wr), and that does have a
900 # callback, and that callback references c2 via c2wr().
901 #
902 # c0 has a wr with callback, which references c2wr
903 # ^
904 # |
905 # | Generation 2 above dots
906 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
907 # | Generation 0 below dots
908 # |
909 # |
910 # ^->c1 ^->c2 has a wr but no callback
911 # | | | |
912 # <--v <--v
913 #
914 # So this is the nightmare: when generation 0 gets collected, we see
915 # that c2 has a callback-free weakref, and c1 doesn't even have a
916 # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
917 # the only object that has a weakref with a callback. gc clears c1
918 # and c2. Clearing c1 has the side effect of dropping the refcount on
919 # c0 to 0, so c0 goes away (despite that it's in an older generation)
920 # and c0's wr callback triggers. That in turn materializes a reference
921 # to c2 via c2wr(), but c2 gets cleared anyway by gc.
Tim Petersead8b7a2004-10-30 23:09:22 +0000922
Guido van Rossumd8faa362007-04-27 19:54:29 +0000923 # We want to let gc happen "naturally", to preserve the distinction
924 # between generations.
925 junk = []
926 i = 0
927 detector = GC_Detector()
928 while not detector.gc_happened:
929 i += 1
930 if i > 10000:
931 self.fail("gc didn't happen after 10000 iterations")
932 self.assertEqual(len(ouch), 0)
933 junk.append([]) # this will eventually trigger gc
Tim Petersead8b7a2004-10-30 23:09:22 +0000934
Guido van Rossumd8faa362007-04-27 19:54:29 +0000935 self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
936 for x in ouch:
937 # If the callback resurrected c2, the instance would be damaged,
938 # with an empty __dict__.
939 self.assertEqual(x, None)
Tim Petersead8b7a2004-10-30 23:09:22 +0000940
Guido van Rossumd8faa362007-04-27 19:54:29 +0000941 def test_bug1055820d(self):
942 # Corresponds to temp2d.py in the bug report. This is very much like
943 # test_bug1055820c, but uses a __del__ method instead of a weakref
944 # callback to sneak in a resurrection of cyclic trash.
Tim Petersead8b7a2004-10-30 23:09:22 +0000945
Guido van Rossumd8faa362007-04-27 19:54:29 +0000946 ouch = []
947 class D(C1055820):
948 def __del__(self):
949 ouch[:] = [c2wr()]
Tim Petersead8b7a2004-10-30 23:09:22 +0000950
Guido van Rossumd8faa362007-04-27 19:54:29 +0000951 d0 = D(0)
952 # Move all the above into generation 2.
953 gc.collect()
Tim Petersead8b7a2004-10-30 23:09:22 +0000954
Guido van Rossumd8faa362007-04-27 19:54:29 +0000955 c1 = C1055820(1)
956 c1.keep_d0_alive = d0
957 del d0.loop # now only c1 keeps d0 alive
Tim Petersead8b7a2004-10-30 23:09:22 +0000958
Guido van Rossumd8faa362007-04-27 19:54:29 +0000959 c2 = C1055820(2)
960 c2wr = weakref.ref(c2) # no callback!
Tim Petersead8b7a2004-10-30 23:09:22 +0000961
Guido van Rossumd8faa362007-04-27 19:54:29 +0000962 d0 = c1 = c2 = None
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000963
Guido van Rossumd8faa362007-04-27 19:54:29 +0000964 # What we've set up: d0, c1, and c2 are all trash now. d0 is in
965 # generation 2. The only thing keeping it alive is that c1 points to
966 # it. c1 and c2 are in generation 0, and are in self-loops. There's
967 # a global weakref to c2 (c2wr), but that weakref has no callback.
968 # There are no other weakrefs.
969 #
970 # d0 has a __del__ method that references c2wr
971 # ^
972 # |
973 # | Generation 2 above dots
974 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
975 # | Generation 0 below dots
976 # |
977 # |
978 # ^->c1 ^->c2 has a wr but no callback
979 # | | | |
980 # <--v <--v
981 #
982 # So this is the nightmare: when generation 0 gets collected, we see
983 # that c2 has a callback-free weakref, and c1 doesn't even have a
984 # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
985 # c1 and c2. Clearing c1 has the side effect of dropping the refcount
986 # on d0 to 0, so d0 goes away (despite that it's in an older
987 # generation) and d0's __del__ triggers. That in turn materializes
988 # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
989
990 # We want to let gc happen "naturally", to preserve the distinction
991 # between generations.
992 detector = GC_Detector()
993 junk = []
994 i = 0
995 while not detector.gc_happened:
996 i += 1
997 if i > 10000:
998 self.fail("gc didn't happen after 10000 iterations")
999 self.assertEqual(len(ouch), 0)
1000 junk.append([]) # this will eventually trigger gc
1001
1002 self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
1003 for x in ouch:
1004 # If __del__ resurrected c2, the instance would be damaged, with an
1005 # empty __dict__.
1006 self.assertEqual(x, None)
1007
1008def test_main():
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001009 enabled = gc.isenabled()
1010 gc.disable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001011 assert not gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001012 debug = gc.get_debug()
1013 gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001014
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001015 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001016 gc.collect() # Delete 2nd generation garbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001017 run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001018 finally:
1019 gc.set_debug(debug)
1020 # test gc.enable() even if GC is disabled by default
1021 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001022 print("restoring automatic collection")
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001023 # make sure to always test gc.enable()
1024 gc.enable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001025 assert gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001026 if not enabled:
1027 gc.disable()
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001028
Guido van Rossumd8faa362007-04-27 19:54:29 +00001029if __name__ == "__main__":
1030 test_main()