o
    ¯b|�  ã                   @   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ZddlmZ ddl	Z	ddl
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mZ ddlmZ dd	l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& eej'ƒ (¡ Z)ee
j*ƒ +¡  +¡ Z,dZ-dZ.e/ej0ƒZ1ej2 3ej4¡e1d< zddl5Z6ddlm7Z8 e 9¡ dkr­dZ-dZ.W n e:y¿   dZ5dZ7dZ-dZ.Y nw e6Z5e8Z7dd„ Z;G dd„ deƒZ<G dd„ deƒZ=G dd„ de=ƒZ>e?ƒ  @e> A¡ ¡ G dd„ de=ƒZBe?ƒ  @eB A¡ ¡ G d d!„ d!e&ƒZCG d"d#„ d#e&ƒZDG d$d%„ d%e&ƒZEdS )&z»
Tests for implementations of L{IReactorProcess}.

@var properEnv: A copy of L{os.environ} which has L{bytes} keys/values on POSIX
    platforms and native L{str} keys/values on Windows.
é    N)ÚskipIf)Úutils)ÚDeferredÚinlineCallbacksÚsucceed)ÚProcessDoneÚProcessTerminated)ÚIProcessTransportÚIReactorProcess)ÚProcessProtocol)ÚReactorBuilder)ÚnetworkString)ÚFilePathÚ_asFilesystemBytes)ÚerrÚmsg)Úplatform)ÚTestCaseFÚ Ú
PYTHONPATH©ÚprocessTz$Cannot change UID/GID except as rootz Cannot change UID/GID on Windowsc                 C   s   t du rd| _| S )z”
    Only run this test on POSIX platforms.

    @param testMethod: A test function, being decorated.

    @return: the C{testMethod} argument.
    Nz%Test only applies to POSIX platforms.)ÚresourceÚskip)Ú
testMethod© r   úD/usr/lib/python3/dist-packages/twisted/internet/test/test_process.pyÚonlyOnPOSIX=   s   r   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú _ShutdownCallbackProcessProtocolzõ
    An L{IProcessProtocol} which fires a Deferred when the process it is
    associated with ends.

    @ivar received: A C{dict} mapping file descriptors to lists of bytes
        received from the child process on those file descriptors.
    c                 C   s   || _ i | _d S ©N)ÚwhenFinishedÚreceived)Úselfr    r   r   r   Ú__init__S   s   
z)_ShutdownCallbackProcessProtocol.__init__c                 C   s   | j  |g ¡ |¡ d S r   )r!   Ú
setdefaultÚappend)r"   ÚfdÚbytesr   r   r   ÚchildDataReceivedW   ó   z2_ShutdownCallbackProcessProtocol.childDataReceivedc                 C   s   | j  d ¡ d S r   )r    Úcallback©r"   Úreasonr   r   r   ÚprocessEndedZ   ó   z-_ShutdownCallbackProcessProtocol.processEndedN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r#   r(   r-   r   r   r   r   r   J   s
    r   c                   @   sÈ   e Zd ZdZegZdd„ Zdd„ Zdd„ Zdd	„ Z	d
