o
    pjGÅ  ã                   @   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Zddlm	Z	 ddl
mZ ddlmZ ddlmZ ddlmZ ddlmZmZ dd	l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# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/ e+dƒZ0e+dƒZ1e+dƒZ2e1rÒe0rÒz(ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z; ddl<m=Z= ddlm>Z> W n	 e?yÑ   Y nw dZ@de2e1e0e Aed¡fv râdZ@ee@dƒG d d!„ d!e/ƒƒZBG d"d#„ d#e/ƒZCG d$d%„ d%e-ƒZDG d&d'„ d'ƒZEG d(d)„ d)ƒZFeeƒG d*d+„ d+e	ƒƒZGee@dƒG d,d-„ d-e/ƒƒZHG d.d/„ d/ƒZIG d0d1„ d1ejJƒZKG d2d3„ d3eƒZLee@dƒG d4d5„ d5eLƒƒZMee@dƒG d6d7„ d7eLƒƒZNee@dƒee)d8ƒ d9ƒG d:d;„ d;eLƒƒƒZOdS )<z*
Tests for L{twisted.conch.scripts.cftp}.
é    N)ÚBytesIO)ÚskipIf)Úimplementer)Úls)Ú	ISFTPFile)ÚFileTransferTestAvatarÚSFTPTestBase)Úportal)ÚdeferÚerrorÚ
interfacesÚprotocolÚreactor)ÚClock)ÚgetProcessOutputAndValueÚgetProcessValue)Úlog)ÚUserDatabase)ÚFilePath)Úwhich)ÚrequireModule)ÚStringTransport)ÚTestCaseÚpyasn1Úcryptographyztwisted.conch.unix)Úcftp)Ú
SSHSession)Úfiletransfer)Ú
test_conchÚtest_ssh)Ú	FakeStdio)ÚFileTransferForTestAvatarFTz4don't run w/o spawnProcess or cryptography or pyasn1c                   @   s   e Zd ZdZdd„ ZdS )ÚSSHSessionTestsz=
    Tests for L{twisted.conch.scripts.cftp.SSHSession}.
    c                 C   s*   t ƒ }tƒ }||_| ¡  |  |j¡ dS )z|
        L{twisted.conch.scripts.cftp.SSHSession.eofReceived} loses the write
        half of its stdio connection.
        N)r    r   ÚstdioÚeofReceivedÚ
assertTrueÚwriteConnLost)Úselfr#   Úchannel© r)   ú>/usr/lib/python3/dist-packages/twisted/conch/test/test_cftp.pyÚtest_eofReceived>   s
   z SSHSessionTests.test_eofReceivedN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r+   r)   r)   r)   r*   r"   8   s    r"   c                   @   s¶   e Zd ZdZeeddƒdu rdZdd„ Zdd„ Zd	d
„ Z	dd„ Z
dd„ Ze ¡ Zzz	e ejd¡ W n ejy>   dZY nw e eje¡ W n   Y eedƒdd„ ƒZdd„ ZdS )ÚListingTestszƒ
    Tests for L{lsLine}, the function which generates an entry for a file or
    directory in an SFTP I{ls} command's output.
    ÚtzsetNz8Cannot test timestamp formatting code without time.tzsetc                    sj   dˆ _ ‡ fdd„}ˆ  td|¡ dtjv r*ˆ  tjtjdtjd ¡ ˆ  tj	¡ dS dd„ }ˆ  |¡ dS )	zo
        Patch the L{ls} module's time function so the results of L{lsLine} are
        deterministic.
        iÍ[c                      s   ˆ j S ©N)Únowr)   ©r'   r)   r*   ÚfakeTimeZ   s   z$ListingTests.setUp.<locals>.fakeTimeÚtimeÚTZc                   S   s,   zt jd= W n	 ty   Y nw t ¡  d S )Nr7   )ÚosÚenvironÚKeyErrorr6   r1   r)   r)   r)   r*   Úcleanupf   s   ÿz#ListingTests.setUp.<locals>.cleanupN)
r3   Úpatchr   r8   r9   Ú
addCleanupÚoperatorÚsetitemr6   r1   )r'   r5   r;   r)   r4   r*   ÚsetUpS   s   
zListingTests.setUpc                 C   s   |t jd< t ¡  t d|¡S )zl
        Call L{ls.lsLine} after setting the timezone to C{timezone} and return
        the result.
        r7   Úfoo)r8   r9   r6   r1   r   ÚlsLine)r'   ÚtimezoneÚstatr)   r)   r*   Ú_lsInTimezonep   s   
zListingTests._lsInTimezonec                 C   óT   | j d }t dddddddd|df
¡}|  |  d|¡d¡ |  |  d|¡d¡ dS )z‘
        A file with an mtime six months (approximately) or more in the past has
        a listing including a low-resolution timestamp.
        é€r   úAmerica/New_Yorkz;!---------    0 0        0               0 Apr 26  1973 fooúPacific/Aucklandz;!---------    0 0        0               0 Apr 27  1973 fooN©r3   r8   Ústat_resultÚassertEqualrE   ©r'   ÚthenrD   r)   r)   r*   Útest_oldFile{   ó   

þ
þzListingTests.test_oldFilec                 C   óX   | j d d }t dddddddd|df
¡}|  |  d|¡d¡ |  |  d|¡d¡ dS )	úæ
        A file with a high-resolution timestamp which falls on a day of the
        month which can be represented by one decimal digit is formatted with
        one padding 0 to preserve the columns which come after it.
        rG   i€— r   rH   z;!---------    0 0        0               0 May 01  1973 foorI   z;!---------    0 0        0               0 May 02  1973 fooNrJ   rM   r)   r)   r*   Útest_oldSingleDigitDayOfMonth�   ó   
þ
þz*ListingTests.test_oldSingleDigitDayOfMonthc                 C   rF   )z¨
        A file with an mtime fewer than six months (approximately) in the past
        has a listing including a high-resolution timestamp excluding the year.
        é€›z r   rH   ú;!---------    0 0        0               0 Aug 28 17:33 foorI   ú;!---------    0 0        0               0 Aug 29 09:33 fooNrJ   rM   r)   r)   r*   Útest_newFile¡   rP   zListingTests.test_newFileú
es_AR.UTF8Tz'The es_AR.UTF8 locale is not installed.c                 C   s|   | j d }t dddddddd|df
¡}t ¡ }t tjd¡ |  tjtj|¡ |  |  	d|¡d¡ |  |  	d|¡d¡ dS )	zC
        The month name in the date is locale independent.
        rU   r   rY   rH   rV   rI   rW   N)
r3   r8   rK   ÚlocaleÚ	getlocaleÚ	setlocaleÚLC_ALLr=   rL   rE   )r'   rN   rD   ÚcurrentLocaler)   r)   r*   Útest_localeIndependentÀ   s   

