U
    n5{i™8  ã                   @  s  d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZmZmZmZ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 ddlmZ ddlmZ ddlm Z  ddl!m"Z"m#Z# dZ$e%ej&ƒZ'ej( )ej*¡e'd< G dd„ dejƒZ+G dd„ de#ƒZ,dS )z¯
Tests for L{twisted.internet.stdio}.

@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.
é    )ÚannotationsN)ÚAnyÚCallable)ÚskipIf)ÚdeferÚerrorÚprotocolÚreactorÚstdio)ÚIProcessTransportÚIReactorProcess)ÚProcessProtocol)ÚfilepathÚlog)ÚFailure)ÚrequireModule)Úplatform)ÚConnectionLostNotifyingProtocol)ÚSkipTestÚTestCases   xyz123abc Twisted is great!Ú
PYTHONPATHc                   @  sL   e Zd ZU dZdZded< ded< ddœd	d
„Zdd„ Zdd„ Zdd„ Z	dS )ÚStandardIOTestProcessProtocolaÕ  
    Test helper for collecting output from a child process and notifying
    something when it exits.

    @ivar onConnection: A L{defer.Deferred} which will be called back with
    L{None} when the connection to the child process is established.

    @ivar onCompletion: A L{defer.Deferred} which will be errbacked with the
    failure associated with the child process exiting when it exits.

    @ivar onDataReceived: A L{defer.Deferred} which will be called back with
    this instance whenever C{childDataReceived} is called, or L{None} to
    suppress these callbacks.

    @ivar data: A C{dict} mapping file descriptors to strings containing all
    bytes received from the child process on each file descriptor.
    Nzdefer.Deferred[None] | NoneÚonDataReceivedr   Ú	transportÚNone©Úreturnc                 C  s   t  ¡ | _t  ¡ | _i | _d S ©N)r   ÚDeferredÚonConnectionÚonCompletionÚdata©Úself© r$   ú;/tmp/pip-unpacked-wheel-mnhg7r0q/twisted/test/test_stdio.pyÚ__init__=   s    

z&StandardIOTestProcessProtocol.__init__c                 C  s   | j  d ¡ d S r   )r   Úcallbackr"   r$   r$   r%   ÚconnectionMadeB   s    z,StandardIOTestProcessProtocol.connectionMadec                 C  s>   | j  |d¡| | j |< | jdk	r:| jd }| _| | ¡ dS )z“
        Record all bytes received from the child process in the C{data}
        dictionary.  Fire C{onDataReceived} if it is not L{None}.
        ó    N)r!   Úgetr   r'   )r#   ÚnameÚbytesÚdr$   r$   r%   ÚchildDataReceivedE   s    
z/StandardIOTestProcessProtocol.childDataReceivedc                 C  s   | j  |¡ d S r   )r    r'   )r#   Úreasonr$   r$   r%   ÚprocessEndedO   s    z*StandardIOTestProcessProtocol.processEnded)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__annotations__r&   r(   r.   r0   r$   r$   r$   r%   r   '   s   

r   c                   @  sà   e Zd Ze ¡ r edƒdkr dZdddddd	œd
d„Zddddœdd„Zdd„ Z	d0ddddœdd„Z
ddœdd„Zddœdd„Zddœdd„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/„ ƒZdS )1ÚStandardInputOutputTestsZwin32processNzIOn windows, spawnProcess is not available in the absence of win32process.r   zstr | bytesÚstrr   r   )ÚprotoÚsiblingÚargsÚkwr   c                 O  sP   t |tƒr| ¡ }tjdd| tjjgt|ƒ }t	tƒj
|tj|fdti|—ŽS )ak  
        Launch a child Python process and communicate with it using the given
        ProcessProtocol.

        @param proto: A L{ProcessProtocol} instance which will be connected to
            the child process.

        @param sibling: The basename of a file containing the Python program to
            run in the child process.

        @param *args: strings which will be passed to the child process on the
            command line as C{argv[2:]}.

        @param **kw: additional arguments to pass to L{reactor.spawnProcess}.

        @return: The L{IProcessTransport} provider for the spawned process.
        z-mztwisted.test.Úenv)Ú
