a
    )¶(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                   @   s   e Zd ZdZdd„ ZdS )ÚFakeTransportz*
    A simple fake process transport.
    c                 C   s   dS )z%
        Ignore write calls.
        N© )ÚselfÚfdÚdatar    r    úFlib/python3.9/site-packages/twisted/trial/_dist/test/test_disttrial.pyÚwriteToChild(   s    zFakeTransport.writeToChildN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r%   r    r    r    r$   r   #   s   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)r-   ÚappendÚmakeConnectionr   Ú
spawnCount)
r!   Z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}.
        r/   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}.
        r/   TN)ÚrunCountZrunningZhasRunZwhenRunningHooks)r!   Úfr4   Úkwargsr    r    r$   Úrun[   s
    zCountingReactor.run)r&   r'   r(   r)   r2   r=   r?   r,   r;   r<   rB   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+   )r.   r*   r   r>   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   ZverifyObjectr   ÚIReactorProcessr   r>   r    r    r$   Útest_providesIReactorProcessr   s    z1CountingReactorTests.test_providesIReactorProcessc                 C   sj   |   | jj¡ tƒ }dD ]L}| 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.
        ©r/   é   ©r4   N)ÚassertFalser   r2   r   r;   Úsysr3   Ú
assertTrueZ	transportÚassertEqualr.   )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}
        rG   N)rJ   r   r=   r<   rM   )r!   rO   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.
        NrG   r   )	rJ   r   r?   ZcallWhenRunningr0   rB   rM   r=   Úlen)r!   ZwhenRunningCallsrO   r    r    r$   Útest_run   s    
zCountingReactorTests.test_runN)	r&   r'   r(   r)   rD   rF   rP   rQ   rS   r    r    r    r$   rC   i   s   	rC   c                   @   s   e Zd ZdZdd„ ZdS )Ú"EternalTerminationPredicateFactoryzI
    A rigged terminationPredicateFactory for which time never pass.
    c                 C   s   dS )z%
        See: L{task._Timer}
        Fr    r>   r    r    r$   Ú__call__¦   s    z+EternalTerminationPredicateFactory.__call__N)r&   r'   r(   r)   rU   r    r    r    r$   rT   ¡   s   rT   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   Ú_streamr>   r    r    r$   rD   ²   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)ZendDeferredZ
addErrbackr   Ztrapr   ZConnectionDoneZprocessEndedr   )r!   r.   Ú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)
        )Ú	schedulerZterminationPredicateFactory)r   r   rT   )r!   r^   Ú
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   rZ   ZwriteResultsrL   Útell)r!   Z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   s   g | ]
}t ƒ ‘qS r    )Úobject)Ú.0Úxr    r    r$   Ú
<listcomp>ç   ó    z@DistTrialRunnerTests.test_createLocalWorkers.<locals>.<listcomp>rW   r6   N)ÚrangerZ   ZcreateLocalWorkersÚassertIsInstancer   rM   rR   )r!   Ú	protocolsr.   Ú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   s   g | ]
}t ƒ ‘qS r    )r   )re   Úir    r    r$   rg   ò   rh   zCDistTrialRunnerTests.test_launchWorkerProcesses.<locals>.<listcomp>rW   r    Nr   c	           	         s"   ˆ   |¡ ˆ  |¡ ˆ |¡ d S r+   )r0   ÚextendÚupdate)	ZprocessProtocolr3   r4   r5   r6   r7   r8   r9   r:   ©Z	argumentsZenvironmentr    r$   ÚfakeSpawnProcessö   s    

zIDistTrialRunnerTests.test_launchWorkerProcesses.<locals>.fakeSpawnProcessZfoor/   rH   é   ZTRIAL_PYTHONPATH)ri   rZ   ZlaunchWorkerProcessesrM   rL   Úosr6   ÚexistsÚpathsepÚjoinrK   )r!   rk   rr   r    rq   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.
        é
   r/   N)r*   Ú
addCleanupr]   r   ri   ÚaddTestr   rZ   rB   rM   r?   r2   Z_workerNumber)r!   r.   ÚfakeReactorÚsuitern   r    r    r$   rS     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ƒ ¡ q†ˆ 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.lockr/   c                  W   s   t d ƒS r+   ©r   rI   r    r    r$   Ú<lambda>.  rh   zjDistTrialRunnerTests.test_runUsedDirectory.<locals>.CountingReactorWithLock.spawnProcess.<locals>.<lambda>)r-   r0   rM   rt   r6   ÚabspathZ_logDirectoryrw   Ústrr2   r   rJ   Úlockr1   r   Ú_ampProtocolrB   )Zoselfr\   r4   rA   Ú	localLock©r!   rX   r    r$   r;   "  s    ÿþzXDistTrialRunnerTests.test_runUsedDirectory.<locals>.CountingReactorWithLock.spawnProcessN)r&   r'   r(   r;   r    r…   r    r$   ÚCountingReactorWithLock!  s   r†   Z_trial_tempú.lockry   N)r*   rY   rt   Úmkdirr6   rw   r   r‚   rz   ZunlockrZ   Ú_workingDirectoryr]   r   ri   r{   r   rB   )r!   r†   ZnewDirectoryr‚   r.   r|   r}   rn   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.
        r/   N)	r*   rz   r]   rZ   rB   r   rM   r?   r2   )r!   r.   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*   rz   r]   rZ   Z_uncleanWarningsrB   r   rj   r   Úoriginalr   )r!   r.   r|   rb   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)	rd   r   rZ   rB   rj   r   r[   ÚgetvalueÚassertIn)r!   r|   r}   rb   Ú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=1ZFAILEDN)rd   r   r   ÚRuntimeErrorrZ   rB   rj   r   r[   r   r‘   )r!   r|   r   rb   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                   @   s   e Zd Zdd„ Zdd„ ZdS )zMDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFailc                 _   s4   | j  |¡ | tƒ ¡ |  jd7  _| j|j_d S ©Nr/   )r-   r0   r1   r   r2   Ú
