Back to index

python3.2  3.2.2
Public Member Functions | Public Attributes
test.test_gc.GCTests Class Reference

List of all members.

Public Member Functions

def test_list
def test_dict
def test_tuple
def test_class
def test_newstyleclass
def test_instance
def test_newinstance
def test_method
def test_finalizer
def test_finalizer_newclass
def test_function
def test_frame
def test_saveall
def test_del
def test_del_newclass
def test_get_count
def test_collect_generations
def test_trashcan
def test_boom
def test_boom2
def test_boom_new
def test_boom2_new
def test_get_referents
def test_is_tracked
def test_bug1055820b
def test_garbage_at_shutdown

Public Attributes

 init
 x

Detailed Description

Definition at line 38 of file test_gc.py.


Member Function Documentation

Definition at line 313 of file test_gc.py.

00313 
00314     def test_boom(self):
00315         class Boom:
00316             def __getattr__(self, someattribute):
00317                 del self.attr
00318                 raise AttributeError
00319 
00320         a = Boom()
00321         b = Boom()
00322         a.attr = b
00323         b.attr = a
00324 
00325         gc.collect()
00326         garbagelen = len(gc.garbage)
00327         del a, b
00328         # a<->b are in a trash cycle now.  Collection will invoke
00329         # Boom.__getattr__ (to see whether a and b have __del__ methods), and
00330         # __getattr__ deletes the internal "attr" attributes as a side effect.
00331         # That causes the trash cycle to get reclaimed via refcounts falling to
00332         # 0, thus mutating the trash graph as a side effect of merely asking
00333         # whether __del__ exists.  This used to (before 2.3b1) crash Python.
00334         # Now __getattr__ isn't called.
00335         self.assertEqual(gc.collect(), 4)
00336         self.assertEqual(len(gc.garbage), garbagelen)

Here is the call graph for this function:

Definition at line 337 of file test_gc.py.

00337 
00338     def test_boom2(self):
00339         class Boom2:
00340             def __init__(self):
00341                 self.x = 0
00342 
00343             def __getattr__(self, someattribute):
00344                 self.x += 1
00345                 if self.x > 1:
00346                     del self.attr
00347                 raise AttributeError
00348 
00349         a = Boom2()
00350         b = Boom2()
00351         a.attr = b
00352         b.attr = a
00353 
00354         gc.collect()
00355         garbagelen = len(gc.garbage)
00356         del a, b
00357         # Much like test_boom(), except that __getattr__ doesn't break the
00358         # cycle until the second time gc checks for __del__.  As of 2.3b1,
00359         # there isn't a second time, so this simply cleans up the trash cycle.
00360         # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get
00361         # reclaimed this way.
00362         self.assertEqual(gc.collect(), 4)
00363         self.assertEqual(len(gc.garbage), garbagelen)

Here is the call graph for this function:

Definition at line 384 of file test_gc.py.

00384 
00385     def test_boom2_new(self):
00386         class Boom2_New(object):
00387             def __init__(self):
00388                 self.x = 0
00389 
00390             def __getattr__(self, someattribute):
00391                 self.x += 1
00392                 if self.x > 1:
00393                     del self.attr
00394                 raise AttributeError
00395 
00396         a = Boom2_New()
00397         b = Boom2_New()
00398         a.attr = b
00399         b.attr = a
00400 
00401         gc.collect()
00402         garbagelen = len(gc.garbage)
00403         del a, b
00404         self.assertEqual(gc.collect(), 4)
00405         self.assertEqual(len(gc.garbage), garbagelen)

Here is the call graph for this function:

Definition at line 364 of file test_gc.py.