isinstancer,   ÚdecodeÚsysÚ
executabler	   Ú	__class__r2   Úlistr   ZspawnProcessÚ	properEnv)r#   r8   r9   r:   r;   Zprocargsr$   r$   r%   Ú_spawnProcessZ   s$    
üû  ÿÿÿz&StandardInputOutputTests._spawnProcessúdefer.Deferred[None]zCallable[[Failure], object])r-   r'   r   c                   s$   ‡fdd„}‡ fdd„}|  ||¡S )Nc                   s   ˆ   d| ›�¡ d S )Nz%Process terminated with non-Failure: )Zfail)Úresultr"   r$   r%   Úcb}   s    z4StandardInputOutputTests._requireFailure.<locals>.cbc                   s   ˆ | ƒS r   r$   )Úerr)r'   r$   r%   Úeb€   s    z4StandardInputOutputTests._requireFailure.<locals>.eb)ZaddCallbacks)r#   r-   r'   rG   rI   r$   )r'   r#   r%   Ú_requireFailurez   s    z(StandardInputOutputTests._requireFailurec                   sL   ˆ  ¡ ‰ t dˆ  ¡ tƒ ‰ˆj}ˆ ˆdˆ ¡ ‡ ‡‡fdd„}ˆ ||¡S )z„
        Verify that a protocol connected to L{StandardIO} can disconnect
        itself using C{transport.loseConnection}.
        zChild process logging to s   stdio_test_loseconnc              	     sN   t ˆ ƒ�"}|D ]}t d| ¡  ¡ qW 5 Q R X ˆ dˆj¡ |  tj¡ d S )NzChild logged: é   )	Úopenr   ÚmsgÚrstripZfailIfInr!   Útrapr   ÚProcessDone)r/   ÚfÚline©ÚerrorLogFileÚpr#   r$   r%   r0   �   s
    
zBStandardInputOutputTests.test_loseConnection.<locals>.processEnded)Úmktempr   rM   r   r    rD   rJ   ©r#   r-   r0   r$   rS   r%   Útest_loseConnection…   s    	z,StandardInputOutputTests.test_loseConnectionFÚbool)ÚexampleÚoutr   c                   sb   |   ¡ }tƒ ‰t ¡ ˆ_dddœ‡ ‡fdd„}ˆj |¡ dd„ }|  ˆj|¡}|  ˆ||¡ |S )Nr   rE   )Úignoredr   c                   s$   ˆj }ˆ rˆj ¡  n
ˆj ¡  |S r   )r    r   ZcloseStdoutZ
closeStdin)r\   r-   ©r[   rU   r$   r%   ÚcbBytes¢   s
    
zGStandardInputOutputTests.exampleOutputsAndZeroExitCode.<locals>.cbBytesc                 S  s   |   tj¡ d S r   )rO   r   rP   ©r/   r$   r$   r%   r0   ¬   s    zLStandardInputOutputTests.exampleOutputsAndZeroExitCode.<locals>.processEnded)rV   r   r   r   r   ÚaddCallbackrJ   rD   )r#   rZ   r[   rT   r^   r0   r-   r$   r]   r%   ÚexampleOutputsAndZeroExitCode›   s    
z6StandardInputOutputTests.exampleOutputsAndZeroExitCoder   c                 C  s
   |   d¡S )z´
        When stdin is closed and the protocol connected to it implements
        L{IHalfCloseableProtocol}, the protocol's C{readConnectionLost} method
        is called.
        Zstdio_test_halfclose©ra   r"   r$   r$   r%   Útest_readConnectionLost´   s    z0StandardInputOutputTests.test_readConnectionLostc                 C  s
   |   d¡S )úë
        When stdin is closed and the protocol connnected to it implements
        L{IHalfCloseableProtocol} but its C{readConnectionLost} method raises
        an exception its regular C{connectionLost} method will be called.
        Zstdio_test_halfclose_buggyrb   r"   r$   r$   r%   Útest_buggyReadConnectionLost¼   s    z5StandardInputOutputTests.test_buggyReadConnectionLostc                 C  s   | j ddd�S )rd   Z stdio_test_halfclose_buggy_writeT)r[   rb   r"   r$   r$   r%   Útest_buggyWriteConnectionLostÄ   s     ÿz6StandardInputOutputTests.test_buggyWriteConnectionLostc              
     sh   t ƒ ‰ zˆjˆ dtdd� W n. tk
