test_call_policies.py 5.19 KB
Newer Older
Wenzel Jakob's avatar
Wenzel Jakob committed
1
import pytest
2
3
from pybind11_tests import call_policies as m
from pybind11_tests import ConstructorStats
Dean Moldovan's avatar
Dean Moldovan committed
4
5
6


def test_keep_alive_argument(capture):
7
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
8
    with capture:
9
        p = m.Parent()
Dean Moldovan's avatar
Dean Moldovan committed
10
11
    assert capture == "Allocating parent."
    with capture:
12
        p.addChild(m.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
    assert capture == "Releasing parent."

    with capture:
24
        p = m.Parent()
Dean Moldovan's avatar
Dean Moldovan committed
25
26
    assert capture == "Allocating parent."
    with capture:
27
        p.addChildKeepAlive(m.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
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
41
    with capture:
42
        p = m.Parent()
Dean Moldovan's avatar
Dean Moldovan committed
43
44
45
    assert capture == "Allocating parent."
    with capture:
        p.returnChild()
46
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
47
48
49
50
51
52
    assert capture == """
        Allocating child.
        Releasing child.
    """
    with capture:
        del p
53
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
54
55
56
    assert capture == "Releasing parent."

    with capture:
57
        p = m.Parent()
Dean Moldovan's avatar
Dean Moldovan committed
58
59
60
    assert capture == "Allocating parent."
    with capture:
        p.returnChildKeepAlive()
61
        assert ConstructorStats.detail_reg_inst() == n_inst + 2
Dean Moldovan's avatar
Dean Moldovan committed
62
63
64
    assert capture == "Allocating child."
    with capture:
        del p
65
66
67
68
69
70
71
72
73
74
75
        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):
    n_inst = ConstructorStats.detail_reg_inst()
76
77
    p = m.ParentGC()
    p.addChildKeepAlive(m.Child())
78
79
80
81
82
83
84
85
86
87
88
89
90
    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):
91
    class Derived(m.Parent):
92
93
94
95
        pass

    n_inst = ConstructorStats.detail_reg_inst()
    p = Derived()
96
    p.addChildKeepAlive(m.Child())
97
98
99
100
101
102
103
104
105
106
107
108
109
    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):
110
    class Derived(m.Parent, m.Child):
111
        def __init__(self):
112
113
            m.Parent.__init__(self)
            m.Child.__init__(self)
114
115
116

    n_inst = ConstructorStats.detail_reg_inst()
    p = Derived()
117
    p.addChildKeepAlive(m.Child())
118
119
120
121
122
123
124
    # +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
125
126
127
    assert capture == """
        Releasing parent.
        Releasing child.
128
        Releasing child.
Dean Moldovan's avatar
Dean Moldovan committed
129
130
131
132
    """


def test_return_none(capture):
133
    n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovan's avatar
Dean Moldovan committed
134
    with capture:
135
        p = m.Parent()
Dean Moldovan's avatar
Dean Moldovan committed
136
137
138
    assert capture == "Allocating parent."
    with capture:
        p.returnNullChildKeepAliveChild()
139
        assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovan's avatar
Dean Moldovan committed
140
141
142
    assert capture == ""
    with capture:
        del p
143
        assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovan's avatar
Dean Moldovan committed
144
145
146
    assert capture == "Releasing parent."

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


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
def test_keep_alive_constructor(capture):
    n_inst = ConstructorStats.detail_reg_inst()

    with capture:
        p = m.Parent(m.Child())
        assert ConstructorStats.detail_reg_inst() == n_inst + 2
    assert capture == """
        Allocating child.
        Allocating parent.
    """
    with capture:
        del p
        assert ConstructorStats.detail_reg_inst() == n_inst
    assert capture == """
        Releasing parent.
        Releasing child.
    """


Dean Moldovan's avatar
Dean Moldovan committed
178
def test_call_guard():
179
180
    assert m.unguarded_call() == "unguarded"
    assert m.guarded_call() == "guarded"
Dean Moldovan's avatar
Dean Moldovan committed
181

182
183
    assert m.multiple_guards_correct_order() == "guarded & guarded"
    assert m.multiple_guards_wrong_order() == "unguarded & guarded"
Dean Moldovan's avatar
Dean Moldovan committed
184

185
186
187
    if hasattr(m, "with_gil"):
        assert m.with_gil() == "GIL held"
        assert m.without_gil() == "GIL released"