þ
þz#ListingTests.test_localeIndependentc                 C   rQ   )	rR   rU   i F r   rH   z;!---------    0 0        0               0 Sep 01 17:33 foorI   z;!---------    0 0        0               0 Sep 02 09:33 fooNrJ   rM   r)   r)   r*   Útest_newSingleDigitDayOfMonth×   rT   z*ListingTests.test_newSingleDigitDayOfMonth)r,   r-   r.   r/   Úgetattrr6   Úskipr@   rE   rO   rS   rX   rZ   r[   r^   r\   r]   ÚErrorÚ
localeSkipr   r_   r`   r)   r)   r)   r*   r0   J   s.    ÿ€
r0   c                       s    e Zd ZdZ‡ fdd„Z‡  ZS )ÚInMemorySSHChannelzp
    Minimal implementation of a L{SSHChannel} like class which only reads and
    writes data from memory.
    c                    s   || _ d| _tƒ  ¡  dS )zt
        @param conn: The SSH connection associated with this channel.
        @type conn: L{SSHConnection}
        r   N)ÚconnÚlocalClosedÚsuperÚ__init__)r'   rf   ©Ú	__class__r)   r*   ri   ò   s   zInMemorySSHChannel.__init__)r,   r-   r.   r/   ri   Ú__classcell__r)   r)   rj   r*   re   ì   s    re   c                   @   ó(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚFilesystemAccessExpectationszC
    A test helper used to support expected filesystem access.
    c                 C   s
   i | _ d S r2   ©Ú_cacher4   r)   r)   r*   ri     ó   
z%FilesystemAccessExpectations.__init__c                 C   s   || j ||f< dS )zü

        @param path: Path at which the stream is requested.
        @type path: L{str}

        @param path: Flags with which the stream is requested.
        @type path: L{str}

        @param stream: A stream.
        @type stream: C{File}
        Nro   )r'   ÚpathÚflagsÚstreamr)   r)   r*   Úput  s   z FilesystemAccessExpectations.putc                 C   s   | j  ||f¡S )a  
        Remove a stream from the memory.

        @param path: Path at which the stream is requested.
        @type path: L{str}

        @param path: Flags with which the stream is requested.
        @type path: L{str}

        @return: A stream.
        @rtype: C{File}
        )rp   Úpop)r'   rr   rs   r)   r)   r*   rv     s   z FilesystemAccessExpectations.popN)r,   r-   r.   r/   ri   ru   rv   r)   r)   r)   r*   rn   ü   s
    rn   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚInMemorySFTPClienta'  
    A L{filetransfer.FileTransferClient} which does filesystem operations in
    memory, without touching the local disc or the network interface.

    @ivar _availableFiles: File like objects which are available to the SFTP
        client.
    @type _availableFiles: L{FilesystemRegister}
    c                 C   s    t | ƒ| _dddœ| _|| _d S )Né   é
   )ÚrequestsÚ
buffersize)re   Ú	transportÚoptionsÚ_availableFiles)r'   ÚavailableFilesr)   r)   r*   ri   ,  s
   
þ
zInMemorySFTPClient.__init__c                 C   s   | j  ||¡S )z}
        @see: L{filetransfer.FileTransferClient.openFile}.

        Retrieve and remove cached file based on flags.
        )r~   rv   )r'   Úfilenamers   Úattrsr)   r)   r*   ÚopenFile4  s   zInMemorySFTPClient.openFileN)r,   r-   r.   r/   ri   r‚   r)   r)   r)   r*   rw   "  s    	rw   c                   @   sH   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )ÚInMemoryRemoteFilez;
    An L{ISFTPFile} which handles all data in memory.
    c                 C   s   || _ t | ¡ dS )zL
        @param name: Name of this file.
        @type name: L{str}
        N)Únamer   ri   )r'   r„   r)   r)   r*   ri   C  s   zInMemoryRemoteFile.__init__c                 C   s   |   |¡ |  |¡ t | ¡S )z/
        @see: L{ISFTPFile.writeChunk}
        )ÚseekÚwriter
   Úsucceed)r'   ÚstartÚdatar)   r)   r*   Ú
writeChunkK  s   


zInMemoryRemoteFile.writeChunkc                 C   s
   d| _ dS )zo
        @see: L{ISFTPFile.writeChunk}

        Keeps data after file was closed to help with testing.
        TN)Ú_closedr4   r)   r)   r*   ÚcloseS  ó   
zInMemoryRemoteFile.closec                 C   ó   d S r2   r)   r4   r)   r)   r*   ÚgetAttrs[  ó   zInMemoryRemoteFile.getAttrsc                 C   rŽ   r2   r)   )r'   ÚoffsetÚlengthr)   r)   r*   Ú	readChunk_  r�   zInMemoryRemoteFile.readChunkc                 C   rŽ   r2   r)   )r'   r�   r)   r)   r*   ÚsetAttrsc  r�   zInMemoryRemoteFile.setAttrsc                 C   s
   t  | ¡S )zb
        Get current data of file.

        Allow reading data event when file is closed.
        )r   Úgetvaluer4   r)   r)   r*   r•   g  r�   zInMemoryRemoteFile.getvalueN)r,   r-   r.   r/   ri   rŠ   rŒ   r�   r“   r”   r•   r)   r)   r)   r*   rƒ   =  s    rƒ   c                   @   s¤   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd)dd„Zd*dd „Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ ZdS )+ÚStdioClientTestsz(
    Tests for L{cftp.StdioClient}.
    c                 C   sT   t ƒ | _t| jƒ}t |¡| _d| j_tƒ  | _| j_	|  
dd¡ | jjj| j_dS )zm
        Create a L{cftp.StdioClient} hooked up to dummy transport and a fake
        user database.
        ú/iô  é   N)rn   ÚfakeFilesystemrw   r   ÚStdioClientÚclientÚcurrentDirectoryr   ÚdatabaseÚ_pwdÚsetKnownConsoleSizer|   )r'   Ú
sftpClientr)   r)   r*   r@   v  s   
zStdioClientTests.setUpc              	   C   s@   | j  t ¡ dt ¡ dddtj¡ | j 	d¡}| 
| jd¡ |S )zs
        The I{exec} command runs its arguments locally in a child process
        using the user's shell.
        ÚsecretéÒ  rA   Úbarzexec print(1 + 2)s   3
)r�   ÚaddUserÚgetpassÚgetuserr8   ÚgetuidÚsysÚ
executabler›   Ú_dispatchCommandÚaddCallbackrL   ©r'   Údr)   r)   r*   Ú	test_exec‰  s   ÿzStdioClientTests.test_execc              	   C   ó>   | j  t ¡ dt ¡ dddd¡ | j d¡}| | j	d¡ |S )zr
        If the local user has no shell, the I{exec} command runs its arguments
        using I{/bin/sh}.
        r¡   r¢   rA   r£   Ú zexec echo helloó   hello
©
r�   r¤   r¥   r¦   r8   r§   r›   rª   r«   rL   r¬   r)   r)   r*   Útest_execWithoutShell–  s   ÿz&StdioClientTests.test_execWithoutShellc              	   C   r¯   )zO
        The I{exec} command is run for lines which start with C{"!"}.
        r¡   r¢   rA   r£   z/bin/shz!echo hellor±   r²   r¬   r)   r)   r*   Ú	test_bang£  s   ÿzStdioClientTests.test_bangc                    s2   ddl ‰G ‡ ‡‡fdd„dƒ}|  td|ƒ ¡ dS )a  
        For the duration of this test, patch C{cftp}'s C{fcntl} module to return
        a fixed width and height.

        @param width: the width in characters
        @type width: L{int}
        @param height: the height in characters
        @type height: L{int}
        r   Nc                       s   e Zd Z‡ ‡‡fdd„ZdS )z7StdioClientTests.setKnownConsoleSize.<locals>.FakeFcntlc                    s&   |ˆj kr
|  d¡ t dˆ ˆdd¡S )Nz#Only window-size queries supported.Ú4Hr   )Ú
TIOCGWINSZÚfailÚstructÚpack)r'   ÚfdÚoptÚmutate©ÚheightÚttyÚwidthr)   r*   Úioctl½  s   

z=StdioClientTests.setKnownConsoleSize.<locals>.FakeFcntl.ioctlN)r,   r-   r.   rÁ   r)   r½   r)   r*   Ú	FakeFcntl¼  s    rÂ   Úfcntl)r¿   r<   r   )r'   rÀ   r¾   rÂ   r)   r½   r*   rŸ   ¯  s   z$StdioClientTests.setKnownConsoleSizec                 C   s‚   |   dd¡ tƒ  }| j_tdƒ}d|_t |¡}d|_| 	¡ }| 
d¡ | jd7  _| j ||¡ d}|  | jj ¡ |¡ d	S )
a(  
        L{StdioClient._printProgressBar} prints a progress description,
        including percent done, amount transferred, transfer rate, and time
        remaining, all based the given start time, the given L{FileWrapper}'s
        progress information and the reactor's current time.
        ry   é"   ó   xó   samplei (  g       @i   s#   b'sample' 40% 4.0kB 2.0kBps 00:03 N)rŸ   r   r›   r   r   r„   r   ÚFileWrapperÚsizeÚsecondsÚadvanceÚtotalÚ_printProgressBarrL   r|   Úvalue©r'   ÚclockÚwrappedÚwrapperÚ	startTimeÚresultr)   r)   r*   Útest_printProgressBarReportingÄ  s   	

z/StdioClientTests.test_printProgressBarReportingc                 C   sd   |   dd¡ tƒ  }| j_tdƒ}d|_t |¡}| ¡ }| j 	||¡ d}|  
| jj ¡ |¡ dS )z½
        L{StdioClient._printProgressBar} prints a progress description that
        indicates 0 bytes transferred if no bytes have been transferred and no
        time has passed.
        ry   rÄ   rÅ   rÆ   s!   b'sample'  0% 0.0B 0.0Bps 00:00 N)rŸ   r   r›   r   r   r„   r   rÇ   rÉ   rÌ   rL   r|   rÍ   rÎ   r)   r)   r*   Útest_printProgressBarNoProgressÜ  s   
z0StdioClientTests.test_printProgressBarNoProgressc                 C   sL   |   dd¡ tƒ }d|_t |¡}| j |d¡ d}|  || jj 	¡ ¡ dS )z5
        Print the progress for empty files.
        ry   rÄ   s
   empty-filer   s%   b'empty-file'100% 0.0B 0.0Bps 00:00 N)
rŸ   r   r„   r   rÇ   r›   rÌ   rL   r|   rÍ   )r'   rÐ   rÑ   rÓ   r)   r)   r*   Útest_printProgressBarEmptyFileî  s   
z/StdioClientTests.test_printProgressBarEmptyFilec                 C   ó   | j  d¡}|  d|¡ dS )zK
        Returns empty value for both filename and remaining data.
        z  )r°   r°   N©r›   Ú_getFilenamerL   ©r'   rÓ   r)   r)   r*   Útest_getFilenameEmptyü  s   z&StdioClientTests.test_getFilenameEmptyc                 C   r×   )zd
        Returns empty value for remaining data when line contains
        only a filename.
        ú
only-local)rÜ   r°   NrØ   rÚ   r)   r)   r*   Útest_getFilenameOnlyLocal  ó   z*StdioClientTests.test_getFilenameOnlyLocalc                 C   r×   )ze
        Returns filename and remaining data striped of leading and trailing
        spaces.
        z local  remote file  )Úlocalzremote fileNrØ   rÚ   r)   r)   r*   Útest_getFilenameNotQuoted  rÞ   z*StdioClientTests.test_getFilenameNotQuotedc                 C   r×   )z‰
        Returns filename and remaining data not striped of leading and trailing
        spaces when quoted paths are requested.
        z" " local file "  " remote  file " )z local file z" remote  file "NrØ   rÚ   r)   r)   r*   Útest_getFilenameQuoted  rÞ   z'StdioClientTests.test_getFilenameQuotedNó    c                 C   sJ   |du r|   ¡ }t|dƒ�}| |¡ W d  ƒ |S 1 sw   Y  |S )ab  
        Create a local file and return its path.

        When `path` is L{None}, it will create a new temporary file.

        @param path: Optional path for the new file.
        @type path: L{str}

        @param content: Content to be written in the new file.
        @type content: L{bytes}

        @return: Path to the newly create file.
        NÚwb)ÚmktempÚopenr†   )r'   rr   ÚcontentÚfiler)   r)   r*   ÚmakeFile  s   
ÿþzStdioClientTests.makeFileFc                 C   sh  | j j ¡ }| d¡}| d¡}g }g }|D ]\}}}g }	|D ]}
|	 |› d|
› �¡ q|	 d|› d|› �¡ | |	¡ | d¡ d¡ d¡}|dd	… }|d	  d
¡ d
¡}| |¡ g }|dd	… D ]$}
|
 ¡  	dd¡d }
|
 ¡  dd¡}
| |
d › d|
d  ¡ › �¡ qd| |d	 ¡ | |¡ q|r£|  
t|ƒt|ƒ¡ n|  
||¡ |  
dt|ƒd¡ dS )a  
        Check output of cftp client for a put request.


        @param transfers: List with tuple of (local, remote, progress).
        @param randomOrder: When set to C{True}, it will ignore the order
            in which put reposes are received

        úutf-8z
ú zTransferred z to r   úNéÿÿÿÿÚ
é   rx   z5There are still put responses which were not checked.)r›   r|   rÍ   ÚdecodeÚsplitÚappendrv   ÚstripÚextendÚrsplitrL   ÚsortedÚlen)r'   Ú	transfersÚrandomOrderÚoutputÚexpectedOutputÚactualOutputrß   ÚremoteÚexpectedÚexpectedTransferÚlineÚprogressPartsÚactualÚlastÚactualTransferr)   r)   r*   ÚcheckPutMessage3  s<   




"ýz StdioClientTests.checkPutMessagec                 C   s°   d}| j |d�}tjtjB tjB }tj dtj |¡¡}t	|ƒ}| j
 ||t |¡¡ d| jjjd< | j |¡}|  |¡ |  || ¡ ¡ |  |j¡ |  ||g d¢fg¡ dS )z�
        A name based on local path is used when remote path is not
        provided.

        The progress is updated while chunks are transferred.
        s   Test
Content)ræ   r—   ry   r{   )z	76% 10.0Bú
100% 13.0Br  N)rè   r   Ú	FXF_WRITEÚ	FXF_CREATÚ	FXF_TRUNCr8   rr   ÚjoinÚbasenamerƒ   r™   ru   r
   r‡   r›   r}   Úcmd_PUTÚsuccessResultOfrL   r•   r%   r‹   r  )r'   ræ   Ú	localPathrs   Ú
remoteNameÚ
remoteFileÚdeferredr)   r)   r*   Útest_cmd_PUTSingleNoRemotePathp  s   
ÿz/StdioClientTests.test_cmd_PUTSingleNoRemotePathc                 C   s’   |   ¡ }tjtjB tjB }d}t|ƒ}| j ||t 	|¡¡ | j
 |› d|› d�¡}|  |¡ |  ||dgfg¡ |  |j¡ |  d| ¡ ¡ dS )z€
        Remote path is extracted from first filename after local file.

        Any other data in the line is ignored.
        z/remote-pathrê   z ignoredú	100% 0.0Brâ   N)rè   r   r  r  r  rƒ   r™   ru   r
   r‡   r›   r  r  r  r%   r‹   rL   r•   )r'   r  rs   r  r  r  r)   r)   r*   Útest_cmd_PUTSingleRemotePathˆ  s   
z-StdioClientTests.test_cmd_PUTSingleRemotePathc                 C   s  |   ¡ }tj |¡}d}tj |¡}| j tj ||¡d�}tjtjB tj	B }d|› �}d|› �}t
|ƒ}	t
|ƒ}
| j ||t |	¡¡ | j ||t |
¡¡ | j tj |d¡¡}|  |¡ |  |	j¡ |  d|	 ¡ ¡ |  |
j¡ |  d|
 ¡ ¡ | j||dgf||dgfgdd� d	S )
z„
        When a gobbing expression is used local files are transferred with
        remote file names based on local names.
        úsecond-name©rr   r—   Ú*râ   r  T©rø   N)rè   r8   rr   r
  Údirnamer	  r   r  r  r  rƒ   r™   ru   r
   r‡   r›   r  r  r%   r‹   rL   r•   r  )r'   ÚfirstÚ	firstNameÚ
secondNameÚparentÚsecondrs   ÚfirstRemotePathÚsecondRemotePathÚfirstRemoteFileÚsecondRemoteFiler  r)   r)   r*   Ú test_cmd_PUTMultipleNoRemotePath›  s4   

ÿ


þ
ûz1StdioClientTests.test_cmd_PUTMultipleNoRemotePathc                 C   s   |   ¡ }tj |¡}d}tj |¡}| j tj ||¡d�}tjtjB tj	B }t
|ƒ}t
|ƒ}d|› �}	d|› �}
| j |	|t |¡¡ | j |
|t |¡¡ | j d tj |d¡¡¡}|  |¡ |  |j¡ |  d| ¡ ¡ |  |j¡ |  d| ¡ ¡ | j||dgf||dgfgdd	� d
S )zõ
        When a gobbing expression is used local files are transferred with
        remote file names based on local names.
        when a remote folder is requested remote paths are composed from
        remote path and local filename.
        r  r  z/remote/z	{} remoter  râ   r  Tr  N)rè   r8   rr   r
  r  r	  r   r  r  r  rƒ   r™   ru   r
   r‡   r›   r  Úformatr  r%   r‹   rL   r•   r  )r'   r  r  r  r  r  rs   r   r!  r  r  r  r)   r)   r*   Ú"test_cmd_PUTMultipleWithRemotePath¾  s4   

ÿ


þ
ûz3StdioClientTests.test_cmd_PUTMultipleWithRemotePath)Nrâ   )F)r,   r-   r.   r/   r@   r®   r³   r´   rŸ   rÔ   rÕ   rÖ   rÛ   rÝ   rà   rá   rè   r  r  r  r"  r$  r)   r)   r)   r*   r–   p  s(    		
	
=#r–   c                   @   s   e Zd Zdd„ Zdd„ ZdS )ÚFileTransferTestRealmc                 C   s
   || _ d S r2   )ÚtestDir)r'   r&  r)   r)   r*   ri   å  rq   zFileTransferTestRealm.__init__c                 G   s   t | jƒ}|d |dd„ fS )Nr   c                   S   rŽ   r2   r)   r)   r)   r)   r*   Ú<lambda>ê  s    z5FileTransferTestRealm.requestAvatar.<locals>.<lambda>)r   r&  )r'   ÚavatarIDÚmindr   Úar)   r)   r*   ÚrequestAvatarè  s   
z#FileTransferTestRealm.requestAvatarN)r,   r-   r.   ri   r+  r)   r)   r)   r*   r%  ä  s    r%  c                   @   s`   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚSFTPTestProcessz³
    Protocol for testing cftp. Provides an interface between Python (where all
    the tests are) and the cftp client process (which does the work that is
    being tested).
    c                 C   s$   |   ¡  || _d| _d| _d| _dS )zr
        @param onOutReceived: A L{Deferred} to be fired as soon as data is
        received from stdout.
        NF)ÚclearBufferÚonOutReceivedÚonProcessEndÚ_expectingCommandÚ_processEnded)r'   r.  r)   r)   r*   ri   ô  s
   