00364 
00365     def test_boom_new(self):
00366         # boom__new and boom2_new are exactly like boom and boom2, except use
00367         # new-style classes.
00368 
00369         class Boom_New(object):
00370             def __getattr__(self, someattribute):
00371                 del self.attr
00372                 raise AttributeError
00373 
00374         a = Boom_New()
00375         b = Boom_New()
00376         a.attr = b
00377         b.attr = a
00378 
00379         gc.collect()
00380         garbagelen = len(gc.garbage)
00381         del a, b
00382         self.assertEqual(gc.collect(), 4)
00383         self.assertEqual(len(gc.garbage), garbagelen)

Here is the call graph for this function:

Definition at line 456 of file test_gc.py.

00456 
00457     def test_bug1055820b(self):
00458         # Corresponds to temp2b.py in the bug report.
00459 
00460         ouch = []
00461         def callback(ignored):
00462             ouch[:] = [wr() for wr in WRs]
00463 
00464         Cs = [C1055820(i) for i in range(2)]
00465         WRs = [weakref.ref(c, callback) for c in Cs]
00466         c = None
00467 
00468         gc.collect()
00469         self.assertEqual(len(ouch), 0)
00470         # Make the two instances trash, and collect again.  The bug was that
00471         # the callback materialized a strong reference to an instance, but gc
00472         # cleared the instance's dict anyway.
00473         Cs = None
00474         gc.collect()
00475         self.assertEqual(len(ouch), 2)  # else the callbacks didn't run
00476         for x in ouch:
00477             # If the callback resurrected one of these guys, the instance
00478             # would be damaged, with an empty __dict__.
00479             self.assertEqual(x, None)

Here is the call graph for this function:

Definition at line 63 of file test_gc.py.

00063 
00064     def test_class(self):
00065         class A:
00066             pass
00067         A.a = A
00068         gc.collect()
00069         del A
00070         self.assertNotEqual(gc.collect(), 0)

Definition at line 258 of file test_gc.py.

00258 
00259     def test_collect_generations(self):
00260         gc.collect()
00261         # This object will "trickle" into generation N + 1 after
00262         # each call to collect(N)
00263         x = []
00264         gc.collect(0)
00265         # x is now in gen 1
00266         a, b, c = gc.get_count()
00267         gc.collect(1)
00268         # x is now in gen 2
00269         d, e, f = gc.get_count()
00270         gc.collect(2)
00271         # x is now in gen 3
00272         g, h, i = gc.get_count()
00273         # We don't check a, d, g since their exact values depends on
00274         # internal implementation details of the interpreter.
00275         self.assertEqual((b, c), (1, 0))
00276         self.assertEqual((e, f), (0, 1))
00277         self.assertEqual((h, i), (0, 0))

Here is the call graph for this function:

Definition at line 209 of file test_gc.py.

00209 
00210     def test_del(self):
00211         # __del__ methods can trigger collection, make this to happen
00212         thresholds = gc.get_threshold()
00213         gc.enable()
00214         gc.set_threshold(1)
00215 
00216         class A:
00217             def __del__(self):
00218                 dir(self)
00219         a = A()
00220         del a
00221 
00222         gc.disable()
00223         gc.set_threshold(*thresholds)

Definition at line 224 of file test_gc.py.

00224 
00225     def test_del_newclass(self):
00226         # __del__ methods can trigger collection, make this to happen
00227         thresholds = gc.get_threshold()
00228         gc.enable()
00229         gc.set_threshold(1)
00230 
00231         class A(object):
00232             def __del__(self):
00233                 dir(self)
00234         a = A()
00235         del a
00236 
00237         gc.disable()
00238         gc.set_threshold(*thresholds)

Definition at line 46 of file test_gc.py.

00046 
00047     def test_dict(self):
00048         d = {}
00049         d[1] = d
00050         gc.collect()
00051         del d
00052         self.assertEqual(gc.collect(), 1)

Here is the call graph for this function:

Definition at line 121 of file test_gc.py.