d„ Z
dd„ Zeeeddƒdu dƒdd„ ƒZdd„ Zdd„ Zedd„ ƒZedd„ ƒZdd„ Zdd„ Zeeeƒdd „ ƒZeeeƒd!d"„ ƒZd#d$„ ZdS )%ÚProcessTestsBuilderBasezæ
    Base class for L{IReactorProcess} tests which defines some tests which
    can be applied to PTY or non-PTY uses of C{spawnProcess}.

    Subclasses are expected to set the C{usePTY} attribute to C{True} or
    C{False}.
    c                    s`   t ƒ }t|ƒ}|  ¡ ‰ ˆ j|ttddg| jd�}|  t |¡¡ | 	‡ fdd„¡ |  
ˆ ¡ dS )z�
        L{IReactorProcess.spawnProcess} connects the protocol passed to it
        to a transport which provides L{IProcessTransport}.
        ó   -có    ©ÚusePTYc                    ó   ˆ   ¡ S r   ©Ústop©Úignored©Úreactorr   r   Ú<lambda>€   ó    zHProcessTestsBuilderBase.test_processTransportInterface.<locals>.<lambda>N)r   r   ÚbuildReactorÚspawnProcessÚpyExer7   Ú
assertTruer	   Ú
providedByÚaddCallbackÚ
runReactor)r"   ÚendedÚprotocolÚ	transportr   r=   r   Útest_processTransportInterfacei   s   ÿz6ProcessTestsBuilderBase.test_processTransportInterfacec                    s~   |   ¡ ‰tƒ }t|ƒ‰dttjƒ ‰ d‰‡ ‡‡‡‡fdd„}ˆ |¡ | ‡fdd„¡ |  ˆ¡ |  	ˆ d 
ˆjd ¡¡ d	S )
a¸  
        Helper for testing L{IProcessTransport} write functionality.  This
        method spawns a child process and gives C{write} a chance to write some
        bytes to it.  It then verifies that the bytes were actually written to
        it (by relying on the child process to echo them back).

        @param write: A two-argument callable.  This is invoked with a process
            transport and some bytes to write to it.
        s   hello, worlds2   import sys
sys.stdout.write(sys.stdin.readline())
c                     sN   ˆ  ˆttdˆg¡} zˆ| ˆ ƒ W d S  ty&   td dƒ |  d¡ Y d S w )Nr4   z!Unhandled exception while writingÚKILL)rB   rC   ÚBaseExceptionr   ÚsignalProcess©rJ   ©ÚbytesToSendÚprogramrI   r>   Úwriter   r   Ústartup•   s   
þz3ProcessTestsBuilderBase._writeTest.<locals>.startupc                    r8   r   r9   r;   r=   r   r   r?   Ÿ   r@   z4ProcessTestsBuilderBase._writeTest.<locals>.<lambda>r5   é   N)rA   r   r   r   ÚosÚlinesepÚcallWhenRunningrF   rG   ÚassertEqualÚjoinr!   )r"   rS   rH   rT   r   rP   r   Ú
_writeTestƒ   s   


z"ProcessTestsBuilderBase._writeTestc                 C   ó   dd„ }|   |¡ dS )z~
        L{IProcessTransport.write} writes the specified C{bytes} to the standard
        input of the child process.
        c                 S   s   |   |¡ d S r   ©rS   ©rJ   rQ   r   r   r   rS   ª   ó   z1ProcessTestsBuilderBase.test_write.<locals>.writeN©r[   ©r"   rS   r   r   r   Ú
test_write¤   ó   z"ProcessTestsBuilderBase.test_writec                 C   r\   )z‘
        L{IProcessTransport.writeSequence} writes the specified C{list} of
        C{bytes} to the standard input of the child process.
        c                 S   s   |   |g¡ d S r   )ÚwriteSequencer^   r   r   r   rS   µ   r.   z9ProcessTestsBuilderBase.test_writeSequence.<locals>.writeNr`   ra   r   r   r   Útest_writeSequence¯   rc   z*ProcessTestsBuilderBase.test_writeSequencec                 C   r\   )z�
        L{IProcessTransport.writeToChild} writes the specified C{bytes} to the
        specified file descriptor of the child process.
        c                 S   s   |   d|¡ d S )Nr   )ÚwriteToChildr^   r   r   r   rS   À   r.   z8ProcessTestsBuilderBase.test_writeToChild.<locals>.writeNr`   ra   r   r   r   Útest_writeToChildº   rc   z)ProcessTestsBuilderBase.test_writeToChildc                    s   ‡ fdd„}ˆ   |¡ dS )z¦
        L{IProcessTransport.writeToChild} raises L{KeyError} if passed a file
        descriptor which is was not set up by L{IReactorProcess.spawnProcess}.
        c              	      s0   zˆ   t| jd|¡ W |  |¡ d S |  |¡ w )Né   )ÚassertRaisesÚKeyErrorrf   rS   r^   ©r"   r   r   rS   Ë   s   zIProcessTestsBuilderBase.test_writeToChildBadFileDescriptor.<locals>.writeNr`   ra   r   rk   r   Ú"test_writeToChildBadFileDescriptorÅ   s   z:ProcessTestsBuilderBase.test_writeToChildBadFileDescriptorÚSIGCHLDNz;Platform lacks SIGCHLD, early-spawnProcess test can't work.c                    s¾   |   ¡ ‰ | jr
d}ni }t ¡ ‰‡fdd„}t tj|¡ tƒ }ˆ jt|ƒt	t	ddg| j|d� ˆ 
d¡ ˆ ¡ s>|  d¡ g }| |j¡ |rJdS | ‡ fd	d
„¡ |  ˆ ¡ |  |¡ dS )zÚ
        If, before the reactor is started with L{IReactorCore.run}, a
        process is started with L{IReactorProcess.spawnProcess} and
        terminates, the process is reaped once the reactor is started.
        Nc                     ó   ˆ   ¡  d S r   )Úset)Úargs)Úsignaledr   r   Úhandlerì   ó   zGProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped.<locals>.handlerr4   r5   )r7   ÚchildFDséx   z,Timed out waiting for child process to exit.c                    r8   r   r9   r;   r=   r   r   r?     r@   zHProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped.<locals>.<lambda>)rA   r7   Ú	threadingÚEventÚsignalrm   r   rB   r   rC   ÚwaitÚisSetÚfailrF   r%   rG   rD   )r"   rt   rr   rH   Úresultr   )r>   rq   r   Útest_spawnProcessEarlyIsReapedÔ   s2   
û


z6ProcessTestsBuilderBase.test_spawnProcessEarlyIsReapedc                    sœ   d‰t tdˆ ƒ‰tƒ ‰ d}G ‡ ‡fdd„dtƒ}ˆ ¡ ‰ˆjˆj|ƒ ttd|gˆjd� ‡‡fdd	„}ˆ  	|¡ ˆ  
t¡ ˆ  	‡fd
d„¡ ˆ ˆ¡ dS )z©
        The C{reason} argument passed to L{IProcessProtocol.processExited} is a
        L{ProcessTerminated} instance if the child process exits with a signal.
        ÚTERMÚSIGsE   import sys