zSFTPTestProcess.__init__c                 C   s   d| _ g | _d| _dS )zR
        Clear any buffered data received from stdout. Should be private.
        râ   N)ÚbufferÚ_linesReceivedÚ_lineBufferr4   r)   r)   r*   r-  ÿ  s   
zSFTPTestProcess.clearBufferc                 C   sr   t  d| ¡ | j|  d¡}| d¡| _| j |¡ | jdur,| jd}| _| |¡ |  j	|7  _	|  
¡  dS )zO
        Called by Twisted when the cftp client prints data to stdout.
        zgot %ró   
rì   N)r   Úmsgr4  rð   rv   r3  ró   r.  Úcallbackr2  Ú_checkForCommand)r'   r‰   Úlinesr­   r)   r)   r*   ÚoutReceived  s   

zSFTPTestProcess.outReceivedc                 C   sf   d}| j r/| j|kr1d | j¡}| |¡r|t|ƒd … }|  ¡  | j d }| _ | |¡ d S d S d S )Ns   cftp> r5  )r0  r4  r	  r3  Ú
startswithrö   r-  r7  )r'   ÚpromptÚbufr­   r)   r)   r*   r8    s   
úz SFTPTestProcess._checkForCommandc                 C   s   t  d| ¡ dS )zO
        Called by Twisted when the cftp client prints data to stderr.
        zerr: %sN)r   r6  )r'   r‰   r)   r)   r*   ÚerrReceived"  s   zSFTPTestProcess.errReceivedc                 C   s   | j S )zQ
        Return the contents of the buffer of data received from stdout.
        )r2  r4   r)   r)   r*   Ú	getBuffer(  s   zSFTPTestProcess.getBufferc                 C   s<   t  ¡ | _|  ¡  t|tƒr| d¡}| j |d ¡ | jS )a¬  
        Issue the given command via the cftp client. Return a C{Deferred} that
        fires when the server returns a result. Note that the C{Deferred} will
        callback even if the server returns some kind of error.

        @param command: A string containing an sftp command.

        @return: A C{Deferred} that fires when the sftp server returns a
        result. The payload is the server's response string.
        ré   r5  )	r
   ÚDeferredr0  r-  Ú
