111986Sandreas.sandberg@arm.comimport pytest 212391Sjason@lowepower.comfrom pybind11_tests import smart_ptr as m 311986Sandreas.sandberg@arm.comfrom pybind11_tests import ConstructorStats 411986Sandreas.sandberg@arm.com 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.comdef test_smart_ptr(capture): 711986Sandreas.sandberg@arm.com # Object1 812391Sjason@lowepower.com for i, o in enumerate([m.make_object_1(), m.make_object_2(), m.MyObject1(3)], start=1): 911986Sandreas.sandberg@arm.com assert o.getRefCount() == 1 1011986Sandreas.sandberg@arm.com with capture: 1112391Sjason@lowepower.com m.print_object_1(o) 1212391Sjason@lowepower.com m.print_object_2(o) 1312391Sjason@lowepower.com m.print_object_3(o) 1412391Sjason@lowepower.com m.print_object_4(o) 1511986Sandreas.sandberg@arm.com assert capture == "MyObject1[{i}]\n".format(i=i) * 4 1611986Sandreas.sandberg@arm.com 1712391Sjason@lowepower.com for i, o in enumerate([m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7], 1812391Sjason@lowepower.com start=4): 1911986Sandreas.sandberg@arm.com print(o) 2011986Sandreas.sandberg@arm.com with capture: 2111986Sandreas.sandberg@arm.com if not isinstance(o, int): 2212391Sjason@lowepower.com m.print_object_1(o) 2312391Sjason@lowepower.com m.print_object_2(o) 2412391Sjason@lowepower.com m.print_object_3(o) 2512391Sjason@lowepower.com m.print_object_4(o) 2612391Sjason@lowepower.com m.print_myobject1_1(o) 2712391Sjason@lowepower.com m.print_myobject1_2(o) 2812391Sjason@lowepower.com m.print_myobject1_3(o) 2912391Sjason@lowepower.com m.print_myobject1_4(o) 3011986Sandreas.sandberg@arm.com assert capture == "MyObject1[{i}]\n".format(i=i) * (4 if isinstance(o, int) else 8) 3111986Sandreas.sandberg@arm.com 3212391Sjason@lowepower.com cstats = ConstructorStats.get(m.MyObject1) 3311986Sandreas.sandberg@arm.com assert cstats.alive() == 0 3411986Sandreas.sandberg@arm.com expected_values = ['MyObject1[{}]'.format(i) for i in range(1, 7)] + ['MyObject1[7]'] * 4 3511986Sandreas.sandberg@arm.com assert cstats.values() == expected_values 3611986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 3711986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 3811986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 3911986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 4011986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 4111986Sandreas.sandberg@arm.com 4211986Sandreas.sandberg@arm.com # Object2 4312391Sjason@lowepower.com for i, o in zip([8, 6, 7], [m.MyObject2(8), m.make_myobject2_1(), m.make_myobject2_2()]): 4411986Sandreas.sandberg@arm.com print(o) 4511986Sandreas.sandberg@arm.com with capture: 4612391Sjason@lowepower.com m.print_myobject2_1(o) 4712391Sjason@lowepower.com m.print_myobject2_2(o) 4812391Sjason@lowepower.com m.print_myobject2_3(o) 4912391Sjason@lowepower.com m.print_myobject2_4(o) 5011986Sandreas.sandberg@arm.com assert capture == "MyObject2[{i}]\n".format(i=i) * 4 5111986Sandreas.sandberg@arm.com 5212391Sjason@lowepower.com cstats = ConstructorStats.get(m.MyObject2) 5311986Sandreas.sandberg@arm.com assert cstats.alive() == 1 5411986Sandreas.sandberg@arm.com o = None 5511986Sandreas.sandberg@arm.com assert cstats.alive() == 0 5611986Sandreas.sandberg@arm.com assert cstats.values() == ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]'] 5711986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 5811986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 5911986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 6011986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 6111986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 6211986Sandreas.sandberg@arm.com 6311986Sandreas.sandberg@arm.com # Object3 6412391Sjason@lowepower.com for i, o in zip([9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()]): 6511986Sandreas.sandberg@arm.com print(o) 6611986Sandreas.sandberg@arm.com with capture: 6712391Sjason@lowepower.com m.print_myobject3_1(o) 6812391Sjason@lowepower.com m.print_myobject3_2(o) 6912391Sjason@lowepower.com m.print_myobject3_3(o) 7012391Sjason@lowepower.com m.print_myobject3_4(o) 7111986Sandreas.sandberg@arm.com assert capture == "MyObject3[{i}]\n".format(i=i) * 4 7211986Sandreas.sandberg@arm.com 7312391Sjason@lowepower.com cstats = ConstructorStats.get(m.MyObject3) 7411986Sandreas.sandberg@arm.com assert cstats.alive() == 1 7511986Sandreas.sandberg@arm.com o = None 7611986Sandreas.sandberg@arm.com assert cstats.alive() == 0 7711986Sandreas.sandberg@arm.com assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]'] 7811986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 7911986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 8011986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 8111986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 8211986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 8311986Sandreas.sandberg@arm.com 8412391Sjason@lowepower.com # Object 8512391Sjason@lowepower.com cstats = ConstructorStats.get(m.Object) 8611986Sandreas.sandberg@arm.com assert cstats.alive() == 0 8711986Sandreas.sandberg@arm.com assert cstats.values() == [] 8811986Sandreas.sandberg@arm.com assert cstats.default_constructions == 10 8911986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 9011986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 9111986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 9211986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 9311986Sandreas.sandberg@arm.com 9412391Sjason@lowepower.com # ref<> 9512391Sjason@lowepower.com cstats = m.cstats_ref() 9611986Sandreas.sandberg@arm.com assert cstats.alive() == 0 9711986Sandreas.sandberg@arm.com assert cstats.values() == ['from pointer'] * 10 9811986Sandreas.sandberg@arm.com assert cstats.default_constructions == 30 9911986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 12 10011986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 10111986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 30 10211986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 10311986Sandreas.sandberg@arm.com 10411986Sandreas.sandberg@arm.com 10512037Sandreas.sandberg@arm.comdef test_smart_ptr_refcounting(): 10612391Sjason@lowepower.com assert m.test_object1_refcounting() 10712037Sandreas.sandberg@arm.com 10812037Sandreas.sandberg@arm.com 10911986Sandreas.sandberg@arm.comdef test_unique_nodelete(): 11012391Sjason@lowepower.com o = m.MyObject4(23) 11111986Sandreas.sandberg@arm.com assert o.value == 23 11212391Sjason@lowepower.com cstats = ConstructorStats.get(m.MyObject4) 11311986Sandreas.sandberg@arm.com assert cstats.alive() == 1 11411986Sandreas.sandberg@arm.com del o 11511986Sandreas.sandberg@arm.com assert cstats.alive() == 1 # Leak, but that's intentional 11611986Sandreas.sandberg@arm.com 11711986Sandreas.sandberg@arm.com 11814299Sbbruce@ucdavis.edudef test_unique_nodelete4a(): 11914299Sbbruce@ucdavis.edu o = m.MyObject4a(23) 12014299Sbbruce@ucdavis.edu assert o.value == 23 12114299Sbbruce@ucdavis.edu cstats = ConstructorStats.get(m.MyObject4a) 12214299Sbbruce@ucdavis.edu assert cstats.alive() == 1 12314299Sbbruce@ucdavis.edu del o 12414299Sbbruce@ucdavis.edu assert cstats.alive() == 1 # Leak, but that's intentional 12514299Sbbruce@ucdavis.edu 12614299Sbbruce@ucdavis.edu 12714299Sbbruce@ucdavis.edudef test_unique_deleter(): 12814299Sbbruce@ucdavis.edu o = m.MyObject4b(23) 12914299Sbbruce@ucdavis.edu assert o.value == 23 13014299Sbbruce@ucdavis.edu cstats4a = ConstructorStats.get(m.MyObject4a) 13114299Sbbruce@ucdavis.edu assert cstats4a.alive() == 2 # Two because of previous test 13214299Sbbruce@ucdavis.edu cstats4b = ConstructorStats.get(m.MyObject4b) 13314299Sbbruce@ucdavis.edu assert cstats4b.alive() == 1 13414299Sbbruce@ucdavis.edu del o 13514299Sbbruce@ucdavis.edu assert cstats4a.alive() == 1 # Should now only be one leftover from previous test 13614299Sbbruce@ucdavis.edu assert cstats4b.alive() == 0 # Should be deleted 13714299Sbbruce@ucdavis.edu 13814299Sbbruce@ucdavis.edu 13912391Sjason@lowepower.comdef test_large_holder(): 14012391Sjason@lowepower.com o = m.MyObject5(5) 14112391Sjason@lowepower.com assert o.value == 5 14212391Sjason@lowepower.com cstats = ConstructorStats.get(m.MyObject5) 14312391Sjason@lowepower.com assert cstats.alive() == 1 14412391Sjason@lowepower.com del o 14512391Sjason@lowepower.com assert cstats.alive() == 0 14612391Sjason@lowepower.com 14712391Sjason@lowepower.com 14811986Sandreas.sandberg@arm.comdef test_shared_ptr_and_references(): 14912391Sjason@lowepower.com s = m.SharedPtrRef() 15012391Sjason@lowepower.com stats = ConstructorStats.get(m.A) 15111986Sandreas.sandberg@arm.com assert stats.alive() == 2 15211986Sandreas.sandberg@arm.com 15311986Sandreas.sandberg@arm.com ref = s.ref # init_holder_helper(holder_ptr=false, owned=false) 15411986Sandreas.sandberg@arm.com assert stats.alive() == 2 15511986Sandreas.sandberg@arm.com assert s.set_ref(ref) 15611986Sandreas.sandberg@arm.com with pytest.raises(RuntimeError) as excinfo: 15711986Sandreas.sandberg@arm.com assert s.set_holder(ref) 15811986Sandreas.sandberg@arm.com assert "Unable to cast from non-held to held instance" in str(excinfo.value) 15911986Sandreas.sandberg@arm.com 16011986Sandreas.sandberg@arm.com copy = s.copy # init_holder_helper(holder_ptr=false, owned=true) 16111986Sandreas.sandberg@arm.com assert stats.alive() == 3 16211986Sandreas.sandberg@arm.com assert s.set_ref(copy) 16311986Sandreas.sandberg@arm.com assert s.set_holder(copy) 16411986Sandreas.sandberg@arm.com 16511986Sandreas.sandberg@arm.com holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false) 16611986Sandreas.sandberg@arm.com assert stats.alive() == 3 16711986Sandreas.sandberg@arm.com assert s.set_ref(holder_ref) 16811986Sandreas.sandberg@arm.com assert s.set_holder(holder_ref) 16911986Sandreas.sandberg@arm.com 17011986Sandreas.sandberg@arm.com holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true) 17111986Sandreas.sandberg@arm.com assert stats.alive() == 3 17211986Sandreas.sandberg@arm.com assert s.set_ref(holder_copy) 17311986Sandreas.sandberg@arm.com assert s.set_holder(holder_copy) 17411986Sandreas.sandberg@arm.com 17511986Sandreas.sandberg@arm.com del ref, copy, holder_ref, holder_copy, s 17611986Sandreas.sandberg@arm.com assert stats.alive() == 0 17711986Sandreas.sandberg@arm.com 17811986Sandreas.sandberg@arm.com 17911986Sandreas.sandberg@arm.comdef test_shared_ptr_from_this_and_references(): 18012391Sjason@lowepower.com s = m.SharedFromThisRef() 18112391Sjason@lowepower.com stats = ConstructorStats.get(m.B) 18211986Sandreas.sandberg@arm.com assert stats.alive() == 2 18311986Sandreas.sandberg@arm.com 18411986Sandreas.sandberg@arm.com ref = s.ref # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false) 18511986Sandreas.sandberg@arm.com assert stats.alive() == 2 18611986Sandreas.sandberg@arm.com assert s.set_ref(ref) 18711986Sandreas.sandberg@arm.com assert s.set_holder(ref) # std::enable_shared_from_this can create a holder from a reference 18811986Sandreas.sandberg@arm.com 18911986Sandreas.sandberg@arm.com bad_wp = s.bad_wp # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true) 19011986Sandreas.sandberg@arm.com assert stats.alive() == 2 19111986Sandreas.sandberg@arm.com assert s.set_ref(bad_wp) 19211986Sandreas.sandberg@arm.com with pytest.raises(RuntimeError) as excinfo: 19311986Sandreas.sandberg@arm.com assert s.set_holder(bad_wp) 19411986Sandreas.sandberg@arm.com assert "Unable to cast from non-held to held instance" in str(excinfo.value) 19511986Sandreas.sandberg@arm.com 19611986Sandreas.sandberg@arm.com copy = s.copy # init_holder_helper(holder_ptr=false, owned=true, bad_wp=false) 19711986Sandreas.sandberg@arm.com assert stats.alive() == 3 19811986Sandreas.sandberg@arm.com assert s.set_ref(copy) 19911986Sandreas.sandberg@arm.com assert s.set_holder(copy) 20011986Sandreas.sandberg@arm.com 20111986Sandreas.sandberg@arm.com holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false) 20211986Sandreas.sandberg@arm.com assert stats.alive() == 3 20311986Sandreas.sandberg@arm.com assert s.set_ref(holder_ref) 20411986Sandreas.sandberg@arm.com assert s.set_holder(holder_ref) 20511986Sandreas.sandberg@arm.com 20611986Sandreas.sandberg@arm.com holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false) 20711986Sandreas.sandberg@arm.com assert stats.alive() == 3 20811986Sandreas.sandberg@arm.com assert s.set_ref(holder_copy) 20911986Sandreas.sandberg@arm.com assert s.set_holder(holder_copy) 21011986Sandreas.sandberg@arm.com 21111986Sandreas.sandberg@arm.com del ref, bad_wp, copy, holder_ref, holder_copy, s 21211986Sandreas.sandberg@arm.com assert stats.alive() == 0 21312037Sandreas.sandberg@arm.com 21412391Sjason@lowepower.com z = m.SharedFromThisVirt.get() 21512391Sjason@lowepower.com y = m.SharedFromThisVirt.get() 21612391Sjason@lowepower.com assert y is z 21712391Sjason@lowepower.com 21812037Sandreas.sandberg@arm.com 21912037Sandreas.sandberg@arm.comdef test_move_only_holder(): 22012391Sjason@lowepower.com a = m.TypeWithMoveOnlyHolder.make() 22112391Sjason@lowepower.com stats = ConstructorStats.get(m.TypeWithMoveOnlyHolder) 22212037Sandreas.sandberg@arm.com assert stats.alive() == 1 22312037Sandreas.sandberg@arm.com del a 22412037Sandreas.sandberg@arm.com assert stats.alive() == 0 22512037Sandreas.sandberg@arm.com 22612037Sandreas.sandberg@arm.com 22714299Sbbruce@ucdavis.edudef test_holder_with_addressof_operator(): 22814299Sbbruce@ucdavis.edu # this test must not throw exception from c++ 22914299Sbbruce@ucdavis.edu a = m.TypeForHolderWithAddressOf.make() 23014299Sbbruce@ucdavis.edu a.print_object_1() 23114299Sbbruce@ucdavis.edu a.print_object_2() 23214299Sbbruce@ucdavis.edu a.print_object_3() 23314299Sbbruce@ucdavis.edu a.print_object_4() 23414299Sbbruce@ucdavis.edu 23514299Sbbruce@ucdavis.edu stats = ConstructorStats.get(m.TypeForHolderWithAddressOf) 23614299Sbbruce@ucdavis.edu assert stats.alive() == 1 23714299Sbbruce@ucdavis.edu 23814299Sbbruce@ucdavis.edu np = m.TypeForHolderWithAddressOf.make() 23914299Sbbruce@ucdavis.edu assert stats.alive() == 2 24014299Sbbruce@ucdavis.edu del a 24114299Sbbruce@ucdavis.edu assert stats.alive() == 1 24214299Sbbruce@ucdavis.edu del np 24314299Sbbruce@ucdavis.edu assert stats.alive() == 0 24414299Sbbruce@ucdavis.edu 24514299Sbbruce@ucdavis.edu b = m.TypeForHolderWithAddressOf.make() 24614299Sbbruce@ucdavis.edu c = b 24714299Sbbruce@ucdavis.edu assert b.get() is c.get() 24814299Sbbruce@ucdavis.edu assert stats.alive() == 1 24914299Sbbruce@ucdavis.edu 25014299Sbbruce@ucdavis.edu del b 25114299Sbbruce@ucdavis.edu assert stats.alive() == 1 25214299Sbbruce@ucdavis.edu 25314299Sbbruce@ucdavis.edu del c 25414299Sbbruce@ucdavis.edu assert stats.alive() == 0 25514299Sbbruce@ucdavis.edu 25614299Sbbruce@ucdavis.edu 25714299Sbbruce@ucdavis.edudef test_move_only_holder_with_addressof_operator(): 25814299Sbbruce@ucdavis.edu a = m.TypeForMoveOnlyHolderWithAddressOf.make() 25914299Sbbruce@ucdavis.edu a.print_object() 26014299Sbbruce@ucdavis.edu 26114299Sbbruce@ucdavis.edu stats = ConstructorStats.get(m.TypeForMoveOnlyHolderWithAddressOf) 26214299Sbbruce@ucdavis.edu assert stats.alive() == 1 26314299Sbbruce@ucdavis.edu 26414299Sbbruce@ucdavis.edu a.value = 42 26514299Sbbruce@ucdavis.edu assert a.value == 42 26614299Sbbruce@ucdavis.edu 26714299Sbbruce@ucdavis.edu del a 26814299Sbbruce@ucdavis.edu assert stats.alive() == 0 26914299Sbbruce@ucdavis.edu 27014299Sbbruce@ucdavis.edu 27112037Sandreas.sandberg@arm.comdef test_smart_ptr_from_default(): 27212391Sjason@lowepower.com instance = m.HeldByDefaultHolder() 27312391Sjason@lowepower.com with pytest.raises(RuntimeError) as excinfo: 27412391Sjason@lowepower.com m.HeldByDefaultHolder.load_shared_ptr(instance) 27514299Sbbruce@ucdavis.edu assert "Unable to load a custom holder type from a " \ 27614299Sbbruce@ucdavis.edu "default-holder instance" in str(excinfo.value) 27712037Sandreas.sandberg@arm.com 27812391Sjason@lowepower.com 27912391Sjason@lowepower.comdef test_shared_ptr_gc(): 28012391Sjason@lowepower.com """#187: issue involving std::shared_ptr<> return value policy & garbage collection""" 28112391Sjason@lowepower.com el = m.ElementList() 28212391Sjason@lowepower.com for i in range(10): 28312391Sjason@lowepower.com el.add(m.ElementA(i)) 28412391Sjason@lowepower.com pytest.gc_collect() 28512391Sjason@lowepower.com for i, v in enumerate(el.get()): 28612391Sjason@lowepower.com assert i == v.value() 287