sys.stdout.write('x')
sys.stdout.flush()
sys.stdin.read()
c                       s4   e Zd Z‡fdd„Zdd„ Z‡ fdd„Zdd„ Zd	S )
zDProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiterc                    s    t d||f ƒ | j ˆ ¡ d S ©NzchildDataReceived(%d, %r))r   rJ   rN   ©r"   r&   Údata)ÚsigNamer   r   r(   )  ó   zVProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.childDataReceivedc                 S   s   t d|f ƒ d S ©NúchildConnectionLost(%d)©r   )r"   r&   r   r   r   ÚchildConnectionLost-  ó   zXProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.childConnectionLostc                    ó    t d|›d�ƒ ˆ  |g¡ d S ©NzprocessExited(ú)©r   r*   r+   ©Úexitedr   r   ÚprocessExited0  s   zRProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.processExitedc                 S   ó   t d|›d�ƒ d S ©NzprocessEnded(rŒ   r‡   r+   r   r   r   r-   9  ó   zQProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.processEndedN©r/   r0   r1   r(   rˆ   r�   r-   r   )r�   rƒ   r   r   ÚExiter(  s
    	r•   r4   r6   c                    sZ   | \}|  t¡ |j}t ¡ rˆ  |j¡ ˆ  |jd¡ d S ˆ  |jˆ¡ ˆ  |j¡ d S )NrU   )	Útrapr   Úvaluer   Ú	isWindowsÚassertIsNonerx   rY   ÚexitCode)rp   Úfailurer   )r"   ÚsigNumr   r   ÚcbExitedE  s   
zFProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.cbExitedc                    r8   r   r9   ©Úignr=   r   r   r?   Z  r@   zFProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.<lambda>N)Úgetattrrx   r   r   rA   rX   rB   rC   r7   rF   Ú
addErrbackr   rG   )r"   Úsourcer•   r�   r   )r�   r>   r"   rƒ   rœ   r   Útest_processExitedWithSignal  s&   ÿû

z4ProcessTestsBuilderBase.test_processExitedWithSignalc                    sL   |   ¡ ‰ g ‰‡ ‡fdd„}ˆ  |¡ |  ˆ ¡ |  ˆdtj d¡ g¡ dS )aÏ  
        If a child process exits while a system call is in progress, the system
        call should not be interfered with.  In particular, it should not fail
        with EINTR.

        Older versions of Twisted installed a SIGCHLD handler on POSIX without
        using the feature exposed by the SA_RESTART flag to sigaction(2).  The
        most noticeable problem this caused was for blocking reads and writes to
        sometimes fail with EINTR.
        c                     s’   zCt  t ¡ ¡} t | ddg¡ tj| ddgtjd�}|j� ˆ |j 	¡ ¡ W d   ƒ n1 s1w   Y  W ˆ  
¡  d S W ˆ  
¡  d S ˆ  
¡  w )Nú-czimport time; time.sleep(0.1)z)import time; time.sleep(0.5);print('Foo'))Ústdout)rC   ÚdecodeÚsysÚgetfilesystemencodingÚ
subprocessÚPopenÚPIPEr¥   r%   Úreadr:   )ÚexeÚf2©r>   r|   r   r   Úfl  s   þÿýzJProcessTestsBuilderBase.test_systemCallUninterruptedByChildExit.<locals>.fs   FooÚasciiN)rA   rX   rG   rY   rV   rW   Úencode)r"   r°   r   r¯   r   Ú'test_systemCallUninterruptedByChildExit^  s   

z?ProcessTestsBuilderBase.test_systemCallUninterruptedByChildExitc           	         sø   t d tj¡ƒ}t ¡ \}}|  tj|¡ |  tj|¡ d}t 	tj
¡d | }t ||¡ |  tj|¡ t ¡ ‰ G ‡ ‡fdd„dtƒ}|  ¡ ‰ˆjˆj|ƒ ttdd|g| jd� |  ˆ¡ ttˆ  ¡ ƒƒ}g d	¢}|  | t||g ƒ¡t|ƒ¡ d
S )z¬
        Processes spawned with spawnProcess() close all extraneous file
        descriptors in the parent.  They do have a stdin, stdout, and stderr
        open.
        z‹
import sys
sys.path.insert(0, '{}')
from twisted.internet import process
sys.stdout.write(repr(process._listOpenFDs()))
sys.stdout.flush()é   r   c                       ó   e Zd Z” jZ‡fdd„ZdS )zKProcessTestsBuilderBase.test_openFileDescriptors.<locals>.GatheringProtocolc                    rn   r   r9   r+   r=   r   r   r-   ¹  rs   zXProcessTestsBuilderBase.test_openFileDescriptors.<locals>.GatheringProtocol.processEndedN)r/   r0   r1   rS   ÚoutReceivedr-   r   ©Úoutputr>   r   r   ÚGatheringProtocol¶  ó    r¹   s   -Wignorer4   r6   ©r   rU   é   N)r   ÚformatÚtwistedRootÚpathrV   ÚpipeÚ
addCleanupÚcloser   Ú	getrlimitÚRLIMIT_NOFILEÚdup2ÚioÚBytesIOr   rA   rX   rB   rC   r7   rG   ro   ÚevalÚgetvaluerY   Úintersection)	r"   r¢   ÚrÚwÚfudgeFactorÚ
unlikelyFDr¹   ÚreportedChildFDsÚstdFDsr   r·   r   Útest_openFileDescriptors�  s:   ÿú
û
ÿz0ProcessTestsBuilderBase.test_openFileDescriptorsc                    sr   dd„ }|   td|¡ |   tddd„ ¡ |  ¡ ‰t ¡ ‰ ˆj‡ ‡fdd„ƒ}| jˆd	d
� |  d 	¡ ˆ  
¡ ¡ dS )zž
        When L{os.execvpe} raises an exception, it will format that exception
        on stderr as UTF-8, regardless of system encoding information.
        c                  _   s0   d}t |tƒs| d¡}td|dƒ}t|ƒ d S )Nu   <â˜ƒ>úutf-8z1/0Úsingle)Ú
