test_call_policies.py 5.1 KB
Newer Older
Wenzel Jakob's avatar
Wenzel Jakob committed
1
import pytest
Dean Moldovan's avatar
Dean Moldovan committed
2
3
4


def test_keep_alive_argument(capture):
5
    from pybind11_tests import Parent, Child, ConstructorStats
Dean Moldovan's avatar
Dean Moldovan committed
6

7
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
8
9
10
11
12
    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.addChild(Child())
13
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
14
15
16
17
18
19
    assert capture == """
        Allocating child.
        Releasing child.
    """
    with capture:
        del p
20
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
21
22
23
24
25
26
27
    assert capture == "Releasing parent."

    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.addChildKeepAlive(Child())
28
        assert ConstructorStats.detail_reg_inst() == n_inst + 2
Dean Moldovan's avatar
Dean Moldovan committed
29
30
31
    assert capture == "Allocating child."
    with capture:
        del p
32
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
33
34
35
36
37
38
39
    assert capture == """
        Releasing parent.
        Releasing child.
    """


def test_keep_alive_return_value(capture):
40
    from pybind11_tests import Parent, ConstructorStats
Dean Moldovan's avatar
Dean Moldovan committed
41

42
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
43
44
45
46
47
    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.returnChild()
48
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
49
50
51
52
53
54
    assert capture == """
        Allocating child.
        Releasing child.
    """
    with capture:
        del p
55
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
56
57
58
59
60
61
62
    assert capture == "Releasing parent."

    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.returnChildKeepAlive()
63
        assert ConstructorStats.detail_reg_inst() == n_inst + 2
Dean Moldovan's avatar
Dean Moldovan committed
64
65
66
    assert capture == "Allocating child."
    with capture:
        del p
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
        assert ConstructorStats.detail_reg_inst() == n_inst
    assert capture == """
        Releasing parent.
        Releasing child.
    """


# https://bitbucket.org/pypy/pypy/issues/2447
@pytest.unsupported_on_pypy
def test_alive_gc(capture):
    from pybind11_tests import ParentGC, Child, ConstructorStats

    n_inst = ConstructorStats.detail_reg_inst()
    p = ParentGC()
    p.addChildKeepAlive(Child())
    assert ConstructorStats.detail_reg_inst() == n_inst + 2
    lst = [p]
    lst.append(lst)   # creates a circular reference
    with capture:
        del p, lst
        assert ConstructorStats.detail_reg_inst() == n_inst
    assert capture == """
        Releasing parent.
        Releasing child.
    """


def test_alive_gc_derived(capture):
    from pybind11_tests import Parent, Child, ConstructorStats

    class Derived(Parent):
        pass

    n_inst = ConstructorStats.detail_reg_inst()
    p = Derived()
    p.addChildKeepAlive(Child())
    assert ConstructorStats.detail_reg_inst() == n_inst + 2
    lst = [p]
    lst.append(lst)   # creates a circular reference
    with capture:
        del p, lst
        assert ConstructorStats.detail_reg_inst() == n_inst
    assert capture == """
        Releasing parent.
        Releasing child.
    """


def test_alive_gc_multi_derived(capture):
    from pybind11_tests import Parent, Child, ConstructorStats

    class Derived(Parent, Child):
119
120
121
        def __init__(self):
            Parent.__init__(self)
            Child.__init__(self)
122
123
124
125
126
127
128
129
130
131
132

    n_inst = ConstructorStats.detail_reg_inst()
    p = Derived()
    p.addChildKeepAlive(Child())
    # +3 rather than +2 because Derived corresponds to two registered instances
    assert ConstructorStats.detail_reg_inst() == n_inst + 3
    lst = [p]
    lst.append(lst)   # creates a circular reference
    with capture:
        del p, lst
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
133
134
135
    assert capture == """
        Releasing parent.
        Releasing child.
136
        Releasing child.
Dean Moldovan's avatar
Dean Moldovan committed
137
138
139
140
    """


def test_return_none(capture):
141
    from pybind11_tests import Parent, ConstructorStats
Dean Moldovan's avatar
Dean Moldovan committed
142

143
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
144
145
146
147
148
    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.returnNullChildKeepAliveChild()
149
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
150
151
152
    assert capture == ""
    with capture:
        del p
153
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
154
155
156
157
158
159
160
    assert capture == "Releasing parent."

    with capture:
        p = Parent()
    assert capture == "Allocating parent."
    with capture:
        p.returnNullChildKeepAliveParent()
161
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
162
163
164
    assert capture == ""
    with capture:
        del p
165
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
166
    assert capture == "Releasing parent."
Dean Moldovan's avatar
Dean Moldovan committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180


def test_call_guard():
    from pybind11_tests import call_policies

    assert call_policies.unguarded_call() == "unguarded"
    assert call_policies.guarded_call() == "guarded"

    assert call_policies.multiple_guards_correct_order() == "guarded & guarded"
    assert call_policies.multiple_guards_wrong_order() == "unguarded & guarded"

    if hasattr(call_policies, "with_gil"):
        assert call_policies.with_gil() == "GIL held"
        assert call_policies.without_gil() == "GIL released"