o
    ¯bÄU  ã                   @   sÒ   d Z ddlZddlZddlZddlZddlZddlmZmZ ddl	m
Z
mZmZmZ ddlmZ G dd„ dƒZe e¡ G dd	„ d	ejƒZG d
d„ dejƒZG dd„ dejƒZG dd„ dƒZG dd„ dejƒZdS )z(
Tests for L{twisted.python.threadpool}
é    N)ÚTeamÚcreateMemoryWorker)ÚcontextÚfailureÚ
threadableÚ
threadpool)Úunittestc                   @   s&   e Zd ZdZdd„ Zdd„ ZdgZdS )ÚSynchronizationr   c                 C   s    || _ || _t ¡ | _g | _d S ©N)ÚNÚwaitingÚ	threadingÚLockÚlockÚruns)Úselfr   r   © r   ú>/usr/lib/python3/dist-packages/twisted/test/test_threadpool.pyÚ__init__   s   

zSynchronization.__init__c                 C   s|   | j  d¡rt| jƒd st d¡ | j  ¡  n|  jd7  _| j  ¡  | j d ¡ t| jƒ| j	kr7| j
 ¡  | j  ¡  d S )NFé   g-Cëâ6*?é   )r   ÚacquireÚlenr   ÚtimeÚsleepÚreleaseÚfailuresÚappendr   r   ©r   r   r   r   Úrun   s   


zSynchronization.runr   N)Ú__name__Ú
__module__Ú__qualname__r   r   r   Úsynchronizedr   r   r   r   r	      s
    
r	   c                   @   s    e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&S )'ÚThreadPoolTestsz
    Test threadpools.
    c                 C   ó   dS )zD
        Return number of seconds to wait before giving up.
        r   r   r   r   r   r   Ú
getTimeout@   ó   zThreadPoolTests.getTimeoutc                 C   s:   t dƒ}|D ]}| d¡r d S t d¡ q|  d¡ d S )Ni@B Fgñhãˆµøä>z%A long time passed without succeeding)Úranger   r   r   Úfail)r   r   ÚitemsÚir   r   r   Ú_waitForLockF   s   
zThreadPoolTests._waitForLockc                 C   s,   t  dd¡}|  |jd¡ |  |jd¡ dS )zy
        L{ThreadPool.min} and L{ThreadPool.max} are set to the values passed to
        L{ThreadPool.__init__}.
        é   é   N)r   Ú
ThreadPoolÚassertEqualÚminÚmax©r   Úpoolr   r   r   Útest_attributesO   s   zThreadPoolTests.test_attributesc                 C   sz   t  dd¡}| ¡  |  |j¡ |  t|jƒd¡ t  dd¡}|  t|jƒd¡ | ¡  |  |j¡ |  t|jƒd¡ dS )zV
        L{ThreadPool.start} creates the minimum number of threads specified.
        r   r   é   é
   N)r   r/   ÚstartÚ
addCleanupÚstopr0   r   Úthreadsr3   r   r   r   Ú
test_startX   s   zThreadPoolTests.test_startc                 C   s<   t  dd¡}| ¡  | ¡  | d¡ |  t|jƒd¡ dS )z
        L{ThreadPool.adjustPoolsize} only modifies the pool size and does not
        start new workers while the pool is not running.
        r   r   é   N)r   r/   r8   r:   ÚadjustPoolsizer0   r   r;   r3   r   r   r   Útest_adjustingWhenPoolStoppedg   s
   
z-ThreadPoolTests.test_adjustingWhenPoolStoppedc                 C   s´   t  dd¡}| ¡  |  |j¡ |  |jg ¡ dd„ }G dd„ dƒ}|ƒ }t |¡}t |¡}| 	||¡ t
 ¡ }| 	|j¡ | |  ¡ ¡ ~~t ¡  |  |ƒ ¡ |  |ƒ ¡ dS )zü
        Test that creating threads in the threadpool with application-level
        objects as arguments doesn't results in those objects never being
        freed, with the thread maintaining a reference to them as long as it
        exists.
        r   r   c                 S   ó   d S r
   r   )Úargr   r   r   Úworker   s   z<ThreadPoolTests.test_threadCreationArguments.<locals>.workerc                   @   ó   e Zd ZdS )z:ThreadPoolTests.test_threadCreationArguments.<locals>.DumbN©r    r!   r"   r   r   r   r   ÚDumb…   ó    rE   N)r   r/   r8   r9   r:   r0   r;   ÚweakrefÚrefÚcallInThreadr   ÚEventÚsetÚwaitr&   ÚgcÚcollectÚassertIsNone)r   ÚtprB   rE   ÚuniqueÚ	workerRefÚ	uniqueRefÚeventr   r   r   Útest_threadCreationArgumentsr   s$   