rJ } ztt|ƒƒ‚W 5 d}~X Y nX ‡ ‡fdd„}ˆ ˆ j|¡S )z¶
        Verify that a write made directly to stdout using L{os.write}
        after StandardIO has finished is reliably received by the
        process reading that stdout.
        s   stdio_test_lastwriteT)ZusePTYNc                   s2   ˆ  ˆ jd  t¡dˆ j›d�¡ |  tj¡ dS )z‰
            Asserts that the parent received the bytes written by the child
            immediately after the child starts.
            rK   z	Received z) from child, did not find expected bytes.N)Ú
assertTruer!   ÚendswithÚUNIQUE_LAST_WRITE_STRINGrO   r   rP   r_   ©rU   r#   r$   r%   r0   è   s
    þzEStandardInputOutputTests.test_lastWriteReceived.<locals>.processEnded)r   rD   ri   Ú
ValueErrorr   r7   rJ   r    )r#   Úer0   r$   rj   r%   Útest_lastWriteReceivedÎ   s       ÿ
z/StandardInputOutputTests.test_lastWriteReceivedc                   s2   t ƒ ‰ ˆ j}ˆ ˆ d¡ ‡ ‡fdd„}ˆ ||¡S )zƒ
        Verify that the transport of a protocol connected to L{StandardIO}
        has C{getHost} and C{getPeer} methods.
        s   stdio_test_hostpeerc                   s6   ˆ j d  ¡ \}}ˆ |¡ ˆ |¡ |  tj¡ d S )NrK   )r!   Ú
splitlinesrg   rO   r   rP   )r/   ÚhostZpeerrj   r$   r%   r0   þ   s    

z?StandardInputOutputTests.test_hostAndPeer.<locals>.processEnded©r   r    rD   rJ   rW   r$   rj   r%   Útest_hostAndPeerõ   s
    z)StandardInputOutputTests.test_hostAndPeerc                   s2   t ƒ ‰ ˆ j}ˆ ˆ d¡ ‡ ‡fdd„}ˆ ||¡S )z�
        Verify that the C{write} method of the transport of a protocol
        connected to L{StandardIO} sends bytes to standard out.
        s   stdio_test_writec                   s"   ˆ  ˆ jd d¡ |  tj¡ d S ©NrK   s   ok!©ÚassertEqualr!   rO   r   rP   r_   rj   r$   r%   r0     s    z9StandardInputOutputTests.test_write.<locals>.processEndedrp   rW   r$   rj   r%   Ú
test_write  s
    z#StandardInputOutputTests.test_writec                   s2   t ƒ ‰ ˆ j}ˆ ˆ d¡ ‡ ‡fdd„}ˆ ||¡S )z˜
        Verify that the C{writeSequence} method of the transport of a
        protocol connected to L{StandardIO} sends bytes to standard out.
        s   stdio_test_writeseqc                   s"   ˆ  ˆ jd d¡ |  tj¡ d S rr   rs   r_   rj   r$   r%   r0      s    zAStandardInputOutputTests.test_writeSequence.<locals>.processEndedrp   rW   r$   rj   r%   Útest_writeSequence  s
    z+StandardInputOutputTests.test_writeSequencec              	   C  s@   |   ¡ }t|dƒ�$}tdƒD ]}| d|f ¡ qW 5 Q R X |S )NÚwbi   ó   %d
)rV   rL   ÚrangeÚwrite)r#   ÚjunkPathZjunkFileÚir$   r$   r%   Ú	_junkPath&  s
    z"StandardInputOutputTests._junkPathc                   sd   t ƒ ‰ˆj}g ‰ttdƒƒ‰‡ ‡‡‡fdd„‰ ˆ ˆd¡‰ˆj ˆ ¡ ‡‡‡‡fdd„}ˆ ||¡S )z€
        Verify that the transport of a protocol connected to L{StandardIO}
        is a working L{IProducer} provider.
        éd   c                   s8   ˆr4ˆ  dˆ ¡ f ¡ ˆ ˆd ¡ t dˆ d ¡ d S )Nrx   éÿÿÿÿg{®Gáz„?)ÚappendÚpoprz   r	   Ú	callLater)Zign)r(   ÚprocÚtoWriteÚwrittenr$   r%   r(   8  s    z>StandardInputOutputTests.test_producer.<locals>.connectionMades   stdio_test_producerc                   s>   ˆ  ˆ jd d ˆ¡¡ ˆ ˆdtˆƒf ¡ |  tj¡ d S )NrK   r)   z*Connection lost with %d writes left to go.)rt   r!   ÚjoinZassertFalseÚlenrO   r   rP   r_   )rU   r#   r„   r…   r$   r%   r0   B  s     ÿz<StandardInputOutputTests.test_producer.<locals>.processEnded)r   r    rB   ry   rD   r   r`   rJ   rW   r$   )r(   rU   rƒ   r#   r„   r…   r%   Útest_producer-  s    z&StandardInputOutputTests.test_producerc                   s>   t ƒ ‰ˆj}ˆ ¡ ‰ ˆ ˆdˆ ¡ ‡ ‡‡fdd„}ˆ ||¡S )z€
        Verify that the transport of a protocol connected to L{StandardIO}
        is a working L{IConsumer} provider.
        s   stdio_test_consumerc              	     s<   t ˆ dƒ�}ˆ ˆjd | ¡ ¡ W 5 Q R X |  tj¡ d S )NÚrbrK   )rL   rt   r!   ÚreadrO   r   rP   )r/   rQ   ©r{   rU   r#   r$   r%   r0   W  s     z<StandardInputOutputTests.test_consumer.<locals>.processEnded)r   r    r}   rD   rJ   rW   r$   r‹   r%   Útest_consumerK  s    z&StandardInputOutputTests.test_consumerzpStandardIO does not accept stdout as an argument to Windows.  Testing redirection to a file is therefore harder.c                   sØ   t  ¡ }t|ƒ}t ˆ ¡ ¡‰ˆ d¡ ˆ_}ˆ |j	¡ t
| ¡ d�}t ¡ s€t ¡ \}}ˆ tj	|¡ ˆ tj	|¡ ||d< tj|f|Ž‰ d‰t ¡ ‰‡ ‡‡‡fdd„‰t dˆ¡ ‡‡‡‡fdd	„}| |¡ |S )
aE  
        If L{StandardIO} is created with a file descriptor which refers to a
        normal file (ie, a file from the filesystem), L{StandardIO.write}
        writes bytes to that file.  In particular, it does not immediately
        consider the file closed or call its protocol's C{connectionLost}
        method.
        rw   )ÚstdoutÚstdiné   c                    sD   ˆD ].} | ˆkrˆ   ¡   d S ˆ  d| f ¡  q4qt dˆ¡ d S )Nó   %dr   )ZloseConnectionrz   r	   r‚   )Úvalue)Ú
