o
    ¯b÷$  ã                   @   sz   d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZ G dd	„ d	eed
ƒƒZG dd„ de	ƒZdS )z&
Tests for L{twisted._threads._team}.
é    )ÚproxyForInterface)ÚcallÚget)ÚFailure)ÚSynchronousTestCaseé   )ÚAlreadyQuitÚIWorkerÚTeamÚcreateMemoryWorkerc                       s(   e Zd ZdZdd„ Z‡ fdd„Z‡  ZS )ÚContextualWorkerz:
    A worker implementation that supplies a context.
    c                 K   s   || _ || _dS )z:
        Create with a real worker and a context.
        N)Ú_realWorkerÚ_context)ÚselfÚ
realWorkerÚctx© r   úA/usr/lib/python3/dist-packages/twisted/_threads/test/test_team.pyÚ__init__   s   
zContextualWorker.__init__c                    s   t ƒ  ‡ ‡fdd„¡ dS )zŠ
        Perform the given work with the context given to __init__.

        @param work: the work to pass on to the real worker.
        c                      s   t ˆ jˆƒS ©N)r   r   r   ©r   Úworkr   r   Ú<lambda>"   s    z%ContextualWorker.do.<locals>.<lambda>N)ÚsuperÚdor   ©Ú	__class__r   r   r      s   zContextualWorker.do)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ú__classcell__r   r   r   r   r      s    r   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"S )#Ú	TeamTestsz
    Tests for L{Team}
    c                    sl   t ƒ \}ˆ _t|ddˆ _g ˆ _g ˆ _g ˆ _g ˆ _dd„ ˆ _‡ fdd„}g ˆ _	‡ fdd„}t
|||ƒˆ _d	S )
zl
        Set up a L{Team} with inspectable, synchronous workers that can be
        single-stepped.
        Úcoordinator©Úworkerc                   S   ó   dS )NFr   r   r   r   r   r   5   ó    z!TeamTests.setUp.<locals>.<lambda>c                     sz   ˆ  ¡ rd S tƒ \} ‰ˆj ˆ¡ ˆj ˆ¡ t| tˆjƒd‰ ˆj ˆ ¡ ˆj ˆ ¡ ˆ j	‰‡ ‡‡‡fdd„}|ˆ _	ˆ S )Nr$   c                      s"   ˆƒ  ˆj  ˆ ¡ ˆj ˆ¡ d S r   )ÚallUnquitWorkersÚremoveÚactivePerformersr   )ÚcwÚ	performerÚrealQuitr   r   r   ÚquitAndRemoveB   s   z<TeamTests.setUp.<locals>.createWorker.<locals>.quitAndRemove)
ÚnoMoreWorkersr   ÚworkerPerformersÚappendr*   r   ÚlenÚallWorkersEverr(   Úquit)r%   r.   ©r   )r+   r,   r-   r   ÚcreateWorker7   s   
z%TeamTests.setUp.<locals>.createWorkerc                      s   ˆ j  tƒ ¡ d S r   )Úfailuresr1   r   r   r5   r   r   ÚlogExceptionL   ó   z%TeamTests.setUp.<locals>.logExceptionN)r   ÚcoordinateOncer   r#   r0   r3   r(   r*   r/   r7   r
   Úteam)r   r#   r6   r8   r   r5   r   ÚsetUp*   s   
zTeamTests.setUpc                 C   s   d}|   ¡ rd}|   ¡ s|S )a  
        Perform all work currently scheduled in the coordinator.

        @return: whether any coordination work was performed; if the
            coordinator was idle when this was called, return L{False}
            (otherwise L{True}).
        @rtype: L{bool}
        FT)r:   )r   Údidr   r   r   Ú
coordinateQ   s
   	ÿzTeamTests.coordinatec                 C   sD   d}|r |   ¡ }| jD ]
}|| jv r|ƒ  q|p|   ¡ }|sdS dS )zj
        Perform all work on the coordinator and worker performers that needs to
        be done.
        TN)r>   r0   r*   )r   Ú
continuingr,   r   r   r   ÚperformAllOutstandingWork_   s   

