blob: ec005c132f9c172fda1570073ada46342e38a2ea [file] [log] [blame]
Henry Schreinerd8c7ee02020-07-20 13:35:21 -04001# -*- coding: utf-8 -*-
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +01002import pytest
Henry Schreiner4d9024e2020-08-16 16:02:12 -04003
4import env # noqa: F401
5
Jason Rhinelander391c7542017-07-25 16:47:36 -04006from pybind11_tests import call_policies as m
7from pybind11_tests import ConstructorStats
Dean Moldovana0c1ccf2016-08-12 13:50:00 +02008
9
Henry Schreiner4d9024e2020-08-16 16:02:12 -040010@pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020011def test_keep_alive_argument(capture):
Bruce Merry9d698f72017-06-24 14:58:42 +020012 n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020013 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040014 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020015 assert capture == "Allocating parent."
16 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040017 p.addChild(m.Child())
Bruce Merry9d698f72017-06-24 14:58:42 +020018 assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020019 assert capture == """
20 Allocating child.
21 Releasing child.
22 """
23 with capture:
24 del p
Bruce Merry9d698f72017-06-24 14:58:42 +020025 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020026 assert capture == "Releasing parent."
27
28 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040029 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020030 assert capture == "Allocating parent."
31 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040032 p.addChildKeepAlive(m.Child())
Bruce Merry9d698f72017-06-24 14:58:42 +020033 assert ConstructorStats.detail_reg_inst() == n_inst + 2
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020034 assert capture == "Allocating child."
35 with capture:
36 del p
Bruce Merry9d698f72017-06-24 14:58:42 +020037 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020038 assert capture == """
39 Releasing parent.
40 Releasing child.
41 """
42
43
44def test_keep_alive_return_value(capture):
Bruce Merry9d698f72017-06-24 14:58:42 +020045 n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020046 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040047 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020048 assert capture == "Allocating parent."
49 with capture:
50 p.returnChild()
Bruce Merry9d698f72017-06-24 14:58:42 +020051 assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020052 assert capture == """
53 Allocating child.
54 Releasing child.
55 """
56 with capture:
57 del p
Bruce Merry9d698f72017-06-24 14:58:42 +020058 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020059 assert capture == "Releasing parent."
60
61 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -040062 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020063 assert capture == "Allocating parent."
64 with capture:
65 p.returnChildKeepAlive()
Bruce Merry9d698f72017-06-24 14:58:42 +020066 assert ConstructorStats.detail_reg_inst() == n_inst + 2
Dean Moldovana0c1ccf2016-08-12 13:50:00 +020067 assert capture == "Allocating child."
68 with capture:
69 del p
Bruce Merry9d698f72017-06-24 14:58:42 +020070 assert ConstructorStats.detail_reg_inst() == n_inst
71 assert capture == """
72 Releasing parent.
73 Releasing child.
74 """
75
76
Henry Schreiner4d9024e2020-08-16 16:02:12 -040077# https://foss.heptapod.net/pypy/pypy/-/issues/2447
78@pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
Bruce Merry9d698f72017-06-24 14:58:42 +020079def test_alive_gc(capture):
Bruce Merry9d698f72017-06-24 14:58:42 +020080 n_inst = ConstructorStats.detail_reg_inst()
Jason Rhinelander391c7542017-07-25 16:47:36 -040081 p = m.ParentGC()
82 p.addChildKeepAlive(m.Child())
Bruce Merry9d698f72017-06-24 14:58:42 +020083 assert ConstructorStats.detail_reg_inst() == n_inst + 2
84 lst = [p]
85 lst.append(lst) # creates a circular reference
86 with capture:
87 del p, lst
88 assert ConstructorStats.detail_reg_inst() == n_inst
89 assert capture == """
90 Releasing parent.
91 Releasing child.
92 """
93
94
95def test_alive_gc_derived(capture):
Jason Rhinelander391c7542017-07-25 16:47:36 -040096 class Derived(m.Parent):
Bruce Merry9d698f72017-06-24 14:58:42 +020097 pass
98
99 n_inst = ConstructorStats.detail_reg_inst()
100 p = Derived()
Jason Rhinelander391c7542017-07-25 16:47:36 -0400101 p.addChildKeepAlive(m.Child())
Bruce Merry9d698f72017-06-24 14:58:42 +0200102 assert ConstructorStats.detail_reg_inst() == n_inst + 2
103 lst = [p]
104 lst.append(lst) # creates a circular reference
105 with capture:
106 del p, lst
107 assert ConstructorStats.detail_reg_inst() == n_inst
108 assert capture == """
109 Releasing parent.
110 Releasing child.
111 """
112
113
114def test_alive_gc_multi_derived(capture):
Jason Rhinelander391c7542017-07-25 16:47:36 -0400115 class Derived(m.Parent, m.Child):
Jason Rhinelander353615f2017-07-25 00:53:23 -0400116 def __init__(self):
Jason Rhinelander391c7542017-07-25 16:47:36 -0400117 m.Parent.__init__(self)
118 m.Child.__init__(self)
Bruce Merry9d698f72017-06-24 14:58:42 +0200119
120 n_inst = ConstructorStats.detail_reg_inst()
121 p = Derived()
Jason Rhinelander391c7542017-07-25 16:47:36 -0400122 p.addChildKeepAlive(m.Child())
Bruce Merry9d698f72017-06-24 14:58:42 +0200123 # +3 rather than +2 because Derived corresponds to two registered instances
124 assert ConstructorStats.detail_reg_inst() == n_inst + 3
125 lst = [p]
126 lst.append(lst) # creates a circular reference
127 with capture:
128 del p, lst
129 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200130 assert capture == """
131 Releasing parent.
132 Releasing child.
Jason Rhinelander353615f2017-07-25 00:53:23 -0400133 Releasing child.
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200134 """
135
136
137def test_return_none(capture):
Bruce Merry9d698f72017-06-24 14:58:42 +0200138 n_inst = ConstructorStats.detail_reg_inst()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200139 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -0400140 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200141 assert capture == "Allocating parent."
142 with capture:
143 p.returnNullChildKeepAliveChild()
Bruce Merry9d698f72017-06-24 14:58:42 +0200144 assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200145 assert capture == ""
146 with capture:
147 del p
Bruce Merry9d698f72017-06-24 14:58:42 +0200148 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200149 assert capture == "Releasing parent."
150
151 with capture:
Jason Rhinelander391c7542017-07-25 16:47:36 -0400152 p = m.Parent()
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200153 assert capture == "Allocating parent."
154 with capture:
155 p.returnNullChildKeepAliveParent()
Bruce Merry9d698f72017-06-24 14:58:42 +0200156 assert ConstructorStats.detail_reg_inst() == n_inst + 1
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200157 assert capture == ""
158 with capture:
159 del p
Bruce Merry9d698f72017-06-24 14:58:42 +0200160 assert ConstructorStats.detail_reg_inst() == n_inst
Dean Moldovana0c1ccf2016-08-12 13:50:00 +0200161 assert capture == "Releasing parent."
Dean Moldovan1ac19032017-03-16 11:22:26 +0100162
163
Dean Moldovan7939f4b2017-09-04 13:49:19 +0200164def test_keep_alive_constructor(capture):
165 n_inst = ConstructorStats.detail_reg_inst()
166
167 with capture:
168 p = m.Parent(m.Child())
169 assert ConstructorStats.detail_reg_inst() == n_inst + 2
170 assert capture == """
171 Allocating child.
172 Allocating parent.
173 """
174 with capture:
175 del p
176 assert ConstructorStats.detail_reg_inst() == n_inst
177 assert capture == """
178 Releasing parent.
179 Releasing child.
180 """
181
182
Dean Moldovan1ac19032017-03-16 11:22:26 +0100183def test_call_guard():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400184 assert m.unguarded_call() == "unguarded"
185 assert m.guarded_call() == "guarded"
Dean Moldovan1ac19032017-03-16 11:22:26 +0100186
Jason Rhinelander391c7542017-07-25 16:47:36 -0400187 assert m.multiple_guards_correct_order() == "guarded & guarded"
188 assert m.multiple_guards_wrong_order() == "unguarded & guarded"
Dean Moldovan1ac19032017-03-16 11:22:26 +0100189
Jason Rhinelander391c7542017-07-25 16:47:36 -0400190 if hasattr(m, "with_gil"):
191 assert m.with_gil() == "GIL held"
192 assert m.without_gil() == "GIL released"