You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
7.9 KiB

8 years ago
8 years ago
  1. import pytest
  2. from pybind11_tests import ConstructorStats
  3. def test_smart_ptr(capture):
  4. # Object1
  5. from pybind11_tests import (MyObject1, make_object_1, make_object_2,
  6. print_object_1, print_object_2, print_object_3, print_object_4)
  7. for i, o in enumerate([make_object_1(), make_object_2(), MyObject1(3)], start=1):
  8. assert o.getRefCount() == 1
  9. with capture:
  10. print_object_1(o)
  11. print_object_2(o)
  12. print_object_3(o)
  13. print_object_4(o)
  14. assert capture == "MyObject1[{i}]\n".format(i=i) * 4
  15. from pybind11_tests import (make_myobject1_1, make_myobject1_2,
  16. print_myobject1_1, print_myobject1_2,
  17. print_myobject1_3, print_myobject1_4)
  18. for i, o in enumerate([make_myobject1_1(), make_myobject1_2(), MyObject1(6), 7], start=4):
  19. print(o)
  20. with capture:
  21. if not isinstance(o, int):
  22. print_object_1(o)
  23. print_object_2(o)
  24. print_object_3(o)
  25. print_object_4(o)
  26. print_myobject1_1(o)
  27. print_myobject1_2(o)
  28. print_myobject1_3(o)
  29. print_myobject1_4(o)
  30. assert capture == "MyObject1[{i}]\n".format(i=i) * (4 if isinstance(o, int) else 8)
  31. cstats = ConstructorStats.get(MyObject1)
  32. assert cstats.alive() == 0
  33. expected_values = ['MyObject1[{}]'.format(i) for i in range(1, 7)] + ['MyObject1[7]'] * 4
  34. assert cstats.values() == expected_values
  35. assert cstats.default_constructions == 0
  36. assert cstats.copy_constructions == 0
  37. # assert cstats.move_constructions >= 0 # Doesn't invoke any
  38. assert cstats.copy_assignments == 0
  39. assert cstats.move_assignments == 0
  40. # Object2
  41. from pybind11_tests import (MyObject2, make_myobject2_1, make_myobject2_2,
  42. make_myobject3_1, make_myobject3_2,
  43. print_myobject2_1, print_myobject2_2,
  44. print_myobject2_3, print_myobject2_4)
  45. for i, o in zip([8, 6, 7], [MyObject2(8), make_myobject2_1(), make_myobject2_2()]):
  46. print(o)
  47. with capture:
  48. print_myobject2_1(o)
  49. print_myobject2_2(o)
  50. print_myobject2_3(o)
  51. print_myobject2_4(o)
  52. assert capture == "MyObject2[{i}]\n".format(i=i) * 4
  53. cstats = ConstructorStats.get(MyObject2)
  54. assert cstats.alive() == 1
  55. o = None
  56. assert cstats.alive() == 0
  57. assert cstats.values() == ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]']
  58. assert cstats.default_constructions == 0
  59. assert cstats.copy_constructions == 0
  60. # assert cstats.move_constructions >= 0 # Doesn't invoke any
  61. assert cstats.copy_assignments == 0
  62. assert cstats.move_assignments == 0
  63. # Object3
  64. from pybind11_tests import (MyObject3, print_myobject3_1, print_myobject3_2,
  65. print_myobject3_3, print_myobject3_4)
  66. for i, o in zip([9, 8, 9], [MyObject3(9), make_myobject3_1(), make_myobject3_2()]):
  67. print(o)
  68. with capture:
  69. print_myobject3_1(o)
  70. print_myobject3_2(o)
  71. print_myobject3_3(o)
  72. print_myobject3_4(o)
  73. assert capture == "MyObject3[{i}]\n".format(i=i) * 4
  74. cstats = ConstructorStats.get(MyObject3)
  75. assert cstats.alive() == 1
  76. o = None
  77. assert cstats.alive() == 0
  78. assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]']
  79. assert cstats.default_constructions == 0
  80. assert cstats.copy_constructions == 0
  81. # assert cstats.move_constructions >= 0 # Doesn't invoke any
  82. assert cstats.copy_assignments == 0
  83. assert cstats.move_assignments == 0
  84. # Object and ref
  85. from pybind11_tests import Object, cstats_ref
  86. cstats = ConstructorStats.get(Object)
  87. assert cstats.alive() == 0
  88. assert cstats.values() == []
  89. assert cstats.default_constructions == 10
  90. assert cstats.copy_constructions == 0
  91. # assert cstats.move_constructions >= 0 # Doesn't invoke any
  92. assert cstats.copy_assignments == 0
  93. assert cstats.move_assignments == 0
  94. cstats = cstats_ref()
  95. assert cstats.alive() == 0
  96. assert cstats.values() == ['from pointer'] * 10
  97. assert cstats.default_constructions == 30
  98. assert cstats.copy_constructions == 12
  99. # assert cstats.move_constructions >= 0 # Doesn't invoke any
  100. assert cstats.copy_assignments == 30
  101. assert cstats.move_assignments == 0
  102. def test_smart_ptr_refcounting():
  103. from pybind11_tests import test_object1_refcounting
  104. assert test_object1_refcounting()
  105. def test_unique_nodelete():
  106. from pybind11_tests import MyObject4
  107. o = MyObject4(23)
  108. assert o.value == 23
  109. cstats = ConstructorStats.get(MyObject4)
  110. assert cstats.alive() == 1
  111. del o
  112. cstats = ConstructorStats.get(MyObject4)
  113. assert cstats.alive() == 1 # Leak, but that's intentional
  114. def test_shared_ptr_and_references():
  115. from pybind11_tests.smart_ptr import SharedPtrRef, A
  116. s = SharedPtrRef()
  117. stats = ConstructorStats.get(A)
  118. assert stats.alive() == 2
  119. ref = s.ref # init_holder_helper(holder_ptr=false, owned=false)
  120. assert stats.alive() == 2
  121. assert s.set_ref(ref)
  122. with pytest.raises(RuntimeError) as excinfo:
  123. assert s.set_holder(ref)
  124. assert "Unable to cast from non-held to held instance" in str(excinfo.value)
  125. copy = s.copy # init_holder_helper(holder_ptr=false, owned=true)
  126. assert stats.alive() == 3
  127. assert s.set_ref(copy)
  128. assert s.set_holder(copy)
  129. holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false)
  130. assert stats.alive() == 3
  131. assert s.set_ref(holder_ref)
  132. assert s.set_holder(holder_ref)
  133. holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true)
  134. assert stats.alive() == 3
  135. assert s.set_ref(holder_copy)
  136. assert s.set_holder(holder_copy)
  137. del ref, copy, holder_ref, holder_copy, s
  138. assert stats.alive() == 0
  139. def test_shared_ptr_from_this_and_references():
  140. from pybind11_tests.smart_ptr import SharedFromThisRef, B
  141. s = SharedFromThisRef()
  142. stats = ConstructorStats.get(B)
  143. assert stats.alive() == 2
  144. ref = s.ref # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false)
  145. assert stats.alive() == 2
  146. assert s.set_ref(ref)
  147. assert s.set_holder(ref) # std::enable_shared_from_this can create a holder from a reference
  148. bad_wp = s.bad_wp # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true)
  149. assert stats.alive() == 2
  150. assert s.set_ref(bad_wp)
  151. with pytest.raises(RuntimeError) as excinfo:
  152. assert s.set_holder(bad_wp)
  153. assert "Unable to cast from non-held to held instance" in str(excinfo.value)
  154. copy = s.copy # init_holder_helper(holder_ptr=false, owned=true, bad_wp=false)
  155. assert stats.alive() == 3
  156. assert s.set_ref(copy)
  157. assert s.set_holder(copy)
  158. holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false)
  159. assert stats.alive() == 3
  160. assert s.set_ref(holder_ref)
  161. assert s.set_holder(holder_ref)
  162. holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false)
  163. assert stats.alive() == 3
  164. assert s.set_ref(holder_copy)
  165. assert s.set_holder(holder_copy)
  166. del ref, bad_wp, copy, holder_ref, holder_copy, s
  167. assert stats.alive() == 0
  168. def test_move_only_holder():
  169. from pybind11_tests.smart_ptr import TypeWithMoveOnlyHolder
  170. a = TypeWithMoveOnlyHolder.make()
  171. stats = ConstructorStats.get(TypeWithMoveOnlyHolder)
  172. assert stats.alive() == 1
  173. del a
  174. assert stats.alive() == 0
  175. def test_smart_ptr_from_default():
  176. from pybind11_tests.smart_ptr import HeldByDefaultHolder
  177. instance = HeldByDefaultHolder()
  178. with pytest.raises(RuntimeError) as excinfo:
  179. HeldByDefaultHolder.load_shared_ptr(instance)
  180. assert "Unable to load a custom holder type from a default-holder instance" in str(excinfo)