o
    ¯blA  ã                   @   sj  d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	m
Z
mZ ddlmZmZmZmZ ddlmZ ddlmZmZ dd	lmZmZ dd
lmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z(m)Z)m*Z* ddl+m,Z,m-Z- ddl.m/Z/m0Z0 G dd„ dƒZ1ee
j2ƒG dd„ deƒƒZ3G dd„ de/ƒZ4G dd„ dƒZ5G dd„ de0ƒZ6dS )z-
Tests for L{twisted.trial._dist.disttrial}.
é    N)ÚStringIO)ÚimplementerÚverify)ÚerrorÚ
interfacesÚreactor)ÚfailÚgatherResultsÚmaybeDeferredÚsucceed)ÚCONNECTION_DONE)ÚProcessProtocolÚProtocol)Ú
CooperatorÚ
deferLater)ÚFailure)ÚFilesystemLock)ÚMemoryReactorClock)ÚFakeScheduler)ÚDistReporter)ÚDistTrialRunner)ÚLocalWorker)ÚReporterÚTreeReporterÚUncleanWarningsReporterWrapper)ÚErrorHolderÚ
TrialSuite)ÚSynchronousTestCaseÚTestCasec                   @   ó   e Zd ZdZdd„ ZdS )ÚFakeTransportz*
    A simple fake process transport.
    c                 C   ó   dS )z%
        Ignore write calls.
        N© )ÚselfÚfdÚdatar"   r"   úI/usr/lib/python3/dist-packages/twisted/trial/_dist/test/test_disttrial.pyÚwriteToChild(   s    zFakeTransport.writeToChildN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r'   r"   r"   r"   r&   r    #   ó    r    c                   @   sL   e Zd ZdZdZdZdZdd„ Zdi dddddfdd„Zd	d
„ Z	dd„ Z
dS )ÚCountingReactorz…
    A fake reactor that counts the calls to L{IReactorCore.run},
    L{IReactorCore.stop}, and L{IReactorProcess.spawnProcess}.
    r   c                 C   s   t  | ¡ || _d S ©N)r   Ú__init__Ú_workers)r#   Úworkersr"   r"   r&   r/   9   s   

zCountingReactor.__init__r"   Nc
           
      C   s*   | j  |¡ | tƒ ¡ |  jd7  _dS )zî
        See L{IReactorProcess.spawnProcess}.

        @param workerProto: See L{IReactorProcess.spawnProcess}.
        @param args: See L{IReactorProcess.spawnProcess}.
        @param kwargs: See L{IReactorProcess.spawnProcess}.
        é   N)r0   ÚappendÚmakeConnectionr    Ú
spawnCount)
r#   ÚworkerProtoÚ
executableÚargsÚenvÚpathÚuidÚgidÚusePTYÚchildFDsr"   r"   r&   ÚspawnProcess=   s   zCountingReactor.spawnProcessc                 C   s   t  | ¡ |  jd7  _dS )z+
        See L{IReactorCore.stop}.
        r2   N)r   ÚstopÚ	stopCount©r#   r"   r"   r&   r@   T   s   
zCountingReactor.stopc                 C   s>   |  j d7  _ d| _d| _| jD ]\}}}||i |¤Ž qdS )z*
        See L{IReactorCore.run}.
        r2   TN)ÚrunCountÚrunningÚhasRunÚwhenRunningHooks)r#   Úfr8   Úkwargsr"   r"   r&   Úrun[   s   ÿzCountingReactor.run)r(   r)   r*   r+   r5   rA   rC   r/   r?   r@   rI   r"   r"   r"   r&   r-   .   s     
ör-   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )ÚCountingReactorTestsz'
    Tests for L{CountingReactor}.
    c                 C   s   g | _ t| j ƒ| _d S r.   )r1   r-   r   rB   r"   r"   r&   ÚsetUpn   s   zCountingReactorTests.setUpc                 C   s   t  tj| j¡ dS )zJ
        L{CountingReactor} instances provide L{IReactorProcess}.
        N)r   ÚverifyObjectr   ÚIReactorProcessr   rB   r"   r"   r&   Útest_providesIReactorProcessr   s   z1CountingReactorTests.test_providesIReactorProcessc                 C   sj   |   | jj¡ tƒ }dD ]&}| jj|tjtjgd� |  |j¡ |  	| j
|g| ¡ |  	| jj|¡ qdS )zÃ
        The process protocol for a spawned process is connected to a
        transport and appended onto the provided C{workers} list, and
        the reactor's C{spawnCount} increased.
        ©r2   é   ©r8   N)ÚassertFalser   r5   r   r?   Úsysr7   Ú
