Merge pull request #704 from williamsardar/master · pythonnet/pythonnet@fb84cd2
@@ -832,3 +832,137 @@ def test_case_sensitive():
832832833833with pytest.raises(AttributeError):
834834MethodTest.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\nMemory 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\nMemory 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\nMemory 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