z,ThreadPoolTests.test_threadCreationArgumentsc                    s*  t  dd¡}| ¡  ˆ |j¡ ˆ |jg ¡ i ‰t ¡ ‰t ¡ ‰g ‰‡‡‡‡‡‡‡fdd„}‡ fdd„}G dd„ dƒ‰ ˆ ƒ }t	 
|¡}t	 
|¡‰t	 
|¡‰|j||||d	 ~~ˆ ¡  ˆ ˆ ¡ ¡ t ¡  ˆ ˆƒ ¡ ˆ ˆƒ ¡ ~t ¡  ˆ |ƒ ¡ ˆ ˆd ƒ ¡ ˆ tˆ ¡ ƒd
d
g¡ d
S )ze
        As C{test_threadCreationArguments} above, but for
        callInThreadWithCallback.
        r   r   c                    sF   t  ¡  ˆ ˆ ¡ ¡ ˆƒ ˆd< ˆƒ ˆd< ˆ  ¡  ˆ t |¡¡ d S )NrR   rS   )rM   rN   rL   r&   rK   r   rG   rH   ©ÚsuccessÚresult)ÚonResultDoneÚonResultWaitÚrefdictÚ	resultRefr   rS   rR   r   r   ÚonResult²   s   

zVThreadPoolTests.test_threadCreationArgumentsCallInThreadWithCallback.<locals>.onResultc                    s   ˆ ƒ S r
   r   )rA   Útest)rE   r   r   rB   ½   ó   zTThreadPoolTests.test_threadCreationArgumentsCallInThreadWithCallback.<locals>.workerc                   @   rC   )zRThreadPoolTests.test_threadCreationArgumentsCallInThreadWithCallback.<locals>.DumbNrD   r   r   r   r   rE   Á   rF   rE   )r^   N)r   r/   r8   r9   r:   r0   r;   r   rJ   rG   rH   ÚcallInThreadWithCallbackrK   rL   r&   rM   rN   rO   ÚlistÚvalues)r   rP   r]   rB   rQ   ÚonResultRefr   )rE   rY   rZ   r[   r\   r   rS   rR   r   Ú4test_threadCreationArgumentsCallInThreadWithCallbackœ   s8   


zDThreadPoolTests.test_threadCreationArgumentsCallInThreadWithCallbackc                 C   sX   t  dd¡}|  |jd¡ |  |jd¡ t t |¡¡}|  |jd¡ |  |jd¡ dS )z…
        Threadpools can be pickled and unpickled, which should preserve the
        number of threads and other parameters.
        é   é   N)r   r/   r0   r1   r2   ÚpickleÚloadsÚdumps)r   r4   Úcopyr   r   r   Útest_persistenceæ   s   z ThreadPoolTests.test_persistencec                 C   sx   d}t  ¡ }| ¡  |  |j¡ t ¡ }| ¡  t||ƒ}t	|ƒD ]}|||ƒ q!|  
|¡ |  |jd|j› d¡ dS )z 
        Test synchronization of calls made with C{method}, which should be
        one of the mechanisms of the threadpool to execute work in threads.
        r7   zrun() re-entered z timesN)r   r/   r8   r9   r:   r   r   r   r	   r(   r,   ÚassertFalser   )r   Úmethodr   rP   r   Úactorr+   r   r   r   Ú_threadpoolTestö   s   	

