Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:57

0001 import pytest
0002 
0003 m = pytest.importorskip("pybind11_tests.smart_ptr")
0004 from pybind11_tests import ConstructorStats  # noqa: E402
0005 
0006 
0007 def test_smart_ptr(capture):
0008     # Object1
0009     for i, o in enumerate(
0010         [m.make_object_1(), m.make_object_2(), m.MyObject1(3)], start=1
0011     ):
0012         assert o.getRefCount() == 1
0013         with capture:
0014             m.print_object_1(o)
0015             m.print_object_2(o)
0016             m.print_object_3(o)
0017             m.print_object_4(o)
0018         assert capture == f"MyObject1[{i}]\n" * 4
0019 
0020     for i, o in enumerate(
0021         [m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7], start=4
0022     ):
0023         print(o)
0024         with capture:
0025             if not isinstance(o, int):
0026                 m.print_object_1(o)
0027                 m.print_object_2(o)
0028                 m.print_object_3(o)
0029                 m.print_object_4(o)
0030             m.print_myobject1_1(o)
0031             m.print_myobject1_2(o)
0032             m.print_myobject1_3(o)
0033             m.print_myobject1_4(o)
0034 
0035         times = 4 if isinstance(o, int) else 8
0036         assert capture == f"MyObject1[{i}]\n" * times
0037 
0038     cstats = ConstructorStats.get(m.MyObject1)
0039     assert cstats.alive() == 0
0040     expected_values = [f"MyObject1[{i}]" for i in range(1, 7)] + ["MyObject1[7]"] * 4
0041     assert cstats.values() == expected_values
0042     assert cstats.default_constructions == 0
0043     assert cstats.copy_constructions == 0
0044     # assert cstats.move_constructions >= 0 # Doesn't invoke any
0045     assert cstats.copy_assignments == 0
0046     assert cstats.move_assignments == 0
0047 
0048     # Object2
0049     for i, o in zip(
0050         [8, 6, 7], [m.MyObject2(8), m.make_myobject2_1(), m.make_myobject2_2()]
0051     ):
0052         print(o)
0053         with capture:
0054             m.print_myobject2_1(o)
0055             m.print_myobject2_2(o)
0056             m.print_myobject2_3(o)
0057             m.print_myobject2_4(o)
0058         assert capture == f"MyObject2[{i}]\n" * 4
0059 
0060     cstats = ConstructorStats.get(m.MyObject2)
0061     assert cstats.alive() == 1
0062     o = None
0063     assert cstats.alive() == 0
0064     assert cstats.values() == ["MyObject2[8]", "MyObject2[6]", "MyObject2[7]"]
0065     assert cstats.default_constructions == 0
0066     assert cstats.copy_constructions == 0
0067     # assert cstats.move_constructions >= 0 # Doesn't invoke any
0068     assert cstats.copy_assignments == 0
0069     assert cstats.move_assignments == 0
0070 
0071     # Object3
0072     for i, o in zip(
0073         [9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()]
0074     ):
0075         print(o)
0076         with capture:
0077             m.print_myobject3_1(o)
0078             m.print_myobject3_2(o)
0079             m.print_myobject3_3(o)
0080             m.print_myobject3_4(o)
0081         assert capture == f"MyObject3[{i}]\n" * 4
0082 
0083     cstats = ConstructorStats.get(m.MyObject3)
0084     assert cstats.alive() == 1
0085     o = None
0086     assert cstats.alive() == 0
0087     assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"]
0088     assert cstats.default_constructions == 0
0089     assert cstats.copy_constructions == 0
0090     # assert cstats.move_constructions >= 0 # Doesn't invoke any
0091     assert cstats.copy_assignments == 0
0092     assert cstats.move_assignments == 0
0093 
0094     # Object
0095     cstats = ConstructorStats.get(m.Object)
0096     assert cstats.alive() == 0
0097     assert cstats.values() == []
0098     assert cstats.default_constructions == 10
0099     assert cstats.copy_constructions == 0
0100     # assert cstats.move_constructions >= 0 # Doesn't invoke any
0101     assert cstats.copy_assignments == 0
0102     assert cstats.move_assignments == 0
0103 
0104     # ref<>
0105     cstats = m.cstats_ref()
0106     assert cstats.alive() == 0
0107     assert cstats.values() == ["from pointer"] * 10
0108     assert cstats.default_constructions == 30
0109     assert cstats.copy_constructions == 12
0110     # assert cstats.move_constructions >= 0 # Doesn't invoke any
0111     assert cstats.copy_assignments == 30
0112     assert cstats.move_assignments == 0
0113 
0114 
0115 def test_smart_ptr_refcounting():
0116     assert m.test_object1_refcounting()
0117 
0118 
0119 def test_unique_nodelete():
0120     o = m.MyObject4(23)
0121     assert o.value == 23
0122     cstats = ConstructorStats.get(m.MyObject4)
0123     assert cstats.alive() == 1
0124     del o
0125     assert cstats.alive() == 1
0126     m.MyObject4.cleanup_all_instances()
0127     assert cstats.alive() == 0
0128 
0129 
0130 def test_unique_nodelete4a():
0131     o = m.MyObject4a(23)
0132     assert o.value == 23
0133     cstats = ConstructorStats.get(m.MyObject4a)
0134     assert cstats.alive() == 1
0135     del o
0136     assert cstats.alive() == 1
0137     m.MyObject4a.cleanup_all_instances()
0138     assert cstats.alive() == 0
0139 
0140 
0141 def test_unique_deleter():
0142     m.MyObject4a(0)
0143     o = m.MyObject4b(23)
0144     assert o.value == 23
0145     cstats4a = ConstructorStats.get(m.MyObject4a)
0146     assert cstats4a.alive() == 2
0147     cstats4b = ConstructorStats.get(m.MyObject4b)
0148     assert cstats4b.alive() == 1
0149     del o
0150     assert cstats4a.alive() == 1  # Should now only be one leftover
0151     assert cstats4b.alive() == 0  # Should be deleted
0152     m.MyObject4a.cleanup_all_instances()
0153     assert cstats4a.alive() == 0
0154     assert cstats4b.alive() == 0
0155 
0156 
0157 def test_large_holder():
0158     o = m.MyObject5(5)
0159     assert o.value == 5
0160     cstats = ConstructorStats.get(m.MyObject5)
0161     assert cstats.alive() == 1
0162     del o
0163     assert cstats.alive() == 0
0164 
0165 
0166 def test_shared_ptr_and_references():
0167     s = m.SharedPtrRef()
0168     stats = ConstructorStats.get(m.A)
0169     assert stats.alive() == 2
0170 
0171     ref = s.ref  # init_holder_helper(holder_ptr=false, owned=false)
0172     assert stats.alive() == 2
0173     assert s.set_ref(ref)
0174     with pytest.raises(RuntimeError) as excinfo:
0175         assert s.set_holder(ref)
0176     assert "Unable to cast from non-held to held instance" in str(excinfo.value)
0177 
0178     copy = s.copy  # init_holder_helper(holder_ptr=false, owned=true)
0179     assert stats.alive() == 3
0180     assert s.set_ref(copy)
0181     assert s.set_holder(copy)
0182 
0183     holder_ref = s.holder_ref  # init_holder_helper(holder_ptr=true, owned=false)
0184     assert stats.alive() == 3
0185     assert s.set_ref(holder_ref)
0186     assert s.set_holder(holder_ref)
0187 
0188     holder_copy = s.holder_copy  # init_holder_helper(holder_ptr=true, owned=true)
0189     assert stats.alive() == 3
0190     assert s.set_ref(holder_copy)
0191     assert s.set_holder(holder_copy)
0192 
0193     del ref, copy, holder_ref, holder_copy, s
0194     assert stats.alive() == 0
0195 
0196 
0197 def test_shared_ptr_from_this_and_references():
0198     s = m.SharedFromThisRef()
0199     stats = ConstructorStats.get(m.B)
0200     assert stats.alive() == 2
0201 
0202     ref = s.ref  # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false)
0203     assert stats.alive() == 2
0204     assert s.set_ref(ref)
0205     assert s.set_holder(
0206         ref
0207     )  # std::enable_shared_from_this can create a holder from a reference
0208 
0209     bad_wp = s.bad_wp  # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true)
0210     assert stats.alive() == 2
0211     assert s.set_ref(bad_wp)
0212     with pytest.raises(RuntimeError) as excinfo:
0213         assert s.set_holder(bad_wp)
0214     assert "Unable to cast from non-held to held instance" in str(excinfo.value)
0215 
0216     copy = s.copy  # init_holder_helper(holder_ptr=false, owned=true, bad_wp=false)
0217     assert stats.alive() == 3
0218     assert s.set_ref(copy)
0219     assert s.set_holder(copy)
0220 
0221     holder_ref = (
0222         s.holder_ref
0223     )  # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false)
0224     assert stats.alive() == 3
0225     assert s.set_ref(holder_ref)
0226     assert s.set_holder(holder_ref)
0227 
0228     holder_copy = (
0229         s.holder_copy
0230     )  # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false)
0231     assert stats.alive() == 3
0232     assert s.set_ref(holder_copy)
0233     assert s.set_holder(holder_copy)
0234 
0235     del ref, bad_wp, copy, holder_ref, holder_copy, s
0236     assert stats.alive() == 0
0237 
0238     z = m.SharedFromThisVirt.get()
0239     y = m.SharedFromThisVirt.get()
0240     assert y is z
0241 
0242 
0243 def test_move_only_holder():
0244     a = m.TypeWithMoveOnlyHolder.make()
0245     b = m.TypeWithMoveOnlyHolder.make_as_object()
0246     stats = ConstructorStats.get(m.TypeWithMoveOnlyHolder)
0247     assert stats.alive() == 2
0248     del b
0249     assert stats.alive() == 1
0250     del a
0251     assert stats.alive() == 0
0252 
0253 
0254 def test_holder_with_addressof_operator():
0255     # this test must not throw exception from c++
0256     a = m.TypeForHolderWithAddressOf.make()
0257     a.print_object_1()
0258     a.print_object_2()
0259     a.print_object_3()
0260     a.print_object_4()
0261 
0262     stats = ConstructorStats.get(m.TypeForHolderWithAddressOf)
0263     assert stats.alive() == 1
0264 
0265     np = m.TypeForHolderWithAddressOf.make()
0266     assert stats.alive() == 2
0267     del a
0268     assert stats.alive() == 1
0269     del np
0270     assert stats.alive() == 0
0271 
0272     b = m.TypeForHolderWithAddressOf.make()
0273     c = b
0274     assert b.get() is c.get()
0275     assert stats.alive() == 1
0276 
0277     del b
0278     assert stats.alive() == 1
0279 
0280     del c
0281     assert stats.alive() == 0
0282 
0283 
0284 def test_move_only_holder_with_addressof_operator():
0285     a = m.TypeForMoveOnlyHolderWithAddressOf.make()
0286     a.print_object()
0287 
0288     stats = ConstructorStats.get(m.TypeForMoveOnlyHolderWithAddressOf)
0289     assert stats.alive() == 1
0290 
0291     a.value = 42
0292     assert a.value == 42
0293 
0294     del a
0295     assert stats.alive() == 0
0296 
0297 
0298 def test_smart_ptr_from_default():
0299     instance = m.HeldByDefaultHolder()
0300     with pytest.raises(RuntimeError) as excinfo:
0301         m.HeldByDefaultHolder.load_shared_ptr(instance)
0302     assert (
0303         "Unable to load a custom holder type from a "
0304         "default-holder instance" in str(excinfo.value)
0305     )
0306 
0307 
0308 def test_shared_ptr_gc():
0309     """#187: issue involving std::shared_ptr<> return value policy & garbage collection"""
0310     el = m.ElementList()
0311     for i in range(10):
0312         el.add(m.ElementA(i))
0313     pytest.gc_collect()
0314     for i, v in enumerate(el.get()):
0315         assert i == v.value()