forked from pybind/pybind11
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest_trampoline_shared_ptr_cpp_arg.py
131 lines (94 loc) · 3.26 KB
/
test_trampoline_shared_ptr_cpp_arg.py
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
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
131
# -*- coding: utf-8 -*-
import pytest
import pybind11_tests.trampoline_shared_ptr_cpp_arg as m
def test_shared_ptr_cpp_arg():
import weakref
class PyChild(m.SpBase):
def is_base_used(self):
return False
tester = m.SpBaseTester()
obj = PyChild()
objref = weakref.ref(obj)
# Pass the last python reference to the C++ function
tester.set_object(obj)
del obj
pytest.gc_collect()
# python reference is still around since C++ has it now
assert objref() is not None
assert tester.is_base_used() is False
assert tester.obj.is_base_used() is False
assert tester.get_object() is objref()
def test_shared_ptr_cpp_prop():
class PyChild(m.SpBase):
def is_base_used(self):
return False
tester = m.SpBaseTester()
# Set the last python reference as a property of the C++ object
tester.obj = PyChild()
pytest.gc_collect()
# python reference is still around since C++ has it now
assert tester.is_base_used() is False
assert tester.has_python_instance() is True
assert tester.obj.is_base_used() is False
assert tester.obj.has_python_instance() is True
def test_shared_ptr_arg_identity():
import weakref
tester = m.SpBaseTester()
obj = m.SpBase()
objref = weakref.ref(obj)
tester.set_object(obj)
del obj
pytest.gc_collect()
# python reference is still around since C++ has it
assert objref() is not None
assert tester.get_object() is objref()
assert tester.has_python_instance() is True
# python reference disappears once the C++ object releases it
tester.set_object(None)
pytest.gc_collect()
assert objref() is None
def test_shared_ptr_alias_nonpython():
tester = m.SpBaseTester()
# C++ creates the object, a python instance shouldn't exist
tester.set_nonpython_instance()
assert tester.is_base_used() is True
assert tester.has_instance() is True
assert tester.has_python_instance() is False
# Now a python instance exists
cobj = tester.get_object()
assert cobj.has_python_instance()
assert tester.has_instance() is True
assert tester.has_python_instance() is True
# Now it's gone
del cobj
pytest.gc_collect()
assert tester.has_instance() is True
assert tester.has_python_instance() is False
# When we pass it as an arg to a new tester the python instance should
# disappear because it wasn't created with an alias
new_tester = m.SpBaseTester()
cobj = tester.get_object()
assert cobj.has_python_instance()
new_tester.set_object(cobj)
assert tester.has_python_instance() is True
assert new_tester.has_python_instance() is True
del cobj
pytest.gc_collect()
# Gone!
assert tester.has_instance() is True
assert tester.has_python_instance() is False
assert new_tester.has_instance() is True
assert new_tester.has_python_instance() is False
def test_shared_ptr_goaway():
import weakref
tester = m.SpGoAwayTester()
obj = m.SpGoAway()
objref = weakref.ref(obj)
assert tester.obj is None
tester.obj = obj
del obj
pytest.gc_collect()
# python reference is no longer around
assert objref() is None
# C++ reference is still around
assert tester.obj is not None