@@ -832,3 +832,137 @@ def test_case_sensitive():
832
832
833
833
with pytest .raises (AttributeError ):
834
834
MethodTest .casesensitive ()
835
+
836
+ def test_getting_generic_method_binding_does_not_leak_ref_count ():
837
+ """Test that managed object is freed after calling generic method. Issue #691"""
838
+
839
+ from PlainOldNamespace import PlainOldClass
840
+
841
+ import sys
842
+
843
+ refCount = sys .getrefcount (PlainOldClass ().GenericMethod [str ])
844
+ assert refCount == 1
845
+
846
+ def test_getting_generic_method_binding_does_not_leak_memory ():
847
+ """Test that managed object is freed after calling generic method. Issue #691"""
848
+
849
+ from PlainOldNamespace import PlainOldClass
850
+
851
+ import psutil , os , gc , clr
852
+
853
+ process = psutil .Process (os .getpid ())
854
+ processBytesBeforeCall = process .memory_info ().rss
855
+ print ("\n \n Memory consumption (bytes) at start of test: " + str (processBytesBeforeCall ))
856
+
857
+ iterations = 500
858
+ for i in range (iterations ):
859
+ PlainOldClass ().GenericMethod [str ]
860
+
861
+ gc .collect ()
862
+ clr .System .GC .Collect ()
863
+
864
+ processBytesAfterCall = process .memory_info ().rss
865
+ print ("Memory consumption (bytes) at end of test: " + str (processBytesAfterCall ))
866
+ processBytesDelta = processBytesAfterCall - processBytesBeforeCall
867
+ print ("Memory delta: " + str (processBytesDelta ))
868
+
869
+ bytesAllocatedPerIteration = pow (2 , 20 ) # 1MB
870
+ bytesLeakedPerIteration = processBytesDelta / iterations
871
+
872
+ # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration
873
+ failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2
874
+
875
+ assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration
876
+
877
+ def test_getting_overloaded_method_binding_does_not_leak_ref_count ():
878
+ """Test that managed object is freed after calling overloaded method. Issue #691"""
879
+
880
+ from PlainOldNamespace import PlainOldClass
881
+
882
+ import sys
883
+
884
+ refCount = sys .getrefcount (PlainOldClass ().OverloadedMethod .Overloads [int ])
885
+ assert refCount == 1
886
+
887
+ def test_getting_overloaded_method_binding_does_not_leak_memory ():
888
+ """Test that managed object is freed after calling overloaded method. Issue #691"""
889
+
890
+ from PlainOldNamespace import PlainOldClass
891
+
892
+ import psutil , os , gc , clr
893
+
894
+ process = psutil .Process (os .getpid ())
895
+ processBytesBeforeCall = process .memory_info ().rss
896
+ print ("\n \n Memory consumption (bytes) at start of test: " + str (processBytesBeforeCall ))
897
+
898
+ iterations = 500
899
+ for i in range (iterations ):
900
+ PlainOldClass ().OverloadedMethod .Overloads [int ]
901
+
902
+ gc .collect ()
903
+ clr .System .GC .Collect ()
904
+
905
+ processBytesAfterCall = process .memory_info ().rss
906
+ print ("Memory consumption (bytes) at end of test: " + str (processBytesAfterCall ))
907
+ processBytesDelta = processBytesAfterCall - processBytesBeforeCall
908
+ print ("Memory delta: " + str (processBytesDelta ))
909
+
910
+ bytesAllocatedPerIteration = pow (2 , 20 ) # 1MB
911
+ bytesLeakedPerIteration = processBytesDelta / iterations
912
+
913
+ # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration
914
+ failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2
915
+
916
+ assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration
917
+
918
+ def test_getting_method_overloads_binding_does_not_leak_ref_count ():
919
+ """Test that managed object is freed after calling overloaded method. Issue #691"""
920
+
921
+ from PlainOldNamespace import PlainOldClass
922
+
923
+ import sys
924
+
925
+ refCount = sys .getrefcount (PlainOldClass ().OverloadedMethod .Overloads )
926
+ assert refCount == 1
927
+
928
+ def test_getting_method_overloads_binding_does_not_leak_memory ():
929
+ """Test that managed object is freed after calling overloaded method. Issue #691"""
930
+
931
+ from PlainOldNamespace import PlainOldClass
932
+
933
+ import psutil , os , gc , clr
934
+
935
+ process = psutil .Process (os .getpid ())
936
+ processBytesBeforeCall = process .memory_info ().rss
937
+ print ("\n \n Memory consumption (bytes) at start of test: " + str (processBytesBeforeCall ))
938
+
939
+ iterations = 500
940
+ for i in range (iterations ):
941
+ PlainOldClass ().OverloadedMethod .Overloads
942
+
943
+ gc .collect ()
944
+ clr .System .GC .Collect ()
945
+
946
+ processBytesAfterCall = process .memory_info ().rss
947
+ print ("Memory consumption (bytes) at end of test: " + str (processBytesAfterCall ))
948
+ processBytesDelta = processBytesAfterCall - processBytesBeforeCall
949
+ print ("Memory delta: " + str (processBytesDelta ))
950
+
951
+ bytesAllocatedPerIteration = pow (2 , 20 ) # 1MB
952
+ bytesLeakedPerIteration = processBytesDelta / iterations
953
+
954
+ # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration
955
+ failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2
956
+
957
+ assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration
958
+
959
+ def test_getting_overloaded_constructor_binding_does_not_leak_ref_count ():
960
+ """Test that managed object is freed after calling overloaded constructor, constructorbinding.cs mp_subscript. Issue #691"""
961
+
962
+ from PlainOldNamespace import PlainOldClass
963
+
964
+ import sys
965
+
966
+ # simple test
967
+ refCount = sys .getrefcount (PlainOldClass .Overloads [int ])
968
+ assert refCount == 1
0 commit comments