assertTrueÚ	transportÚassertEqualr1   )r#   ÚprotoÚcountr"   r"   r&   Útest_spawnProcessx   s   üz&CountingReactorTests.test_spawnProcessc                 C   s6   |   | jj¡ dD ]}| j ¡  |  | jj|¡ q	dS )zB
        Stopping the reactor increments its C{stopCount}
        rO   N)rR   r   rA   r@   rV   )r#   rX   r"   r"   r&   Ú	test_stop‡   s
   
þzCountingReactorTests.test_stopc                 C   sj   |   | jj¡ g }| j |jd¡ dD ]}| j ¡  |  | jj|¡ |  | jjd¡ |  t|ƒ|¡ qdS )z’
        Running the reactor increments its C{runCount}, does not imply
        C{stop}, and calls L{IReactorCore.callWhenRunning} hooks.
        NrO   r   )	rR   r   rC   ÚcallWhenRunningr3   rI   rV   rA   Úlen)r#   ÚwhenRunningCallsrX   r"   r"   r&   Útest_run�   s   
üzCountingReactorTests.test_runN)	r(   r)   r*   r+   rK   rN   rY   rZ   r^   r"   r"   r"   r&   rJ   i   s    	rJ   c                   @   r   )Ú"EternalTerminationPredicateFactoryzI
    A rigged terminationPredicateFactory for which time never pass.
    c                 C   r!   )z%
        See: L{task._Timer}
        Fr"   rB   r"   r"   r&   Ú__call__¦   s   z+EternalTerminationPredicateFactory.__call__N)r(   r)   r*   r+   r`   r"   r"   r"   r&   r_   ¡   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 )#ÚDistTrialRunnerTestsz'
    Tests for L{DistTrialRunner}.
    c                 C   s$   t tdg |  ¡ d�| _tƒ | j_dS )z.
        Create a runner for testing.
        é   )ÚworkingDirectoryN)r   r   ÚmktempÚrunnerr   Ú_streamrB   r"   r"   r&   rK   ²   s   ÿzDistTrialRunnerTests.setUpc                 C   s.   |D ]}|j  tjtj¡ | ttƒ¡ qdS )zË
        Reap the workers and trap L{ConnectionDone} failures on their
        C{endDeferred}s.

        @param workers: The workers to reap.
        @type workers: An iterable of L{LocalWorker}
        N)ÚendDeferredÚ
addErrbackr   Útrapr   ÚConnectionDoneÚprocessEndedr   )r#   r1   Úworkerr"   r"   r&   Úreap»   s   	þzDistTrialRunnerTests.reapc                 C   s   t ƒ }t|td�}||fS )a  
        Helper to create fake scheduler and cooperator in tests.

        The cooperator has a termination timer which will never inform
        the scheduler that the task needs to be terminated.

        @return: L{tuple} of (scheduler, cooperator)
        )Ú	schedulerÚterminationPredicateFactory)r   r   r_   )r#   rn   Ú
cooperatorr"   r"   r&   Ú$getFakeSchedulerAndEternalCooperatorÈ   s   	þz9DistTrialRunnerTests.getFakeSchedulerAndEternalCooperatorc                 C   s4   t ƒ }tt|ƒƒ}| j |¡ |  | ¡ dk¡ dS )ze
        L{DistTrialRunner.writeResults} writes to the stream specified in the
        init.
        r   N)r   r   r   re   ÚwriteResultsrT   Útell)r#   ÚstringIOÚresultr"   r"   r&   Útest_writeResultsØ   s   z&DistTrialRunnerTests.test_writeResultsc                 C   sJ   dd„ t dƒD ƒ}| j |d¡}|D ]}|  |t¡ q|  dt|ƒ¡ dS )zv
        C{createLocalWorkers} iterates the list of protocols and create one
        L{LocalWorker} for each.
        c                 S   ó   g | ]}t ƒ ‘qS r"   )Úobject)Ú.0Úxr"   r"   r&   Ú
<listcomp>ç   ó    z@DistTrialRunnerTests.test_createLocalWorkers.<locals>.<listcomp>rb   r:   N)Úrangere   ÚcreateLocalWorkersÚassertIsInstancer   rV   r\   )r#   Ú	protocolsr1   Úsr"   r"   r&   Útest_createLocalWorkersâ   s
   z,DistTrialRunnerTests.test_createLocalWorkersc                    s¢   dd„ t dƒD ƒ}g ‰ i ‰di dddddf‡ ‡fdd„	}| j ||d	g¡ |  ˆ d ˆ d
 ¡ |  tj ˆ d ¡¡ |  d	ˆ d ¡ |  tj 	t