isinstanceÚstrÚencoder|   r†   ©r'   Úcommandr)   r)   r*   Ú
runCommand.  s   


zSFTPTestProcess.runCommandc                    s(   t  d¡‰‡ ‡fdd„|D ƒ}t  |¡S )ax  
        Run each command in sequence and return a Deferred that fires when all
        commands are completed.

        @param commands: A list of strings containing sftp commands.

        @return: A C{Deferred} that fires when all commands are completed. The
        payload is a list of response strings from the server, in the same
        order as the commands.
        rx   c                    s   g | ]	}ˆ  ˆ j|¡‘qS r)   )ÚrunrF  )Ú.0rE  ©r'   Úsemr)   r*   Ú
<listcomp>L  s    z-SFTPTestProcess.runScript.<locals>.<listcomp>)r
   ÚDeferredSemaphoreÚgatherResults)r'   ÚcommandsÚdlr)   rI  r*   Ú	runScript@  s   

zSFTPTestProcess.runScriptc                 C   s,   | j rt d¡S t ¡ | _| j d¡ | jS )zø
        Kill the process if it is still running.

        If the process is still running, sends a KILL signal to the transport
        and returns a C{Deferred} which fires when L{processEnded} is called.

        @return: a C{Deferred}.
        NÚKILL)r1  r
   r‡   r@  r/  r|   ÚsignalProcessr4   r)   r)   r*   ÚkillProcessO  s
   	