00121 
00122     def test_finalizer(self):
00123         # A() is uncollectable if it is part of a cycle, make sure it shows up
00124         # in gc.garbage.
00125         class A:
00126             def __del__(self): pass
00127         class B:
00128             pass
00129         a = A()
00130         a.a = a
00131         id_a = id(a)
00132         b = B()
00133         b.b = b
00134         gc.collect()
00135         del a
00136         del b
00137         self.assertNotEqual(gc.collect(), 0)
00138         for obj in gc.garbage:
00139             if id(obj) == id_a:
00140                 del obj.a
00141                 break
00142         else:
00143             self.fail("didn't find obj in garbage (finalizer)")
00144         gc.garbage.remove(obj)

Definition at line 145 of file test_gc.py.

00145 
00146     def test_finalizer_newclass(self):
00147         # A() is uncollectable if it is part of a cycle, make sure it shows up
00148         # in gc.garbage.
00149         class A(object):
00150             def __del__(self): pass
00151         class B(object):
00152             pass
00153         a = A()
00154         a.a = a
00155         id_a = id(a)
00156         b = B()
00157         b.b = b
00158         gc.collect()
00159         del a
00160         del b
00161         self.assertNotEqual(gc.collect(), 0)
00162         for obj in gc.garbage:
00163             if id(obj) == id_a:
00164                 del obj.a
00165                 break
00166         else:
00167             self.fail("didn't find obj in garbage (finalizer)")
00168         gc.garbage.remove(obj)

Definition at line 178 of file test_gc.py.

00178 
00179     def test_frame(self):
00180         def f():
00181             frame = sys._getframe()
00182         gc.collect()
00183         f()
00184         self.assertEqual(gc.collect(), 1)

Here is the call graph for this function:

Definition at line 169 of file test_gc.py.

00169 
00170     def test_function(self):
00171         # Tricky: f -> d -> f, code should call d.clear() after the exec to
00172         # break the cycle.
00173         d = {}
00174         exec("def f(): pass\n", d)
00175         gc.collect()
00176         del d
00177         self.assertEqual(gc.collect(), 2)

Here is the call graph for this function:

Definition at line 480 of file test_gc.py.

00480 
00481     def test_garbage_at_shutdown(self):
00482         import subprocess
00483         code = """if 1:
00484             import gc
00485             class X:
00486                 def __init__(self, name):
00487                     self.name = name
00488                 def __repr__(self):
00489                     return "<X %%r>" %% self.name
00490                 def __del__(self):
00491                     pass
00492 
00493             x = X('first')
00494             x.x = x
00495             x.y = X('second')
00496             del x
00497             gc.set_debug(%s)
00498         """
00499         def run_command(code):
00500             p = subprocess.Popen([sys.executable, "-Wd", "-c", code],
00501                 stdout=subprocess.PIPE,
00502                 stderr=subprocess.PIPE)
00503             stdout, stderr = p.communicate()
00504             p.stdout.close()
00505             p.stderr.close()
00506             self.assertEqual(p.returncode, 0)
00507             self.assertEqual(stdout.strip(), b"")
00508             return strip_python_stderr(stderr)
00509 
00510         stderr = run_command(code % "0")
00511         self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
00512                       b"shutdown; use", stderr)
00513         self.assertNotIn(b"<X 'first'>", stderr)
00514         # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
00515         stderr = run_command(code % "gc.DEBUG_UNCOLLECTABLE")
00516         self.assertIn(b"ResourceWarning: gc: 2 uncollectable objects at "
00517                       b"shutdown", stderr)
00518         self.assertTrue(
00519             (b"[<X 'first'>, <X 'second'>]" in stderr) or
00520             (b"[<X 'second'>, <X 'first'>]" in stderr), stderr)
00521         # With DEBUG_SAVEALL, no additional message should get printed
00522         # (because gc.garbage also contains normally reclaimable cyclic
00523         # references, and its elements get printed at runtime anyway).
00524         stderr = run_command(code % "gc.DEBUG_SAVEALL")
00525         self.assertNotIn(b"uncollectable objects at shutdown", stderr)
00526 