j¡ˆd ¡ dS )z“
        Given a C{spawnProcess} function, C{launchWorkerProcess} launches a
        python process with an existing path as its argument.
        c                 S   rw   r"   )r   )ry   Úir"   r"   r&   r{   ò   r|   zCDistTrialRunnerTests.test_launchWorkerProcesses.<locals>.<listcomp>rb   r"   Nr   c	           	         s"   ˆ   |¡ ˆ  |¡ ˆ |¡ d S r.   )r3   ÚextendÚupdate)	ÚprocessProtocolr7   r8   r9   r:   r;   r<   r=   r>   ©Ú	argumentsÚenvironmentr"   r&   ÚfakeSpawnProcessö   s   

zIDistTrialRunnerTests.test_launchWorkerProcesses.<locals>.fakeSpawnProcessÚfoor2   rP   é   ÚTRIAL_PYTHONPATH)r}   re   ÚlaunchWorkerProcessesrV   rT   Úosr:   ÚexistsÚpathsepÚjoinrS   )r#   r€   rŠ   r"   r‡   r&   Útest_launchWorkerProcessesí   s    ÷z/DistTrialRunnerTests.test_launchWorkerProcessesc                 C   sl   g }t |ƒ}|  | j|¡ tƒ }tdƒD ]}| tƒ ¡ q| j ||¡ |  	|j
d¡ |  	|j| jj¡ dS )zm
        C{run} starts the reactor exactly once and spawns each of the workers
        exactly once.
        é
   r2   N)r-   Ú
addCleanuprm   r   r}   ÚaddTestr   re   rI   rV   rC   r5   Ú_workerNumber)r#   r1   ÚfakeReactorÚsuiterƒ   r"   r"   r&   r^     s   zDistTrialRunnerTests.test_runc                    sª   G ‡ ‡fdd„dt ƒ}ˆ  ¡ }t |¡ tj |d¡‰tˆd ƒ}| ¡  ˆ  |j	¡ ˆˆ j
_g }||ƒ}ˆ  ˆ j|¡ tƒ }tdƒD ]}| tƒ ¡ qCˆ j
 ||¡ dS )z‡
        L{DistTrialRunner} checks if the test directory is already locked, and
        if it is generates a name based on it.
        c                       s   e Zd Z‡ ‡fdd„ZdS )zKDistTrialRunnerTests.test_runUsedDirectory.<locals>.CountingReactorWithLockc              
      s‚   | j  |¡ ˆ  tj |j¡tj tj ˆd t| j	ƒ¡¡¡ t
ˆd ƒ}ˆ  | ¡ ¡ |  j	d7  _	| tƒ ¡ dd„ |j_d S )Nz-1z-1.lockr2   c                  W   ó   t d ƒS r.   ©r   rQ   r"   r"   r&   Ú<lambda>.  s    zjDistTrialRunnerTests.test_runUsedDirectory.<locals>.CountingReactorWithLock.spawnProcess.<locals>.<lambda>)r0   r3   rV   r�   r:   ÚabspathÚ_logDirectoryr’   Ústrr5   r   rR   Úlockr4   r    Ú_ampProtocolrI   )Úoselfrl   r8   rH   Ú	localLock©r#   rc   r"   r&   r?   "  s   ÿþzXDistTrialRunnerTests.test_runUsedDirectory.<locals>.CountingReactorWithLock.spawnProcessN)r(   r)   r*   r?   r"   r¤   r"   r&   ÚCountingReactorWithLock!  s    r¥   Ú_trial_tempú.lockr”   N)r-   rd   r�   Úmkdirr:   r’   r   r    r•   Úunlockre   Ú_workingDirectoryrm   r   r}   r–   r   rI   )r#   r¥   ÚnewDirectoryr    r1   r˜   r™   rƒ   r"   r¤   r&   Útest_runUsedDirectory  s   
z*DistTrialRunnerTests.test_runUsedDirectoryc                 C   sJ   g }t |ƒ}|  | j|¡ | j tƒ |¡ |  |jd¡ |  |jd¡ dS )zh
        L{DistTrialRunner} doesn't try to start more workers than the number of
        tests.
        r2   N)	r-   r•   rm   re   rI   r   rV   rC   r5   )r#   r1   r˜   r"   r"   r&   Útest_minimalWorkerC  s   z'DistTrialRunnerTests.test_minimalWorkerc                 C   sP   g }t |ƒ}|  | j|¡ d| j_| j tƒ |¡}|  |t¡ |  |j	t