zThreadPoolTests._threadpoolTestc                 C   s   |   dd„ ¡S )z?
        Call C{_threadpoolTest} with C{callInThread}.
        c                 S   s   |   |j¡S r
   )rI   r   )rP   rn   r   r   r   Ú<lambda>  s    z3ThreadPoolTests.test_callInThread.<locals>.<lambda>)ro   r   r   r   r   Útest_callInThread  s   z!ThreadPoolTests.test_callInThreadc                    s`   G dd„ dt ƒ‰ ‡ fdd„}t dd¡}| |¡ | ¡  | ¡  |  ˆ ¡}|  t|ƒd¡ dS )zi
        L{ThreadPool.callInThread} logs exceptions raised by the callable it
        is passed.
        c                   @   rC   )z<ThreadPoolTests.test_callInThreadException.<locals>.NewErrorNrD   r   r   r   r   ÚNewError  rF   rr   c                      ó   ˆ ƒ ‚r
   r   r   ©rr   r   r   Ú
raiseError  r_   z>ThreadPoolTests.test_callInThreadException.<locals>.raiseErrorr   r   N)	Ú	Exceptionr   r/   rI   r8   r:   ÚflushLoggedErrorsr0   r   )r   ru   rP   Úerrorsr   rt   r   Útest_callInThreadException  s   

z*ThreadPoolTests.test_callInThreadExceptionc                    sŠ   t  ¡ ‰ˆ ¡  g ‰ ‡ ‡fdd„}t dd¡}| |dd„ ¡ | ¡  z|  ˆ¡ W | ¡  n| ¡  w |  	ˆ d ¡ |  
ˆ d d¡ dS )	zÀ
        L{ThreadPool.callInThreadWithCallback} calls C{onResult} with a
        two-tuple of C{(True, result)} where C{result} is the value returned
        by the callable supplied.
        c                    ó    ˆ  ¡  ˆ  | ¡ ˆ  |¡ d S r
   ©r   r   rV   ©ÚresultsÚwaiterr   r   r]   5  ó   
z?ThreadPoolTests.test_callInThreadWithCallback.<locals>.onResultr   r   c                   S   r%   )Nr^   r   r   r   r   r   rp   ;  ó    z?ThreadPoolTests.test_callInThreadWithCallback.<locals>.<lambda>r^   N)r   r   r   r   r/   r`   r8   r,   r:   Ú
assertTruer0   )r   r]   rP   r   r|   r   Útest_callInThreadWithCallback*  s   z-ThreadPoolTests.test_callInThreadWithCallbackc                    sº   G dd„ dt ƒ‰ ‡ fdd„}t ¡ ‰ˆ ¡  g ‰‡‡fdd„}t dd¡}| ||¡ | ¡  z|  ˆ¡ W | 	¡  n| 	¡  w |  
ˆd ¡ |  ˆd tj¡ |  tˆd jˆ ƒ¡ d	S )
zÍ
        L{ThreadPool.callInThreadWithCallback} calls C{onResult} with a
        two-tuple of C{(False, failure)} where C{failure} represents the
        exception raised by the callable supplied.
        c                   @   rC   )zRThreadPoolTests.test_callInThreadWithCallbackExceptionInCallback.<locals>.NewErrorNrD   r   r   r   r   rr   M  rF   rr   c                      rs   r
   r   r   rt   r   r   ru   P  r_   zTThreadPoolTests.test_callInThreadWithCallbackExceptionInCallback.<locals>.raiseErrorc                    rz   r
   r{   rV   r|   r   r   r]   X  r   zRThreadPoolTests.test_callInThreadWithCallbackExceptionInCallback.<locals>.onResultr   r   N)rv   r   r   r   r   r/   r`   r8   r,   r:   rl   ÚassertIsInstancer   ÚFailurer   Ú
issubclassÚtype)r   ru   r]   rP   r   )rr   r}   r~   r   Ú0test_callInThreadWithCallbackExceptionInCallbackF  s   z@ThreadPoolTests.test_callInThreadWithCallbackExceptionInCallbackc                    s¾   G dd„ dt ƒ‰ t ¡ }| ¡  g ‰‡ ‡fdd„}t dd¡}| |dd„ ¡ | |j¡ | 	¡  z|  
|¡ W | ¡  n| ¡  w |  ˆ ¡}|  t|ƒd¡ |  ˆd ¡ |  ˆd ¡ d	S )
zj
        L{ThreadPool.callInThreadWithCallback} logs the exception raised by
        C{onResult}.
        c                   @   rC   )zRThreadPoolTests.test_callInThreadWithCallbackExceptionInOnResult.<locals>.NewErrorNrD   r   r   r   r   rr   p  rF   rr   c                    s   ˆ  | ¡ ˆ  |¡ ˆ ƒ ‚r
   )r   rV   ©rr   r}   r   r   r]   x  s   

zRThreadPoolTests.test_callInThreadWithCallbackExceptionInOnResult.<locals>.onResultr   r   c                   S   r@   r
   r   r   r   r   r   rp   ~  r€   zRThreadPoolTests.test_callInThreadWithCallbackExceptionInOnResult.<locals>.<lambda>N)rv   r   r   r   r   r/   r`   rI   r   r8   r,   r:   rw   r0   r   r   rO   )r   r~   r]   rP   rx   r   rˆ   r   Ú0test_callInThreadWithCallbackExceptionInOnResultj  s    
