10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport unittest 20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.test_support import verbose, run_unittest 30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys 40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport time 50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport gc 60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport weakref 70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitry: 90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import threading 100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiexcept ImportError: 110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi threading = None 120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi### Support code 140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi############################################################################### 150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Bug 1055820 has several tests of longstanding bugs involving weakrefs and 170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# cyclic gc. 180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# An instance of C1055820 has a self-loop, so becomes cyclic trash when 200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# unreachable. 210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass C1055820(object): 220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self, i): 230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.i = i 240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.loop = self 250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass GC_Detector(object): 270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Create an instance I. Then gc hasn't happened again so long as 280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # I.gc_happened is false. 290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self): 310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.gc_happened = False 320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def it_happened(ignored): 340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.gc_happened = True 350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Create a piece of cyclic trash that triggers it_happened when 370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # gc collects it. 380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.wr = weakref.ref(C1055820(666), it_happened) 390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi### Tests 420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi############################################################################### 430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass GCTests(unittest.TestCase): 450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_list(self): 460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi l = [] 470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi l.append(l) 480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del l 500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 1) 510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_dict(self): 530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi d = {} 540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi d[1] = d 550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del d 570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 1) 580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_tuple(self): 600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # since tuples are immutable we close the loop with a list 610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi l = [] 620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = (l,) 630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi l.append(t) 640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del t 660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del l 670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 2) 680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_class(self): 700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A: 710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi A.a = A 730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del A 750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_newstyleclass(self): 780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A(object): 790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del A 820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_instance(self): 850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A: 860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.a = a 890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_newinstance(self): 940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A(object): 950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.a = a 980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class B(list): 1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class C(B, A): 1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = C() 1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.a = a 1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del B, C 1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi A.a = A() 1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del A 1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 0) 1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_method(self): 1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Tricky: self.__init__ is a bound method, it references the instance. 1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A: 1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self): 1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.init = self.__init__ 1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_finalizer(self): 1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # A() is uncollectable if it is part of a cycle, make sure it shows up 1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # in gc.garbage. 1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A: 1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): pass 1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class B: 1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.a = a 1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi id_a = id(a) 1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = B() 1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.b = b 1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del b 1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for obj in gc.garbage: 1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if id(obj) == id_a: 1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del obj.a 1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi break 1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.fail("didn't find obj in garbage (finalizer)") 1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.garbage.remove(obj) 1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_finalizer_newclass(self): 1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # A() is uncollectable if it is part of a cycle, make sure it shows up 1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # in gc.garbage. 1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A(object): 1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): pass 1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class B(object): 1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.a = a 1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi id_a = id(a) 1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = B() 1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.b = b 1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del b 1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertNotEqual(gc.collect(), 0) 1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for obj in gc.garbage: 1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if id(obj) == id_a: 1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del obj.a 1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi break 1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.fail("didn't find obj in garbage (finalizer)") 1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.garbage.remove(obj) 1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_function(self): 1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Tricky: f -> d -> f, code should call d.clear() after the exec to 1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # break the cycle. 1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi d = {} 1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi exec("def f(): pass\n") in d 1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del d 1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 2) 1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_frame(self): 1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def f(): 1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi frame = sys._getframe() 1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi f() 1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 1) 1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_saveall(self): 1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Verify that cyclic garbage like lists show up in gc.garbage if the 1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # SAVEALL option is enabled. 1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # First make sure we don't save away other stuff that just happens to 1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # be waiting for collection. 1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # if this fails, someone else created immortal trash 1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.garbage, []) 2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi L = [] 2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi L.append(L) 2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi id_L = id(L) 2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi debug = gc.get_debug() 2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_debug(debug | gc.DEBUG_SAVEALL) 2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del L 2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_debug(debug) 2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(gc.garbage), 1) 2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi obj = gc.garbage.pop() 2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(id(obj), id_L) 2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_del(self): 2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # __del__ methods can trigger collection, make this to happen 2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi thresholds = gc.get_threshold() 2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.enable() 2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_threshold(1) 2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A: 2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): 2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir(self) 2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_threshold(*thresholds) 2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_del_newclass(self): 2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # __del__ methods can trigger collection, make this to happen 2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi thresholds = gc.get_threshold() 2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.enable() 2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_threshold(1) 2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class A(object): 2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): 2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dir(self) 2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = A() 2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a 2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_threshold(*thresholds) 2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The following two tests are fragile: 2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # They precisely count the number of allocations, 2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # which is highly implementation-dependent. 2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # For example: 2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # - disposed tuples are not freed, but reused 2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # - the call to assertEqual somehow avoids building its args tuple 2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_count(self): 2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Avoid future allocation of method object 2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual = self._baseAssertEqual 2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual(gc.get_count(), (0, 0, 0)) 2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = dict() 2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # since gc.collect(), we created two objects: 2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # the dict, and the tuple returned by get_count() 2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual(gc.get_count(), (2, 0, 0)) 2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_collect_generations(self): 2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Avoid future allocation of method object 2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual = self.assertEqual 2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = dict() 2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect(0) 2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual(gc.get_count(), (0, 1, 0)) 2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect(1) 2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual(gc.get_count(), (0, 0, 1)) 2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect(2) 2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assertEqual(gc.get_count(), (0, 0, 0)) 2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_trashcan(self): 2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class Ouch: 2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi n = 0 2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): 2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Ouch.n = Ouch.n + 1 2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if Ouch.n % 17 == 0: 2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # "trashcan" is a hack to prevent stack overflow when deallocating 2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # very deeply nested tuples etc. It works in part by abusing the 2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # type pointer and refcount fields, and that can yield horrible 2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # problems when gc tries to traverse the structures. 2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # If this test fails (as it does in 2.0, 2.1 and 2.2), it will 2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # most likely die via segfault. 2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Note: In 2.3 the possibility for compiling without cyclic gc was 2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # removed, and that in turn allows the trashcan mechanism to work 2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # via much simpler means (e.g., it never abuses the type pointer or 2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # refcount fields anymore). Since it's much less likely to cause a 2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # problem now, the various constants in this expensive (we force a lot 2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # of full collections) test are cut back from the 2.2 version. 2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.enable() 2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi N = 150 2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for count in range(2): 2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = [] 2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for i in range(N): 2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = [t, Ouch()] 3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi u = [] 3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for i in range(N): 3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi u = [u, Ouch()] 3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi v = {} 3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for i in range(N): 3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi v = {1: v, 2: Ouch()} 3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi @unittest.skipUnless(threading, "test meaningless on builds without threads") 3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_trashcan_threads(self): 3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Issue #13992: trashcan mechanism should be thread-safe 3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi NESTING = 60 3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi N_THREADS = 2 3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def sleeper_gen(): 3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """A generator that releases the GIL when closed or dealloc'ed.""" 3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi yield 3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.sleep(0.000001) 3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class C(list): 3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Appending to a list is atomic, which avoids the use of a lock. 3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi inits = [] 3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dels = [] 3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self, alist): 3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self[:] = alist 3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi C.inits.append(None) 3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): 3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This __del__ is called by subtype_dealloc(). 3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi C.dels.append(None) 3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # `g` will release the GIL when garbage-collected. This 3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # helps assert subtype_dealloc's behaviour when threads 3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # switch in the middle of it. 3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = sleeper_gen() 3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi next(g) 3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Now that __del__ is finished, subtype_dealloc will proceed 3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # to call list_dealloc, which also uses the trashcan mechanism. 3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def make_nested(): 3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Create a sufficiently nested container object so that the 3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi trashcan mechanism is invoked when deallocating it.""" 3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = C([]) 3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for i in range(NESTING): 3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = [C([x])] 3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del x 3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def run_thread(): 3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Exercise make_nested() in a loop.""" 3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi while not exit: 3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi make_nested() 3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi old_checkinterval = sys.getcheckinterval() 3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.setcheckinterval(3) 3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi exit = False 3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi threads = [] 3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for i in range(N_THREADS): 3580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = threading.Thread(target=run_thread) 3590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi threads.append(t) 3600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for t in threads: 3610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t.start() 3620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.sleep(1.0) 3630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi exit = True 3640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for t in threads: 3650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t.join() 3660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 3670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.setcheckinterval(old_checkinterval) 3680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 3690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(C.inits), len(C.dels)) 3700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boom(self): 3720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class Boom: 3730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __getattr__(self, someattribute): 3740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del self.attr 3750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise AttributeError 3760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = Boom() 3780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = Boom() 3790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.attr = b 3800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.attr = a 3810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 3830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi garbagelen = len(gc.garbage) 3840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a, b 3850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # a<->b are in a trash cycle now. Collection will invoke 3860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Boom.__getattr__ (to see whether a and b have __del__ methods), and 3870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # __getattr__ deletes the internal "attr" attributes as a side effect. 3880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # That causes the trash cycle to get reclaimed via refcounts falling to 3890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 0, thus mutating the trash graph as a side effect of merely asking 3900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # whether __del__ exists. This used to (before 2.3b1) crash Python. 3910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Now __getattr__ isn't called. 3920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 4) 3930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(gc.garbage), garbagelen) 3940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boom2(self): 3960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class Boom2: 3970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self): 3980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.x = 0 3990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __getattr__(self, someattribute): 4010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.x += 1 4020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if self.x > 1: 4030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del self.attr 4040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise AttributeError 4050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = Boom2() 4070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = Boom2() 4080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.attr = b 4090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.attr = a 4100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 4120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi garbagelen = len(gc.garbage) 4130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a, b 4140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Much like test_boom(), except that __getattr__ doesn't break the 4150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # cycle until the second time gc checks for __del__. As of 2.3b1, 4160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # there isn't a second time, so this simply cleans up the trash cycle. 4170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get 4180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # reclaimed this way. 4190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 4) 4200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(gc.garbage), garbagelen) 4210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boom_new(self): 4230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # boom__new and boom2_new are exactly like boom and boom2, except use 4240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # new-style classes. 4250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class Boom_New(object): 4270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __getattr__(self, someattribute): 4280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del self.attr 4290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise AttributeError 4300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = Boom_New() 4320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = Boom_New() 4330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.attr = b 4340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.attr = a 4350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 4370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi garbagelen = len(gc.garbage) 4380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a, b 4390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 4) 4400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(gc.garbage), garbagelen) 4410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boom2_new(self): 4430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class Boom2_New(object): 4440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __init__(self): 4450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.x = 0 4460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __getattr__(self, someattribute): 4480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.x += 1 4490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if self.x > 1: 4500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del self.attr 4510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise AttributeError 4520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = Boom2_New() 4540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = Boom2_New() 4550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a.attr = b 4560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b.attr = a 4570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 4590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi garbagelen = len(gc.garbage) 4600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del a, b 4610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.collect(), 4) 4620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(gc.garbage), garbagelen) 4630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_referents(self): 4650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi alist = [1, 3, 5] 4660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got = gc.get_referents(alist) 4670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got.sort() 4680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(got, alist) 4690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi atuple = tuple(alist) 4710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got = gc.get_referents(atuple) 4720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got.sort() 4730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(got, alist) 4740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi adict = {1: 3, 5: 7} 4760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi expected = [1, 3, 5, 7] 4770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got = gc.get_referents(adict) 4780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got.sort() 4790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(got, expected) 4800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0)) 4820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi got.sort() 4830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(got, [0, 0] + range(5)) 4840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(gc.get_referents(1, 'a', 4j), []) 4860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_is_tracked(self): 4880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Atomic built-in types are not tracked, user-defined objects and 4890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # mutable containers are. 4900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # NOTE: types with special optimizations (e.g. tuple) have tests 4910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # in their own test files instead. 4920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(None)) 4930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(1)) 4940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(1.0)) 4950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(1.0 + 5.0j)) 4960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(True)) 4970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(False)) 4980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked("a")) 4990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(u"a")) 5000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(bytearray("a"))) 5010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(type)) 5020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(int)) 5030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(object)) 5040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(gc.is_tracked(object())) 5050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class OldStyle: 5070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 5080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class NewStyle(object): 5090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 5100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(gc)) 5110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(OldStyle)) 5120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(OldStyle())) 5130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(NewStyle)) 5140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(NewStyle())) 5150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked([])) 5160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(gc.is_tracked(set())) 5170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bug1055820b(self): 5190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Corresponds to temp2b.py in the bug report. 5200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch = [] 5220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def callback(ignored): 5230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch[:] = [wr() for wr in WRs] 5240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Cs = [C1055820(i) for i in range(2)] 5260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi WRs = [weakref.ref(c, callback) for c in Cs] 5270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = None 5280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 5300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 0) 5310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make the two instances trash, and collect again. The bug was that 5320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # the callback materialized a strong reference to an instance, but gc 5330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # cleared the instance's dict anyway. 5340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Cs = None 5350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 5360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 2) # else the callbacks didn't run 5370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for x in ouch: 5380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # If the callback resurrected one of these guys, the instance 5390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # would be damaged, with an empty __dict__. 5400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(x, None) 5410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass GCTogglingTests(unittest.TestCase): 5430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 5440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.enable() 5450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def tearDown(self): 5470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 5480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bug1055820c(self): 5500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Corresponds to temp2c.py in the bug report. This is pretty 5510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # elaborate. 5520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c0 = C1055820(0) 5540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Move c0 into generation 2. 5550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 5560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c1 = C1055820(1) 5580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c1.keep_c0_alive = c0 5590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del c0.loop # now only c1 keeps c0 alive 5600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c2 = C1055820(2) 5620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c2wr = weakref.ref(c2) # no callback! 5630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch = [] 5650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def callback(ignored): 5660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch[:] = [c2wr()] 5670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The callback gets associated with a wr on an object in generation 2. 5690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c0wr = weakref.ref(c0, callback) 5700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c0 = c1 = c2 = None 5720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # What we've set up: c0, c1, and c2 are all trash now. c0 is in 5740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # generation 2. The only thing keeping it alive is that c1 points to 5750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # it. c1 and c2 are in generation 0, and are in self-loops. There's a 5760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # global weakref to c2 (c2wr), but that weakref has no callback. 5770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # There's also a global weakref to c0 (c0wr), and that does have a 5780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # callback, and that callback references c2 via c2wr(). 5790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 5800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # c0 has a wr with callback, which references c2wr 5810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # ^ 5820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 5830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | Generation 2 above dots 5840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . 5850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | Generation 0 below dots 5860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 5870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 5880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # ^->c1 ^->c2 has a wr but no callback 5890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | | | | 5900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # <--v <--v 5910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 5920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # So this is the nightmare: when generation 0 gets collected, we see 5930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # that c2 has a callback-free weakref, and c1 doesn't even have a 5940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # weakref. Collecting generation 0 doesn't see c0 at all, and c0 is 5950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # the only object that has a weakref with a callback. gc clears c1 5960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # and c2. Clearing c1 has the side effect of dropping the refcount on 5970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # c0 to 0, so c0 goes away (despite that it's in an older generation) 5980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # and c0's wr callback triggers. That in turn materializes a reference 5990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # to c2 via c2wr(), but c2 gets cleared anyway by gc. 6000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # We want to let gc happen "naturally", to preserve the distinction 6020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # between generations. 6030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi junk = [] 6040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi i = 0 6050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi detector = GC_Detector() 6060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi while not detector.gc_happened: 6070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi i += 1 6080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if i > 10000: 6090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.fail("gc didn't happen after 10000 iterations") 6100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 0) 6110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi junk.append([]) # this will eventually trigger gc 6120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 1) # else the callback wasn't invoked 6140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for x in ouch: 6150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # If the callback resurrected c2, the instance would be damaged, 6160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # with an empty __dict__. 6170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(x, None) 6180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bug1055820d(self): 6200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Corresponds to temp2d.py in the bug report. This is very much like 6210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # test_bug1055820c, but uses a __del__ method instead of a weakref 6220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # callback to sneak in a resurrection of cyclic trash. 6230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch = [] 6250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class D(C1055820): 6260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def __del__(self): 6270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ouch[:] = [c2wr()] 6280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi d0 = D(0) 6300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Move all the above into generation 2. 6310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() 6320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c1 = C1055820(1) 6340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c1.keep_d0_alive = d0 6350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del d0.loop # now only c1 keeps d0 alive 6360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c2 = C1055820(2) 6380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c2wr = weakref.ref(c2) # no callback! 6390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi d0 = c1 = c2 = None 6410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # What we've set up: d0, c1, and c2 are all trash now. d0 is in 6430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # generation 2. The only thing keeping it alive is that c1 points to 6440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # it. c1 and c2 are in generation 0, and are in self-loops. There's 6450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # a global weakref to c2 (c2wr), but that weakref has no callback. 6460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # There are no other weakrefs. 6470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 6480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # d0 has a __del__ method that references c2wr 6490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # ^ 6500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 6510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | Generation 2 above dots 6520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi #. . . . . . . .|. . . . . . . . . . . . . . . . . . . . . . . . 6530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | Generation 0 below dots 6540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 6550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | 6560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # ^->c1 ^->c2 has a wr but no callback 6570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # | | | | 6580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # <--v <--v 6590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 6600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # So this is the nightmare: when generation 0 gets collected, we see 6610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # that c2 has a callback-free weakref, and c1 doesn't even have a 6620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # weakref. Collecting generation 0 doesn't see d0 at all. gc clears 6630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # c1 and c2. Clearing c1 has the side effect of dropping the refcount 6640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # on d0 to 0, so d0 goes away (despite that it's in an older 6650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # generation) and d0's __del__ triggers. That in turn materializes 6660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # a reference to c2 via c2wr(), but c2 gets cleared anyway by gc. 6670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # We want to let gc happen "naturally", to preserve the distinction 6690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # between generations. 6700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi detector = GC_Detector() 6710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi junk = [] 6720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi i = 0 6730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi while not detector.gc_happened: 6740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi i += 1 6750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if i > 10000: 6760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.fail("gc didn't happen after 10000 iterations") 6770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 0) 6780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi junk.append([]) # this will eventually trigger gc 6790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(ouch), 1) # else __del__ wasn't invoked 6810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for x in ouch: 6820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # If __del__ resurrected c2, the instance would be damaged, with an 6830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # empty __dict__. 6840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(x, None) 6850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main(): 6870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi enabled = gc.isenabled() 6880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 6890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assert not gc.isenabled() 6900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi debug = gc.get_debug() 6910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak 6920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 6940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.collect() # Delete 2nd generation garbage 6950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi run_unittest(GCTests, GCTogglingTests) 6960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 6970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.set_debug(debug) 6980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # test gc.enable() even if GC is disabled by default 6990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 7000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print "restoring automatic collection" 7010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # make sure to always test gc.enable() 7020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.enable() 7030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assert gc.isenabled() 7040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if not enabled: 7050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gc.disable() 7060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == "__main__": 7080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi test_main() 709