1import pytest 2from pybind11_tests import call_policies as m 3from pybind11_tests import ConstructorStats 4 5 6def test_keep_alive_argument(capture): 7 n_inst = ConstructorStats.detail_reg_inst() 8 with capture: 9 p = m.Parent() 10 assert capture == "Allocating parent." 11 with capture: 12 p.addChild(m.Child()) 13 assert ConstructorStats.detail_reg_inst() == n_inst + 1 14 assert capture == """ 15 Allocating child. 16 Releasing child. 17 """ 18 with capture: 19 del p 20 assert ConstructorStats.detail_reg_inst() == n_inst 21 assert capture == "Releasing parent." 22 23 with capture: 24 p = m.Parent() 25 assert capture == "Allocating parent." 26 with capture: 27 p.addChildKeepAlive(m.Child()) 28 assert ConstructorStats.detail_reg_inst() == n_inst + 2 29 assert capture == "Allocating child." 30 with capture: 31 del p 32 assert ConstructorStats.detail_reg_inst() == n_inst 33 assert capture == """ 34 Releasing parent. 35 Releasing child. 36 """ 37 38 39def test_keep_alive_return_value(capture): 40 n_inst = ConstructorStats.detail_reg_inst() 41 with capture: 42 p = m.Parent() 43 assert capture == "Allocating parent." 44 with capture: 45 p.returnChild() 46 assert ConstructorStats.detail_reg_inst() == n_inst + 1 47 assert capture == """ 48 Allocating child. 49 Releasing child. 50 """ 51 with capture: 52 del p 53 assert ConstructorStats.detail_reg_inst() == n_inst 54 assert capture == "Releasing parent." 55 56 with capture: 57 p = m.Parent() 58 assert capture == "Allocating parent." 59 with capture: 60 p.returnChildKeepAlive() 61 assert ConstructorStats.detail_reg_inst() == n_inst + 2 62 assert capture == "Allocating child." 63 with capture: 64 del p 65 assert ConstructorStats.detail_reg_inst() == n_inst 66 assert capture == """ 67 Releasing parent. 68 Releasing child. 69 """ 70 71 72# https://bitbucket.org/pypy/pypy/issues/2447 73@pytest.unsupported_on_pypy 74def test_alive_gc(capture): 75 n_inst = ConstructorStats.detail_reg_inst() 76 p = m.ParentGC() 77 p.addChildKeepAlive(m.Child()) 78 assert ConstructorStats.detail_reg_inst() == n_inst + 2 79 lst = [p] 80 lst.append(lst) # creates a circular reference 81 with capture: 82 del p, lst 83 assert ConstructorStats.detail_reg_inst() == n_inst 84 assert capture == """ 85 Releasing parent. 86 Releasing child. 87 """ 88 89 90def test_alive_gc_derived(capture): 91 class Derived(m.Parent): 92 pass 93 94 n_inst = ConstructorStats.detail_reg_inst() 95 p = Derived() 96 p.addChildKeepAlive(m.Child()) 97 assert ConstructorStats.detail_reg_inst() == n_inst + 2 98 lst = [p] 99 lst.append(lst) # creates a circular reference 100 with capture: 101 del p, lst 102 assert ConstructorStats.detail_reg_inst() == n_inst 103 assert capture == """ 104 Releasing parent. 105 Releasing child. 106 """ 107 108 109def test_alive_gc_multi_derived(capture): 110 class Derived(m.Parent, m.Child): 111 def __init__(self): 112 m.Parent.__init__(self) 113 m.Child.__init__(self) 114 115 n_inst = ConstructorStats.detail_reg_inst() 116 p = Derived() 117 p.addChildKeepAlive(m.Child()) 118 # +3 rather than +2 because Derived corresponds to two registered instances 119 assert ConstructorStats.detail_reg_inst() == n_inst + 3 120 lst = [p] 121 lst.append(lst) # creates a circular reference 122 with capture: 123 del p, lst 124 assert ConstructorStats.detail_reg_inst() == n_inst 125 assert capture == """ 126 Releasing parent. 127 Releasing child. 128 Releasing child. 129 """ 130 131 132def test_return_none(capture): 133 n_inst = ConstructorStats.detail_reg_inst() 134 with capture: 135 p = m.Parent() 136 assert capture == "Allocating parent." 137 with capture: 138 p.returnNullChildKeepAliveChild() 139 assert ConstructorStats.detail_reg_inst() == n_inst + 1 140 assert capture == "" 141 with capture: 142 del p 143 assert ConstructorStats.detail_reg_inst() == n_inst 144 assert capture == "Releasing parent." 145 146 with capture: 147 p = m.Parent() 148 assert capture == "Allocating parent." 149 with capture: 150 p.returnNullChildKeepAliveParent() 151 assert ConstructorStats.detail_reg_inst() == n_inst + 1 152 assert capture == "" 153 with capture: 154 del p 155 assert ConstructorStats.detail_reg_inst() == n_inst 156 assert capture == "Releasing parent." 157 158 159def test_keep_alive_constructor(capture): 160 n_inst = ConstructorStats.detail_reg_inst() 161 162 with capture: 163 p = m.Parent(m.Child()) 164 assert ConstructorStats.detail_reg_inst() == n_inst + 2 165 assert capture == """ 166 Allocating child. 167 Allocating parent. 168 """ 169 with capture: 170 del p 171 assert ConstructorStats.detail_reg_inst() == n_inst 172 assert capture == """ 173 Releasing parent. 174 Releasing child. 175 """ 176 177 178def test_call_guard(): 179 assert m.unguarded_call() == "unguarded" 180 assert m.guarded_call() == "guarded" 181 182 assert m.multiple_guards_correct_order() == "guarded & guarded" 183 assert m.multiple_guards_wrong_order() == "unguarded & guarded" 184 185 if hasattr(m, "with_gil"): 186 assert m.with_gil() == "GIL held" 187 assert m.without_gil() == "GIL released" 188