U
    
W[2                     @   s   d Z ddlmZ ddl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mZmZmZmZmZmZ ddlZddlmZ dd ZG dd dejj j!Z"G dd dejj j!Z#eeG dd de$Z%dS )z3
Tests for L{twisted.application.runner._pidfile}.
    wrapsN)getpidname)BytesIO)implementer)verifyObject)	IFilePath)platform   )_pidfile   )IPIDFilePIDFileNonePIDFileAlreadyRunningErrorInvalidPIDFileErrorStalePIDFileError
NoPIDFound)SkipTestc                    s   t   fdd}|S )aQ  
    Decorator for tests that are not expected to work on all platforms.

    Calling L{PIDFile.isRunning} currently raises L{NotImplementedError} on
    non-POSIX platforms.

    On an unsupported platform, we expect to see any test that calls
    L{PIDFile.isRunning} to raise either L{NotImplementedError}, L{SkipTest},
    or C{self.failureException}.
    (C{self.failureException} may occur in a test that checks for a specific
    exception but it gets NotImplementedError instead.)

    @param f: The test method to decorate.
    @type f: method

    @return: The wrapped callable.
    c                    s`   t  dk}|r  | f||S | jtt| jf | f||}t|tr\| t|	d d S )Nposixz isRunning is not implemented on )
r
   ZgetTypeassertRaisesNotImplementedErrorr   ZfailureException
isinstance
assertTruestr
startswith)selfargskwargsZ	supportedef N/usr/lib/python3/dist-packages/twisted/application/runner/test/test_pidfile.pywrapper0   s     
 
z$ifPlatformSupported.<locals>.wrapperr   )r"   r%   r#   r!   r$   ifPlatformSupported   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edd Zedd Zedd Zedd Zed d! Zed"d# Zd$d% Zd&d' Zed(d) Zed*d+ Zd,S )-PIDFileTestsz
    Tests for L{PIDFile}.
    c                 C   s   t t }tt| dS )z5
        L{PIDFile} conforms to L{IPIDFile}.
        N)r   DummyFilePathr   r   r   pidFiler#   r#   r$   test_interfaceI   s    
zPIDFileTests.test_interfacec                 C   s   |  tjddd dS )zR
        L{PIDFile._format} returns the expected format when given a PID.
        9  pids   1337
N)assertEqualr   _formatr   r#   r#   r$   test_formatWithPIDQ   s    zPIDFileTests.test_formatWithPIDc                 C   s,   d}t tt j|d}| ||  dS )zK
        L{PIDFile.read} returns the PID from the given file path.
        r,   r-   N)r   r(   r0   r/   readr   r.   r*   r#   r#   r$   test_readWithPIDX   s    zPIDFileTests.test_readWithPIDc                 C   s8   d}t td}| t|j}| t|d| dS )f
        L{PIDFile.read} raises L{InvalidPIDFileError} when given an empty file
        path.
            'non-integer PID value in PID file: {!r}Nr   r(   r   r   r3   r/   r   formatr   ZpidValuer*   r    r#   r#   r$   test_readEmptyPIDc   s    zPIDFileTests.test_readEmptyPIDc                 C   s8   d}t t|}| t|j}| t|d| dS )r6   s   $foo!r8   Nr9   r;   r#   r#   r$   test_readWithBogusPIDr   s    z"PIDFileTests.test_readWithBogusPIDc                 C   s,   t t }| t|j}| t|d dS )zc
        L{PIDFile.read} raises L{NoPIDFound} when given a non-existing file
        path.
        PID file does not existN)r   r(   r   r   r3   r/   r   r   r*   r    r#   r#   r$   test_readDoesntExist   s    
z!PIDFileTests.test_readDoesntExistc                 C   sD   ddd}|  td| tt }| t|j}| |jtj dS )z
        L{PIDFile.read} re-raises L{OSError} if the associated C{errno} is
        anything other than L{errno.ENOENT}.
        rc                 S   s   t tjdd S )Nz	I/O error)OSErrorerrnoEIO)moder#   r#   r$   oops   s    z>PIDFileTests.test_readOpenRaisesOSErrorNotENOENT.<locals>.oopsopenN)rA   )	patchr(   r   r   rB   r3   r/   rC   rD   )r   rF   r*   errorr#   r#   r$   #test_readOpenRaisesOSErrorNotENOENT   s
    

z0PIDFileTests.test_readOpenRaisesOSErrorNotENOENTc                 C   s,   d}t t }|| | | | dS )z9
        L{PIDFile._write} stores the given PID.
        i  N)r   r(   _writer/   r3   r4   r#   r#   r$   test_writePID   s    

zPIDFileTests.test_writePIDc                 C   s   t t }| t|jd dS )zS
        L{PIDFile._write} raises L{ValueError} when given an invalid PID.
        ZburpN)r   r(   r   
ValueErrorrK   r)   r#   r#   r$   test_writePIDInvalid   s    
z!PIDFileTests.test_writePIDInvalidc                 C   s(   t t }|  | | t  dS )zT
        L{PIDFile.writeRunningPID} stores the PID for the current process.
        N)r   r(   writeRunningPIDr/   r3   r   r)   r#   r#   r$   test_writeRunningPID   s    
z!PIDFileTests.test_writeRunningPIDc                 C   s8   t td}| |j  |  | |j  dS )z9
        L{PIDFile.remove} removes the PID file.
        r7   N)r   r(   r   filePathexistsremoveassertFalser)   r#   r#   r$   test_remove   s    zPIDFileTests.test_removec                 C   s<   t t }|d dd }| td| | |  dS )zR
        L{PIDFile.isRunning} returns true for a process that does exist.
        r,   c                 S   s   d S Nr#   r.   signalr#   r#   r$   kill   s    z2PIDFileTests.test_isRunningDoesExist.<locals>.killrY   Nr   r(   rK   rH   r   r   	isRunningr   r*   rY   r#   r#   r$   test_isRunningDoesExist   s
    

z$PIDFileTests.test_isRunningDoesExistc                 C   s$   t t }|  | |  dS )a@  
        L{PIDFile.isRunning} returns true for this process (which is running).

        @note: This differs from L{PIDFileTests.test_isRunningDoesExist} in
        that it actually invokes the C{kill} system call, which is useful for
        testing of our chosen method for probing the existence of a process.
        N)r   r(   rO   r   r[   r)   r#   r#   r$   test_isRunningThis   s    	
zPIDFileTests.test_isRunningThisc                 C   s<   t t }|d dd }| td| | t|j dS )z{
        L{PIDFile.isRunning} raises L{StalePIDFileError} for a process that
        does not exist (errno=ESRCH).
        r,   c                 S   s   t tjdd S NzNo such processrB   rC   ZESRCHrW   r#   r#   r$   rY      s    z5PIDFileTests.test_isRunningDoesNotExist.<locals>.killrY   N)r   r(   rK   rH   r   r   r   r[   r\   r#   r#   r$   test_isRunningDoesNotExist   s
    

z'PIDFileTests.test_isRunningDoesNotExistc                 C   s<   t t }|d dd }| td| | |  dS )zx
        L{PIDFile.isRunning} returns true for a process that we are not allowed
        to kill (errno=EPERM).
        r,   c                 S   s   t tjdd S )NzOperation not permitted)rB   rC   EPERMrW   r#   r#   r$   rY      s    z3PIDFileTests.test_isRunningNotAllowed.<locals>.killrY   NrZ   r\   r#   r#   r$   test_isRunningNotAllowed   s
    

z%PIDFileTests.test_isRunningNotAllowedc                 C   s6   t dkrtdtt }|d | |  dS )ac  
        L{PIDFile.isRunning} returns true for a process that we are not allowed
        to kill (errno=EPERM).

        @note: This differs from L{PIDFileTests.test_isRunningNotAllowed} in
        that it actually invokes the C{kill} system call, which is useful for
        testing of our chosen method for probing the existence of a process
        that we are not allowed to kill.

        @note: In this case, we try killing C{init}, which is process #1 on
        POSIX systems, so this test is not portable.  C{init} should always be
        running and should not be killable by non-root users.
        r   zThis test assumes POSIX   N)SYSTEM_NAMEr   r   r(   rK   r   r[   r)   r#   r#   r$   test_isRunningInit  s
    

zPIDFileTests.test_isRunningInitc                 C   s:   t t }|  dd }| td| | t|j dS )z
        L{PIDFile.isRunning} re-raises L{OSError} if the attached C{errno}
        value from L{os.kill} is not an expected one.
        c                 S   s   t tjdd S )NzFile exists)rB   rC   ZEEXISTrW   r#   r#   r$   rY   (  s    z5PIDFileTests.test_isRunningUnknownErrno.<locals>.killrY   N)r   r(   rO   rH   r   r   rB   r[   r\   r#   r#   r$   test_isRunningUnknownErrno  s
    
z'PIDFileTests.test_isRunningUnknownErrnoc                 C   s   t t }| |  dS )zS
        L{PIDFile.isRunning} returns false if the PID file doesn't exist.
        N)r   r(   rT   r[   r)   r#   r#   r$   test_isRunningNoPIDFile0  s    
z$PIDFileTests.test_isRunningNoPIDFilec              	   C   s`   t t }| |j  |( | |j  | | t  W 5 Q R X | |j  dS )z
        When used as a context manager, a L{PIDFile} will store the current pid
        on entry, then removes the PID file on exit.
        N)	r   r(   rT   rQ   rR   r   r/   r3   r   r)   r#   r#   r$   test_contextManager9  s    