Here is the call graph for this function:

Definition at line 245 of file test_gc.py.

00245 
00246     def test_get_count(self):
00247         gc.collect()
00248         a, b, c = gc.get_count()
00249         x = []
00250         d, e, f = gc.get_count()
00251         self.assertEqual((b, c), (0, 0))
00252         self.assertEqual((e, f), (0, 0))
00253         # This is less fragile than asserting that a equals 0.
00254         self.assertLess(a, 5)
00255         # Between the two calls to get_count(), at least one object was
00256         # created (the list).
00257         self.assertGreater(d, a)

Here is the call graph for this function:

Definition at line 406 of file test_gc.py.

00406 
00407     def test_get_referents(self):
00408         alist = [1, 3, 5]
00409         got = gc.get_referents(alist)
00410         got.sort()
00411         self.assertEqual(got, alist)
00412 
00413         atuple = tuple(alist)
00414         got = gc.get_referents(atuple)
00415         got.sort()
00416         self.assertEqual(got, alist)
00417 
00418         adict = {1: 3, 5: 7}
00419         expected = [1, 3, 5, 7]
00420         got = gc.get_referents(adict)
00421         got.sort()
00422         self.assertEqual(got, expected)
00423 
00424         got = gc.get_referents([1, 2], {3: 4}, (0, 0, 0))
00425         got.sort()
00426         self.assertEqual(got, [0, 0] + list(range(5)))
00427 
00428         self.assertEqual(gc.get_referents(1, 'a', 4j), [])

Here is the call graph for this function:

Definition at line 78 of file test_gc.py.

00078 
00079     def test_instance(self):
00080         class A:
00081             pass
00082         a = A()
00083         a.a = a
00084         gc.collect()
00085         del a
00086         self.assertNotEqual(gc.collect(), 0)

Definition at line 429 of file test_gc.py.

00429 
00430     def test_is_tracked(self):
00431         # Atomic built-in types are not tracked, user-defined objects and
00432         # mutable containers are.
00433         # NOTE: types with special optimizations (e.g. tuple) have tests
00434         # in their own test files instead.
00435         self.assertFalse(gc.is_tracked(None))
00436         self.assertFalse(gc.is_tracked(1))
00437         self.assertFalse(gc.is_tracked(1.0))
00438         self.assertFalse(gc.is_tracked(1.0 + 5.0j))
00439         self.assertFalse(gc.is_tracked(True))
00440         self.assertFalse(gc.is_tracked(False))
00441         self.assertFalse(gc.is_tracked(b"a"))
00442         self.assertFalse(gc.is_tracked("a"))
00443         self.assertFalse(gc.is_tracked(bytearray(b"a")))
00444         self.assertFalse(gc.is_tracked(type))
00445         self.assertFalse(gc.is_tracked(int))
00446         self.assertFalse(gc.is_tracked(object))
00447         self.assertFalse(gc.is_tracked(object()))
00448 
00449         class UserClass:
00450             pass
00451         self.assertTrue(gc.is_tracked(gc))
00452         self.assertTrue(gc.is_tracked(UserClass))
00453         self.assertTrue(gc.is_tracked(UserClass()))
00454         self.assertTrue(gc.is_tracked([]))
00455         self.assertTrue(gc.is_tracked(set()))

Here is the call graph for this function:

Definition at line 39 of file test_gc.py.

00039 
00040     def test_list(self):
00041         l = []
00042         l.append(l)
00043         gc.collect()
00044         del l
00045         self.assertEqual(gc.collect(), 1)

Here is the call graph for this function:

Definition at line 111 of file test_gc.py.

00111 
00112     def test_method(self):
00113         # Tricky: self.__init__ is a bound method, it references the instance.
00114         class A:
00115             def __init__(self):
00116                 self.init = self.__init__
00117         a = A()
00118         gc.collect()
00119         del a
00120         self.assertNotEqual(gc.collect(), 0)