zSFTPTestProcess.killProcessc                 C   s,   d| _ | jr| jd}| _| d¡ dS dS )zF
        Called by Twisted when the cftp client process ends.
        TN)r1  r/  r7  )r'   Úreasonr­   r)   r)   r*   ÚprocessEnded^  s
   þzSFTPTestProcess.processEndedN)r,   r-   r.   r/   ri   r-  r:  r8  r>  r?  rF  rP  rS  rU  r)   r)   r)   r*   r,  í  s    
r,  c                   @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚCFTPClientTestBasec                 C   s¼   t ddƒ�}| tj¡ W d   ƒ n1 sw   Y  t ddƒ�}| tj¡ W d   ƒ n1 s1w   Y  t dd¡ t ddƒ�}| dtj ¡ W d   ƒ n1 sTw   Y  t 	| ¡S )Núdsa_test.pubrã   Údsa_testi€�  Úkh_tests
   127.0.0.1 )
rå   r†   r   ÚpublicDSA_opensshÚprivateDSA_opensshr8   ÚchmodÚpublicRSA_opensshr   r@   ©r'   Úfr)   r)   r*   r@   i  s   ÿÿÿ
zCFTPClientTestBase.setUpc                 C   sF   t | jƒ}t |¡}| t ¡ ¡ t ¡ }||_tj	d|dd�| _
d S )Nr   z	127.0.0.1)Ú	interface)r%  r&  r	   ÚPortalÚregisterCheckerr   ÚconchTestPublicKeyCheckerÚConchTestServerFactoryr   Ú	listenTCPÚserver)r'   ÚrealmÚpÚfacr)   r)   r*   ÚstartServers  s   

zCFTPClientTestBase.startServerc                 C   sH   t | jjdƒs|  d ¡S d| jjj_t | jjjjj	¡}| 
| j¡ |S )NÚprotorx   )Úhasattrrf  ÚfactoryÚ_cbStopServerrk  ÚexpectedLoseConnectionr
   ÚmaybeDeferredr|   ÚloseConnectionr«   r¬   r)   r)   r*   Ú
stopServer{  s   
zCFTPClientTestBase.stopServerc                 C   s   t  | jj¡S r2   )r
   rp  rf  ÚstopListening©r'   Úignoredr)   r)   r*   rn  ƒ  s   z CFTPClientTestBase._cbStopServerc              	   C   s4   dD ]}zt  |¡ W q ty   Y qw t | ¡S )N)rW  rX  rY  )r8   ÚremoveÚBaseExceptionr   ÚtearDownr^  r)   r)   r*   rx  †  s   ÿ
zCFTPClientTestBase.tearDownN)r,   r-   r.   r@   rj  rr  rn  rx  r)   r)   r)   r*   rV  h  s    
rV  c                   @   sº   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zd-dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ ZdS ).ÚOurServerCmdLineClientTestszí
    Functional tests which launch a SFTP server over TCP on localhost and check
    cftp command line interface using a spawned process.

    Due to the spawned process you can not add a debugger breakpoint for the
    client code.
    c           
         s0  t  ˆ ¡ ˆ  ¡  d}ˆ j ¡ j}tj||  ¡ dd�}t	 
dtj› d|› �¡ t ¡ }t|ƒˆ _| ‡ fdd„¡ tj ¡ }tj tj¡|d< g }i }|D ]}t|tƒrZ| d	¡}| |¡ qN|D ]}|| }	t|tƒrr| d	¡}t|	tƒr||	 d	¡}	|	||< qbt	 
|¡ t	 
|¡ tjˆ jtj||d
� |S )Nz‚-p %i -l testuser --known-hosts kh_test --user-authentications publickey --host-key-algorithms ssh-rsa -i dsa_test -a -v 127.0.0.1r   ©Úmodúrunning rê   c                    ó
   ˆ j  ¡ S r2   )ÚprocessProtocolr-  ©Ú_r4   r)   r*   r'  ¬  ó   
 z3OurServerCmdLineClientTests.setUp.<locals>.<lambda>Ú
PYTHONPATHré   ©Úenv)rV  r@   rj  rf  ÚgetHostÚportr   Ú	_makeArgsrð   r   r6  r¨   r©   r
   r@  r,  r~  r«   r8   r9   ÚcopyÚpathsepr	  rr   rA  rB  rC  rñ   r   ÚspawnProcess)
r'   Úcmdsr†  r­   r„  ÚencodedCmdsÚ
encodedEnvÚcmdÚvarÚvalr)   r4   r*   r@   ™  s>   
ÿ











ÿz!OurServerCmdLineClientTests.setUpc                    s   ˆ   ¡ }| ‡ fdd„¡ |S )Nc                    r}  r2   )r~  rS  r  r4   r)   r*   r'  Å  r�  z6OurServerCmdLineClientTests.tearDown.<locals>.<lambda>)rr  r«   r¬   r)   r4   r*   rx  Ã  s   z$OurServerCmdLineClientTests.tearDownc                 C   s,   z
| j j d¡ W d S  tjy   Y d S w )NrQ  )r~  r|   rR  r   ÚProcessExitedAlreadyrt  r)   r)   r*   Ú_killProcessÈ  s
   ÿz(OurServerCmdLineClientTests._killProcessc                 C   ó   | j  |¡S )z¼
        Run the given command with the cftp client. Return a C{Deferred} that
        fires when the command is complete. Payload is the server's output for
        that command.
        )r~  rF  rD  r)   r)   r*   rF  Î  ó   z&OurServerCmdLineClientTests.runCommandc                 G   r“  )zÓ
        Run the given commands with the cftp client. Returns a C{Deferred}
        that fires when the commands are all complete. The C{Deferred}'s
        payload is a list of output for each command.
        )r~  rP  )r'   rN  r)   r)   r*   rP  Ö  r”  z%OurServerCmdLineClientTests.runScriptc                 C   sL   | j }|  ddddd¡}dd„ }| |¡ | | j|jt ¡ d|jg¡ |S )zý
        Test that 'pwd' reports the current remote directory, that 'lpwd'
        reports the current local directory, and that changing to a
        subdirectory then changing to its parent leaves you in the original
        remote directory.
        ÚpwdÚlpwdzcd testDirectoryúcd ..c                 S   sD   g }| D ]}t |tƒr| d¡}| |¡ q|dd… |dd…  S )zH
            Callback function for handling command output.
            ré   Né   é   )rA  Úbytesrï   rñ   )rù   r‹  rŽ  r)   r)   r*   Ú	cmdOutputé  s   