isinstanceÚstrr²   ÚcompilerÈ   )rp   ÚkwÚfilenameÚcodeobjr   r   r   ÚexecvpeÙ  s
   

z=ProcessTestsBuilderBase.test_errorDuringExec.<locals>.execvperÚ   r¨   c                   S   s   dS )Nr±   r   r   r   r   r   r?   ã  ó    z>ProcessTestsBuilderBase.test_errorDuringExec.<locals>.<lambda>c                     s0   G ‡ ‡fdd„dt ƒ} ˆ | ƒ ttddg¡ d S )Nc                       rµ   )z[ProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunning.<locals>.TracebackCatcherc                    rn   r   r9   r+   r=   r   r   r-   í  rs   zhProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunning.<locals>.TracebackCatcher.processEndedN)r/   r0   r1   rS   ÚerrReceivedr-   r   r·   r   r   ÚTracebackCatcherê  rº   rÝ   r4   r5   )r   rB   rC   )rÝ   r·   r   r   ÚwhenRunningè  s   zAProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunningé   ©Útimeoutu   â˜ƒN)ÚpatchrV   r§   rA   rÆ   rÇ   rX   rG   ÚassertInr²   rÉ   )r"   rÚ   rÞ   r   r·   r   Útest_errorDuringExecÒ  s   		z,ProcessTestsBuilderBase.test_errorDuringExecc                    s`   ˆ  ¡ ‰ G ‡ ‡fdd„dtƒ}|ƒ }ˆ jˆ j|ttddgˆjd� ˆjˆ dd� ˆ |j¡ dS )	zi
        If a spawned process exits, C{processExited} will be called in a
        timely manner.
        c                       s   e Zd ZdZ‡ ‡fdd„ZdS )zIProcessTestsBuilderBase.test_timelyProcessExited.<locals>.ExitingProtocolFc                    s"   d| _ ˆ  ¡  ˆ |jjd¡ d S )NTr   )r�   r:   rY   r—   rš   )Ú	protoSelfr,   ©r>   r"   r   r   r�   ÿ  s   zWProcessTestsBuilderBase.test_timelyProcessExited.<locals>.ExitingProtocol.processExitedN)r/   r0   r1   r�   r�   r   ræ   r   r   ÚExitingProtocolü  s    rç   r4   s   raise SystemExit(0)r6   rß   rà   N)	rA   r   rX   rB   rC   r7   rG   rD   r�   )r"   rç   rI   r   ræ   r   Útest_timelyProcessExitedõ  s   û	z0ProcessTestsBuilderBase.test_timelyProcessExitedc              	      s„   dd|› d�g}g ‰ G ‡ ‡fdd„dt ƒ}|  ¡ ‰|ƒ }ˆjˆj|ttdd |¡gfi |di¤Ž |  ˆ¡ |  d	ˆ d	 jj	¡ d
S )aT  
        Launch a child process, using either the C{uid} or C{gid} argument to
        L{IReactorProcess.spawnProcess} to change either its UID or GID to a
        different value.  If the child process reports this hasn't happened,
        raise an exception to fail the test.

        @param which: Either C{b"uid"} or C{b"gid"}.
        z	import oszraise SystemExit(os.getz() != 1)c                       ó   e Zd Z‡ ‡fdd„ZdS )z@ProcessTestsBuilderBase._changeIDTest.<locals>.CaptureExitStatusc                    s   ˆ   |¡ ˆ ¡  d S r   )r%   r:   r+   ©Ú	containerr>   r   r   r-     s   
zMProcessTestsBuilderBase._changeIDTest.<locals>.CaptureExitStatus.processEndedN)r/   r0   r1   r-   r   rê   r   r   ÚCaptureExitStatus  ó    rì   r¤   Ú
rU   r   N)
r   rA   rX   rB   rC   rZ   rG   rY   r—   rš   )r"   ÚwhichrR   rì   rI   r   rê   r   Ú_changeIDTest  s   	üû
z%ProcessTestsBuilderBase._changeIDTestc                 C   ó   |   d¡ dS )z„
        If a value is passed for L{IReactorProcess.spawnProcess}'s C{uid}, the
        child process is run with that UID.
        ÚuidN©rð   rk   r   r   r   Útest_changeUID1  ó   z&ProcessTestsBuilderBase.test_changeUIDc                 C   rñ   )z„
        If a value is passed for L{IReactorProcess.spawnProcess}'s C{gid}, the
        child process is run with that GID.
        ÚgidNró   rk   r   r   r   Útest_changeGID9  rõ   z&ProcessTestsBuilderBase.test_changeGIDc                    s²   |   ¡ ‰G dd„ dtƒ‰ G ‡ ‡fdd„dtƒ}|ƒ }ˆj|ttddg| jd�}|  ˆ¡ tdurLttj	 
¡ ƒD ]\}}||ur@q7t ||¡ |  d	¡ q7|  d
t|  ˆ ¡ƒ¡ dS )zY
        If L{IProcessProtocol.processExited} raises an exception, it is logged.
        c                   @   s   e Zd ZdS )zGProcessTestsBuilderBase.test_processExitedRaises.<locals>.TestExceptionN)r/   r0   r1   r   r   r   r   ÚTestExceptionI  s    rø   c                       ré   )zBProcessTestsBuilderBase.test_processExitedRaises.<locals>.Protocolc                    s   ˆ  ¡  ˆ dƒ‚)NzprocessedExited raisedr9   r+   ©rø   r>   r   r   r�   M  s   zPProcessTestsBuilderBase.test_processExitedRaises.<locals>.Protocol.processExitedN)r/   r0   r1   r�   r   rù   r   r   ÚProtocolL  rí   rú   r4   r5   r6   NzEAfter processExited raised, transport was left in reapProcessHandlersrU   )rA   Ú	Exceptionr   rB   rC   r7   rG   r   ÚlistÚreapProcessHandlersÚitemsÚunregisterReapProcessHandlerr{   rY   ÚlenÚflushLoggedErrors)r"   rú   rI   rJ   Úpidrr   r   rù   r   Útest_processExitedRaisesA  s"   ÿ
