test_smart_ptr.py revision 11986
111986Sandreas.sandberg@arm.comimport pytest 211986Sandreas.sandberg@arm.comfrom pybind11_tests import ConstructorStats 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com 511986Sandreas.sandberg@arm.comdef test_smart_ptr(capture): 611986Sandreas.sandberg@arm.com # Object1 711986Sandreas.sandberg@arm.com from pybind11_tests import (MyObject1, make_object_1, make_object_2, 811986Sandreas.sandberg@arm.com print_object_1, print_object_2, print_object_3, print_object_4) 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com for i, o in enumerate([make_object_1(), make_object_2(), MyObject1(3)], start=1): 1111986Sandreas.sandberg@arm.com assert o.getRefCount() == 1 1211986Sandreas.sandberg@arm.com with capture: 1311986Sandreas.sandberg@arm.com print_object_1(o) 1411986Sandreas.sandberg@arm.com print_object_2(o) 1511986Sandreas.sandberg@arm.com print_object_3(o) 1611986Sandreas.sandberg@arm.com print_object_4(o) 1711986Sandreas.sandberg@arm.com assert capture == "MyObject1[{i}]\n".format(i=i) * 4 1811986Sandreas.sandberg@arm.com 1911986Sandreas.sandberg@arm.com from pybind11_tests import (make_myobject1_1, make_myobject1_2, 2011986Sandreas.sandberg@arm.com print_myobject1_1, print_myobject1_2, 2111986Sandreas.sandberg@arm.com print_myobject1_3, print_myobject1_4) 2211986Sandreas.sandberg@arm.com 2311986Sandreas.sandberg@arm.com for i, o in enumerate([make_myobject1_1(), make_myobject1_2(), MyObject1(6), 7], start=4): 2411986Sandreas.sandberg@arm.com print(o) 2511986Sandreas.sandberg@arm.com with capture: 2611986Sandreas.sandberg@arm.com if not isinstance(o, int): 2711986Sandreas.sandberg@arm.com print_object_1(o) 2811986Sandreas.sandberg@arm.com print_object_2(o) 2911986Sandreas.sandberg@arm.com print_object_3(o) 3011986Sandreas.sandberg@arm.com print_object_4(o) 3111986Sandreas.sandberg@arm.com print_myobject1_1(o) 3211986Sandreas.sandberg@arm.com print_myobject1_2(o) 3311986Sandreas.sandberg@arm.com print_myobject1_3(o) 3411986Sandreas.sandberg@arm.com print_myobject1_4(o) 3511986Sandreas.sandberg@arm.com assert capture == "MyObject1[{i}]\n".format(i=i) * (4 if isinstance(o, int) else 8) 3611986Sandreas.sandberg@arm.com 3711986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(MyObject1) 3811986Sandreas.sandberg@arm.com assert cstats.alive() == 0 3911986Sandreas.sandberg@arm.com expected_values = ['MyObject1[{}]'.format(i) for i in range(1, 7)] + ['MyObject1[7]'] * 4 4011986Sandreas.sandberg@arm.com assert cstats.values() == expected_values 4111986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 4211986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 4311986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 4411986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 4511986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 4611986Sandreas.sandberg@arm.com 4711986Sandreas.sandberg@arm.com # Object2 4811986Sandreas.sandberg@arm.com from pybind11_tests import (MyObject2, make_myobject2_1, make_myobject2_2, 4911986Sandreas.sandberg@arm.com make_myobject3_1, make_myobject3_2, 5011986Sandreas.sandberg@arm.com print_myobject2_1, print_myobject2_2, 5111986Sandreas.sandberg@arm.com print_myobject2_3, print_myobject2_4) 5211986Sandreas.sandberg@arm.com 5311986Sandreas.sandberg@arm.com for i, o in zip([8, 6, 7], [MyObject2(8), make_myobject2_1(), make_myobject2_2()]): 5411986Sandreas.sandberg@arm.com print(o) 5511986Sandreas.sandberg@arm.com with capture: 5611986Sandreas.sandberg@arm.com print_myobject2_1(o) 5711986Sandreas.sandberg@arm.com print_myobject2_2(o) 5811986Sandreas.sandberg@arm.com print_myobject2_3(o) 5911986Sandreas.sandberg@arm.com print_myobject2_4(o) 6011986Sandreas.sandberg@arm.com assert capture == "MyObject2[{i}]\n".format(i=i) * 4 6111986Sandreas.sandberg@arm.com 6211986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(MyObject2) 6311986Sandreas.sandberg@arm.com assert cstats.alive() == 1 6411986Sandreas.sandberg@arm.com o = None 6511986Sandreas.sandberg@arm.com assert cstats.alive() == 0 6611986Sandreas.sandberg@arm.com assert cstats.values() == ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]'] 6711986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 6811986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 6911986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 7011986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 7111986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 7211986Sandreas.sandberg@arm.com 7311986Sandreas.sandberg@arm.com # Object3 7411986Sandreas.sandberg@arm.com from pybind11_tests import (MyObject3, print_myobject3_1, print_myobject3_2, 7511986Sandreas.sandberg@arm.com print_myobject3_3, print_myobject3_4) 7611986Sandreas.sandberg@arm.com 7711986Sandreas.sandberg@arm.com for i, o in zip([9, 8, 9], [MyObject3(9), make_myobject3_1(), make_myobject3_2()]): 7811986Sandreas.sandberg@arm.com print(o) 7911986Sandreas.sandberg@arm.com with capture: 8011986Sandreas.sandberg@arm.com print_myobject3_1(o) 8111986Sandreas.sandberg@arm.com print_myobject3_2(o) 8211986Sandreas.sandberg@arm.com print_myobject3_3(o) 8311986Sandreas.sandberg@arm.com print_myobject3_4(o) 8411986Sandreas.sandberg@arm.com assert capture == "MyObject3[{i}]\n".format(i=i) * 4 8511986Sandreas.sandberg@arm.com 8611986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(MyObject3) 8711986Sandreas.sandberg@arm.com assert cstats.alive() == 1 8811986Sandreas.sandberg@arm.com o = None 8911986Sandreas.sandberg@arm.com assert cstats.alive() == 0 9011986Sandreas.sandberg@arm.com assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]'] 9111986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 9211986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 9311986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 9411986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 9511986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 9611986Sandreas.sandberg@arm.com 9711986Sandreas.sandberg@arm.com # Object and ref 9811986Sandreas.sandberg@arm.com from pybind11_tests import Object, cstats_ref 9911986Sandreas.sandberg@arm.com 10011986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(Object) 10111986Sandreas.sandberg@arm.com assert cstats.alive() == 0 10211986Sandreas.sandberg@arm.com assert cstats.values() == [] 10311986Sandreas.sandberg@arm.com assert cstats.default_constructions == 10 10411986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 10511986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 10611986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 10711986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 10811986Sandreas.sandberg@arm.com 10911986Sandreas.sandberg@arm.com cstats = cstats_ref() 11011986Sandreas.sandberg@arm.com assert cstats.alive() == 0 11111986Sandreas.sandberg@arm.com assert cstats.values() == ['from pointer'] * 10 11211986Sandreas.sandberg@arm.com assert cstats.default_constructions == 30 11311986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 12 11411986Sandreas.sandberg@arm.com # assert cstats.move_constructions >= 0 # Doesn't invoke any 11511986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 30 11611986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 11711986Sandreas.sandberg@arm.com 11811986Sandreas.sandberg@arm.com 11911986Sandreas.sandberg@arm.comdef test_unique_nodelete(): 12011986Sandreas.sandberg@arm.com from pybind11_tests import MyObject4 12111986Sandreas.sandberg@arm.com o = MyObject4(23) 12211986Sandreas.sandberg@arm.com assert o.value == 23 12311986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(MyObject4) 12411986Sandreas.sandberg@arm.com assert cstats.alive() == 1 12511986Sandreas.sandberg@arm.com del o 12611986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(MyObject4) 12711986Sandreas.sandberg@arm.com assert cstats.alive() == 1 # Leak, but that's intentional 12811986Sandreas.sandberg@arm.com 12911986Sandreas.sandberg@arm.com 13011986Sandreas.sandberg@arm.comdef test_shared_ptr_and_references(): 13111986Sandreas.sandberg@arm.com from pybind11_tests.smart_ptr import SharedPtrRef, A 13211986Sandreas.sandberg@arm.com 13311986Sandreas.sandberg@arm.com s = SharedPtrRef() 13411986Sandreas.sandberg@arm.com stats = ConstructorStats.get(A) 13511986Sandreas.sandberg@arm.com assert stats.alive() == 2 13611986Sandreas.sandberg@arm.com 13711986Sandreas.sandberg@arm.com ref = s.ref # init_holder_helper(holder_ptr=false, owned=false) 13811986Sandreas.sandberg@arm.com assert stats.alive() == 2 13911986Sandreas.sandberg@arm.com assert s.set_ref(ref) 14011986Sandreas.sandberg@arm.com with pytest.raises(RuntimeError) as excinfo: 14111986Sandreas.sandberg@arm.com assert s.set_holder(ref) 14211986Sandreas.sandberg@arm.com assert "Unable to cast from non-held to held instance" in str(excinfo.value) 14311986Sandreas.sandberg@arm.com 14411986Sandreas.sandberg@arm.com copy = s.copy # init_holder_helper(holder_ptr=false, owned=true) 14511986Sandreas.sandberg@arm.com assert stats.alive() == 3 14611986Sandreas.sandberg@arm.com assert s.set_ref(copy) 14711986Sandreas.sandberg@arm.com assert s.set_holder(copy) 14811986Sandreas.sandberg@arm.com 14911986Sandreas.sandberg@arm.com holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false) 15011986Sandreas.sandberg@arm.com assert stats.alive() == 3 15111986Sandreas.sandberg@arm.com assert s.set_ref(holder_ref) 15211986Sandreas.sandberg@arm.com assert s.set_holder(holder_ref) 15311986Sandreas.sandberg@arm.com 15411986Sandreas.sandberg@arm.com holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true) 15511986Sandreas.sandberg@arm.com assert stats.alive() == 3 15611986Sandreas.sandberg@arm.com assert s.set_ref(holder_copy) 15711986Sandreas.sandberg@arm.com assert s.set_holder(holder_copy) 15811986Sandreas.sandberg@arm.com 15911986Sandreas.sandberg@arm.com del ref, copy, holder_ref, holder_copy, s 16011986Sandreas.sandberg@arm.com assert stats.alive() == 0 16111986Sandreas.sandberg@arm.com 16211986Sandreas.sandberg@arm.com 16311986Sandreas.sandberg@arm.comdef test_shared_ptr_from_this_and_references(): 16411986Sandreas.sandberg@arm.com from pybind11_tests.smart_ptr import SharedFromThisRef, B 16511986Sandreas.sandberg@arm.com 16611986Sandreas.sandberg@arm.com s = SharedFromThisRef() 16711986Sandreas.sandberg@arm.com stats = ConstructorStats.get(B) 16811986Sandreas.sandberg@arm.com assert stats.alive() == 2 16911986Sandreas.sandberg@arm.com 17011986Sandreas.sandberg@arm.com ref = s.ref # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false) 17111986Sandreas.sandberg@arm.com assert stats.alive() == 2 17211986Sandreas.sandberg@arm.com assert s.set_ref(ref) 17311986Sandreas.sandberg@arm.com assert s.set_holder(ref) # std::enable_shared_from_this can create a holder from a reference 17411986Sandreas.sandberg@arm.com 17511986Sandreas.sandberg@arm.com bad_wp = s.bad_wp # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true) 17611986Sandreas.sandberg@arm.com assert stats.alive() == 2 17711986Sandreas.sandberg@arm.com assert s.set_ref(bad_wp) 17811986Sandreas.sandberg@arm.com with pytest.raises(RuntimeError) as excinfo: 17911986Sandreas.sandberg@arm.com assert s.set_holder(bad_wp) 18011986Sandreas.sandberg@arm.com assert "Unable to cast from non-held to held instance" in str(excinfo.value) 18111986Sandreas.sandberg@arm.com 18211986Sandreas.sandberg@arm.com copy = s.copy # init_holder_helper(holder_ptr=false, owned=true, bad_wp=false) 18311986Sandreas.sandberg@arm.com assert stats.alive() == 3 18411986Sandreas.sandberg@arm.com assert s.set_ref(copy) 18511986Sandreas.sandberg@arm.com assert s.set_holder(copy) 18611986Sandreas.sandberg@arm.com 18711986Sandreas.sandberg@arm.com holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false) 18811986Sandreas.sandberg@arm.com assert stats.alive() == 3 18911986Sandreas.sandberg@arm.com assert s.set_ref(holder_ref) 19011986Sandreas.sandberg@arm.com assert s.set_holder(holder_ref) 19111986Sandreas.sandberg@arm.com 19211986Sandreas.sandberg@arm.com holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false) 19311986Sandreas.sandberg@arm.com assert stats.alive() == 3 19411986Sandreas.sandberg@arm.com assert s.set_ref(holder_copy) 19511986Sandreas.sandberg@arm.com assert s.set_holder(holder_copy) 19611986Sandreas.sandberg@arm.com 19711986Sandreas.sandberg@arm.com del ref, bad_wp, copy, holder_ref, holder_copy, s 19811986Sandreas.sandberg@arm.com assert stats.alive() == 0 199