Merge pull request #704 from williamsardar/master · pythonnet/pythonnet@fb84cd2

@@ -832,3 +832,137 @@ def test_case_sensitive():

832832833833

with pytest.raises(AttributeError):

834834

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\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