blob: 2dab53004452aefc7dbb9286af43d95b574827c8 [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,
Serhiy Storchakaa7930372016-07-03 22:27:26 +03003 strip_python_stderr, cpython_only, start_threads,
Victor Stinner626bff82018-10-25 17:31:10 +02004 temp_dir, requires_type_collecting, TESTFN, unlink,
5 import_module)
Berker Peksagce643912015-05-06 06:33:17 +03006from test.support.script_helper import assert_python_ok, make_script
Antoine Pitrou5f454a02013-05-06 21:15:57 +02007
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +00008import gc
Victor Stinner626bff82018-10-25 17:31:10 +02009import sys
10import sysconfig
11import textwrap
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020012import threading
Victor Stinner626bff82018-10-25 17:31:10 +020013import time
14import weakref
Antoine Pitrou2b0218a2012-09-06 00:59:49 +020015
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020016try:
17 from _testcapi import with_tp_del
18except ImportError:
19 def with_tp_del(cls):
20 class C(object):
21 def __new__(cls, *args, **kwargs):
22 raise TypeError('requires _testcapi.with_tp_del')
23 return C
24
Guido van Rossumd8faa362007-04-27 19:54:29 +000025### Support code
26###############################################################################
Tim Peters0f81ab62003-04-08 16:39:48 +000027
Tim Petersead8b7a2004-10-30 23:09:22 +000028# Bug 1055820 has several tests of longstanding bugs involving weakrefs and
29# cyclic gc.
30
31# An instance of C1055820 has a self-loop, so becomes cyclic trash when
32# unreachable.
33class C1055820(object):
34 def __init__(self, i):
35 self.i = i
36 self.loop = self
37
38class GC_Detector(object):
39 # Create an instance I. Then gc hasn't happened again so long as
40 # I.gc_happened is false.
41
42 def __init__(self):
43 self.gc_happened = False
44
45 def it_happened(ignored):
46 self.gc_happened = True
47
48 # Create a piece of cyclic trash that triggers it_happened when
49 # gc collects it.
50 self.wr = weakref.ref(C1055820(666), it_happened)
51
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020052@with_tp_del
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000053class Uncollectable(object):
54 """Create a reference cycle with multiple __del__ methods.
55
56 An object in a reference cycle will never have zero references,
57 and so must be garbage collected. If one or more objects in the
58 cycle have __del__ methods, the gc refuses to guess an order,
59 and leaves the cycle uncollected."""
60 def __init__(self, partner=None):
61 if partner is None:
62 self.partner = Uncollectable(partner=self)
63 else:
64 self.partner = partner
Antoine Pitrou796564c2013-07-30 19:59:21 +020065 def __tp_del__(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +000066 pass
Tim Petersead8b7a2004-10-30 23:09:22 +000067
Victor Stinner626bff82018-10-25 17:31:10 +020068if sysconfig.get_config_vars().get('PY_CFLAGS', ''):
69 BUILD_WITH_NDEBUG = ('-DNDEBUG' in sysconfig.get_config_vars()['PY_CFLAGS'])
70else:
71 # Usually, sys.gettotalrefcount() is only present if Python has been
72 # compiled in debug mode. If it's missing, expect that Python has
73 # been released in release mode: with NDEBUG defined.
74 BUILD_WITH_NDEBUG = (not hasattr(sys, 'gettotalrefcount'))
75
Guido van Rossumd8faa362007-04-27 19:54:29 +000076### Tests
77###############################################################################
Tim Petersead8b7a2004-10-30 23:09:22 +000078
Guido van Rossumd8faa362007-04-27 19:54:29 +000079class GCTests(unittest.TestCase):
80 def test_list(self):
81 l = []
82 l.append(l)
83 gc.collect()
84 del l
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_dict(self):
88 d = {}
89 d[1] = d
90 gc.collect()
91 del d
92 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +000093
Guido van Rossumd8faa362007-04-27 19:54:29 +000094 def test_tuple(self):
95 # since tuples are immutable we close the loop with a list
96 l = []
97 t = (l,)
98 l.append(t)
99 gc.collect()
100 del t
101 del l
102 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000103
Guido van Rossumd8faa362007-04-27 19:54:29 +0000104 def test_class(self):
105 class A:
106 pass
107 A.a = A
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_newstyleclass(self):
113 class A(object):
114 pass
115 gc.collect()
116 del A
117 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000118
Guido van Rossumd8faa362007-04-27 19:54:29 +0000119 def test_instance(self):
120 class A:
121 pass
122 a = A()
123 a.a = a
124 gc.collect()
125 del a
126 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000127
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300128 @requires_type_collecting
Guido van Rossumd8faa362007-04-27 19:54:29 +0000129 def test_newinstance(self):
130 class A(object):
131 pass
132 a = A()
133 a.a = a
134 gc.collect()
135 del a
136 self.assertNotEqual(gc.collect(), 0)
137 class B(list):
138 pass
139 class C(B, A):
140 pass
141 a = C()
142 a.a = a
143 gc.collect()
144 del a
145 self.assertNotEqual(gc.collect(), 0)
146 del B, C
147 self.assertNotEqual(gc.collect(), 0)
148 A.a = A()
149 del A
150 self.assertNotEqual(gc.collect(), 0)
151 self.assertEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000152
Guido van Rossumd8faa362007-04-27 19:54:29 +0000153 def test_method(self):
154 # Tricky: self.__init__ is a bound method, it references the instance.
155 class A:
156 def __init__(self):
157 self.init = self.__init__
158 a = A()
159 gc.collect()
160 del a
161 self.assertNotEqual(gc.collect(), 0)
Tim Petersead8b7a2004-10-30 23:09:22 +0000162
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200163 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200164 def test_legacy_finalizer(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000165 # A() is uncollectable if it is part of a cycle, make sure it shows up
166 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200167 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000168 class A:
Antoine Pitrou796564c2013-07-30 19:59:21 +0200169 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000170 class B:
171 pass
172 a = A()
173 a.a = a
174 id_a = id(a)
175 b = B()
176 b.b = b
177 gc.collect()
178 del a
179 del b
180 self.assertNotEqual(gc.collect(), 0)
181 for obj in gc.garbage:
182 if id(obj) == id_a:
183 del obj.a
184 break
185 else:
186 self.fail("didn't find obj in garbage (finalizer)")
187 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000188
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200189 @cpython_only
Antoine Pitrou796564c2013-07-30 19:59:21 +0200190 def test_legacy_finalizer_newclass(self):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000191 # A() is uncollectable if it is part of a cycle, make sure it shows up
192 # in gc.garbage.
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200193 @with_tp_del
Guido van Rossumd8faa362007-04-27 19:54:29 +0000194 class A(object):
Antoine Pitrou796564c2013-07-30 19:59:21 +0200195 def __tp_del__(self): pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000196 class B(object):
197 pass
198 a = A()
199 a.a = a
200 id_a = id(a)
201 b = B()
202 b.b = b
203 gc.collect()
204 del a
205 del b
206 self.assertNotEqual(gc.collect(), 0)
207 for obj in gc.garbage:
208 if id(obj) == id_a:
209 del obj.a
210 break
211 else:
212 self.fail("didn't find obj in garbage (finalizer)")
213 gc.garbage.remove(obj)
Tim Petersead8b7a2004-10-30 23:09:22 +0000214
Guido van Rossumd8faa362007-04-27 19:54:29 +0000215 def test_function(self):
216 # Tricky: f -> d -> f, code should call d.clear() after the exec to
217 # break the cycle.
218 d = {}
219 exec("def f(): pass\n", d)
220 gc.collect()
221 del d
222 self.assertEqual(gc.collect(), 2)
Tim Petersead8b7a2004-10-30 23:09:22 +0000223
Brett Cannon7a540732011-02-22 03:04:06 +0000224 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000225 def test_frame(self):
226 def f():
227 frame = sys._getframe()
228 gc.collect()
229 f()
230 self.assertEqual(gc.collect(), 1)
Tim Petersead8b7a2004-10-30 23:09:22 +0000231
Guido van Rossumd8faa362007-04-27 19:54:29 +0000232 def test_saveall(self):
233 # Verify that cyclic garbage like lists show up in gc.garbage if the
234 # SAVEALL option is enabled.
Tim Petersead8b7a2004-10-30 23:09:22 +0000235
Guido van Rossumd8faa362007-04-27 19:54:29 +0000236 # First make sure we don't save away other stuff that just happens to
237 # be waiting for collection.
238 gc.collect()
239 # if this fails, someone else created immortal trash
240 self.assertEqual(gc.garbage, [])
241
242 L = []
243 L.append(L)
244 id_L = id(L)
245
246 debug = gc.get_debug()
247 gc.set_debug(debug | gc.DEBUG_SAVEALL)
248 del L
249 gc.collect()
250 gc.set_debug(debug)
251
252 self.assertEqual(len(gc.garbage), 1)
253 obj = gc.garbage.pop()
254 self.assertEqual(id(obj), id_L)
255
256 def test_del(self):
257 # __del__ methods can trigger collection, make this to happen
258 thresholds = gc.get_threshold()
259 gc.enable()
260 gc.set_threshold(1)
261
262 class A:
263 def __del__(self):
264 dir(self)
265 a = A()
266 del a
267
268 gc.disable()
269 gc.set_threshold(*thresholds)
270
271 def test_del_newclass(self):
272 # __del__ methods can trigger collection, make this to happen
273 thresholds = gc.get_threshold()
274 gc.enable()
275 gc.set_threshold(1)
276
277 class A(object):
278 def __del__(self):
279 dir(self)
280 a = A()
281 del a
282
283 gc.disable()
284 gc.set_threshold(*thresholds)
285
Christian Heimesa156e092008-02-16 07:38:31 +0000286 # The following two tests are fragile:
287 # They precisely count the number of allocations,
288 # which is highly implementation-dependent.
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200289 # For example, disposed tuples are not freed, but reused.
290 # To minimize variations, though, we first store the get_count() results
291 # and check them at the end.
Brett Cannon7a540732011-02-22 03:04:06 +0000292 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000293 def test_get_count(self):
294 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200295 a, b, c = gc.get_count()
296 x = []
297 d, e, f = gc.get_count()
298 self.assertEqual((b, c), (0, 0))
299 self.assertEqual((e, f), (0, 0))
300 # This is less fragile than asserting that a equals 0.
301 self.assertLess(a, 5)
302 # Between the two calls to get_count(), at least one object was
303 # created (the list).
304 self.assertGreater(d, a)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000305
Brett Cannon7a540732011-02-22 03:04:06 +0000306 @refcount_test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000307 def test_collect_generations(self):
308 gc.collect()
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200309 # This object will "trickle" into generation N + 1 after
310 # each call to collect(N)
311 x = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000312 gc.collect(0)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200313 # x is now in gen 1
314 a, b, c = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000315 gc.collect(1)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200316 # x is now in gen 2
317 d, e, f = gc.get_count()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000318 gc.collect(2)
Antoine Pitroub35f29a2011-04-04 19:50:42 +0200319 # x is now in gen 3
320 g, h, i = gc.get_count()
321 # We don't check a, d, g since their exact values depends on
322 # internal implementation details of the interpreter.
323 self.assertEqual((b, c), (1, 0))
324 self.assertEqual((e, f), (0, 1))
325 self.assertEqual((h, i), (0, 0))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000326
327 def test_trashcan(self):
328 class Ouch:
329 n = 0
330 def __del__(self):
331 Ouch.n = Ouch.n + 1
332 if Ouch.n % 17 == 0:
333 gc.collect()
334
335 # "trashcan" is a hack to prevent stack overflow when deallocating
336 # very deeply nested tuples etc. It works in part by abusing the
337 # type pointer and refcount fields, and that can yield horrible
338 # problems when gc tries to traverse the structures.
339 # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
340 # most likely die via segfault.
341
342 # Note: In 2.3 the possibility for compiling without cyclic gc was
343 # removed, and that in turn allows the trashcan mechanism to work
344 # via much simpler means (e.g., it never abuses the type pointer or
345 # refcount fields anymore). Since it's much less likely to cause a
346 # problem now, the various constants in this expensive (we force a lot
347 # of full collections) test are cut back from the 2.2 version.
348 gc.enable()
349 N = 150
350 for count in range(2):
351 t = []
352 for i in range(N):
353 t = [t, Ouch()]
354 u = []
355 for i in range(N):
356 u = [u, Ouch()]
357 v = {}
358 for i in range(N):
359 v = {1: v, 2: Ouch()}
360 gc.disable()
361
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200362 def test_trashcan_threads(self):
363 # Issue #13992: trashcan mechanism should be thread-safe
364 NESTING = 60
365 N_THREADS = 2
366
367 def sleeper_gen():
368 """A generator that releases the GIL when closed or dealloc'ed."""
369 try:
370 yield
371 finally:
372 time.sleep(0.000001)
373
374 class C(list):
375 # Appending to a list is atomic, which avoids the use of a lock.
376 inits = []
377 dels = []
378 def __init__(self, alist):
379 self[:] = alist
380 C.inits.append(None)
381 def __del__(self):
382 # This __del__ is called by subtype_dealloc().
383 C.dels.append(None)
384 # `g` will release the GIL when garbage-collected. This
385 # helps assert subtype_dealloc's behaviour when threads
386 # switch in the middle of it.
387 g = sleeper_gen()
388 next(g)
389 # Now that __del__ is finished, subtype_dealloc will proceed
390 # to call list_dealloc, which also uses the trashcan mechanism.
391
392 def make_nested():
393 """Create a sufficiently nested container object so that the
394 trashcan mechanism is invoked when deallocating it."""
395 x = C([])
396 for i in range(NESTING):
397 x = [C([x])]
398 del x
399
400 def run_thread():
401 """Exercise make_nested() in a loop."""
402 while not exit:
403 make_nested()
404
405 old_switchinterval = sys.getswitchinterval()
406 sys.setswitchinterval(1e-5)
407 try:
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300408 exit = []
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200409 threads = []
410 for i in range(N_THREADS):
411 t = threading.Thread(target=run_thread)
412 threads.append(t)
Serhiy Storchaka263dcd22015-04-01 13:01:14 +0300413 with start_threads(threads, lambda: exit.append(1)):
Serhiy Storchaka9db55002015-03-28 20:38:37 +0200414 time.sleep(1.0)
Antoine Pitrou2b0218a2012-09-06 00:59:49 +0200415 finally:
416 sys.setswitchinterval(old_switchinterval)
417 gc.collect()
418 self.assertEqual(len(C.inits), len(C.dels))
419
Guido van Rossumd8faa362007-04-27 19:54:29 +0000420 def test_boom(self):
421 class Boom:
422 def __getattr__(self, someattribute):
423 del self.attr
424 raise AttributeError
425
426 a = Boom()
427 b = Boom()
428 a.attr = b
429 b.attr = a
430
431 gc.collect()
432 garbagelen = len(gc.garbage)
433 del a, b
434 # a<->b are in a trash cycle now. Collection will invoke
435 # Boom.__getattr__ (to see whether a and b have __del__ methods), and
436 # __getattr__ deletes the internal "attr" attributes as a side effect.
437 # That causes the trash cycle to get reclaimed via refcounts falling to
438 # 0, thus mutating the trash graph as a side effect of merely asking
439 # whether __del__ exists. This used to (before 2.3b1) crash Python.
440 # Now __getattr__ isn't called.
441 self.assertEqual(gc.collect(), 4)
442 self.assertEqual(len(gc.garbage), garbagelen)
443
444 def test_boom2(self):
445 class Boom2:
446 def __init__(self):
447 self.x = 0
448
449 def __getattr__(self, someattribute):
450 self.x += 1
451 if self.x > 1:
452 del self.attr
453 raise AttributeError
454
455 a = Boom2()
456 b = Boom2()
457 a.attr = b
458 b.attr = a
459
460 gc.collect()
461 garbagelen = len(gc.garbage)
462 del a, b
463 # Much like test_boom(), except that __getattr__ doesn't break the
464 # cycle until the second time gc checks for __del__. As of 2.3b1,
465 # there isn't a second time, so this simply cleans up the trash cycle.
466 # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
467 # reclaimed this way.
468 self.assertEqual(gc.collect(), 4)
469 self.assertEqual(len(gc.garbage), garbagelen)
470
471 def test_boom_new(self):
472 # boom__new and boom2_new are exactly like boom and boom2, except use
473 # new-style classes.
474
475 class Boom_New(object):
476 def __getattr__(self, someattribute):
477 del self.attr
478 raise AttributeError
479
480 a = Boom_New()
481 b = Boom_New()
482 a.attr = b
483 b.attr = a
484
485 gc.collect()
486 garbagelen = len(gc.garbage)
487 del a, b
488 self.assertEqual(gc.collect(), 4)
489 self.assertEqual(len(gc.garbage), garbagelen)
490
491 def test_boom2_new(self):
492 class Boom2_New(object):
493 def __init__(self):
494 self.x = 0
495
496 def __getattr__(self, someattribute):
497 self.x += 1
498 if self.x > 1:
499 del self.attr
500 raise AttributeError
501
502 a = Boom2_New()
503 b = Boom2_New()
504 a.attr = b
505 b.attr = a
506
507 gc.collect()
508 garbagelen = len(gc.garbage)
509 del a, b
510 self.assertEqual(gc.collect(), 4)
511 self.assertEqual(len(gc.garbage), garbagelen)
512
513 def test_get_referents(self):
514 alist = [1, 3, 5]
515 got = gc.get_referents(alist)
516 got.sort()
517 self.assertEqual(got, alist)
518
519 atuple = tuple(alist)
520 got = gc.get_referents(atuple)
521 got.sort()
522 self.assertEqual(got, alist)
523
524 adict = {1: 3, 5: 7}
525 expected = [1, 3, 5, 7]
526 got = gc.get_referents(adict)
527 got.sort()
528 self.assertEqual(got, expected)
529
530 got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
531 got.sort()
Guido van Rossum805365e2007-05-07 22:24:25 +0000532 self.assertEqual(got, [0, 0] + list(range(5)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000533
534 self.assertEqual(gc.get_referents(1, 'a', 4j), [])
535
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000536 def test_is_tracked(self):
537 # Atomic built-in types are not tracked, user-defined objects and
538 # mutable containers are.
539 # NOTE: types with special optimizations (e.g. tuple) have tests
540 # in their own test files instead.
541 self.assertFalse(gc.is_tracked(None))
542 self.assertFalse(gc.is_tracked(1))
543 self.assertFalse(gc.is_tracked(1.0))
544 self.assertFalse(gc.is_tracked(1.0 + 5.0j))
545 self.assertFalse(gc.is_tracked(True))
546 self.assertFalse(gc.is_tracked(False))
547 self.assertFalse(gc.is_tracked(b"a"))
548 self.assertFalse(gc.is_tracked("a"))
549 self.assertFalse(gc.is_tracked(bytearray(b"a")))
550 self.assertFalse(gc.is_tracked(type))
551 self.assertFalse(gc.is_tracked(int))
552 self.assertFalse(gc.is_tracked(object))
553 self.assertFalse(gc.is_tracked(object()))
554
555 class UserClass:
556 pass
Antoine Pitroua63cc212015-04-13 20:10:06 +0200557
558 class UserInt(int):
559 pass
560
561 # Base class is object; no extra fields.
562 class UserClassSlots:
563 __slots__ = ()
564
565 # Base class is fixed size larger than object; no extra fields.
566 class UserFloatSlots(float):
567 __slots__ = ()
568
569 # Base class is variable size; no extra fields.
570 class UserIntSlots(int):
571 __slots__ = ()
572
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000573 self.assertTrue(gc.is_tracked(gc))
574 self.assertTrue(gc.is_tracked(UserClass))
575 self.assertTrue(gc.is_tracked(UserClass()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200576 self.assertTrue(gc.is_tracked(UserInt()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000577 self.assertTrue(gc.is_tracked([]))
578 self.assertTrue(gc.is_tracked(set()))
Antoine Pitroua63cc212015-04-13 20:10:06 +0200579 self.assertFalse(gc.is_tracked(UserClassSlots()))
580 self.assertFalse(gc.is_tracked(UserFloatSlots()))
581 self.assertFalse(gc.is_tracked(UserIntSlots()))
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000582
Guido van Rossumd8faa362007-04-27 19:54:29 +0000583 def test_bug1055820b(self):
584 # Corresponds to temp2b.py in the bug report.
585
586 ouch = []
587 def callback(ignored):
588 ouch[:] = [wr() for wr in WRs]
589
590 Cs = [C1055820(i) for i in range(2)]
591 WRs = [weakref.ref(c, callback) for c in Cs]
592 c = None
593
594 gc.collect()
595 self.assertEqual(len(ouch), 0)
596 # Make the two instances trash, and collect again. The bug was that
597 # the callback materialized a strong reference to an instance, but gc
598 # cleared the instance's dict anyway.
599 Cs = None
600 gc.collect()
601 self.assertEqual(len(ouch), 2) # else the callbacks didn't run
602 for x in ouch:
603 # If the callback resurrected one of these guys, the instance
604 # would be damaged, with an empty __dict__.
605 self.assertEqual(x, None)
606
Tim Peters5fbc7b12014-05-08 17:42:19 -0500607 def test_bug21435(self):
608 # This is a poor test - its only virtue is that it happened to
609 # segfault on Tim's Windows box before the patch for 21435 was
610 # applied. That's a nasty bug relying on specific pieces of cyclic
611 # trash appearing in exactly the right order in finalize_garbage()'s
612 # input list.
613 # But there's no reliable way to force that order from Python code,
614 # so over time chances are good this test won't really be testing much
615 # of anything anymore. Still, if it blows up, there's _some_
616 # problem ;-)
617 gc.collect()
618
619 class A:
620 pass
621
622 class B:
623 def __init__(self, x):
624 self.x = x
625
626 def __del__(self):
627 self.attr = None
628
629 def do_work():
630 a = A()
631 b = B(A())
632
633 a.attr = b
634 b.attr = a
635
636 do_work()
637 gc.collect() # this blows up (bad C pointer) when it fails
638
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200639 @cpython_only
Antoine Pitrou696e0352010-08-08 22:18:46 +0000640 def test_garbage_at_shutdown(self):
641 import subprocess
642 code = """if 1:
643 import gc
Antoine Pitrou796564c2013-07-30 19:59:21 +0200644 import _testcapi
645 @_testcapi.with_tp_del
Antoine Pitrou696e0352010-08-08 22:18:46 +0000646 class X:
647 def __init__(self, name):
648 self.name = name
649 def __repr__(self):
650 return "<X %%r>" %% self.name
Antoine Pitrou796564c2013-07-30 19:59:21 +0200651 def __tp_del__(self):
Antoine Pitrou696e0352010-08-08 22:18:46 +0000652 pass
653
654 x = X('first')
655 x.x = x
656 x.y = X('second')
657 del x
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000658 gc.set_debug(%s)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000659 """
660 def run_command(code):
Georg Brandl08be72d2010-10-24 15:11:22 +0000661 p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
Antoine Pitrou696e0352010-08-08 22:18:46 +0000662 stdout=subprocess.PIPE,
663 stderr=subprocess.PIPE)
664 stdout, stderr = p.communicate()
Brian Curtin8291af22010-11-01 16:40:17 +0000665 p.stdout.close()
666 p.stderr.close()
Antoine Pitrou696e0352010-08-08 22:18:46 +0000667 self.assertEqual(p.returncode, 0)
668 self.assertEqual(stdout.strip(), b"")
669 return strip_python_stderr(stderr)
670
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000671 stderr = run_command(code % "0")
Georg Brandl08be72d2010-10-24 15:11:22 +0000672 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
673 b"shutdown; use", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000674 self.assertNotIn(b"<X 'first'>", stderr)
Antoine Pitrou696e0352010-08-08 22:18:46 +0000675 # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000676 stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
Georg Brandl08be72d2010-10-24 15:11:22 +0000677 self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
678 b"shutdown", stderr)
Antoine Pitrouaee47562010-09-16 15:04:49 +0000679 self.assertTrue(
680 (b"[<X 'first'>, <X 'second'>]" in stderr) or
681 (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
Antoine Pitrou2ed94eb2010-09-14 09:48:39 +0000682 # With DEBUG_SAVEALL, no additional message should get printed
683 # (because gc.garbage also contains normally reclaimable cyclic
684 # references, and its elements get printed at runtime anyway).
685 stderr = run_command(code % "gc.DEBUG_SAVEALL")
686 self.assertNotIn(b"uncollectable objects at shutdown", stderr)
687
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300688 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200689 def test_gc_main_module_at_shutdown(self):
690 # Create a reference cycle through the __main__ module and check
691 # it gets collected at interpreter shutdown.
692 code = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200693 class C:
694 def __del__(self):
695 print('__del__ called')
696 l = [C()]
697 l.append(l)
698 """
699 rc, out, err = assert_python_ok('-c', code)
700 self.assertEqual(out.strip(), b'__del__ called')
701
Serhiy Storchakaa7930372016-07-03 22:27:26 +0300702 @requires_type_collecting
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200703 def test_gc_ordinary_module_at_shutdown(self):
704 # Same as above, but with a non-__main__ module.
705 with temp_dir() as script_dir:
706 module = """if 1:
Antoine Pitrou5f454a02013-05-06 21:15:57 +0200707 class C:
708 def __del__(self):
709 print('__del__ called')
710 l = [C()]
711 l.append(l)
712 """
713 code = """if 1:
714 import sys
715 sys.path.insert(0, %r)
716 import gctest
717 """ % (script_dir,)
718 make_script(script_dir, 'gctest', module)
719 rc, out, err = assert_python_ok('-c', code)
720 self.assertEqual(out.strip(), b'__del__ called')
721
Zackery Spytzd8cba5d2018-07-03 13:47:22 -0600722 @requires_type_collecting
723 def test_global_del_SystemExit(self):
724 code = """if 1:
725 class ClassWithDel:
726 def __del__(self):
727 print('__del__ called')
728 a = ClassWithDel()
729 a.link = a
730 raise SystemExit(0)"""
731 self.addCleanup(unlink, TESTFN)
732 with open(TESTFN, 'w') as script:
733 script.write(code)
734 rc, out, err = assert_python_ok(TESTFN)
735 self.assertEqual(out.strip(), b'__del__ called')
736
Antoine Pitroud4156c12012-10-30 22:43:19 +0100737 def test_get_stats(self):
738 stats = gc.get_stats()
739 self.assertEqual(len(stats), 3)
740 for st in stats:
741 self.assertIsInstance(st, dict)
742 self.assertEqual(set(st),
743 {"collected", "collections", "uncollectable"})
744 self.assertGreaterEqual(st["collected"], 0)
745 self.assertGreaterEqual(st["collections"], 0)
746 self.assertGreaterEqual(st["uncollectable"], 0)
747 # Check that collection counts are incremented correctly
748 if gc.isenabled():
749 self.addCleanup(gc.enable)
750 gc.disable()
751 old = gc.get_stats()
752 gc.collect(0)
753 new = gc.get_stats()
754 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
755 self.assertEqual(new[1]["collections"], old[1]["collections"])
756 self.assertEqual(new[2]["collections"], old[2]["collections"])
757 gc.collect(2)
758 new = gc.get_stats()
759 self.assertEqual(new[0]["collections"], old[0]["collections"] + 1)
760 self.assertEqual(new[1]["collections"], old[1]["collections"])
761 self.assertEqual(new[2]["collections"], old[2]["collections"] + 1)
762
brainfvckc75edab2017-10-16 12:49:41 -0700763 def test_freeze(self):
764 gc.freeze()
765 self.assertGreater(gc.get_freeze_count(), 0)
766 gc.unfreeze()
767 self.assertEqual(gc.get_freeze_count(), 0)
768
Pablo Galindo175421b2019-02-23 03:02:06 +0000769 def test_get_objects(self):
770 gc.collect()
771 l = []
772 l.append(l)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800773 self.assertTrue(
774 any(l is element for element in gc.get_objects(generation=0))
775 )
776 self.assertFalse(
777 any(l is element for element in gc.get_objects(generation=1))
778 )
779 self.assertFalse(
780 any(l is element for element in gc.get_objects(generation=2))
781 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000782 gc.collect(generation=0)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800783 self.assertFalse(
784 any(l is element for element in gc.get_objects(generation=0))
785 )
786 self.assertTrue(
787 any(l is element for element in gc.get_objects(generation=1))
788 )
789 self.assertFalse(
790 any(l is element for element in gc.get_objects(generation=2))
791 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000792 gc.collect(generation=1)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800793 self.assertFalse(
794 any(l is element for element in gc.get_objects(generation=0))
795 )
796 self.assertFalse(
797 any(l is element for element in gc.get_objects(generation=1))
798 )
799 self.assertTrue(
800 any(l is element for element in gc.get_objects(generation=2))
801 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000802 gc.collect(generation=2)
Pablo Galindod60a79a2019-03-01 01:12:27 -0800803 self.assertFalse(
804 any(l is element for element in gc.get_objects(generation=0))
805 )
806 self.assertFalse(
807 any(l is element for element in gc.get_objects(generation=1))
808 )
809 self.assertTrue(
810 any(l is element for element in gc.get_objects(generation=2))
811 )
Pablo Galindo175421b2019-02-23 03:02:06 +0000812 del l
813 gc.collect()
814
815 def test_get_objects_arguments(self):
816 gc.collect()
817 self.assertEqual(len(gc.get_objects()),
818 len(gc.get_objects(generation=None)))
819
820 self.assertRaises(ValueError, gc.get_objects, 1000)
821 self.assertRaises(ValueError, gc.get_objects, -1000)
822 self.assertRaises(TypeError, gc.get_objects, "1")
823 self.assertRaises(TypeError, gc.get_objects, 1.234)
824
Antoine Pitrou696e0352010-08-08 22:18:46 +0000825
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000826class GCCallbackTests(unittest.TestCase):
827 def setUp(self):
828 # Save gc state and disable it.
829 self.enabled = gc.isenabled()
830 gc.disable()
831 self.debug = gc.get_debug()
832 gc.set_debug(0)
833 gc.callbacks.append(self.cb1)
834 gc.callbacks.append(self.cb2)
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200835 self.othergarbage = []
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000836
837 def tearDown(self):
838 # Restore gc state
839 del self.visit
840 gc.callbacks.remove(self.cb1)
841 gc.callbacks.remove(self.cb2)
842 gc.set_debug(self.debug)
843 if self.enabled:
844 gc.enable()
845 # destroy any uncollectables
846 gc.collect()
847 for obj in gc.garbage:
848 if isinstance(obj, Uncollectable):
849 obj.partner = None
850 del gc.garbage[:]
Antoine Pitrou6b64fc62012-04-16 21:29:02 +0200851 del self.othergarbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000852 gc.collect()
853
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000854 def preclean(self):
855 # Remove all fluff from the system. Invoke this function
856 # manually rather than through self.setUp() for maximum
857 # safety.
858 self.visit = []
859 gc.collect()
860 garbage, gc.garbage[:] = gc.garbage[:], []
861 self.othergarbage.append(garbage)
862 self.visit = []
863
864 def cb1(self, phase, info):
865 self.visit.append((1, phase, dict(info)))
866
867 def cb2(self, phase, info):
868 self.visit.append((2, phase, dict(info)))
869 if phase == "stop" and hasattr(self, "cleanup"):
870 # Clean Uncollectable from garbage
871 uc = [e for e in gc.garbage if isinstance(e, Uncollectable)]
872 gc.garbage[:] = [e for e in gc.garbage
873 if not isinstance(e, Uncollectable)]
874 for e in uc:
875 e.partner = None
876
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200877 def test_collect(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000878 self.preclean()
879 gc.collect()
880 # Algorithmically verify the contents of self.visit
881 # because it is long and tortuous.
882
883 # Count the number of visits to each callback
884 n = [v[0] for v in self.visit]
885 n1 = [i for i in n if i == 1]
886 n2 = [i for i in n if i == 2]
887 self.assertEqual(n1, [1]*2)
888 self.assertEqual(n2, [2]*2)
889
890 # Count that we got the right number of start and stop callbacks.
891 n = [v[1] for v in self.visit]
892 n1 = [i for i in n if i == "start"]
893 n2 = [i for i in n if i == "stop"]
894 self.assertEqual(n1, ["start"]*2)
895 self.assertEqual(n2, ["stop"]*2)
896
897 # Check that we got the right info dict for all callbacks
898 for v in self.visit:
899 info = v[2]
900 self.assertTrue("generation" in info)
901 self.assertTrue("collected" in info)
902 self.assertTrue("uncollectable" in info)
903
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200904 def test_collect_generation(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000905 self.preclean()
906 gc.collect(2)
907 for v in self.visit:
908 info = v[2]
909 self.assertEqual(info["generation"], 2)
910
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200911 @cpython_only
Antoine Pitroude3c73b2012-04-16 21:29:58 +0200912 def test_collect_garbage(self):
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +0000913 self.preclean()
914 # Each of these cause four objects to be garbage: Two
915 # Uncolectables and their instance dicts.
916 Uncollectable()
917 Uncollectable()
918 C1055820(666)
919 gc.collect()
920 for v in self.visit:
921 if v[1] != "stop":
922 continue
923 info = v[2]
924 self.assertEqual(info["collected"], 2)
925 self.assertEqual(info["uncollectable"], 8)
926
927 # We should now have the Uncollectables in gc.garbage
928 self.assertEqual(len(gc.garbage), 4)
929 for e in gc.garbage:
930 self.assertIsInstance(e, Uncollectable)
931
932 # Now, let our callback handle the Uncollectable instances
933 self.cleanup=True
934 self.visit = []
935 gc.garbage[:] = []
936 gc.collect()
937 for v in self.visit:
938 if v[1] != "stop":
939 continue
940 info = v[2]
941 self.assertEqual(info["collected"], 0)
942 self.assertEqual(info["uncollectable"], 4)
943
944 # Uncollectables should be gone
945 self.assertEqual(len(gc.garbage), 0)
946
947
Victor Stinner626bff82018-10-25 17:31:10 +0200948 @unittest.skipIf(BUILD_WITH_NDEBUG,
949 'built with -NDEBUG')
950 def test_refcount_errors(self):
951 self.preclean()
952 # Verify the "handling" of objects with broken refcounts
953
954 # Skip the test if ctypes is not available
955 import_module("ctypes")
956
957 import subprocess
958 code = textwrap.dedent('''
959 from test.support import gc_collect, SuppressCrashReport
960
961 a = [1, 2, 3]
962 b = [a]
963
964 # Avoid coredump when Py_FatalError() calls abort()
965 SuppressCrashReport().__enter__()
966
967 # Simulate the refcount of "a" being too low (compared to the
968 # references held on it by live data), but keeping it above zero
969 # (to avoid deallocating it):
970 import ctypes
971 ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
972
973 # The garbage collector should now have a fatal error
974 # when it reaches the broken object
975 gc_collect()
976 ''')
977 p = subprocess.Popen([sys.executable, "-c", code],
978 stdout=subprocess.PIPE,
979 stderr=subprocess.PIPE)
980 stdout, stderr = p.communicate()
981 p.stdout.close()
982 p.stderr.close()
983 # Verify that stderr has a useful error message:
984 self.assertRegex(stderr,
985 br'gcmodule\.c:[0-9]+: gc_decref: Assertion "gc_get_refs\(g\) > 0" failed.')
986 self.assertRegex(stderr,
987 br'refcount is too small')
988 self.assertRegex(stderr,
989 br'object : \[1, 2, 3\]')
990 self.assertRegex(stderr,
991 br'type : list')
992 self.assertRegex(stderr,
993 br'refcount: 1')
994 # "address : 0x7fb5062efc18"
995 # "address : 7FB5062EFC18"
996 self.assertRegex(stderr,
997 br'address : [0-9a-fA-Fx]+')
998
999
Guido van Rossumd8faa362007-04-27 19:54:29 +00001000class GCTogglingTests(unittest.TestCase):
1001 def setUp(self):
1002 gc.enable()
1003
1004 def tearDown(self):
1005 gc.disable()
1006
1007 def test_bug1055820c(self):
1008 # Corresponds to temp2c.py in the bug report. This is pretty
1009 # elaborate.
1010
1011 c0 = C1055820(0)
1012 # Move c0 into generation 2.
1013 gc.collect()
1014
1015 c1 = C1055820(1)
1016 c1.keep_c0_alive = c0
1017 del c0.loop # now only c1 keeps c0 alive
1018
1019 c2 = C1055820(2)
1020 c2wr = weakref.ref(c2) # no callback!
1021
1022 ouch = []
1023 def callback(ignored):
Tim Petersead8b7a2004-10-30 23:09:22 +00001024 ouch[:] = [c2wr()]
1025
Guido van Rossumd8faa362007-04-27 19:54:29 +00001026 # The callback gets associated with a wr on an object in generation 2.
1027 c0wr = weakref.ref(c0, callback)
Tim Petersead8b7a2004-10-30 23:09:22 +00001028
Guido van Rossumd8faa362007-04-27 19:54:29 +00001029 c0 = c1 = c2 = None
Tim Petersead8b7a2004-10-30 23:09:22 +00001030
Guido van Rossumd8faa362007-04-27 19:54:29 +00001031 # What we've set up: c0, c1, and c2 are all trash now. c0 is in
1032 # generation 2. The only thing keeping it alive is that c1 points to
1033 # it. c1 and c2 are in generation 0, and are in self-loops. There's a
1034 # global weakref to c2 (c2wr), but that weakref has no callback.
1035 # There's also a global weakref to c0 (c0wr), and that does have a
1036 # callback, and that callback references c2 via c2wr().
1037 #
1038 # c0 has a wr with callback, which references c2wr
1039 # ^
1040 # |
1041 # | Generation 2 above dots
1042 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1043 # | Generation 0 below dots
1044 # |
1045 # |
1046 # ^->c1 ^->c2 has a wr but no callback
1047 # | | | |
1048 # <--v <--v
1049 #
1050 # So this is the nightmare: when generation 0 gets collected, we see
1051 # that c2 has a callback-free weakref, and c1 doesn't even have a
1052 # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is
1053 # the only object that has a weakref with a callback. gc clears c1
1054 # and c2. Clearing c1 has the side effect of dropping the refcount on
1055 # c0 to 0, so c0 goes away (despite that it's in an older generation)
1056 # and c0's wr callback triggers. That in turn materializes a reference
1057 # to c2 via c2wr(), but c2 gets cleared anyway by gc.
Tim Petersead8b7a2004-10-30 23:09:22 +00001058
Guido van Rossumd8faa362007-04-27 19:54:29 +00001059 # We want to let gc happen "naturally", to preserve the distinction
1060 # between generations.
1061 junk = []
1062 i = 0
1063 detector = GC_Detector()
1064 while not detector.gc_happened:
1065 i += 1
1066 if i > 10000:
1067 self.fail("gc didn't happen after 10000 iterations")
1068 self.assertEqual(len(ouch), 0)
1069 junk.append([]) # this will eventually trigger gc
Tim Petersead8b7a2004-10-30 23:09:22 +00001070
Guido van Rossumd8faa362007-04-27 19:54:29 +00001071 self.assertEqual(len(ouch), 1) # else the callback wasn't invoked
1072 for x in ouch:
1073 # If the callback resurrected c2, the instance would be damaged,
1074 # with an empty __dict__.
1075 self.assertEqual(x, None)
Tim Petersead8b7a2004-10-30 23:09:22 +00001076
Guido van Rossumd8faa362007-04-27 19:54:29 +00001077 def test_bug1055820d(self):
1078 # Corresponds to temp2d.py in the bug report. This is very much like
1079 # test_bug1055820c, but uses a __del__ method instead of a weakref
1080 # callback to sneak in a resurrection of cyclic trash.
Tim Petersead8b7a2004-10-30 23:09:22 +00001081
Guido van Rossumd8faa362007-04-27 19:54:29 +00001082 ouch = []
1083 class D(C1055820):
1084 def __del__(self):
1085 ouch[:] = [c2wr()]
Tim Petersead8b7a2004-10-30 23:09:22 +00001086
Guido van Rossumd8faa362007-04-27 19:54:29 +00001087 d0 = D(0)
1088 # Move all the above into generation 2.
1089 gc.collect()
Tim Petersead8b7a2004-10-30 23:09:22 +00001090
Guido van Rossumd8faa362007-04-27 19:54:29 +00001091 c1 = C1055820(1)
1092 c1.keep_d0_alive = d0
1093 del d0.loop # now only c1 keeps d0 alive
Tim Petersead8b7a2004-10-30 23:09:22 +00001094
Guido van Rossumd8faa362007-04-27 19:54:29 +00001095 c2 = C1055820(2)
1096 c2wr = weakref.ref(c2) # no callback!
Tim Petersead8b7a2004-10-30 23:09:22 +00001097
Guido van Rossumd8faa362007-04-27 19:54:29 +00001098 d0 = c1 = c2 = None
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001099
Guido van Rossumd8faa362007-04-27 19:54:29 +00001100 # What we've set up: d0, c1, and c2 are all trash now. d0 is in
1101 # generation 2. The only thing keeping it alive is that c1 points to
1102 # it. c1 and c2 are in generation 0, and are in self-loops. There's
1103 # a global weakref to c2 (c2wr), but that weakref has no callback.
1104 # There are no other weakrefs.
1105 #
1106 # d0 has a __del__ method that references c2wr
1107 # ^
1108 # |
1109 # | Generation 2 above dots
1110 #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . .
1111 # | Generation 0 below dots
1112 # |
1113 # |
1114 # ^->c1 ^->c2 has a wr but no callback
1115 # | | | |
1116 # <--v <--v
1117 #
1118 # So this is the nightmare: when generation 0 gets collected, we see
1119 # that c2 has a callback-free weakref, and c1 doesn't even have a
1120 # weakref. Collecting generation 0 doesn't see d0 at all. gc clears
1121 # c1 and c2. Clearing c1 has the side effect of dropping the refcount
1122 # on d0 to 0, so d0 goes away (despite that it's in an older
1123 # generation) and d0's __del__ triggers. That in turn materializes
1124 # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc.
1125
1126 # We want to let gc happen "naturally", to preserve the distinction
1127 # between generations.
1128 detector = GC_Detector()
1129 junk = []
1130 i = 0
1131 while not detector.gc_happened:
1132 i += 1
1133 if i > 10000:
1134 self.fail("gc didn't happen after 10000 iterations")
1135 self.assertEqual(len(ouch), 0)
1136 junk.append([]) # this will eventually trigger gc
1137
1138 self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked
1139 for x in ouch:
1140 # If __del__ resurrected c2, the instance would be damaged, with an
1141 # empty __dict__.
1142 self.assertEqual(x, None)
1143
1144def test_main():
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001145 enabled = gc.isenabled()
1146 gc.disable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001147 assert not gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001148 debug = gc.get_debug()
1149 gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001150
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001151 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001152 gc.collect() # Delete 2nd generation garbage
Kristján Valur Jónsson69c63522012-04-15 11:41:32 +00001153 run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001154 finally:
1155 gc.set_debug(debug)
1156 # test gc.enable() even if GC is disabled by default
1157 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001158 print("restoring automatic collection")
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001159 # make sure to always test gc.enable()
1160 gc.enable()
Guido van Rossumd8faa362007-04-27 19:54:29 +00001161 assert gc.isenabled()
Neil Schemenauerfaae2662000-09-22 15:26:20 +00001162 if not enabled:
1163 gc.disable()
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +00001164
Guido van Rossumd8faa362007-04-27 19:54:29 +00001165if __name__ == "__main__":
1166 test_main()