ÿz0ProcessTestsBuilderBase.test_processExitedRaises)r/   r0   r1   r2   r
   ÚrequiredInterfacesrK   r[   rb   re   rg   rl   r   r    rx   r}   r£   r³   r   rÑ   rä   rè   rð   Ú_uidgidSkipÚ_uidgidSkipReasonrô   r÷   r  r   r   r   r   r3   ^   s6    !þ
<J#
P
" 

r3   c                   @   sn   e Zd ZdZdZdZe ¡ rdZndZdd„ Z	dd	„ Z
d
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZdS )ÚProcessTestsBuilderzp
    Builder defining tests relating to L{IReactorProcess} for child processes
    which do not have a PTY.
    Fs$   twisted.internet.test.process_helpers   windowsr5   c                    sÈ   t ƒ ‰ t ƒ t ƒ t ƒ dœ‰G ‡ ‡fdd„dtƒ}d}|  ¡ ‰ˆjˆj|ƒ ttd|gt| jd� ‡fdd„}ˆ  |¡ ‡fd	d
„}ˆ  |¡ dd„ }ˆ  |¡ ˆ  	t
¡ ‡fdd„}ˆ  |¡ |  ˆ¡ dS )z’
        L{IProcessProtocol.childConnectionLost} is called each time a file
        descriptor associated with a child process is closed.
        r»   c                       s$   e Zd Z‡ fdd„Z‡fdd„ZdS )z<ProcessTestsBuilder.test_childConnectionLost.<locals>.Closerc                    s   ˆ   |¡ d S r   ©r*   )r"   rJ   )Ú	connectedr   r   ÚmakeConnection�  r_   zKProcessTestsBuilder.test_childConnectionLost.<locals>.Closer.makeConnectionc                    s   ˆ |   d ¡ d S r   r  ©r"   ÚchildFD©Úlostr   r   rˆ   „  r‰   zPProcessTestsBuilder.test_childConnectionLost.<locals>.Closer.childConnectionLostN)r/   r0   r1   r
  rˆ   r   )r	  r  r   r   ÚCloser€  s    r  s,   twisted.internet.test.process_loseconnectionó   -m©Úenvr7   c                    ó    ˆ   d¡ ˆd  ‡ fdd„¡S )Ns   2
r¼   c                    ó   ˆ S r   r   rž   rO   r   r   r?   •  rÛ   zSProcessTestsBuilder.test_childConnectionLost.<locals>.cbConnected.<locals>.<lambda>©rS   rF   rO   r  rO   r   ÚcbConnected“  ó   
zAProcessTestsBuilder.test_childConnectionLost.<locals>.cbConnectedc                    r  )Ns   1
rU   c                    r  r   r   rž   rO   r   r   r?   ›  rÛ   zRProcessTestsBuilder.test_childConnectionLost.<locals>.lostSecond.<locals>.<lambda>r  rO   r  rO   r   Ú
lostSecond™  r  z@ProcessTestsBuilder.test_childConnectionLost.<locals>.lostSecondc                 S   s   |   d¡ d S )Nó   
r]   rO   r   r   r   Ú	lostFirstŸ  r_   z?ProcessTestsBuilder.test_childConnectionLost.<locals>.lostFirstc                    rn   r   r9   r;   r=   r   r   ÚcbEnded¥  rs   z=ProcessTestsBuilder.test_childConnectionLost.<locals>.cbEndedN)r   r   rA   rX   rB   rC   Ú	properEnvr7   rF   r¡   r   rG   )r"   r  Útargetr  r  r  r  r   )r	  r  r>   r   Útest_childConnectionLostx  s.   ú	




z,ProcessTestsBuilder.test_childConnectionLostc              	      s”   t ƒ ‰ g ‰G ‡ ‡fdd„dtƒ}ˆ ¡ ‰ˆjˆj|ƒ ttdˆjdˆjgtˆj	d� ‡‡fdd„}ˆ  
|¡ ˆ  t¡ ˆ  
‡fdd	„¡ ˆ ˆ¡ d
S )zÂ
        L{IProcessProtocol.processEnded} is called after the child process
        exits and L{IProcessProtocol.childConnectionLost} is called for each of
        its file descriptors.
        c                       s4   e Zd Zdd„ Z‡fdd„Zdd„ Z‡ fdd„Zd	S )