Here is the call graph for this function:

Definition at line 87 of file test_gc.py.

00087 
00088     def test_newinstance(self):
00089         class A(object):
00090             pass
00091         a = A()
00092         a.a = a
00093         gc.collect()
00094         del a
00095         self.assertNotEqual(gc.collect(), 0)
00096         class B(list):
00097             pass
00098         class C(B, A):
00099             pass
00100         a = C()
00101         a.a = a
00102         gc.collect()
00103         del a
00104         self.assertNotEqual(gc.collect(), 0)
00105         del B, C
00106         self.assertNotEqual(gc.collect(), 0)
00107         A.a = A()
00108         del A
00109         self.assertNotEqual(gc.collect(), 0)
00110         self.assertEqual(gc.collect(), 0)

Definition at line 71 of file test_gc.py.

00071 
00072     def test_newstyleclass(self):
00073         class A(object):
00074             pass
00075         gc.collect()
00076         del A
00077         self.assertNotEqual(gc.collect(), 0)

Definition at line 185 of file test_gc.py.

00185 
00186     def test_saveall(self):
00187         # Verify that cyclic garbage like lists show up in gc.garbage if the
00188         # SAVEALL option is enabled.
00189 
00190         # First make sure we don't save away other stuff that just happens to
00191         # be waiting for collection.
00192         gc.collect()
00193         # if this fails, someone else created immortal trash
00194         self.assertEqual(gc.garbage, [])
00195 
00196         L = []
00197         L.append(L)
00198         id_L = id(L)
00199 
00200         debug = gc.get_debug()
00201         gc.set_debug(debug | gc.DEBUG_SAVEALL)
00202         del L
00203         gc.collect()
00204         gc.set_debug(debug)
00205 
00206         self.assertEqual(len(gc.garbage), 1)
00207         obj = gc.garbage.pop()
00208         self.assertEqual(id(obj), id_L)

Here is the call graph for this function:

Definition at line 278 of file test_gc.py.

00278 
00279     def test_trashcan(self):
00280         class Ouch:
00281             n = 0
00282             def __del__(self):
00283                 Ouch.n = Ouch.n + 1
00284                 if Ouch.n % 17 == 0:
00285                     gc.collect()
00286 
00287         # "trashcan" is a hack to prevent stack overflow when deallocating
00288         # very deeply nested tuples etc.  It works in part by abusing the
00289         # type pointer and refcount fields, and that can yield horrible
00290         # problems when gc tries to traverse the structures.
00291         # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
00292         # most likely die via segfault.
00293 
00294         # Note:  In 2.3 the possibility for compiling without cyclic gc was
00295         # removed, and that in turn allows the trashcan mechanism to work
00296         # via much simpler means (e.g., it never abuses the type pointer or
00297         # refcount fields anymore).  Since it's much less likely to cause a
00298         # problem now, the various constants in this expensive (we force a lot
00299         # of full collections) test are cut back from the 2.2 version.
00300         gc.enable()
00301         N = 150
00302         for count in range(2):
00303             t = []
00304             for i in range(N):
00305                 t = [t, Ouch()]
00306             u = []
00307             for i in range(N):
00308                 u = [u, Ouch()]
00309             v = {}
00310             for i in range(N):
00311                 v = {1: v, 2: Ouch()}
00312         gc.disable()

Definition at line 53 of file test_gc.py.

00053 
00054     def test_tuple(self):
00055         # since tuples are immutable we close the loop with a list
00056         l = []
00057         t = (l,)
00058         l.append(t)
00059         gc.collect()
00060         del t
00061         del l
00062         self.assertEqual(gc.collect(), 2)

Here is the call graph for this function:


Member Data Documentation

Definition at line 115 of file test_gc.py.

Definition at line 340 of file test_gc.py.


The documentation for this class was generated from the following file: