1616
1717# pylint: disable=invalid-name, missing-docstring, too-many-public-methods
1818
19- from ctypes import pointer
19+ from ctypes import pointer , sizeof
20+ import functools
21+ import gc
2022import itertools
2123import sys
2224import unittest
25+ import weakref
2326import usb1
2427from . import libusb1
2528
@@ -38,7 +41,50 @@ def open(self):
3841 'usb1.USBContext() fails - no USB bus on system ?'
3942 )
4043
44+ def checkTransferAllocCount (func ):
45+ @functools .wraps (func )
46+ def wrapper (self , * args , ** kw ):
47+ before = self .transfer_alloc_count
48+ libusb_free_transfer = libusb1 .libusb_free_transfer
49+ libusb_alloc_transfer = libusb1 .libusb_alloc_transfer
50+ try :
51+ libusb1 .libusb_free_transfer = self ._fakeFreeTransfer
52+ libusb1 .libusb_alloc_transfer = self ._fakeAllocTransfer
53+ print ('running' )
54+ result = func (self , * args , ** kw )
55+ print ('done' )
56+ finally :
57+ libusb1 .libusb_free_transfer = libusb_free_transfer
58+ libusb1 .libusb_alloc_transfer = libusb_alloc_transfer
59+ gc .collect ()
60+ self .assertEqual (self .transfer_alloc_count , before )
61+ return result
62+ return wrapper
63+
4164class USBTransferTests (unittest .TestCase ):
65+ def __init__ (self , * args , ** kw ):
66+ super ().__init__ (* args , ** kw )
67+ usb1 .loadLibrary ()
68+ self .transfer_alloc_count = 0
69+
70+ def _fakeFreeTransfer (self , _ ):
71+ self .transfer_alloc_count -= 1
72+
73+ def _fakeAllocTransfer (self , isochronous_count ):
74+ self .transfer_alloc_count += 1
75+ buffer = bytearray (
76+ sizeof (
77+ libusb1 .libusb_transfer ,
78+ ) + sizeof (
79+ libusb1 .libusb_iso_packet_descriptor ,
80+ ) * max (0 , isochronous_count - 1 ),
81+ )
82+ transfer = libusb1 .libusb_transfer .from_buffer (buffer )
83+ # Keep a reference (in the finalizer itself) to the buffer for as long
84+ # as transfer is alive.
85+ weakref .finalize (transfer , lambda _ : None , buffer )
86+ return pointer (transfer )
87+
4288 @staticmethod
4389 def getTransfer (iso_packets = 0 ):
4490 # Dummy handle
@@ -66,6 +112,7 @@ def testHasCapability():
66112 """
67113 usb1 .hasCapability (usb1 .CAP_HAS_CAPABILITY )
68114
115+ @checkTransferAllocCount
69116 def testSetControl (self ):
70117 """
71118 Simplest test: feed some data, must not raise.
@@ -129,20 +176,23 @@ def callback(transfer):
129176 # No callback
130177 setter (endpoint , buff )
131178
179+ @checkTransferAllocCount
132180 def testSetBulk (self ):
133181 """
134182 Simplest test: feed some data, must not raise.
135183 Also, test setBuffer/getBuffer.
136184 """
137185 self ._testTransferSetter (self .getTransfer (), 'setBulk' )
138186
187+ @checkTransferAllocCount
139188 def testSetInterrupt (self ):
140189 """
141190 Simplest test: feed some data, must not raise.
142191 Also, test setBuffer/getBuffer.
143192 """
144193 self ._testTransferSetter (self .getTransfer (), 'setInterrupt' )
145194
195+ @checkTransferAllocCount
146196 def testSetIsochronous (self ):
147197 """
148198 Simplest test: feed some data, must not raise.
@@ -174,6 +224,7 @@ def testSetIsochronous(self):
174224 buff ,
175225 )
176226
227+ @checkTransferAllocCount
177228 def testSetGetCallback (self ):
178229 transfer = self .getTransfer ()
179230 def callback (transfer ):
0 commit comments