test_call_policies.py 4.73 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


def test_call_guard():
160
161
    assert m.unguarded_call() == "unguarded"
    assert m.guarded_call() == "guarded"
Dean Moldovan's avatar
Dean Moldovan committed
162

163
164
    assert m.multiple_guards_correct_order() == "guarded & guarded"
    assert m.multiple_guards_wrong_order() == "unguarded & guarded"
Dean Moldovan's avatar
Dean Moldovan committed
165

166
167
168
    if hasattr(m, "with_gil"):
        assert m.with_gil() == "GIL held"
        assert m.without_gil() == "GIL released"