z@ThreadPoolTests.test_callInThreadWithCallbackExceptionInOnResultc                    sˆ   g ‰t  ¡ ‰ ‡ ‡fdd„}‡fdd„}t dd¡}| ||¡ | ¡  |  |j¡ ˆ  |  	¡ ¡ |  
tˆƒd¡ |  
ˆd ˆd ¡ dS )	z
        L{ThreadPool.callInThreadWithCallback} calls the function it is
        given and the C{onResult} callback in the same thread.
        c                    s   ˆ  t ¡ j¡ ˆ  ¡  d S r
   )r   r   Úcurrent_threadÚidentrK   rV   ©rT   Ú	threadIdsr   r   r]   –  s   z5ThreadPoolTests.test_callbackThread.<locals>.onResultc                      s   ˆ   t ¡ j¡ d S r
   )r   r   rŠ   r‹   r   )r   r   r   Úfuncš  s   z1ThreadPoolTests.test_callbackThread.<locals>.funcr   r   r=   N)r   rJ   r   r/   r`   r8   r9   r:   rL   r&   r0   r   )r   r]   rŽ   rP   r   rŒ   r   Útest_callbackThread  s   z#ThreadPoolTests.test_callbackThreadc                    s¬   t j ¡ jd }d|d< g ‰ t ¡ ‰‡ ‡fdd„}‡ fdd„}t dd	¡}| ||¡ | 	¡  |  
|j¡ ˆ |  ¡ ¡ |  tˆ ƒd
¡ |  |ˆ d ¡ |  |ˆ d	 ¡ dS )z±
        The context L{ThreadPool.callInThreadWithCallback} is invoked in is
        shared by the context the callable and C{onResult} callback are
        invoked in.
        éÿÿÿÿzthis must be presentÚtestingc                    s&   t j ¡ jd }ˆ  |¡ ˆ ¡  d S ©Nr   )r   ÚtheContextTrackerÚcurrentContextÚcontextsr   rK   )rW   rX   Úctx©r•   rT   r   r   r]   ³  s   
z6ThreadPoolTests.test_callbackContext.<locals>.onResultc                     s   t j ¡ jd } ˆ  | ¡ d S r’   )r   r“   r”   r•   r   )r–   )r•   r   r   rŽ   ¸  s   z2ThreadPoolTests.test_callbackContext.<locals>.funcr   r   r=   N)r   r“   r”   r•   r   rJ   r   r/   r`   r8   r9   r:   rL   r&   r0   r   )r   Úmyctxr]   rŽ   rP   r   r—   r   Útest_callbackContext¦  s   z$ThreadPoolTests.test_callbackContextc                 C   sT   t  ¡ }| ¡  t dd¡}| |j¡ | ¡  z|  |¡ W | 	¡  dS | 	¡  w )zÃ
        Work added to the threadpool before its start should be executed once
        the threadpool is started: this is ensured by trying to release a lock
        previously acquired.
        r   r   N)
r   r   r   r   r/   rI   r   r8   r,   r:   )r   r~   rP   r   r   r   Útest_existingWorkÇ  s   z!ThreadPoolTests.test_existingWorkc                    s  t  dd¡}| ¡  |  |j¡ |  |jd¡ |  t|jƒd¡ |  t|j	ƒd¡ t
 ¡ ‰t
 ¡ ‰ ‡ ‡fdd„}| |¡ ˆ d¡ |  |jd¡ |  t|jƒd¡ |  t|j	ƒd¡ ˆ  ¡  t|jƒsnt d¡ t|jƒrd|  t|jƒd¡ |  t|j	ƒd¡ dS )z{
        As the worker receives and completes work, it transitions between
        the working and waiting states.
        r   r   c                      s   ˆ  ¡  ˆ  d¡ d S )Nr7   )rK   rL   r   ©ÚthreadFinishÚthreadWorkingr   r   Ú_threadë  s   z;ThreadPoolTests.test_workerStateTransition.<locals>._threadr7   gü©ñÒMb@?N)r   r/   r8   r9   r:   r0   Úworkersr   ÚwaitersÚworkingr   rJ   rI   rL   rK   r   r   )r   r4   rž   r   r›   r   Útest_workerStateTransitionÙ  s(   




ÿz*ThreadPoolTests.test_workerStateTransitionN)r    r!   r"   Ú__doc__r&   r,   r5   r<   r?   rU   rd   rk   ro   rq   ry   r‚   r‡   r‰   r   r™   rš   r¢   r   r   r   r   r$   ;   s(    		*J$#!r$   c                   @   s$   e Zd Zdd„ Zdd„ Zdd„ ZdS )ÚRaceConditionTestsc                    s<   t  dd¡ˆ _ t ¡ ˆ _ˆ j  ¡  ‡ fdd„}ˆ  |¡ d S )Nr   r7   c                      s   ˆ j  ¡  ˆ ` d S r
   )r   r:   r   r   r   r   Údone  s   