z8OurServerCmdLineClientTests.testCdPwd.<locals>.cmdOutputr°   )r&  rP  r«   rL   rr   r8   Úgetcwd)r'   ÚhomeDirr­   r›  r)   r)   r*   Ú	testCdPwdÞ  s   
z%OurServerCmdLineClientTests.testCdPwdc                    s&   ‡ fdd„}ˆ   dddd¡}| |¡S )zŒ
        Check that 'ls -l' output includes the access permissions and that
        this output changes appropriately with 'chmod'.
        c                    sZ   ˆ   ¡  ˆ  | d  d¡¡ ˆ  | d d¡ ˆ  | d  d¡| d ¡ ˆ  | d d¡ d S )Nr   s
   -rw-r--r--rx   râ   rî   s
   ----------r˜  )ÚflushLoggedErrorsr%   r;  rL   ©Úresultsr4   r)   r*   Ú_checkþ  s
   z7OurServerCmdLineClientTests.testChAttrs.<locals>._checkzls -l testfile1zchmod 0 testfile1zchmod 644 testfile1©rP  r«   ©r'   r¢  r­   r)   r4   r*   ÚtestChAttrsø  s   ü
z'OurServerCmdLineClientTests.testChAttrsc                    s@   ‡ fdd„}ˆ   ddˆ j ¡  ddd¡}| dd	„ ¡ | |¡S )
zŽ
        Check 'ls' works as expected. Checks for wildcards, hidden files,
        listing directories and listing empty directories.
        c                    sf   ˆ   | d g d¢¡ ˆ   | d g d¢¡ ˆ   | d ddg¡ ˆ   | d g d¢¡ ˆ   | d	 d
g¡ d S )Nr   ©s   testDirectoryó   testRemoveFileó   testRenameFiles	   testfile1rx   rî   r§  r¨  r˜  )s   .testHiddenFiler§  r¨  r™  râ   ©rL   r   r4   r)   r*   r¢    s   þþÿz4OurServerCmdLineClientTests.testList.<locals>._checkr   zls ../zls *Filezls -a *Filezls -l testDirectoryc                 S   s   dd„ | D ƒS )Nc                 S   s   g | ]}|  d ¡‘qS )r5  )rð   )rH  Úxr)   r)   r*   rK  *  ó    zJOurServerCmdLineClientTests.testList.<locals>.<lambda>.<locals>.<listcomp>r)   )Úxsr)   r)   r*   r'  *  s    z6OurServerCmdLineClientTests.testList.<locals>.<lambda>)rP  r&  r
  r«   r¤  r)   r4   r*   ÚtestList  s   û
z$OurServerCmdLineClientTests.testListc                 C   sD   |   d¡}t d¡ d¡ ¡ }t|tƒr| d¡}| | j	|¡ |S )zB
        Check that running the '?' command returns help.
        ú?Nr°   ré   )
rF  r   rš   Úcmd_HELPrò   rA  rB  rC  r«   rL   )r'   r­   ÚhelpTextr)   r)   r*   ÚtestHelp-  s   


z$OurServerCmdLineClientTests.testHelpNc                 C   s   |   | ¡ | ¡ |¡ dS )zg
        Assert that the files at C{name1} and C{name2} contain exactly the
        same data.
        N)rL   Ú
getContent)r'   Úname1Úname2r6  r)   r)   r*   ÚassertFilesEqual9  s   z,OurServerCmdLineClientTests.assertFilesEqualc                    sl   d  ˆjjˆjj¡‰ tˆ tƒrˆ  d¡‰ ‡ ‡fdd„}ˆ dˆjj› d�¡}| |¡ | ‡fdd„¡ |S )	z³
        Test that 'get' saves the remote file to the correct local location,
        that the output of 'get' is correct and that 'rm' actually removes
        the file.
        z)Transferred {}/testfile1 to {}/test file2ré   c                    s8   ˆ  |  ˆ ¡¡ ˆ ˆj d¡ˆj d¡d¡ ˆ d¡S )NÚ	testfile1ú
test file2z
get failedzrm "test file2")r%   Úendswithrµ  r&  ÚchildrF  ©rÓ   ©rú   r'   r)   r*   Ú	_checkGetN  s   

ý
z6OurServerCmdLineClientTests.testGet.<locals>._checkGetzget testfile1 "z/test file2"c                    ó   ˆ   ˆ j d¡ ¡ ¡S )Nr·  ©ÚassertFalser&  r¹  Úexistsr  r4   r)   r*   r'  Z  r«  z5OurServerCmdLineClientTests.testGet.<locals>.<lambda>)r#  r&  rr   rA  rB  rC  rF  r«   )r'   r¼  r­   r)   r»  r*   ÚtestGet@  s   þ

	

ÿz#OurServerCmdLineClientTests.testGetc                    s    ‡ fdd„}ˆ   d¡}| |¡S )zQ
        Test that 'get' works correctly when given wildcard parameters.
        c                    s8   ˆ   ˆ j d¡tdƒd¡ ˆ   ˆ j d¡tdƒd¡ d S )NÚtestRemoveFileútestRemoveFile get failedÚtestRenameFileútestRenameFile get failed)rµ  r&  r¹  r   )ru  r4   r)   r*   r¢  c  s   
ý
ýz;OurServerCmdLineClientTests.testWildcardGet.<locals>._checkz
get testR*)rF  r«   r¤  r)   r4   r*   ÚtestWildcardGet^  s   

z+OurServerCmdLineClientTests.testWildcardGetc                    sh   dˆj  ¡ j d ˆj  ¡ j d ‰ ‡ ‡fdd„}ˆ dˆj j› d�¡}| |¡ | ‡fdd	„¡ |S )
z—
        Check that 'put' uploads files correctly and that they can be
        successfully removed. Also check the output of the put command.
        s   Transferred s   /testfile1 to s   /test"file2c                    s6   ˆ  ˆj d¡ˆj d¡¡ ˆ |  ˆ ¡¡ ˆ d¡S )Nr¶  ú
test"file2zrm "test\"file2")rµ  r&  r¹  r%   r¸  rF  rº  r»  r)   r*   Ú	_checkPut€  s
   ÿ
z6OurServerCmdLineClientTests.testPut.<locals>._checkPutúput z/testfile1 "test\"file2"c                    r½  )NrÇ  r¾  r  r4   r)   r*   r'  Š  r«  z5OurServerCmdLineClientTests.testPut.<locals>.<lambda>)r&  ÚasBytesModerr   rF  r«   )r'   rÈ  r­   r)   r»  r*   ÚtestPutr  s"   
ÿþ
ýüÿ

ÿz#OurServerCmdLineClientTests.testPutc                    s¬   ˆ j  d¡jdd��}| d¡ W d  ƒ n1 sw   Y  ˆ j  d¡jdd��}| d¡ W d  ƒ n1 s9w   Y  ‡ fdd	„}ˆ  d
ˆ j j› d�¡}| |¡ |S )zb
        Check that 'put' uploads files correctly when overwriting a longer
        file.
        ÚshorterFileÚw©Úmodeó   aNÚ