¡ dS )zŠ
        Running with the C{unclean-warnings} option makes L{DistTrialRunner}
        uses the L{UncleanWarningsReporterWrapper}.
        TN)r-   r•   rm   re   Ú_uncleanWarningsrI   r   r   r   Úoriginalr   )r#   r1   r˜   ru   r"   r"   r&   Útest_runUncleanWarningsP  s   z,DistTrialRunnerTests.test_runUncleanWarningsc                 C   sN   t ƒ }tƒ }| j ||¡}|  |t¡ | jj ¡ }|  d|¡ |  d|¡ dS )zš
        When the suite contains no test, L{DistTrialRunner} takes a shortcut
        path without launching any process or starting the reactor.
        úRunning 0 testÚPASSEDN)	rx   r   re   rI   r   r   rf   ÚgetvalueÚassertIn)r#   r˜   r™   ru   Úoutputr"   r"   r&   Útest_runWithoutTest^  s   z(DistTrialRunnerTests.test_runWithoutTestc                 C   s~   t ƒ }tdttdƒƒƒ}| j ||¡}|  |t¡ | jj 	¡ }|  
d|¡ |  
d|¡ |  
d|¡ |  
d|¡ |  
d|¡ dS )zº
        Even if there is no test, the suite can contain an error (most likely,
        an import error): this should make the run fail, and the error should
        be printed.
        zan errorzfoo barr±   zerrors=1ÚFAILEDN)rx   r   r   ÚRuntimeErrorre   rI   r   r   rf   r³   r´   )r#   r˜   r   ru   rµ   r"   r"   r&   Ú!test_runWithoutTestButWithAnErrork  s   z6DistTrialRunnerTests.test_runWithoutTestButWithAnErrorc                 C   s†   G dd„ dt ƒ}|  ¡ \}}g }||ƒ}|  | j|¡ | j tƒ ||j¡}|  |j	d¡ |  |j
d¡ | ¡  |  dt|jjƒ¡ dS )zw
        If for some reasons we can't connect to the worker process, the test
        suite catches and fails.
        c                   @   ó   e Zd Zdd„ Zdd„ ZdS )zMDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFailc                 _   ó4   | j  |¡ | tƒ ¡ |  jd7  _| j|j_d S ©Nr2   )r0   r3   r4   r    r5   Ú
failingRunr¡   rI   ©r#   rl   r8   rH   r"   r"   r&   r?   ƒ  ó   zZDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFail.spawnProcessc                 S   s   t tdƒƒS )NÚoops)r   r¸   ©r#   Úcaseru   r"   r"   r&   r½   ‰  s   zXDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFail.failingRunN)r(   r)   r*   r?   r½   r"   r"   r"   r&   ÚCountingReactorWithFail‚  ó    rÃ   r2   N)r-   rq   r•   rm   re   rI   r   Ú	cooperaterV   rC   r5   Úpumpr\   r¯   Úfailures)r#   rÃ   rn   rp   r1   r˜   ru   r"   r"   r&   Útest_runUnexpectedError|  s   
z,DistTrialRunnerTests.test_runUnexpectedErrorc                    sŠ   G dd„ dt ƒ}ˆjj‰g }||ƒ‰ ˆj tƒ ˆ ¡ ‡ ‡‡fdd„}ˆ tˆ j ¡ ƒdg¡ ˆ tˆ jd ƒdg¡ ˆ 	|¡ t
td|ƒS )zz
        L{DistTrialRunner} calls C{reactor.stop} and unlocks the test directory
        once the tests have run.
        c                   @   rº   )zODistTrialRunnerTests.test_runStopAfterTests.<locals>.CountingReactorWithSuccessc                 _   r»   r¼   ©r0   r3   r4   r    r5   ÚsucceedingRunr¡   rI   r¾   r"   r"   r&   r?   Ÿ  r¿   z\DistTrialRunnerTests.test_runStopAfterTests.<locals>.CountingReactorWithSuccess.spawnProcessc                 S   rš   r.   r›   rÁ   r"   r"   r&   rÊ   ¥  s   z]DistTrialRunnerTests.test_runStopAfterTests.<locals>.CountingReactorWithSuccess.succeedingRunN©r(   r)   r*   r?   rÊ   r"   r"   r"   r&   ÚCountingReactorWithSuccessž  rÄ   rÌ   c                     ó,   t ˆd ƒ} ˆ |  ¡ ¡ ˆ dˆ j¡ d S )Nr§   r2   ©r   rT   r    rV   rA   ©r£   ©r˜   r#   rc   r"   r&   Úcheck¯  s   z:DistTrialRunnerTests.test_runStopAfterTests.<locals>.checkÚbeforeÚshutdownr   )r-   re   rª   rI   r   rV   ÚlistÚtriggersÚkeysrm   r   r   )r#   rÌ   r1   rÑ   r"   rÐ   r&   Útest_runStopAfterTests˜  s   