z&RaceConditionTests.setUp.<locals>.done)r   r/   r   rJ   rT   r8   r9   )r   r¥   r   r   r   ÚsetUp   s
   

zRaceConditionTests.setUpc                 C   r%   )z=
        A reasonable number of seconds to time out.
        r   r   r   r   r   r   r&     r'   zRaceConditionTests.getTimeoutc                 C   sŽ   |   ¡ }| j | jj¡ | j |¡ | j ¡  tdƒD ]
}| j | jj¡ q| j | jj¡ | j |¡ | j ¡ sE| j ¡  |  	d¡ dS dS )a  
        If multiple threads are waiting on an event (via blocking on something
        in a callable passed to L{threadpool.ThreadPool.callInThread}), and
        there is spare capacity in the threadpool, sending another callable
        which will cause those to un-block to
        L{threadpool.ThreadPool.callInThread} will reliably run that callable
        and un-block the blocked threads promptly.

        @note: This is not really a unit test, it is a stress-test.  You may
            need to run it with C{trial -u} to fail reliably if there is a
            problem.  It is very hard to regression-test for this particular
            bug - one where the thread pool may consider itself as having
            "enough capacity" when it really needs to spin up a new thread if
            it possibly can - in a deterministic way, since the bug can only be
            provoked by subtle race conditions.
        r6   z9'set' did not run in thread; timed out waiting on 'wait'.N)
r&   r   rI   rT   rK   rL   Úclearr(   ÚisSetr)   )r   Útimeoutr+   r   r   r   Útest_synchronization  s   


þz'RaceConditionTests.test_synchronizationN)r    r!   r"   r¦   r&   rª   r   r   r   r   r¤   ÿ  s    r¤   c                   @   ó    e Zd ZdZdd„ Zdd„ ZdS )Ú
MemoryPoolz
    A deterministic threadpool that uses in-memory data structures to queue
    work rather than threads to execute work.
    c                 O   s0   || _ || _|| _tjj| g|¢R i |¤Ž dS )aÄ  
        Initialize this L{MemoryPool} with a test case.

        @param coordinator: a worker used to coordinate work in the L{Team}
            underlying this threadpool.
        @type coordinator: L{twisted._threads.IExclusiveWorker}

        @param failTest: A 1-argument callable taking an exception and raising
            a test-failure exception.
        @type failTest: 1-argument callable taking (L{Failure}) and raising
            L{unittest.FailTest}.

        @param newWorker: a 0-argument callable that produces a new
            L{twisted._threads.IWorker} provider on each invocation.
        @type newWorker: 0-argument callable returning
            L{twisted._threads.IWorker}.
        N)Ú_coordinatorÚ	_failTestÚ
_newWorkerr   r/   r   )r   ÚcoordinatorÚfailTestÚ	newWorkerÚargsÚkwargsr   r   r   r   5  s   zMemoryPool.__init__c                    s&   ‡ ‡‡fdd„}t ˆj|ˆjd‰ˆS )a§  
        Override testing hook to create a deterministic threadpool.

        @param currentLimit: A 1-argument callable which returns the current
            threadpool size limit.

        @param threadFactory: ignored in this invocation; a 0-argument callable
            that would produce a thread.

        @return: a L{Team} backed by the coordinator and worker passed to
            L{MemoryPool.__init__}.
        c                     s&   ˆ  ¡ } | j| j ˆ ƒ krd S ˆ ¡ S r
   )Ú