longerFileó   bbc                    s    ˆ   ˆ j d¡ˆ j d¡¡ d S )NrÌ  rÑ  )rµ  r&  r¹  rº  r4   r)   r*   rÈ  ™  s   ÿzEOurServerCmdLineClientTests.test_putOverLongerFile.<locals>._checkPutrÉ  z/shorterFile longerFile)r&  r¹  rå   r†   rF  rr   r«   ©r'   r_  rÈ  r­   r)   r4   r*   Útest_putOverLongerFileŽ  s   ÿÿ
z2OurServerCmdLineClientTests.test_putOverLongerFilec                    sÀ   ˆ j  d¡‰ˆ ¡  ˆ d¡jdd��}| d¡ W d  ƒ n1 s#w   Y  ˆ j  d¡jdd��}| d¡ W d  ƒ n1 sBw   Y  ‡ ‡fdd	„}ˆ  d
ˆ j j› d�¡}| |¡ |S )z˜
        Check that 'put' uploads files correctly when overwriting a longer
        file and you use a wildcard to specify the files to upload.
        Údirrç   rÍ  rÎ  rÐ  NrÒ  c                    s   ˆ   ˆ d¡ˆ j d¡¡ d S )Nrç   )rµ  r¹  r&  rº  ©r'   ÚsomeDirr)   r*   rÈ  ¯  s   zMOurServerCmdLineClientTests.test_putMultipleOverLongerFile.<locals>._checkPutrÉ  z/dir/*)r&  r¹  ÚcreateDirectoryrå   r†   rF  rr   r«   rÓ  r)   rÖ  r*   Útest_putMultipleOverLongerFile¢  s   ÿÿ
z:OurServerCmdLineClientTests.test_putMultipleOverLongerFilec                    s>   ‡ fdd„}ˆ   ddˆ jj› d�dˆ j ¡  ¡}| |¡ |S )zÍ
        What happens if you issue a 'put' command and include a wildcard (i.e.
        '*') in parameter? Check that all files matching the wildcard are
        uploaded to the correct directory.
        c                    sh   ˆ   | d d¡ ˆ   | d d¡ ˆ  ˆ j d¡ˆ j ¡  d¡d¡ ˆ  ˆ j d¡ˆ j ¡  d¡d¡ d S )Nr   râ   rî   rÂ  rÃ  rÄ  rÅ  )rL   rµ  r&  r¹  r  r   r4   r)   r*   Úcheck½  s   
ý
ýz:OurServerCmdLineClientTests.testWildcardPut.<locals>.checkr—  rÉ  z/testR*zcd %s)rP  r&  rr   r
  r«   )r'   rÚ  r­   r)   r4   r*   ÚtestWildcardPut¶  s   ý
z+OurServerCmdLineClientTests.testWildcardPutc                    ó4   ‡ fdd„}ˆ   dd¡}| |¡ | ˆ jd¡ |S )z 
        Test that 'ln' creates a file which appears as a link in the output of
        'ls'. Check that removing the new file succeeds without output.
        c                    s8   ˆ   ¡  ˆ  | d d¡ ˆ  | d  d¡d¡ ˆ  d¡S )Nr   râ   rx   ó   lzlink failedzrm testLink)rŸ  rL   r%   r;  rF  r   r4   r)   r*   r¢  Ú  s   
z4OurServerCmdLineClientTests.testLink.<locals>._checkzln testLink testfile1zls -l testLinkrâ   ©rP  r«   rL   r¤  r)   r4   r*   ÚtestLinkÔ  s
   
z$OurServerCmdLineClientTests.testLinkc                    rÜ  )zV
        Test that we can create and remove directories with the cftp client.
        c                    s.   ˆ   | d d¡ ˆ  | d  d¡¡ ˆ  d¡S )Nr   râ   rx   ó   dzrmdir testMakeDirectory)rL   r%   r;  rF  r   r4   r)   r*   r¢  ê  s   
z?OurServerCmdLineClientTests.testRemoteDirectory.<locals>._checkúmkdir testMakeDirectoryzls -l testMakeDirector?râ   rÞ  r¤  r)   r4   r*   ÚtestRemoteDirectoryå  ó
   
z/OurServerCmdLineClientTests.testRemoteDirectoryc                    s&   ‡ fdd„}ˆ   dd¡}| |¡ |S )z—
        Test that a C{mkdir} on an existing directory fails with the
        appropriate error, and doesn't log an useless error server side.
        c                    s$   ˆ   | d d¡ ˆ   | d d¡ d S )Nr   râ   rx   s   remote error 11: mkdir failedr©  r   r4   r)   r*   r¢  ú  s   zHOurServerCmdLineClientTests.test_existingRemoteDirectory.<locals>._checkrá  r£  r¤  r)   r4   r*   Útest_existingRemoteDirectoryô  s   
z8OurServerCmdLineClientTests.test_existingRemoteDirectoryc                    sH   ˆ   dˆ jj› d�¡}| ˆ jd¡ | ‡ fdd„¡ | ˆ jd¡ |S )zÂ
        Test that we can create a directory locally and remove it with the
        cftp client. This test works because the 'remote' server is running
        out of a local directory.
        zlmkdir z/testLocalDirectoryrâ   c                    s
   ˆ   d¡S )Nzrmdir testLocalDirectory)rF  r  r4   r)   r*   r'  
  r�  z@OurServerCmdLineClientTests.testLocalDirectory.<locals>.<lambda>)rF  r&  rr   r«   rL   r¬   r)   r4   r*   ÚtestLocalDirectory  s
   z.OurServerCmdLineClientTests.testLocalDirectoryc                    rÜ  )z1
        Test that we can rename a file.
        c                    s*   ˆ   | d d¡ ˆ   | d d¡ ˆ  d¡S )Nr   râ   rx   s	   testfile2zrename testfile2 testfile1)rL   rF  r   r4   r)   r*   r¢    s   
z6OurServerCmdLineClientTests.testRename.<locals>._checkzrename testfile1 testfile2zls testfile?râ   rÞ  r¤  r)   r4   r*   Ú
testRename  rã  z&OurServerCmdLineClientTests.testRenamer2   )r,   r-   r.   r/   r@   rx  r’  rF  rP  rž  r¥  r­  r±  rµ  rÁ  rÆ  rË  rÔ  rÙ  rÛ  rß  râ  rä  rå  ræ  r)   r)   r)   r*   ry  �  s.    *
ry  c                   @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )ÚOurServerBatchFileTestszm
    Functional tests which launch a SFTP server over localhost and checks csftp
    in batch interface.
    c                 C   s   t  | ¡ |  ¡  d S r2   ©rV  r@   rj  r4   r)   r)   r*   r@   %  s   