€ûz#TeamTests.performAllOutstandingWorkc                    sb   ‡ fdd„‰ | j  ˆ ¡ |  ¡  |  | j  ¡ jd¡ |  ¡  |  ˆ jd¡ |  | j  ¡ jd¡ dS )zd
        L{Team.do} does the work in a worker created by the createWorker
        callable.
        c                      s   t dƒˆ _d S )Nr%   )r   Úwhor   ©Ú	somethingr   r   rC   r   s   z4TeamTests.test_doDoesWorkInWorker.<locals>.somethingé   r   N)r;   r   r>   ÚassertEqualÚ
statisticsÚbusyWorkerCountr@   rA   r5   r   rB   r   Útest_doDoesWorkInWorkerl   s   z!TeamTests.test_doDoesWorkInWorkerc                 C   s8   | j  ¡ }|  |jd¡ |  |jd¡ |  |jd¡ dS )z‘
        L{Team.statistics} returns an object with idleWorkerCount,
        busyWorkerCount, and backloggedWorkCount integer attributes.
        r   N)r;   rF   rE   ÚidleWorkerCountrG   ÚbackloggedWorkCount)r   Ústatsr   r   r   Útest_initialStatistics|   s   
z TeamTests.test_initialStatisticsc                 C   s*   | j  d¡ |  ¡  |  t| jƒd¡ dS )zN
        L{Team.grow} increases the number of available idle workers.
        é   N)r;   Úgrowr@   rE   r2   r0   r5   r   r   r   Útest_growCreatesIdleWorkers†   s   z%TeamTests.test_growCreatesIdleWorkersc                    sL   ‡ fdd„ˆ _ ˆ j d¡ ˆ  ¡  ˆ  tˆ jƒd¡ ˆ  ˆ j ¡ jd¡ dS )z
        L{Team.grow} increases the number of available idle workers until the
        C{createWorker} callable starts returning None.
        c                      s   t ˆ jƒdkS )Né   )r2   r3   r   r5   r   r   r   “   s    z0TeamTests.test_growCreateLimit.<locals>.<lambda>rM   rP   N)	r/   r;   rN   r@   rE   r2   r3   rF   rI   r5   r   r5   r   Útest_growCreateLimitŽ   s
   zTeamTests.test_growCreateLimitc                 C   s>   | j  d¡ |  ¡  | j  d¡ |  ¡  |  t| jƒd¡ dS )zG
        L{Team.shrink} will quit the given number of workers.
        rM   rP   r   N)r;   rN   r@   ÚshrinkrE   r2   r(   r5   r   r   r   Útest_shrinkQuitsWorkers™   s
   z!TeamTests.test_shrinkQuitsWorkersc                 C   s`   | j  d¡ |  ¡  |  t| jƒd¡ | j  ¡  |  t| jƒd¡ |  ¡  |  t| jƒd¡ dS )zU
        L{Team.shrink} with no arguments will stop all outstanding workers.
        é
   r   N)r;   rN   r@   rE   r2   r(   rR   r5   r   r   r   Útest_shrinkToZero£   s   
zTeamTests.test_shrinkToZeroc                    sä   | j  d¡ |  ¡  ‡ fdd„‰ dˆ _|  | j  ¡ jd¡ tdƒD ]}| j  ˆ ¡ q!|  ¡  |  | j  ¡ jd¡ dd„ | _	| j  ˆ ¡ |  ¡  |  | j  ¡ jd¡ |  | j  ¡ j
d¡ |  ¡  |  | j  ¡ j
d¡ |  ˆ jd¡ d	S )
z
        When no additional workers are available, the given work is backlogged,
        and then performed later when the work was.
        rP   c                      s   ˆ  j d7  _ d S )NrD   )Útimesr   rB   r   r   rC   ·   r9   z@TeamTests.test_moreWorkWhenNoWorkersAvailable.<locals>.somethingr   c                   S   r&   )NTr   r   r   r   r   r   Â   r'   z?TeamTests.test_moreWorkWhenNoWorkersAvailable.<locals>.<lambda>rD   é   N)r;   rN   r>   rV   rE   rF   rI   Úranger   r/   rJ   r@   )r   Úir   rB   r   Ú#test_moreWorkWhenNoWorkersAvailable¯   s"   
z-TeamTests.test_moreWorkWhenNoWorkersAvailablec                 C   sB   | j  dd„ ¡ |  ¡  |  t| jƒd¡ |  | jd jt¡ dS )z»
        When an exception is raised in a task passed to L{Team.do}, the
        C{logException} given to the L{Team} at construction is invoked in the
        exception context.
        c                   S   s   dd S )NrD   r   r   r   r   r   r   r   Ñ   s    z0TeamTests.test_exceptionInTask.<locals>.<lambda>rD   r   N)r;   r   r@   rE   r2   r7   ÚtypeÚZeroDivisionErrorr5   r   r   r   Útest_exceptionInTaskË   s   zTeamTests.test_exceptionInTaskc                 C   s0   | j  ¡  |  t| j j¡ |  t| j jt¡ dS )zx
        L{Team.quit} causes future invocations of L{Team.do} and L{Team.quit}
        to raise L{AlreadyQuit}.
        N)r;   r4   ÚassertRaisesr   r   Úlistr5   r   r   r   Ú	test_quitÖ   s   
zTeamTests.test_quitc                 C   sZ   t dƒD ]}| j t¡ q|  ¡  | j ¡  |  ¡  |  t| jƒd¡ |  	t
| jj¡ dS )zk
        L{Team.quit} causes all idle workers, as well as the coordinator
        worker, to quit.
        rT   r   N)rX   r;   r   r_   r@   r4   rE   r2   r(   r^   r   r#   ©r   Úxr   r   r   Útest_quitQuitsß   s   
zTeamTests.test_quitQuitsc                 C   s€   | j  d¡ tdƒD ]}| j  t¡ q
|  ¡  | j  ¡  |  ¡  |  t| j	ƒd¡ |  
¡  |  t| j	ƒd¡ |  t| jj¡ dS )z|
        L{Team.quit} causes all busy workers to be quit once they've finished
        the work they've been given.
        rT   rM   r   N)r;   rN   rX   r   r_   r>   r4   rE   r2   r(   r@   r^   r   r#   ra   r   r   r   Útest_quitQuitsLaterWhenBusyì   s   
z%TeamTests.test_quitQuitsLaterWhenBusyc                    s^   ˆj  t¡ ˆj jj‰ ‡ ‡fdd„}|ˆj j_ˆj  ¡  ˆ tˆj j¡ ˆ tˆj jt¡ dS )z¤
        If work happens after L{Team.quit} sets its C{Quit} flag, but before
        any other work takes place, the L{Team} should still exit gracefully.
        c                      s   ˆ ƒ  ˆ  ¡  d S r   )r@   r   ©ÚoriginalSetr   r   r   ÚperformWorkConcurrently  s   zOTeamTests.test_quitConcurrentWithWorkHappening.<locals>.performWorkConcurrentlyN)r;   r   r_   Ú_quitÚsetr4   r^   r   )r   rg   r   re   r   Ú$test_quitConcurrentWithWorkHappeningü   s   


z.TeamTests.test_quitConcurrentWithWorkHappeningc                 C   s^   t dƒD ]}| j t¡ q|  ¡  |  t| jƒd¡ | j d¡ |  	¡  |  t| jƒd¡ dS )zl
        L{Team.shrink} will wait for busy workers to finish being busy and then
        quit them.
        rT   é   rP   N)
rX   r;   r   r_   r>   rE   r2   r(   rR   r@   ra   r   r   r   Útest_shrinkWhenBusy  s   zTeamTests.test_shrinkWhenBusyN)r   r   r   r    r<   r>   r@   rH   rL   rO   rQ   rS   rU   rZ   r]   r`   rc   rd   rj   rl   r   r   r   r   r"   %   s$    '

	r"   N)r    Útwisted.python.componentsr   Útwisted.python.contextr   r   Útwisted.python.failurer   Útwisted.trial.unittestr   Ú r   r	   r
   r   r   r"   r   r   r   r   Ú<module>   s   