statisticsÚbusyWorkerCountÚidleWorkerCountr¯   )Ústats©ÚcurrentLimitr   Úteamr   r   ÚrespectLimitZ  s   z&MemoryPool._pool.<locals>.respectLimit)r°   ÚcreateWorkerÚlogException)r   r­   r®   )r   rº   ÚthreadFactoryr¼   r   r¹   r   Ú_poolL  s   	ýzMemoryPool._poolN)r    r!   r"   r£   r   rÀ   r   r   r   r   r¬   /  s    r¬   c                   @   r«   )Ú
PoolHelpera  
    A L{PoolHelper} constructs a L{threadpool.ThreadPool} that doesn't actually
    use threads, by using the internal interfaces in L{twisted._threads}.

    @ivar performCoordination: a 0-argument callable that will perform one unit
        of "coordination" - work involved in delegating work to other threads -
        and return L{True} if it did any work, L{False} otherwise.

    @ivar workers: the workers which represent the threads within the pool -
        the workers other than the coordinator.
    @type workers: L{list} of 2-tuple of (L{IWorker}, C{workPerformer}) where
        C{workPerformer} is a 0-argument callable like C{performCoordination}.

    @ivar threadpool: a modified L{threadpool.ThreadPool} to test.
    @type threadpool: L{MemoryPool}
    c                    s@   t ƒ \}ˆ _g ˆ _‡ fdd„}t||j|g|¢R i |¤Žˆ _dS )zû
        Create a L{PoolHelper}.

        @param testCase: a test case attached to this helper.

        @type args: The arguments passed to a L{threadpool.ThreadPool}.

        @type kwargs: The arguments passed to a L{threadpool.ThreadPool}
        c                      s   ˆ j  tƒ ¡ ˆ j d d S )Nr   r   )rŸ   r   r   r   r   r   r   r²   Š  s   z&PoolHelper.__init__.<locals>.newWorkerN)r   ÚperformCoordinationrŸ   r¬   r)   r   )r   ÚtestCaser³   r´   r°   r²   r   r   r   r   }  s   
ÿÿÿzPoolHelper.__init__c                 C   s   |   ¡ r	 |   ¡ sdS dS )z‰
        Perform all currently scheduled "coordination", which is the work
        involved in delegating work to other threads.
        N)rÂ   r   r   r   r   ÚperformAllCoordination’  s   ÿz!PoolHelper.performAllCoordinationN)r    r!   r"   r£   r   rÄ   r   r   r   r   rÁ   k  s    rÁ   c                   @   r«   )ÚMemoryBackedTestszn
    Tests using L{PoolHelper} to deterministically test properties of the
    threadpool implementation.
    c                 C   sl   t | ddƒ}d}t|ƒD ]
}|j dd„ ¡ q| ¡  |  |jg ¡ |j ¡  | ¡  |  t|jƒ|¡ dS )zÂ
        If a threadpool is told to do work before starting, then upon starting
        up, it will start enough workers to handle all of the enqueued work
        that it's been given.
        r   r7   r   c                   S   r@   r
   r   r   r   r   r   rp   ª  r€   z;MemoryBackedTests.test_workBeforeStarting.<locals>.<lambda>N)	rÁ   r(   r   rI   rÄ   r0   rŸ   r8   r   ©r   ÚhelperÚnÚxr   r   r   Útest_workBeforeStarting¡  s   
z)MemoryBackedTests.test_workBeforeStartingc                 C   sp   t | ddƒ}d}t|ƒD ]
}|j dd„ ¡ q| ¡  |  |jg ¡ |j ¡  | ¡  |  t|jƒ|jj	¡ dS )z°
        If the amount of work before starting exceeds the maximum number of
        threads allowed to the threadpool, only the maximum count will be
        started.
        r   r7   é2   c                   S   r@   r
   r   r   r   r   r   rp   º  r€   zBMemoryBackedTests.test_tooMuchWorkBeforeStarting.<locals>.<lambda>N)
rÁ   r(   r   rI   rÄ   r0   rŸ   r8   r   r2   rÆ   r   r   r   Útest_tooMuchWorkBeforeStarting±  s   
z0MemoryBackedTests.test_tooMuchWorkBeforeStartingN)r    r!   r"   r£   rÊ   rÌ   r   r   r   r   rÅ   ›  s    rÅ   )r£   rM   rg   r   r   rG   Útwisted._threadsr   r   Útwisted.pythonr   r   r   r   Útwisted.trialr   r	   ÚsynchronizeÚSynchronousTestCaser$   r¤   r/   r¬   rÁ   rÅ   r   r   r   r   Ú<module>   s&   
$   G0<0