zOurServerBatchFileTests.setUpc                 C   ó   t  | ¡ |  ¡ S r2   )rV  rx  rr  r4   r)   r)   r*   rx  )  ó   
z OurServerBatchFileTests.tearDownc                    sä   |   ¡ ‰ tˆ dƒ�}| |¡ W d   ƒ n1 sw   Y  | j ¡ j}d|ˆ f }tj| ¡ dd�dd … }t	 
dtj› d|› �¡ tj ¡ }tj tj¡|d< d| jj_ttj||d	�}‡ fd
d„}| dd„ ¡ | |¡ |S )NrÍ  zˆ-p %i -l testuser --known-hosts kh_test --user-authentications publickey --host-key-algorithms ssh-rsa -i dsa_test -a -v -b %s 127.0.0.1r   rz  rx   r|  rê   r‚  rƒ  c                    s   t  ˆ ¡ | S r2   )r8   rv  ©Úres©Úfnr)   r*   Ú_cleanupD  s   
z9OurServerBatchFileTests._getBatchOutput.<locals>._cleanupc                 S   s   | d S )Nr   r)   rë  r)   r)   r*   r'  H  s    z9OurServerBatchFileTests._getBatchOutput.<locals>.<lambda>)rä   rå   r†   rf  r…  r†  r   r‡  rð   r   r6  r¨   r©   r8   r9   rˆ  r‰  r	  rr   rm  ro  r   r«   ÚaddBoth)r'   r_  Úfpr†  r‹  r„  r­   rï  r)   rí  r*   Ú_getBatchOutput-  s$   ÿø	


z'OurServerBatchFileTests._getBatchOutputc                    ó(   d}‡ fdd„}ˆ   |¡}| |¡ |S )zš
        Test whether batch file function of cftp ('cftp -b batchfile').
        This works by treating the file as a list of commands to be run.
        zpwd
ls
exit
c                    sP   |   d¡} t dt| ƒ ¡ ˆ  ˆ j ¡ j| d ¡ ˆ  | dd… g d¢¡ d S )Nr5  zRES %srx   r˜  éþÿÿÿr¦  )	rð   r   r6  ÚreprÚassertInr&  rÊ  rr   rL   rë  r4   r)   r*   Ú_cbCheckResultW  s   

þz=OurServerBatchFileTests.testBatchFile.<locals>._cbCheckResult©rò  r«   ©r'   r‹  r÷  r­   r)   r4   r*   ÚtestBatchFileM  s
   
	
z%OurServerBatchFileTests.testBatchFilec                    ró  )zO
        Test that an error in the batch file stops running the batch.
        zchown 0 missingFile
pwd
exit
c                    ó   ˆ   ˆ j ¡ j| ¡ d S r2   )ÚassertNotInr&  rÊ  rr   rë  r4   r)   r*   r÷  m  ó   z9OurServerBatchFileTests.testError.<locals>._cbCheckResultrø  rù  r)   r4   r*   Ú	testErrord  s
   

z!OurServerBatchFileTests.testErrorc                    ró  )z_
        Test that a minus sign '-' at the front of a line ignores
        any errors.
        z-chown 0 missingFile
pwd
exit
c                    rû  r2   )rö  r&  rÊ  rr   rë  r4   r)   r*   r÷  ~  rý  z@OurServerBatchFileTests.testIgnoredError.<locals>._cbCheckResultrø  rù  r)   r4   r*   ÚtestIgnoredErrort  s
   

z(OurServerBatchFileTests.testIgnoredErrorN)
r,   r-   r.   r/   r@   rx  rò  rú  rþ  rÿ  r)   r)   r)   r*   rç    s     rç  Úsftpz%no sftp command-line client availablec                   @   rm   )	ÚOurServerSftpClientTestsz@
    Test the sftp server against sftp command line client.
    c                 C   ré  r2   rè  r4   r)   r)   r*   r@   �  rê  zOurServerSftpClientTests.setUpc                 C   s   |   ¡ S r2   )rr  r4   r)   r)   r*   rx  ‘  s   z!OurServerSftpClientTests.tearDownc                    s¸   ˆ  ¡ ‰ tˆ dƒ�}| d¡ W d  ƒ n1 sw   Y  ˆj ¡ j‰tj‰‡fdd„}ˆ td|¡ dˆjj	_
tdd	ƒ}‡ ‡fd
d„}‡fdd„}| |¡ | dd„ ¡ | |¡S )a  
        Test the return of extended attributes by the server: the sftp client
        should ignore them, but still be able to parse the response correctly.

        This test is mainly here to check that
        L{filetransfer.FILEXFER_ATTR_EXTENDED} has the correct value.
        rÍ  z	ls .
exitNc                    s   ˆ | |ƒ}d|d< |S )Nr£   Úext_foor)   )r'   Úsr�   )Ú
oldGetAttrr)   r*   Ú	_getAttrs£  s   
zCOurServerSftpClientTests.test_extendedAttributes.<locals>._getAttrsr  TÚssh)ú-oúPubkeyAcceptedKeyTypes=ssh-dssz-Vc                    s>   | dkrd}nd}|dddddddd	dd
ˆf dˆ df7 }|S )Nr   )r  r  r)   z-Fz	/dev/nullr  zIdentityFile=dsa_testzUserKnownHostsFile=kh_testzHostKeyAlgorithms=ssh-rsazPort=%iz-bztestuser@127.0.0.1r)   )ÚstatusÚargs)rî  r†  r)   r*   ÚhasPAKT±  s&   ózAOurServerSftpClientTests.test_extendedAttributes.<locals>.hasPAKTc                    s.   ˆ   | d d¡ dD ]
}ˆ  || d ¡ q
d S )Nrî   r   r¦  )rL   rö  )rÓ   Úir4   r)   r*   rÚ  Ê  s   úz?OurServerSftpClientTests.test_extendedAttributes.<locals>.checkc                 S   s
   t d| ƒS )Nr   )r   )r
  r)   r)   r*   r'  Õ  r�  zBOurServerSftpClientTests.test_extendedAttributes.<locals>.<lambda>)rä   rå   r†   rf  r…  r†  r!   r  r<   rm  ro  r   r«   )r'   r_  r  r­   r  rÚ  r)   )rî  r  r†  r'   r*   Útest_extendedAttributes”  s   ÿ




z0OurServerSftpClientTests.test_extendedAttributesN)r,   r-   r.   r/   r@   rx  r  r)   r)   r)   r*   r  †  s
    r  )Pr/   r¥   rZ   r>   r8   r¸   r¨   r6   Úior   Úunittestr   Úzope.interfacer   Útwisted.conchr   Útwisted.conch.interfacesr   Ú$twisted.conch.test.test_filetransferr   r   Útwisted.credr	   Útwisted.internetr
   r   r   r   r   Útwisted.internet.taskr   Útwisted.internet.utilsr   r   Útwisted.pythonr   Útwisted.python.fakepwdr   Útwisted.python.filepathr   Útwisted.python.procutilsr   Útwisted.python.reflectr   Útwisted.test.proto_helpersr   Útwisted.trial.unittestr   r   r   ÚunixÚtwisted.conch.scriptsr   Útwisted.conch.scripts.cftpr   Útwisted.conch.sshr   Útwisted.conch.testr   r   Útwisted.conch.test.test_conchr    r!   ÚImportErrorÚ	skipTestsÚIReactorProcessr"   r0   re   rn   rw   rƒ   r–   r%  ÚProcessProtocolr,  rV  ry  rç  r  r)   r)   r)   r*   Ú<module>   sˆ   ÿ #&2  u	{'   g