1919import random
2020import logging
2121import struct
22+ import operator
2223import test .support
2324import test .script_helper
2425
@@ -1624,6 +1625,18 @@ def mul(x, y):
16241625
16251626class _TestPool (BaseTestCase ):
16261627
1628+ @classmethod
1629+ def setUpClass (cls ):
1630+ super ().setUpClass ()
1631+ cls .pool = cls .Pool (4 )
1632+
1633+ @classmethod
1634+ def tearDownClass (cls ):
1635+ cls .pool .terminate ()
1636+ cls .pool .join ()
1637+ cls .pool = None
1638+ super ().tearDownClass ()
1639+
16271640 def test_apply (self ):
16281641 papply = self .pool .apply
16291642 self .assertEqual (papply (sqr , (5 ,)), sqr (5 ))
@@ -1715,15 +1728,6 @@ def test_make_pool(self):
17151728 p .join ()
17161729
17171730 def test_terminate (self ):
1718- if self .TYPE == 'manager' :
1719- # On Unix a forked process increfs each shared object to
1720- # which its parent process held a reference. If the
1721- # forked process gets terminated then there is likely to
1722- # be a reference leak. So to prevent
1723- # _TestZZZNumberOfObjects from failing we skip this test
1724- # when using a manager.
1725- return
1726-
17271731 result = self .pool .map_async (
17281732 time .sleep , [0.1 for i in range (10000 )], chunksize = 1
17291733 )
@@ -1751,7 +1755,6 @@ def test_context(self):
17511755 with multiprocessing .Pool (2 ) as p :
17521756 r = p .map_async (sqr , L )
17531757 self .assertEqual (r .get (), expected )
1754- print (p ._state )
17551758 self .assertRaises (ValueError , p .map_async , sqr , L )
17561759
17571760def raising ():
@@ -1845,35 +1848,6 @@ def test_pool_worker_lifetime_early_close(self):
18451848 for (j , res ) in enumerate (results ):
18461849 self .assertEqual (res .get (), sqr (j ))
18471850
1848-
1849- #
1850- # Test that manager has expected number of shared objects left
1851- #
1852-
1853- class _TestZZZNumberOfObjects (BaseTestCase ):
1854- # Because test cases are sorted alphabetically, this one will get
1855- # run after all the other tests for the manager. It tests that
1856- # there have been no "reference leaks" for the manager's shared
1857- # objects. Note the comment in _TestPool.test_terminate().
1858-
1859- # If some other test using ManagerMixin.manager fails, then the
1860- # raised exception may keep alive a frame which holds a reference
1861- # to a managed object. This will cause test_number_of_objects to
1862- # also fail.
1863- ALLOWED_TYPES = ('manager' ,)
1864-
1865- def test_number_of_objects (self ):
1866- EXPECTED_NUMBER = 1 # the pool object is still alive
1867- multiprocessing .active_children () # discard dead process objs
1868- gc .collect () # do garbage collection
1869- refs = self .manager ._number_of_objects ()
1870- debug_info = self .manager ._debug_info ()
1871- if refs != EXPECTED_NUMBER :
1872- print (self .manager ._debug_info ())
1873- print (debug_info )
1874-
1875- self .assertEqual (refs , EXPECTED_NUMBER )
1876-
18771851#
18781852# Test of creating a customized manager class
18791853#
@@ -2051,7 +2025,7 @@ def test_rapid_restart(self):
20512025 address = addr , authkey = authkey , serializer = SERIALIZER )
20522026 try :
20532027 manager .start ()
2054- except IOError as e :
2028+ except OSError as e :
20552029 if e .errno != errno .EADDRINUSE :
20562030 raise
20572031 # Retry after some time, in case the old socket was lingering
@@ -2165,9 +2139,9 @@ def test_duplex_false(self):
21652139 self .assertEqual (reader .writable , False )
21662140 self .assertEqual (writer .readable , False )
21672141 self .assertEqual (writer .writable , True )
2168- self .assertRaises (IOError , reader .send , 2 )
2169- self .assertRaises (IOError , writer .recv )
2170- self .assertRaises (IOError , writer .poll )
2142+ self .assertRaises (OSError , reader .send , 2 )
2143+ self .assertRaises (OSError , writer .recv )
2144+ self .assertRaises (OSError , writer .poll )
21712145
21722146 def test_spawn_close (self ):
21732147 # We test that a pipe connection can be closed by parent
@@ -2329,8 +2303,8 @@ def test_context(self):
23292303 if self .TYPE == 'processes' :
23302304 self .assertTrue (a .closed )
23312305 self .assertTrue (b .closed )
2332- self .assertRaises (IOError , a .recv )
2333- self .assertRaises (IOError , b .recv )
2306+ self .assertRaises (OSError , a .recv )
2307+ self .assertRaises (OSError , b .recv )
23342308
23352309class _TestListener (BaseTestCase ):
23362310
@@ -2351,7 +2325,7 @@ def test_context(self):
23512325 self .assertEqual (d .recv (), 1729 )
23522326
23532327 if self .TYPE == 'processes' :
2354- self .assertRaises (IOError , l .accept )
2328+ self .assertRaises (OSError , l .accept )
23552329
23562330class _TestListenerClient (BaseTestCase ):
23572331
@@ -2401,7 +2375,7 @@ def test_issue16955(self):
24012375 c .close ()
24022376 l .close ()
24032377
2404- class _TestPoll (unittest . TestCase ):
2378+ class _TestPoll (BaseTestCase ):
24052379
24062380 ALLOWED_TYPES = ('processes' , 'threads' )
24072381
@@ -2942,27 +2916,18 @@ class TestInvalidHandle(unittest.TestCase):
29422916 def test_invalid_handles (self ):
29432917 conn = multiprocessing .connection .Connection (44977608 )
29442918 try :
2945- self .assertRaises ((ValueError , IOError ), conn .poll )
2919+ self .assertRaises ((ValueError , OSError ), conn .poll )
29462920 finally :
29472921 # Hack private attribute _handle to avoid printing an error
29482922 # in conn.__del__
29492923 conn ._handle = None
2950- self .assertRaises ((ValueError , IOError ),
2924+ self .assertRaises ((ValueError , OSError ),
29512925 multiprocessing .connection .Connection , - 1 )
29522926
29532927#
29542928# Functions used to create test cases from the base ones in this module
29552929#
29562930
2957- def get_attributes (Source , names ):
2958- d = {}
2959- for name in names :
2960- obj = getattr (Source , name )
2961- if type (obj ) == type (get_attributes ):
2962- obj = staticmethod (obj )
2963- d [name ] = obj
2964- return d
2965-
29662931def create_test_cases (Mixin , type ):
29672932 result = {}
29682933 glob = globals ()
@@ -2975,10 +2940,10 @@ def create_test_cases(Mixin, type):
29752940 assert set (base .ALLOWED_TYPES ) <= ALL_TYPES , set (base .ALLOWED_TYPES )
29762941 if type in base .ALLOWED_TYPES :
29772942 newname = 'With' + Type + name [1 :]
2978- class Temp (base , unittest .TestCase , Mixin ):
2943+ class Temp (base , Mixin , unittest .TestCase ):
29792944 pass
29802945 result [newname ] = Temp
2981- Temp .__name__ = newname
2946+ Temp .__name__ = Temp . __qualname__ = newname
29822947 Temp .__module__ = Mixin .__module__
29832948 return result
29842949
@@ -2989,12 +2954,24 @@ class Temp(base, unittest.TestCase, Mixin):
29892954class ProcessesMixin (object ):
29902955 TYPE = 'processes'
29912956 Process = multiprocessing .Process
2992- locals ().update (get_attributes (multiprocessing , (
2993- 'Queue' , 'Lock' , 'RLock' , 'Semaphore' , 'BoundedSemaphore' ,
2994- 'Condition' , 'Event' , 'Barrier' , 'Value' , 'Array' , 'RawValue' ,
2995- 'RawArray' , 'current_process' , 'active_children' , 'Pipe' ,
2996- 'connection' , 'JoinableQueue' , 'Pool'
2997- )))
2957+ connection = multiprocessing .connection
2958+ current_process = staticmethod (multiprocessing .current_process )
2959+ active_children = staticmethod (multiprocessing .active_children )
2960+ Pool = staticmethod (multiprocessing .Pool )
2961+ Pipe = staticmethod (multiprocessing .Pipe )
2962+ Queue = staticmethod (multiprocessing .Queue )
2963+ JoinableQueue = staticmethod (multiprocessing .JoinableQueue )
2964+ Lock = staticmethod (multiprocessing .Lock )
2965+ RLock = staticmethod (multiprocessing .RLock )
2966+ Semaphore = staticmethod (multiprocessing .Semaphore )
2967+ BoundedSemaphore = staticmethod (multiprocessing .BoundedSemaphore )
2968+ Condition = staticmethod (multiprocessing .Condition )
2969+ Event = staticmethod (multiprocessing .Event )
2970+ Barrier = staticmethod (multiprocessing .Barrier )
2971+ Value = staticmethod (multiprocessing .Value )
2972+ Array = staticmethod (multiprocessing .Array )
2973+ RawValue = staticmethod (multiprocessing .RawValue )
2974+ RawArray = staticmethod (multiprocessing .RawArray )
29982975
29992976testcases_processes = create_test_cases (ProcessesMixin , type = 'processes' )
30002977globals ().update (testcases_processes )
@@ -3003,12 +2980,48 @@ class ProcessesMixin(object):
30032980class ManagerMixin (object ):
30042981 TYPE = 'manager'
30052982 Process = multiprocessing .Process
3006- manager = object .__new__ (multiprocessing .managers .SyncManager )
3007- locals ().update (get_attributes (manager , (
3008- 'Queue' , 'Lock' , 'RLock' , 'Semaphore' , 'BoundedSemaphore' ,
3009- 'Condition' , 'Event' , 'Barrier' , 'Value' , 'Array' , 'list' , 'dict' ,
3010- 'Namespace' , 'JoinableQueue' , 'Pool'
3011- )))
2983+ Queue = property (operator .attrgetter ('manager.Queue' ))
2984+ JoinableQueue = property (operator .attrgetter ('manager.JoinableQueue' ))
2985+ Lock = property (operator .attrgetter ('manager.Lock' ))
2986+ RLock = property (operator .attrgetter ('manager.RLock' ))
2987+ Semaphore = property (operator .attrgetter ('manager.Semaphore' ))
2988+ BoundedSemaphore = property (operator .attrgetter ('manager.BoundedSemaphore' ))
2989+ Condition = property (operator .attrgetter ('manager.Condition' ))
2990+ Event = property (operator .attrgetter ('manager.Event' ))
2991+ Barrier = property (operator .attrgetter ('manager.Barrier' ))
2992+ Value = property (operator .attrgetter ('manager.Value' ))
2993+ Array = property (operator .attrgetter ('manager.Array' ))
2994+ list = property (operator .attrgetter ('manager.list' ))
2995+ dict = property (operator .attrgetter ('manager.dict' ))
2996+ Namespace = property (operator .attrgetter ('manager.Namespace' ))
2997+
2998+ @classmethod
2999+ def Pool (cls , * args , ** kwds ):
3000+ return cls .manager .Pool (* args , ** kwds )
3001+
3002+ @classmethod
3003+ def setUpClass (cls ):
3004+ cls .manager = multiprocessing .Manager ()
3005+
3006+ @classmethod
3007+ def tearDownClass (cls ):
3008+ # only the manager process should be returned by active_children()
3009+ # but this can take a bit on slow machines, so wait a few seconds
3010+ # if there are other children too (see #17395)
3011+ t = 0.01
3012+ while len (multiprocessing .active_children ()) > 1 and t < 5 :
3013+ time .sleep (t )
3014+ t *= 2
3015+ gc .collect () # do garbage collection
3016+ if cls .manager ._number_of_objects () != 0 :
3017+ # This is not really an error since some tests do not
3018+ # ensure that all processes which hold a reference to a
3019+ # managed object have been joined.
3020+ print ('Shared objects which still exist at manager shutdown:' )
3021+ print (cls .manager ._debug_info ())
3022+ cls .manager .shutdown ()
3023+ cls .manager .join ()
3024+ cls .manager = None
30123025
30133026testcases_manager = create_test_cases (ManagerMixin , type = 'manager' )
30143027globals ().update (testcases_manager )
@@ -3017,16 +3030,27 @@ class ManagerMixin(object):
30173030class ThreadsMixin (object ):
30183031 TYPE = 'threads'
30193032 Process = multiprocessing .dummy .Process
3020- locals ().update (get_attributes (multiprocessing .dummy , (
3021- 'Queue' , 'Lock' , 'RLock' , 'Semaphore' , 'BoundedSemaphore' ,
3022- 'Condition' , 'Event' , 'Barrier' , 'Value' , 'Array' , 'current_process' ,
3023- 'active_children' , 'Pipe' , 'connection' , 'dict' , 'list' ,
3024- 'Namespace' , 'JoinableQueue' , 'Pool'
3025- )))
3033+ connection = multiprocessing .dummy .connection
3034+ current_process = staticmethod (multiprocessing .dummy .current_process )
3035+ active_children = staticmethod (multiprocessing .dummy .active_children )
3036+ Pool = staticmethod (multiprocessing .Pool )
3037+ Pipe = staticmethod (multiprocessing .dummy .Pipe )
3038+ Queue = staticmethod (multiprocessing .dummy .Queue )
3039+ JoinableQueue = staticmethod (multiprocessing .dummy .JoinableQueue )
3040+ Lock = staticmethod (multiprocessing .dummy .Lock )
3041+ RLock = staticmethod (multiprocessing .dummy .RLock )
3042+ Semaphore = staticmethod (multiprocessing .dummy .Semaphore )
3043+ BoundedSemaphore = staticmethod (multiprocessing .dummy .BoundedSemaphore )
3044+ Condition = staticmethod (multiprocessing .dummy .Condition )
3045+ Event = staticmethod (multiprocessing .dummy .Event )
3046+ Barrier = staticmethod (multiprocessing .dummy .Barrier )
3047+ Value = staticmethod (multiprocessing .dummy .Value )
3048+ Array = staticmethod (multiprocessing .dummy .Array )
30263049
30273050testcases_threads = create_test_cases (ThreadsMixin , type = 'threads' )
30283051globals ().update (testcases_threads )
30293052
3053+
30303054class OtherTest (unittest .TestCase ):
30313055 # TODO: add more tests for deliver/answer challenge.
30323056 def test_deliver_challenge_auth_failure (self ):
@@ -3532,16 +3556,7 @@ def test_ignore_listener(self):
35323556#
35333557#
35343558
3535- testcases_other = [OtherTest , TestInvalidHandle , TestInitializers ,
3536- TestStdinBadfiledescriptor , TestWait , TestInvalidFamily ,
3537- TestFlags , TestTimeouts , TestNoForkBomb ,
3538- TestForkAwareThreadLock , TestIgnoreEINTR ]
3539-
3540- #
3541- #
3542- #
3543-
3544- def test_main (run = None ):
3559+ def setUpModule ():
35453560 if sys .platform .startswith ("linux" ):
35463561 try :
35473562 lock = multiprocessing .RLock ()
@@ -3550,43 +3565,10 @@ def test_main(run=None):
35503565
35513566 check_enough_semaphores ()
35523567
3553- if run is None :
3554- from test .support import run_unittest as run
3555-
35563568 util .get_temp_dir () # creates temp directory for use by all processes
35573569
35583570 multiprocessing .get_logger ().setLevel (LOG_LEVEL )
35593571
3560- ProcessesMixin .pool = multiprocessing .Pool (4 )
3561- ThreadsMixin .pool = multiprocessing .dummy .Pool (4 )
3562- ManagerMixin .manager .__init__ ()
3563- ManagerMixin .manager .start ()
3564- ManagerMixin .pool = ManagerMixin .manager .Pool (4 )
3565-
3566- testcases = (
3567- sorted (testcases_processes .values (), key = lambda tc :tc .__name__ ) +
3568- sorted (testcases_threads .values (), key = lambda tc :tc .__name__ ) +
3569- sorted (testcases_manager .values (), key = lambda tc :tc .__name__ ) +
3570- testcases_other
3571- )
3572-
3573- loadTestsFromTestCase = unittest .defaultTestLoader .loadTestsFromTestCase
3574- suite = unittest .TestSuite (loadTestsFromTestCase (tc ) for tc in testcases )
3575- try :
3576- run (suite )
3577- finally :
3578- ThreadsMixin .pool .terminate ()
3579- ProcessesMixin .pool .terminate ()
3580- ManagerMixin .pool .terminate ()
3581- ManagerMixin .pool .join ()
3582- ManagerMixin .manager .shutdown ()
3583- ManagerMixin .manager .join ()
3584- ThreadsMixin .pool .join ()
3585- ProcessesMixin .pool .join ()
3586- del ProcessesMixin .pool , ThreadsMixin .pool , ManagerMixin .pool
3587-
3588- def main ():
3589- test_main (unittest .TextTestRunner (verbosity = 2 ).run )
35903572
35913573if __name__ == '__main__' :
3592- main ()
3574+ unittest . main ()
0 commit comments