U
    W[-}                     @   s$  d Z ddlmZmZm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ZddlmZ ddlmZ ddlmZmZ ddlmZ ddlmZmZ dd	lmZ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)m*Z* eej+, Z-ee
j./ / Z0dZ1e2 rPdZ3dZ4dZ1e5ej6Z7ej89ej:e7d< nHddl3Z3ddlm4Z4 e; dkrvdZ1e Z7ej89ej:<e= e7d< dd Z>G dd de'Z?G dd deZ@G dd de@ZAeB CeAD  G dd de@ZEeB CeED  G dd deZFG d d! d!eZGd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.
    )divisionabsolute_importprint_functionN)TestCase)ReactorBuilder)msgerr)platform)FilePath_asFilesystemBytes)networkStringrangeitemsbytesEnvironunicode)utils)IReactorProcessIProcessTransport)Deferredsucceed)ProcessProtocol)ProcessDoneProcessTerminatedz Cannot change UID/GID on Windows
PYTHONPATH)processz$Cannot change UID/GID except as roots
   PYTHONPATHc                 C   s   t dk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)Z
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__Q   s    z)_ShutdownCallbackProcessProtocol.__init__c                 C   s   | j |g | d S r!   )r#   
setdefaultappend)r$   fdbytesr   r   r   childDataReceivedV   s    z2_ShutdownCallbackProcessProtocol.childDataReceivedc                 C   s   | j d  d S r!   )r"   callbackr$   reasonr   r   r   processEndedZ   s    z-_ShutdownCallbackProcessProtocol.processEndedN)__name__
__module____qualname____doc__r%   r*   r.   r   r   r   r   r    I   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dd Zeedddkr`de_dd Zdd Zedd Zedd Zdd Zdd Zdd  Zedk	ree_d!d" Zedk	ree_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      S r!   stopZignoredreactorr   r   <lambda>   r5   zHProcessTestsBuilderBase.test_processTransportInterface.<locals>.<lambda>N)r   r    buildReactorspawnProcesspyExer7   
assertTruer   Z
providedByaddCallback
runReactor)r$   endedprotocol	transportr   r;   r   test_processTransportInterfacej   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                     sH    ttdg} z|   W n    td d | d Y nX d S )Nr4   z!Unhandled exception while writingZKILL)r?   r@   r   signalProcessrF   bytesToSendprogramrE   r<   writer   r   startup   s      
z3ProcessTestsBuilderBase._writeTest.<locals>.startupc                    s      S r!   r8   r:   r;   r   r   r=      r5   z4ProcessTestsBuilderBase._writeTest.<locals>.<lambda>r5      N)r>   r   r    r   oslinesepcallWhenRunningrB   rC   assertEqualjoinr#   )r$   rM   rD   rN   r   rJ   r   
_writeTest   s    


z"ProcessTestsBuilderBase._writeTestc                 C   s   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!   rM   rF   rK   r   r   r   rM      s    z1ProcessTestsBuilderBase.test_write.<locals>.writeNrU   r$   rM   r   r   r   
test_write   s    z"ProcessTestsBuilderBase.test_writec                 C   s   dd }|  | dS )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!   )ZwriteSequencerW   r   r   r   rM      s    z9ProcessTestsBuilderBase.test_writeSequence.<locals>.writeNrX   rY   r   r   r   test_writeSequence   s    z*ProcessTestsBuilderBase.test_writeSequencec                 C   s   dd }|  | dS )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   )writeToChildrW   r   r   r   rM      s    z8ProcessTestsBuilderBase.test_writeToChild.<locals>.writeNrX   rY   r   r   r   test_writeToChild   s    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              	      s(   z t| jd| W 5 |  | X d S )N   )rM   assertRaisesKeyErrorr\   rW   r$   r   r   rM      s    zIProcessTestsBuilderBase.test_writeToChildBadFileDescriptor.<locals>.writeNrX   rY   r   ra   r   "test_writeToChildBadFileDescriptor   s    z:ProcessTestsBuilderBase.test_writeToChildBadFileDescriptorc                    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 |rd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                     s       d S r!   )set)args)signaledr   r   handler   s    zGProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped.<locals>.handlerr4   r5   )r7   childFDsx   z,Timed out waiting for child process to exit.c                    s      S r!   r8   r:   r;   r   r   r=     r5   zHProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped.<locals>.<lambda>)r>   r7   	threadingZEventsignalSIGCHLDr   r?   r    r@   waitZisSetfailrB   r'   rC   rA   )r$   rg   rf   rD   resultr   )r<   re   r   test_spawnProcessEarlyIsReaped   s2       


z6ProcessTestsBuilderBase.test_spawnProcessEarlyIsReapedrk   Nz;Platform lacks SIGCHLD, early-spawnProcess test can't work.c                    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.
        ZTERMZ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   rF   rH   r$   r(   data)sigNamer   r   r*   %  s    zVProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.childDataReceivedc                 S   s   t d|f  d S NchildConnectionLost(%d)r   )r$   r(   r   r   r   childConnectionLost)  s    zXProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.childConnectionLostc                    s   t d|f   |g d S NzprocessExited(%r)r   r+   r,   exitedr   r   processExited,  s    zRProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.processExitedc                 S   s   t d|f  d S NzprocessEnded(%r)rv   r,   r   r   r   r.   5  s    zQProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.Exiter.processEndedNr/   r0   r1   r*   rw   r|   r.   r   )r{   rs   r   r   Exiter$  s   	r   r4   r6   c                    sX   | \}| t |j}t r: |j  |jd n |j  |j d S )NrO   )	trapr   valuer	   	isWindowsZassertIsNonerj   rS   exitCode)rd   failurer   )r$   sigNumr   r   cbExited=  s    
zFProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.cbExitedc                    s      S r!   r8   Zignr;   r   r   r=   R  r5   zFProcessTestsBuilderBase.test_processExitedWithSignal.<locals>.<lambda>N)getattrrj   r   r   r>   rR   r?   r@   r7   rB   
addErrbackr   rC   )r$   sourcer   r   r   )r{   r<   r$   rs   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               	      sj   zZtt } t| ddg tj| ddgtjd}|j 	|j
  W 5 Q R X W 5     X d S )N-czimport time; time.sleep(0.1)z)import time; time.sleep(0.5);print('Foo'))stdout)r9   r@   decodesysgetfilesystemencoding
subprocessPopenPIPEr   r'   read)exef2r<   rn   r   r   fe  s    zJProcessTestsBuilderBase.test_systemCallUninterruptedByChildExit.<locals>.fs   FooasciiN)r>   rR   rC   rS   rP   rQ   encode)r$   r   r   r   r   'test_systemCallUninterruptedByChildExitW  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  }dd	d
g}| |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, '{0}')
from twisted.internet import process
sys.stdout.write(repr(process._listOpenFDs()))
sys.stdout.flush()   r   c                       s   e Zd Z jZfddZdS )zKProcessTestsBuilderBase.test_openFileDescriptors.<locals>.GatheringProtocolc                    s       d S r!   r8   r,   r;   r   r   r.     s    zXProcessTestsBuilderBase.test_openFileDescriptors.<locals>.GatheringProtocol.processEndedN)r/   r0   r1   rM   ZoutReceivedr.   r   outputr<   r   r   GatheringProtocol  s   r   s   -Wignorer4   r6   rO      N)r   formattwistedRootpathrP   pipeZ
addCleanupcloser   Z	getrlimitZRLIMIT_NOFILEdup2ioBytesIOr   r>   rR   r?   r@   r7   rC   rc   evalgetvaluerS   intersection)	r$   r   rwZfudgeFactorZ
unlikelyFDr   ZreportedChildFDsZstdFDsr   r   r   test_openFileDescriptors{  s:      
 

z0ProcessTestsBuilderBase.test_openFileDescriptorsc                    st   dd }|  td| |  tddd  |  t  j fdd}| jd	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/0Zsingle)
isinstancestrr   compiler   )rd   kwfilenameZcodeobjr   r   r   execvpe  s
    

z=ProcessTestsBuilderBase.test_errorDuringExec.<locals>.execvper   r   c                   S   s   dS )Nr   r   r   r   r   r   r=     r5   z>ProcessTestsBuilderBase.test_errorDuringExec.<locals>.<lambda>c                     s2   G  fdddt t} |  ttddg d S )Nc                       s   e Zd Z jZfddZdS )z[ProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunning.<locals>.TracebackCatcherc                    s       d S r!   r8   r,   r;   r   r   r.     s    zhProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunning.<locals>.TracebackCatcher.processEndedN)r/   r0   r1   rM   ZerrReceivedr.   r   r   r   r   TracebackCatcher  s   r   r4   r5   )r   objectr?   r@   )r   r   r   r   whenRunning  s    
zAProcessTestsBuilderBase.test_errorDuringExec.<locals>.whenRunning   Ztimeoutu   ☃r   N)ZpatchrP   r   r>   r   r   rR   rC   Z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{   r9   rS   r   r   )Z	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)	r>   r   rR   r?   r@   r7   rC   rA   r{   )r$   r   rE   r   r   r   test_timelyProcessExited  s      z0ProcessTestsBuilderBase.test_timelyProcessExitedc              	      s~   dd|f g}g  G  fdddt }|  | }jj|ttdd|gf|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.get%s() != 1)c                       s   e Zd Z fddZdS )z@ProcessTestsBuilderBase._changeIDTest.<locals>.CaptureExitStatusc                    s     |   d S r!   )r'   r9   r,   Z	containerr<   r   r   r.     s    
zMProcessTestsBuilderBase._changeIDTest.<locals>.CaptureExitStatus.processEndedN)r/   r0   r1   r.   r   r   r   r   CaptureExitStatus  s   r   r   
rO   r   N)
r   r>   rR   r?   r@   rT   rC   rS   r   r   )r$   ZwhichrL   r   rE   r   r   r   _changeIDTest  s"    
  
z%ProcessTestsBuilderBase._changeIDTestc                 C   s   |  d dS )z
        If a value is passed for L{IReactorProcess.spawnProcess}'s C{uid}, the
        child process is run with that UID.
        ZuidNr   ra   r   r   r   test_changeUID!  s    z&ProcessTestsBuilderBase.test_changeUIDc                 C   s   |  d dS )z
        If a value is passed for L{IReactorProcess.spawnProcess}'s C{gid}, the
        child process is run with that GID.
        gidNr   ra   r   r   r   test_changeGID+  s    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k	rttj	D ](\}}||k	r|qjt
|| | d	 qj| 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   TestException=  s   r   c                       s   e Zd Z fddZdS )zBProcessTestsBuilderBase.test_processExitedRaises.<locals>.Protocolc                    s       dd S )NzprocessedExited raisedr8   r,   r   r<   r   r   r|   A  s    zPProcessTestsBuilderBase.test_processExitedRaises.<locals>.Protocol.processExitedN)r/   r0   r1   r|   r   r   r   r   Protocol@  s   r   r4   r5   r6   NzEAfter processExited raised, transport was left in reapProcessHandlersrO   )r>   	Exceptionr   r?   r@   r7   rC   r   r   ZreapProcessHandlersZunregisterReapProcessHandlerrm   rS   lenZflushLoggedErrors)r$   r   rE   rF   pidrf   r   r   r   test_processExitedRaises5  s$      
z0ProcessTestsBuilderBase.test_processExitedRaises)r/   r0   r1   r2   r   ZrequiredInterfacesrG   rU   rZ   r[   r]   rb   ro   r   rj   r   r   r   r   r   r   r   r   r   _uidgidSkipr   r   r   r   r   r   r3   _   s6   %


6F$
I
"r3   c                   @   sZ   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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   rO   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$   rF   )	connectedr   r   makeConnectiont  s    zKProcessTestsBuilder.test_childConnectionLost.<locals>.Closer.makeConnectionc                    s    |  d  d S r!   r   r$   ZchildFDlostr   r   rw   w  s    zPProcessTestsBuilder.test_childConnectionLost.<locals>.Closer.childConnectionLostN)r/   r0   r1   r   rw   r   )r   r   r   r   Closers  s   r   s,   twisted.internet.test.process_loseconnection   -menvr7   c                    s      d d  fddS )Ns   2
r   c                    s    S r!   r   r   rI   r   r   r=     r5   zSProcessTestsBuilder.test_childConnectionLost.<locals>.cbConnected.<locals>.<lambda>rM   rB   rI   r   rI   r   cbConnected  s    
zAProcessTestsBuilder.test_childConnectionLost.<locals>.cbConnectedc                    s      d d  fddS )Ns   1
rO   c                    s    S r!   r   r   rI   r   r   r=     r5   zRProcessTestsBuilder.test_childConnectionLost.<locals>.lostSecond.<locals>.<lambda>r   rI   r   rI   r   
lostSecond  s    
z@ProcessTestsBuilder.test_childConnectionLost.<locals>.lostSecondc                 S   s   |  d d S )N   
rV   rI   r   r   r   	lostFirst  s    z?ProcessTestsBuilder.test_childConnectionLost.<locals>.lostFirstc                    s       d S r!   r8   r:   r;   r   r   cbEnded  s    z=ProcessTestsBuilder.test_childConnectionLost.<locals>.cbEndedN)r   r   r>   rR   r?   r@   	properEnvr7   rB   r   r   rC   )r$   r   targetr   r   r   r   r   )r   r   r<   r   test_childConnectionLostk  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 rp   )r   rF   loseConnectionrq   r   r   r   r*     s    zFProcessTestsBuilder.test_processEnded.<locals>.Ender.childDataReceivedc                    s   t d|f   | d S rt   )r   r'   r   r   r   r   rw     s    zHProcessTestsBuilder.test_processEnded.<locals>.Ender.childConnectionLostc                 S   s   t d|f  d S rx   rv   r,   r   r   r   r|     s    zBProcessTestsBuilder.test_processEnded.<locals>.Ender.processExitedc                    s   t d|f   |g d S r}   ry   r,   )rD   r   r   r.     s    zAProcessTestsBuilder.test_processEnded.<locals>.Ender.processEndedNr~   r   )rD   r   r   r   Ender  s   r   r      childr   c                    s.   | \}| t t tdddg d S Nr   rO   r   )r   r   rS   rc   rd   r   r   r$   r   r   r     s    
z6ProcessTestsBuilder.test_processEnded.<locals>.cbEndedc                    s      S r!   r8   r   r;   r   r   r=     r5   z7ProcessTestsBuilder.test_processEnded.<locals>.<lambda>Nr   r   r>   rR   r?   r@   keepStdioOpenProgramkeepStdioOpenArgr   r7   rB   r   r   rC   )r$   r   r   r   )rD   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 rp   rv   rq   r   r   r   r*     s    zHProcessTestsBuilder.test_processExited.<locals>.Waiter.childDataReceivedc                    s2   t d|f  | tdkr. d  d S )Nru      )r   r'   r   r+   r   )allLostr   r   r   rw     s    
zJProcessTestsBuilder.test_processExited.<locals>.Waiter.childConnectionLostc                    s(   t d|f   |g | j  d S rx   )r   r+   rF   r   r,   rz   r   r   r|     s    zDProcessTestsBuilder.test_processExited.<locals>.Waiter.processExitedN)r/   r0   r1   r*   rw   r|   r   )r   r{   r   r   r   Waiter  s   r   s   -ur   r   r   c                    s.   | \}| t tdf  g   S )NzcbExited; lost = %s)r   r   r   rS   r   )r   r   r$   r   r   r     s
    
z8ProcessTestsBuilder.test_processExited.<locals>.cbExitedc                    s    t tdddg d S r   )rS   rc   r:   r   r   r   	cbAllLost  s    z9ProcessTestsBuilder.test_processExited.<locals>.cbAllLostc                    s      S r!   r8   r   r;   r   r   r=     r5   z8ProcessTestsBuilder.test_processExited.<locals>.<lambda>Nr   )r$   r   r   r   r   )r   r{   r   r<   r$   r   test_processExited  s,       


z&ProcessTestsBuilder.test_processExitedc              	   C   sF   t |  }t|d}|tj|tj  W 5 Q R X tj|S )zj
        Write the given list of lines to a text file and return the absolute
        path to it.
        Zwt)	r   ZmktempopenrM   rP   rQ   rT   r   abspath)r$   ZsourceLinesZscript
scriptFiler   r   r   makeSourceFile  s    "z"ProcessTestsBuilder.makeSourceFilec                    s   d dtdf dddf 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#!%sr   z
import syszsys.stdout.write('%s')zsys.stdout.flush()i  c                    sD   | \}}}t d|||f   |  |d  |d d S )NzcbProcessExited((%r, %r, %d))r5   r   )r   rS   )rd   outr   code)r$   shebangOutputr   r   cbProcessExited  s
    
z9ProcessTestsBuilder.test_shebang.<locals>.cbProcessExitedc                    s       | S r!   r8   )Zpassthroughr;   r   r   shutdown  s    z2ProcessTestsBuilder.test_shebang.<locals>.shutdownc                     s0   t jd} |  |   | t d S )Nr;   )r   getProcessOutputAndValueaddBothrB   r   r   d)r   r<   r   r   r   r   start!  s    

z/ProcessTestsBuilder.test_shebang.<locals>.startN)r   r@   r   rP   chmodr>   rR   rC   )r$   r   r   )r   r<   r   r$   r   r   r   test_shebang  s    
z ProcessTestsBuilder.test_shebangc                    s   ddddddg 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_clis   hello   "s    	|<>^&s   "\\"hello\\"s   "foo\ bar baz\"" rO      r   c                    s,   | \}}}| d}|   | d S )N    )splitpoprS   )ZfinishedArgsr   r   r   )rd   r$   r   r   processFinished:  s    

zMProcessTestsBuilder.test_processCommandLineArguments.<locals>.processFinishedc                    s       | S r!   r8   )rn   r;   r   r   r   A  s    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   r@   r   )Zdummy)rd   r<   usr   r   r=   G  s
    
 zZProcessTestsBuilder.test_processCommandLineArguments.<locals>.spawnChild.<locals>.<lambda>)r   rB   r   r   )rd   r  r<   r   r	  r   r   
spawnChildE  s    
zHProcessTestsBuilder.test_processCommandLineArguments.<locals>.spawnChildN)
rT   mapchrr   r   r   r   r>   rR   rC   )r$   ZallCharsr
  r   )rd   r  r<   r$   r   r	  r    test_processCommandLineArguments+  s    


z4ProcessTestsBuilder.test_processCommandLineArgumentsN)r/   r0   r1   r2   r7   r   r	   r   r   r   r   r   r   r  r  r   r   r   r   r   Z  s   -/3&r   c                   @   s6   e Zd ZdZdZe rdZne r2dZddiZ	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   ZisMacOSXZskippedReactorsr   r   r   r   r  S  s   r  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messageztwisted.internet.error.PotentialZombieWarning was deprecated in Twisted 10.0.0: There is no longer any potential for zombie process.rO   N)twisted.internetr  ZPotentialZombieWarningZflushWarningstest_deprecatedrS   DeprecationWarningr   )r$   r  warningsr   r   r   r  j  s    
z+PotentialZombieWarningTests.test_deprecatedN)r/   r0   r1   r2   r  r   r   r   r   r  f  s   r  c                   @   s&   e Zd ZdZdd Ze s"de_dS )/ProcessIsUnimportableOnUnsupportedPlatormsTestsz
    Tests to ensure that L{twisted.internet.process} is unimportable on
    platforms where it does not work (namely Windows).
    c              	   C   s*   |  t ddl}|jj W 5 Q R X dS )zI
        L{twisted.internet.process} is unimportable on Windows.
        r   N)r_   ImportErrorZtwisted.internet.processZinternetr   )r$   twistedr   r   r   test_unimportableOnWindows  s    zJProcessIsUnimportableOnUnsupportedPlatormsTests.test_unimportableOnWindowszOnly relevant on Windows.N)r/   r0   r1   r2   r  r	   r   r   r   r   r   r   r  ~  s   r  )Hr2   Z
__future__r   r   r   r   rP   rj   r   ri   r  r   Ztwisted.trial.unittestr   Z#twisted.internet.test.reactormixinsr   Ztwisted.python.logr   r   Ztwisted.python.runtimer	   Ztwisted.python.filepathr
   r   Ztwisted.python.compatr   r   r   r   r   r  r   Ztwisted.internet.interfacesr   r   Ztwisted.internet.deferr   r   Ztwisted.internet.protocolr   Ztwisted.internet.errorr   r   
executableZ_asBytesPathr@   __file__parentr   r   r   r   r   dictenvironr   pathseprT   r   getuidr   r   r   r    r3   r   globalsupdateZmakeTestCaseClassesr  r  r  r   r   r   r   <module>   sb   

   ~ v