connectionÚcountÚhowManyÚspinr$   r%   r•   ‚  s    zAStandardInputOutputTests.test_normalFileStandardOut.<locals>.spinr   c                   s<   ˆ  tˆ ƒˆd ¡ ˆ  ˆ ¡ d dd„ tˆƒD ƒ¡¡ d S )NrK   r)   c                 s  s   | ]}d |f V  qdS )r�   Nr$   )Ú.0r|   r$   r$   r%   Ú	<genexpr>’  s     zVStandardInputOutputTests.test_normalFileStandardOut.<locals>.cbLost.<locals>.<genexpr>)rt   ÚnextZ
getContentr†   ry   r_   )r“   r”   Úpathr#   r$   r%   ÚcbLost�  s
     ÿzCStandardInputOutputTests.test_normalFileStandardOut.<locals>.cbLost)r   r   r   r   ZFilePathrV   rL   ÚnormalZ
addCleanupÚcloseÚdictÚfilenor   Ú	isWindowsÚosÚpiper
   Z
StandardIOÚ	itertoolsr“   r	   r‚   r`   )r#   Z
onConnLostr8   r›   ÚkwargsÚrÚwrš   r$   )r’   r“   r”   r™   r#   r•   r%   Útest_normalFileStandardOut^  s&    	
z3StandardInputOutputTests.test_normalFileStandardOut)F)r1   r2   r3   r   rŸ   r   ÚskiprD   rJ   rX   ra   rc   re   rf   rm   rq   ru   rv   r}   rˆ   rŒ   r   r¦   r$   r$   r$   r%   r6   S   s.   ÿ  ÿ
'þr6   )-r4   Ú
__future__r   r¢   r    r?   Útypingr   r   Zunittestr   Ztwisted.internetr   r   r   r	   r
   Ztwisted.internet.interfacesr   r   Ztwisted.internet.protocolr   Ztwisted.pythonr   r   Ztwisted.python.failurer   Ztwisted.python.reflectr   Ztwisted.python.runtimer   Ztwisted.test.test_tcpr   Ztwisted.trial.unittestr   r   ri   r�   ÚenvironrC   Úpathsepr†   r™   r   r6   r$   r$   r$   r%   Ú<module>   s(   
,