failingRunrƒ   rB   ©r!   r\   r4   rA   r    r    r$   r;   ƒ  s    zZDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFail.spawnProcessc                 S   s   t tdƒƒS )NÚoops)r   r”   ©r!   Zcaserb   r    r    r$   r—   ‰  s    zXDistTrialRunnerTests.test_runUnexpectedError.<locals>.CountingReactorWithFail.failingRunN)r&   r'   r(   r;   r—   r    r    r    r$   ÚCountingReactorWithFail‚  s   r›   r/   N)r*   r`   rz   r]   rZ   rB   r   Ú	cooperaterM   r?   r2   ÚpumprR   rŒ   Zfailures)r!   r›   r^   r_   r.   r|   rb   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                   @   s   e Zd Zdd„ Zdd„ ZdS )zODistTrialRunnerTests.test_runStopAfterTests.<locals>.CountingReactorWithSuccessc                 _   s4   | j  |¡ | tƒ ¡ |  jd7  _| j|j_d S r–   ©r-   r0   r1   r   r2   ÚsucceedingRunrƒ   rB   r˜   r    r    r$   r;   Ÿ  s    z\DistTrialRunnerTests.test_runStopAfterTests.<locals>.CountingReactorWithSuccess.spawnProcessc                 S   s   t d ƒS 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ž  s   r¢   c                     s,   t ˆd ƒ} ˆ |  ¡ ¡ ˆ dˆ j¡ d S )Nr‡   r/   ©r   rL   r‚   rM   r=   ©r„   ©r|   r!   rX   r    r$   Úcheck¯  s    z:DistTrialRunnerTests.test_runStopAfterTests.<locals>.checkÚbeforeÚshutdownr   )r*   rZ   r‰   rB   r   rM   ÚlistÚtriggersÚkeysr]   r   r   )r!   r¢   r.   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   )Zign)Ú	realCheckr    r$   r¦   Æ  s    zEDistTrialRunnerTests.test_runWaitForProcessesDeferreds.<locals>.checkc                     s,   t ˆd ƒ} ˆ |  ¡ ¡ ˆ dˆ j¡ d S )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
   )re   r@   ÚaÚkwr    r    r$   rg   Õ  s   ÿzJDistTrialRunnerTests.test_runWaitForProcessesDeferreds.<locals>.<listcomp>)rZ   r‰   r*   rB   r   rM   r©   rª   r«   r]   r	   ZaddCallback)r!   r.   r¦   r    )r|   r­   r!   rX   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                 _   s4   | j  |¡ | tƒ ¡ |  jd7  _| j|j_d S r–   rŸ   r˜   r    r    r$   r;   ã  s    zZDistTrialRunnerTests.test_runUntilFailure.<locals>.CountingReactorWithSuccess.spawnProcessc                    s*   ˆ   d ¡ tˆ ƒdkr"ttdƒƒS td ƒS )Né   r™   )r0   rR   r   r”   r   rš   ©Zcalledr    r$   r    é  s    
z[DistTrialRunnerTests.test_runUntilFailure.<locals>.CountingReactorWithSuccess.succeedingRunNr¡   r    r²   r    r$   r¢   â  s   r¢   T)rœ   ZuntilFailurer±   r   ZFAILN)r*   rz   r]   r`   rZ   rB   r   rœ   r   rM   rR   rJ   ZwasSuccessfulr[   r   r‘   )r!   r¢   r.   r|   r^   r_   rb   r’   r    r²   r$   Útest_runUntilFailureÛ  s    ÿz)DistTrialRunnerTests.test_runUntilFailureN)r&   r'   r(   r)   rD   r]   r`   rc   rm   rx   rS   rŠ   r‹   r   r“   r•   rž   r¬   r°   r³   r    r    r    r$   rV   ­   s"   	
("!rV   )7r)   rt   rK   Úior   Zzope.interfacer   r   Ztwisted.internetr   r   r   Ztwisted.internet.deferr   r	   r
   r   Ztwisted.internet.mainr   Ztwisted.internet.protocolr   r   Ztwisted.internet.taskr   r   Ztwisted.python.failurer   Ztwisted.python.lockfiler   Ztwisted.test.proto_helpersr   Ztwisted.test.test_cooperatorr   Z twisted.trial._dist.distreporterr   Ztwisted.trial._dist.disttrialr   Ztwisted.trial._dist.workerr   Ztwisted.trial.reporterr   r   r   Ztwisted.trial.runnerr   r   Ztwisted.trial.unittestr   r   r   rE   r*   rC   rT   rV   r    r    r    r$   Ú<module>   s2   :8