test_call_policies.py 5 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
119
120
121
122
123
124
125
126
127
128
129
130
        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):
        pass

    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
131
132
133
134
135
136
137
    assert capture == """
        Releasing parent.
        Releasing child.
    """


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

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

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


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"