z4ProcessTestsBuilder.test_processEnded.<locals>.Enderc                 S   s   t d||f ƒ | j ¡  d S r€   )r   rJ   ÚloseConnectionr�   r   r   r   r(   ·  s   zFProcessTestsBuilder.test_processEnded.<locals>.Ender.childDataReceivedc                    s   t d|f ƒ ˆ  |¡ d S r…   )r   r%   r  r  r   r   rˆ   »  s   zHProcessTestsBuilder.test_processEnded.<locals>.Ender.childConnectionLostc                 S   r‘   r‹   r‡   r+   r   r   r   r�   ¿  r“   zBProcessTestsBuilder.test_processEnded.<locals>.Ender.processExitedc                    rŠ   r’   r�   r+   )rH   r   r   r-   Â  r„   zAProcessTestsBuilder.test_processEnded.<locals>.Ender.processEndedNr”   r   )rH   r  r   r   ÚEnder¶  s
    r   r  ó   childr  c                    s(   | \}|  t¡ ˆ tˆ ƒh d£¡ d S ©N>   r   rU   r¼   )r–   r   rY   ro   ©rp   r›   ©r  r"   r   r   r  Ð  s   
z6ProcessTestsBuilder.test_processEnded.<locals>.cbEndedc                    r8   r   r9   rž   r=   r   r   r?   Ø  r@   z7ProcessTestsBuilder.test_processEnded.<locals>.<lambda>N©r   r   rA   rX   rB   rC   ÚkeepStdioOpenProgramÚkeepStdioOpenArgr  r7   rF   r¡   r   rG   )r"   r   r  r   )rH   r  r>   r"   r   Útest_processEnded­  s"   ú	

z%ProcessTestsBuilder.test_processEndedc              
      s¸   t ƒ ‰t ƒ ‰ g ‰G ‡ ‡‡fdd„dtƒ}ˆ ¡ ‰ˆjˆj|ƒ ttddˆjdˆjgtˆj	d� ‡ ‡‡fdd„}ˆ 
|¡ ‡‡fd	d
„}ˆ 
|¡ ˆ t¡ ˆ 
‡fdd„¡ ˆ ˆ¡ dS )z®
        L{IProcessProtocol.processExited} is called when the child process
        exits, even if file descriptors associated with the child are still
        open.
        c                       s.   e Zd Zdd„ Z‡ ‡fdd„Z‡fdd„ZdS )z6ProcessTestsBuilder.test_processExited.<locals>.Waiterc                 S   s   t d||f ƒ d S r€   r‡   r�   r   r   r   r(   ê  r“   zHProcessTestsBuilder.test_processExited.<locals>.Waiter.childDataReceivedc                    s6   t d|f ƒ ˆ |¡ tˆƒdkrˆ  d ¡ d S d S )Nr†   é   )r   r%   r   r*   r  )ÚallLostr  r   r   rˆ   í  s
   
ÿzJProcessTestsBuilder.test_processExited.<locals>.Waiter.childConnectionLostc                    s*   t d|›d�ƒ ˆ  |g¡ | j ¡  d S r‹   )r   r*   rJ   r  r+   rŽ   r   r   r�   ó  s   zDProcessTestsBuilder.test_processExited.<locals>.Waiter.processExitedN)r/   r0   r1   r(   rˆ   r�   r   )r*  r�   r  r   r   ÚWaiteré  s    r+  s   -ur  r!  r  c                    s.   | \}|  t¡ tdˆ› �ƒ ˆ ˆg ¡ ˆ S )NzcbExited; lost = )r–   r   r   rY   r#  )r*  r  r"   r   r   r�   
  s
   
z8ProcessTestsBuilder.test_processExited.<locals>.cbExitedc                    s   ˆ  tˆ ƒh d£¡ d S r"  )rY   ro   r;   r$  r   r   Ú	cbAllLost  r)   z9ProcessTestsBuilder.test_processExited.<locals>.cbAllLostc                    r8   r   r9   rž   r=   r   r   r?     r@   z8ProcessTestsBuilder.test_processExited.<locals>.<lambda>Nr%  )r"   r+  r�   r,  r   )r*  r�   r  r>   r"   r   Útest_processExitedß  s4   úó


z&ProcessTestsBuilder.test_processExitedc                 C   sZ   t |  ¡ ƒ}t|dƒ�}| tj |¡tj ¡ W d  ƒ n1 s"w   Y  tj |¡S )zj
        Write the given list of lines to a text file and return the absolute
        path to it.
        ÚwtN)	r   ÚmktempÚopenrS   rV   rW   rZ   r¿   Úabspath)r"   ÚsourceLinesÚscriptÚ
scriptFiler   r   r   ÚmakeSourceFile  s
   ÿz"ProcessTestsBuilder.makeSourceFilec              	      s†   d‰ˆ  d t d¡¡dd ˆ d¡¡dg¡‰t ˆd¡ ˆ ¡ ‰‡‡fdd	„‰ ‡fd
d„‰‡ ‡‡‡fdd„}ˆ |¡ ˆ ˆ¡ dS )z¹
        Spawning a process with an executable which is a script starting
        with an interpreter definition line (#!) uses that interpreter to
        evaluate the script.
        s   this is the shebang outputz#!{}r±   z
import syszsys.stdout.write('{}')zsys.stdout.flush()iÀ  c                    sD   | \}}}t d|||f ƒ ˆ  |ˆ¡ ˆ  |d¡ ˆ  |d¡ d S )NzcbProcessExited((%r, %r, %d))r5   r   )r   rY   )rp   Úoutr   Úcode)r"   ÚshebangOutputr   r   ÚcbProcessExited;  s
   
z9ProcessTestsBuilder.test_shebang.<locals>.cbProcessExitedc                    ó   ˆ   ¡  | S r   r9   )Úpassthroughr=   r   r   ÚshutdownB  ó   z2ProcessTestsBuilder.test_shebang.<locals>.shutdownc                     s0   t jˆˆd�} |  ˆ¡ |  ˆ ¡ |  t¡ d S )Nr=   )r   ÚgetProcessOutputAndValueÚaddBothrF   r¡   r   ©Úd)r9  r>   r4  r<  r   r   ÚstartF  s   