z PIDFileTests.test_contextManagerc              	   C   sn   t t }|d dd }| td| | t|j}| t	|d | | |
 t  W 5 Q R X dS )z
        When used as a context manager, a L{PIDFile} will replace the
        underlying PIDFile rather than raising L{AlreadyRunningError} if the
        contained PID file exists but refers to a non-running PID.
        r,   c                 S   s   t tjdd S r_   r`   rW   r#   r#   r$   rY   R  s    z9PIDFileTests.test_contextManagerDoesntExist.<locals>.killrY   z'PID file refers to non-existing processN)r   r(   rK   rH   r   r   r   r[   r/   r   r3   r   )r   r*   rY   r    r#   r#   r$   test_contextManagerDoesntExistH  s    

z+PIDFileTests.test_contextManagerDoesntExistc                 C   sJ   t t }|d dd }| td| | |  | t|j	 dS )z
        When used as a context manager, a L{PIDFile} will raise
        L{AlreadyRunningError} if the there is already a running process with
        the contained PID.
        r,   c                 S   s   d S rV   r#   rW   r#   r#   r$   rY   h  s    z<PIDFileTests.test_contextManagerAlreadyRunning.<locals>.killrY   N)
r   r(   rK   rH   r   r   r[   r   r   	__enter__r\   r#   r#   r$   !test_contextManagerAlreadyRunning^  s    

z.PIDFileTests.test_contextManagerAlreadyRunningN)__name__
__module____qualname____doc__r+   r2   r5   r<   r=   r@   rJ   rL   rN   rP   rU   r&   r]   r^   ra   rc   rf   rg   rh   ri   rj   rl   r#   r#   r#   r$   r'   D   s<   	






	
r'   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 )NonePIDFileTestsz#
    Tests for L{NonePIDFile}.
    c                 C   s   t  }tt| dS )z9
        L{NonePIDFile} conforms to L{IPIDFile}.
        N)r   r   r   r)   r#   r#   r$   r+   x  s    zNonePIDFileTests.test_interfacec                 C   s(   t  }| t|j}| t|d dS )z;
        L{NonePIDFile.read} raises L{NoPIDFound}.
        r>   N)r   r   r   r3   r/   r   r?   r#   r#   r$   	test_read  s    zNonePIDFileTests.test_readc                 C   s*   t  }| t|jd}| |jtj dS )zZ
        L{NonePIDFile._write} raises L{OSError} with an errno of L{errno.EPERM}.
        r   N)r   r   rB   rK   r/   rC   rb   r   r*   rI   r#   r#   r$   
test_write  s    zNonePIDFileTests.test_writec                 C   s(   t  }| t|j}| |jtj dS )zk
        L{NonePIDFile.writeRunningPID} raises L{OSError} with an errno of
        L{errno.EPERM}.
        N)r   r   rB   rO   r/   rC   rb   rs   r#   r#   r$   rP     s    z%NonePIDFileTests.test_writeRunningPIDc                 C   s(   t  }| t|j}| |jtj dS )zZ
        L{NonePIDFile.remove} raises L{OSError} with an errno of L{errno.EPERM}.
        N)r   r   rB   rS   r/   rC   ENOENTrs   r#   r#   r$   rU     s    zNonePIDFileTests.test_removec                 C   s   t  }| | d dS )z<
        L{NonePIDFile.isRunning} returns L{False}.
        FN)r   r/   r[   r)   r#   r#   r$   test_isRunning  s    zNonePIDFileTests.test_isRunningc              	   C   s   t  }| W 5 Q R X dS )zo
        When used as a context manager, a L{NonePIDFile} doesn't raise, despite
        not existing.
        N)r   r)   r#   r#   r$   ri     s    z$NonePIDFileTests.test_contextManagerN)rm   rn   ro   rp   r+   rr   rt   rP   rU   rv   ri   r#   r#   r#   r$   rq   s  s   


	rq   c                   @   sD   e Zd ZdZdddZdddZdd	 Zd
d Zdd Zdd Z	dS )r(   z!
    In-memory L{IFilePath}.
    Nc                 C   s   |  | d S rV   
setContentr   Zcontentr#   r#   r$   __init__  s    zDummyFilePath.__init__rA   c                 C   s   | j sttjdt|  S )NzNo such file or directory)_existsrB   rC   ru   r   
getContent)r   rE   r#   r#   r$   rG     s    zDummyFilePath.openc                 C   s   |d k	| _ || _d S rV   )r{   _contentry   r#   r#   r$   rx     s    
zDummyFilePath.setContentc                 C   s   | j S rV   )r}   r1   r#   r#   r$   r|     s    zDummyFilePath.getContentc                 C   s   |  d  d S rV   rw   r1   r#   r#   r$   rS     s    zDummyFilePath.removec                 C   s   | j S rV   )r{   r1   r#   r#   r$   rR     s    zDummyFilePath.exists)N)rA   )
rm   rn   ro   rp   rz   rG   rx   r|   rS   rR   r#   r#   r#   r$   r(     s   

r(   )&rp   	functoolsr   rC   osr   r   re   ior   Zzope.interfacer   Zzope.interface.verifyr   Ztwisted.python.filepathr	   Ztwisted.python.runtimer
   Zrunnerr   r   r   r   r   r   r   r   Ztwisted.trial.unittestZtwistedr   r&   ZtrialZunittestZTestCaser'   rq   objectr(   r#   r#   r#   r$   <module>   s&   $&  1K