z+DistTrialRunnerTests.test_runStopAfterTestsc                    sœ   g }ˆj j‰t|ƒ‰ ˆj  tƒ ˆ ¡ ‡fdd„}‡ ‡‡fdd„‰ˆ tˆ j ¡ ƒdg¡ ˆ tˆ jd ƒdg¡ ˆ 	|¡ t
dd„ ˆ jd d D ƒƒ |¡S )	zÄ
        L{DistTrialRunner} waits for the worker processes to stop when the
        reactor is stopping, and then unlocks the test directory, not trying to
        stop the reactor again.
        c                    s   t tdˆ ƒS )Nr   )r   r   )Úign)Ú	realCheckr"   r&   rÑ   Æ  s   zEDistTrialRunnerTests.test_runWaitForProcessesDeferreds.<locals>.checkc                     rÍ   )Nr§   r   rÎ   rÏ   rÐ   r"   r&   rÙ   Ê  s   zIDistTrialRunnerTests.test_runWaitForProcessesDeferreds.<locals>.realCheckrÒ   rÓ   c                 S   s(   g | ]\}}}t |g|¢R i |¤Ž‘qS r"   )r
   )ry   rG   ÚaÚkwr"   r"   r&   r{   Õ  s    ÿÿzJDistTrialRunnerTests.test_runWaitForProcessesDeferreds.<locals>.<listcomp>)re   rª   r-   rI   r   rV   rÔ   rÕ   rÖ   rm   r	   ÚaddCallback)r#   r1   rÑ   r"   )r˜   rÙ   r#   rc   r&   Ú!test_runWaitForProcessesDeferredsº  s    
þÿûz6DistTrialRunnerTests.test_runWaitForProcessesDeferredsc                    s¤   g ‰ G ‡ fdd„dt ƒ}g }||ƒ}|  | j|¡ |  ¡ \}}| jjtƒ ||jdd�}| ¡  |  	dt
ˆ ƒ¡ |  | ¡ ¡ | jj ¡ }|  d|¡ |  d|¡ dS )	z
        L{DistTrialRunner} can run in C{untilFailure} mode where it will run
        the given tests until they fail.
        c                       s    e Zd Zdd„ Z‡ fdd„ZdS )zMDistTrialRunnerTests.test_runUntilFailure.<locals>.CountingReactorWithSuccessc                 _   r»   r¼   rÉ   r¾   r"   r"   r&   r?   ã  r¿   zZDistTrialRunnerTests.test_runUntilFailure.<locals>.CountingReactorWithSuccess.spawnProcessc                    s*   ˆ   d ¡ tˆ ƒdkrttdƒƒS td ƒS )Né   rÀ   )r3   r\   r   r¸   r   rÁ   ©Úcalledr"   r&   rÊ   é  s   
z[DistTrialRunnerTests.test_runUntilFailure.<locals>.CountingReactorWithSuccess.succeedingRunNrË   r"   rß   r"   r&   rÌ   â  s    rÌ   T)rÅ   ÚuntilFailurerÞ   r²   ÚFAILN)r-   r•   rm   rq   re   rI   r   rÅ   rÆ   rV   r\   rR   ÚwasSuccessfulrf   r³   r´   )r#   rÌ   r1   r˜   rn   rp   ru   rµ   r"   rß   r&   Útest_runUntilFailureÛ  s   ÿz)DistTrialRunnerTests.test_runUntilFailureN)r(   r)   r*   r+   rK   rm   rq   rv   r‚   r“   r^   r¬   r­   r°   r¶   r¹   rÈ   r×   rÝ   rä   r"   r"   r"   r&   ra   ­   s$    	
("!ra   )7r+   r�   rS   Úior   Úzope.interfacer   r   Útwisted.internetr   r   r   Útwisted.internet.deferr   r	   r
   r   Útwisted.internet.mainr   Útwisted.internet.protocolr   r   Útwisted.internet.taskr   r   Útwisted.python.failurer   Útwisted.python.lockfiler   Útwisted.test.proto_helpersr   Útwisted.test.test_cooperatorr   Ú twisted.trial._dist.distreporterr   Útwisted.trial._dist.disttrialr   Útwisted.trial._dist.workerr   Útwisted.trial.reporterr   r   r   Útwisted.trial.runnerr   r   Útwisted.trial.unittestr   r   r    rM   r-   rJ   r_   ra   r"   r"   r"   r&   Ú<module>   s4   :8