z/ProcessTestsBuilder.test_shebang.<locals>.startN)	r5  r½   rC   r¦   rV   ÚchmodrA   rX   rG   )r"   rB  r   )r9  r>   r4  r"   r8  r<  r   Útest_shebang'  s   üÿ
z ProcessTestsBuilder.test_shebangc                    s.   ‡ fdd„}ˆ   ¡ }| ||¡ ˆ  |¡ dS )z<
        Pause producing and then resume producing.
        c                    sJ   zt ƒ }| j|ttddgˆ jd�}| ¡  | ¡  W |  ¡  d S |  ¡  w )Nr4   r5   r6   )r   rB   rC   r7   ÚpauseProducingÚresumeProducingr:   )r>   rI   rJ   rk   r   r   ÚpauseAndResumeT  s   ÿ
zHProcessTestsBuilder.test_pauseAndResumeProducing.<locals>.pauseAndResumeN)rA   rX   rG   )r"   rG  r>   r   rk   r   Útest_pauseAndResumeProducingO  s   z0ProcessTestsBuilder.test_pauseAndResumeProducingc                    s„   d‰g d¢‰ d  tttddƒƒ¡}t|tƒr| d¡ ˆ ¡ ‰‡ ‡fdd„‰‡fd	d
„‰‡ ‡‡‡‡fdd„}ˆ |¡ ˆ 	ˆ¡ dS )zq
        Arguments given to spawnProcess are passed to the child process as
        originally intended.
        s!   twisted.internet.test.process_cli)s   helloó   "s    	|<>^&s   "\\"hello\\"s   "foo\ bar baz\""r   rU   éÿ   rÒ   c                    s,   | \}}}|  d¡}| ¡  ˆ ˆ |¡ d S )Nó    )ÚsplitÚpoprY   )ÚfinishedArgsr¸   r   r7  )rp   r"   r   r   ÚprocessFinishedr  s   

zMProcessTestsBuilder.test_processCommandLineArguments.<locals>.processFinishedc                    r:  r   r9   )r|   r=   r   r   r<  y  r=  zFProcessTestsBuilder.test_processCommandLineArguments.<locals>.shutdownc                     s6   t d ƒ} |  ‡ ‡‡fdd„¡ |  ˆ¡ |  ˆ¡ d S )Nc                    s   t jtdˆgˆ  tˆd�S )Nr  )r  r>   )r   r>  rC   r  )Údummy)rp   r>   Úusr   r   r?   €  s    ÿzZProcessTestsBuilder.test_processCommandLineArguments.<locals>.spawnChild.<locals>.<lambda>)r   rF   r?  r@  )rp   rO  r>   r<  rQ  r   r   Ú
spawnChild}  s   ÿ
zHProcessTestsBuilder.test_processCommandLineArguments.<locals>.spawnChildN)
rZ   ÚmapÚchrÚrangerÔ   rÕ   r²   rA   rX   rG   )r"   ÚallCharsrR  r   )rp   rO  r>   r"   r<  rQ  r   Ú test_processCommandLineArgumentsc  s   



z4ProcessTestsBuilder.test_processCommandLineArgumentsc                    s`   g ‰G ‡fdd„dt ƒ‰ t‡ ‡fdd„ƒ}|  ¡ }| ||¡ |  |¡ t ˆt dg¡¡ dS )z�
        Process is removed from reapProcessHandler dict before running
        ProcessProtocol.processEnded() callback.
        c                       s$   e Zd ZdZdd„ Z‡ fdd„ZdS )ziProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback.<locals>.TestProcessProtocola7  
            Process protocol captures own presence in
            process.reapProcessHandlers at time of .processEnded() callback.

            @ivar deferred: A deferred fired when the .processEnded() callback
                has completed.
            @type deferred: L{Deferred<defer.Deferred>}
            c                 S   s   t ƒ | _d S r   )r   Údeferredrk   r   r   r   r#   œ  rs   zrProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback.<locals>.TestProcessProtocol.__init__c                    sJ   ddl m} |j}| ¡ }| j|v rˆ  d¡ nˆ  d¡ | j d¡ dS )z¯
                Capture whether the process has already been removed
                from process.reapProcessHandlers.

                @param status: unused
                r   r   z!process present but should not beú"process already removed as desiredN)Útwisted.internetr   rý   ÚvaluesrJ   r%   rX  r*   )r"   Ústatusr   ÚhandlersÚ	processes©Úresultsr   r   r-   Ÿ  s   

zvProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback.<locals>.TestProcessProtocol.processEndedN)r/   r0   r1   r2   r#   r-   r   r_  r   r   ÚTestProcessProtocol’  s    	ra  c              
   3   s~   � z8zˆ ƒ }|   |ttdg¡ |jV  W n ty+ } zˆ |¡ W Y d}~nd}~ww W |  ¡  dS W |  ¡  dS |  ¡  w )a  
            Launch and wait for a subprocess and allow the TestProcessProtocol
            to capture the order of the .processEnded() callback vs. removal
            from process.reapProcessHandlers.

            @param reactor: Reactor used to spawn the test process and to be
                stopped when checks are complete.
            @type reactor: object providing
                L{twisted.internet.interfaces.IReactorProcess} and
                L{twisted.internet.interfaces.IReactorCore}.
            z	--versionN)rB   rC   rX  rû   r%   r:   )r>   ÚtestProcessProtocolÚe©ra  r`  r   r   ÚlaunchProcessAndWait²  s"   €ý€ÿÿþzjProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback.<locals>.launchProcessAndWaitrY  N)r   r   rA   rX   rG   ÚhamcrestÚassert_thatÚequal_to)r"   re  r>   r   rd  r   Ú8test_process_unregistered_before_protocol_ended_callbackŠ  s    

þzLProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callbackN)r/   r0   r1   r2   r7   r&  r   r˜   r'  r  r(  r-  r5  rD  rH  rW  r   ri  r   r   r   r   r  g  s     52>
('r  c                   @   s<   e Zd ZdZdZe ¡ rdZdS e ¡ rdZddiZ	dS dS )ÚPTYProcessTestsBuilderzi
    Builder defining tests relating to L{IReactorProcess} for child processes
    which have a PTY.
    Tz"PTYs are not supported on Windows.z,PTYs are flaky from a Darwin bug. See #8840.z(twisted.internet.pollreactor.PollReactorz$macOS's poll() does not support PTYsN)
r/   r0   r1   r2   r7   r   r˜   r   ÚisMacOSXÚskippedReactorsr   r   r   r   rj  Ù  s    ÿýrj  c                   @   s   e Zd ZdZdd„ ZdS )ÚPotentialZombieWarningTestszE
    Tests for L{twisted.internet.error.PotentialZombieWarning}.
    c                 C   s\   ddl m} |j |  | jg¡}|  |d d t¡ |  |d d d¡ |  t|ƒd¡ dS )z¾
        Accessing L{PotentialZombieWarning} via the
        I{PotentialZombieWarning} attribute of L{twisted.internet.error}
        results in a deprecation warning being emitted.
        r   )ÚerrorÚcategoryÚmessagez„twisted.internet.error.PotentialZombieWarning was deprecated in Twisted 10.0.0: There is no longer any potential for zombie process.rU   N)rZ  rn  ÚPotentialZombieWarningÚflushWarningsÚtest_deprecatedrY   ÚDeprecationWarningr   )r"   rn  Úwarningsr   r   r   rs  ó  s   
þz+PotentialZombieWarningTests.test_deprecatedN)r/   r0   r1   r2   rs  r   r   r   r   rm  î  s    rm  c                   @   s(   e Zd ZdZee ¡  dƒdd„ ƒZdS )Ú/ProcessIsUnimportableOnUnsupportedPlatormsTestsz„
    Tests to ensure that L{twisted.internet.process} is unimportable on
    platforms where it does not work (namely Windows).
    zOnly relevant on Windows.c                 C   s@   |   t¡� ddl}|jj W d  ƒ dS 1 sw   Y  dS )zI
        L{twisted.internet.process} is unimportable on Windows.
        r   N)ri   ÚImportErrorÚtwisted.internet.processÚinternetr   )r"   Útwistedr   r   r   Útest_unimportableOnWindows  s   
"ýzJProcessIsUnimportableOnUnsupportedPlatormsTests.test_unimportableOnWindowsN)r/   r0   r1   r2   r   r   r˜   r{  r   r   r   r   rv    s    rv  c                
   @   sj   e Zd Zze dd¡ W n ey& Z zeeƒZe	eƒZ
W Y dZ[ndZ[ww edd„ ƒZedd„ ƒZdS )ÚReapingNonePidsLogsProperlyNc                 C   sF   t  d d ¡ |  ¡ \}|  t|jƒ| jd¡ |  t|jƒ| jd¡ d S ©NzWrong error type loggedzWrong error message logged)	r   ÚregisterReapProcessHandlerr  rY   Útyper—   Úexpected_typerÕ   Úexpected_message)r"   rn  r   r   r   Útest_registerReapProcessHandler"  s   
ýýz;ReapingNonePidsLogsProperly.test_registerReapProcessHandlerc                 C   sL   t  d ¡}| ¡  |  ¡ \}|  t|jƒ| jd¡ |  t|jƒ| j	d¡ d S r}  )
r   Ú_BaseProcessÚreapProcessr  rY   r  r—   r€  rÕ   r�  )r"   Ú_baseProcessrn  r   r   r   Útest__BaseProcess_reapProcess2  s   

ýýz9ReapingNonePidsLogsProperly.test__BaseProcess_reapProcess)r/   r0   r1   rV   Úwaitpidrû   rc  rÕ   r�  r  r€  r   r‚  r†  r   r   r   r   r|    s    €þ
r|  )Fr2   rÆ   rV   rx   r©   r§   rv   Úunittestr   rf  rz  rZ  r   Útwisted.internet.deferr   r   r   Útwisted.internet.errorr   r   Útwisted.internet.interfacesr	   r
   Útwisted.internet.protocolr   Ú#twisted.internet.test.reactormixinsr   Útwisted.python.compatr   Útwisted.python.filepathr   r   Útwisted.python.logr   r   Útwisted.python.runtimer   Útwisted.trial.unittestr   Ú
executableÚ_asBytesPathrC   Ú__file__Úparentr¾   r  r  ÚdictÚenvironr  ÚpathseprZ   r¿   r   Ú	_resourcer   Ú_processÚgetuidrw  r   r   r3   r  ÚglobalsÚupdateÚmakeTestCaseClassesrj  rm  rv  r|  r   r   r   r   Ú<module>   st   
€ü      q