File: test_weakref.py

package info (click to toggle)
obsub 0.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 160 kB
  • sloc: python: 351; makefile: 5; sh: 2
file content (86 lines) | stat: -rw-r--r-- 2,037 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
'''
These tests that the event handling mechanism does not produce memory leaks.
This could in principle happen, since it introduces a cyclic dependency that
might prevent garbage collection.

'''

import weakref
import gc

from obsub import event


def test_memory_leak():

    # Define a test class and an event handler
    class A(object):
        @event
        def on_blubb(self):
            pass

    def handler(self):
        pass

    # Instantiate and attach event handler
    a = A()
    a.on_blubb += handler

    # Weak reference for testing
    wr = weakref.ref(a)

    # At first, weak reference exists
    assert wr() is not None

    # (implicitly) delete the A-instance by reassigning the only hard-ref.
    # This is equivalent to `del a` but serves the purpose to demonstrate
    # that there are very subtle ways to delete an instance:
    a = None

    # Trigger the garbage collection manually
    gc.collect()

    # after deletion it should be dead
    assert wr() is None


def test_object_stays_alive_during_handler_execution():

    # Define a test class and event handlers
    class A(object):
        @event
        def on_blubb(self):
            pass
        deleted = False

    class B(object):
        def __init__(self, a):
            # capture the only hard-ref on the A-instance:
            self.a = a
            self.a.on_blubb += self.handler

        def handler(self, a):
            # delete the A-instance
            del self.a
            a.deleted = True
            del a
            gc.collect()

    def handler(a):
        # We want a valid reference to the handled object, ...
        assert a is not None
        # ..., even if the deletion handler has already been called:
        assert a.deleted

    # Instantiate and attach event handler
    b = B(A())
    b.a.on_blubb += handler

    wr = weakref.ref(b.a)
    b.a.on_blubb()

    # Trigger the garbage collection manually
    gc.collect()

    # make sure, b.a has been deleted after event handling
    assert wr() is None