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j23ej4e1d< zddl5Z6ddlm7Z8 e9 dkrd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? @eBA  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   childFDsx   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messageztwisted.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