U
    
W[2[  ć                   @   s¶   d Z ddlZddlmZ ddlmZmZ ddlmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZ G d
d deZG dd deeZG dd dejZG dd dejZdS )z&
Tests for L{twisted.runner.procmon}.
é    N)Śunittest)ŚLoggingProtocolŚProcessMonitor)ŚProcessDoneŚProcessTerminatedŚProcessExitedAlready)ŚClock)ŚFailure)Ślog)ŚMemoryReactorc                   @   s6   e Zd ZdZdZdZdZdddZdd Zd	d
 Z	dS )ŚDummyProcessa   
    An incomplete and fake L{IProcessTransport} implementation for testing how
    L{ProcessMonitor} behaves when its monitored processes exit.

    @ivar _terminationDelay: the delay in seconds after which the DummyProcess
        will appear to exit when it receives a TERM signal
    é   Nr   c                 C   s@   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	d S ©N)
ŚprotoŚ_reactorZ_executableZ_argsŚ_environmentŚ_pathZ_uidZ_gidZ_usePTYZ	_childFDs)ŚselfŚreactorŚ
executableŚargsZenvironmentŚpathr   ŚuidŚgidŚusePTYŚchildFDs© r   śB/usr/lib/python3/dist-packages/twisted/runner/test/test_procmon.pyŚ__init__"   s    zDummyProcess.__init__c                 C   sL   | j dfdd}| jdkr t ||krH|| \}}| j || j|”| _dS )ań  
        A partial implementation of signalProcess which can only handle TERM and
        KILL signals.
         - When a TERM signal is given, the dummy process will appear to exit
           after L{DummyProcess._terminationDelay} seconds with exit code 0
         - When a KILL signal is given, the dummy process will appear to exit
           immediately with exit code 1.

        @param signalID: The signal name or number to be issued to the process.
        @type signalID: C{str}
        r   ©r   r   )ZTERMŚKILLN)Ś_terminationDelayŚpidr   r   Z	callLaterŚprocessEndedZ_signalHandler)r   ZsignalIDZparamsŚdelayŚstatusr   r   r   ŚsignalProcess2   s    ž
  ’zDummyProcess.signalProcessc                 C   s,   d| _ ttd}| j t|| |” dS )zC
        Deliver the process ended event to C{self.proto}.
        Nr   )r"   r   r   r   r#   r	   )r   r%   Z	statusMapr   r   r   r#   L   s
    žzDummyProcess.processEnded)NNr   N)
Ś__name__Ś
__module__Ś__qualname__Ś__doc__r"   r   r!   r   r&   r#   r   r   r   r   r      s          ’
r   c                   @   s0   e Zd ZdZdd Zdi dddddfddZdS )	ŚDummyProcessReactorz
    @ivar spawnedProcesses: a list that keeps track of the fake process
        instances built by C{spawnProcess}.
    @type spawnedProcesses: C{list}
    c                 C   s   t  | ” t | ” g | _d S r   )r   r   r   ŚspawnedProcesses©r   r   r   r   r   _   s    

zDummyProcessReactor.__init__r   Nr   c
                 C   s4   t | |||||||||	
}
| |
” | j |
” |
S )zz
        Fake L{reactor.spawnProcess}, that logs all the process
        arguments and returns a L{DummyProcess}.
        )r   ZmakeConnectionr,   Śappend)r   ZprocessProtocolr   r   Śenvr   r   r   r   r   Śprocr   r   r   ŚspawnProcessf   s        ’
z DummyProcessReactor.spawnProcess)r'   r(   r)   r*   r   r1   r   r   r   r   r+   Y   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 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d0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Z d<d= Z!d>d? Z"d@S )AŚProcmonTestsz&
    Tests for L{ProcessMonitor}.
    c                 C   s2   t  | _t| jd| _d| j_d| j_d| j_dS )zL
        Create an L{ProcessMonitor} wrapped around a fake reactor.
        ©r   é   é
   N)r+   r   r   ŚpmŚminRestartDelayŚmaxRestartDelayŚ	thresholdr-   r   r   r   ŚsetUp{   s
    zProcmonTests.setUpc                 C   sL   | j jdddgddi d t| j }|  d|” |  d|” |  d|” d	S )
z+
        Repr includes all details
        ŚfooŚarg1Śarg2r   r4   ©r   r   r/   Ś1Ś2N)r6   Ś
addProcessŚreprŚassertIn©r   Zrepresentationr   r   r   Śtest_reprLooksGood   s      ’
zProcmonTests.test_reprLooksGoodc                 C   s<   | j jdddgi d t| j }|  d|” |  d|” dS )z·
        Repr does not include unneeded details.

        Values of attributes that just mean "inherit from launching
        process" do not appear in the repr of a process.
        r;   r<   r=   )r/   ś(ś)N)r6   rA   rB   ŚassertNotInrD   r   r   r   Śtest_simpleReprLooksGood   s    
z%ProcmonTests.test_simpleReprLooksGoodc                 C   sD   | j jdddgddi d |  | j  ” d dddgddi fi” dS )	zW
        The list of monitored processes must be included in the pickle state.
        r;   r<   r=   r   r4   r>   Ś	processesN)r6   rA   ŚassertEqualŚ__getstate__r-   r   r   r   Śtest_getStateIncludesProcesses   s      ’’z+ProcmonTests.test_getStateIncludesProcessesc                 C   s   |   d| j ” ” dS )z~
        The private L{ProcessMonitor._reactor} instance variable should not be
        included in the pickle state.
        r   N)rH   r6   rL   r-   r   r   r   Śtest_getStateExcludesReactor©   s    z)ProcmonTests.test_getStateExcludesReactorc                 C   s~   | j jdddgddi d |  | j ji ” |  | j jdddgddi fi” | j  ”  | j d” |  t| j j 	” dg” dS )	z
        L{ProcessMonitor.addProcess} only starts the named program if
        L{ProcessMonitor.startService} has been called.
        r;   r<   r=   r   r4   r>   r   N)
r6   rA   rK   Ś	protocolsrJ   ŚstartServicer   ŚadvanceŚlistŚkeysr-   r   r   r   Śtest_addProcess±   s      ’
’
zProcmonTests.test_addProcessc              	   C   s>   | j jdddgddi d | jt| j jdddgddi d dS )z|
        L{ProcessMonitor.addProcess} raises a C{KeyError} if a process with the
        given name already exists.
        r;   r<   r=   r   r4   r>   N)r6   rA   ŚassertRaisesŚKeyErrorr-   r   r   r   Ś test_addProcessDuplicateKeyErrorĄ   s      ’    ’z-ProcmonTests.test_addProcessDuplicateKeyErrorc                 C   sP   ddi}| j  ”  | j jddgdd|d | j d” |  | jjd j|” dS )	z
        L{ProcessMonitor.addProcess} takes an C{env} parameter that is passed to
        L{IReactorProcess.spawnProcess}.
        ZKEYŚvaluer;   r   r4   r>   r   N)r6   rP   rA   r   rQ   rK   r,   r   )r   ZfakeEnvr   r   r   Śtest_addProcessEnvĖ   s    
 ’zProcmonTests.test_addProcessEnvc                 C   sD   | j  ”  | j jddgdd | j d” |  | jjd jd” dS )z
        L{ProcessMonitor.addProcess} takes an C{cwd} parameter that is passed
        to L{IReactorProcess.spawnProcess}.
        r;   z	/mnt/lala)Ścwdr   N)r6   rP   rA   r   rQ   rK   r,   r   r-   r   r   r   Śtest_addProcessCwdŲ   s    
 ’zProcmonTests.test_addProcessCwdc                 C   sR   | j  ”  | j  ddg” |  t| j jd” | j  d” |  t| j jd” dS )zm
        L{ProcessMonitor.removeProcess} removes the process from the public
        processes list.
        r;   r   r   N)r6   rP   rA   rK   ŚlenrJ   ŚremoveProcessr-   r   r   r   Śtest_removeProcessä   s
    
zProcmonTests.test_removeProcessc                 C   s    | j  ”  |  t| j jd” dS )zz
        L{ProcessMonitor.removeProcess} raises a C{KeyError} if the given
        process name isn't recognised.
        r;   N)r6   rP   rU   rV   r]   r-   r   r   r   Ś!test_removeProcessUnknownKeyErrorš   s    
z.ProcmonTests.test_removeProcessUnknownKeyErrorc                 C   sH   | j  ddg” | j  d” |  | j jd t” |  d| j j ” ” dS )a  
        When a process has been started, an instance of L{LoggingProtocol} will
        be added to the L{ProcessMonitor.protocols} dict and the start time of
        the process will be recorded in the L{ProcessMonitor.timeStarted}
        dictionary.
        r;   N)	r6   rA   ŚstartProcessZassertIsInstancerO   r   rC   ŚtimeStartedrS   r-   r   r   r   Śtest_startProcessł   s    zProcmonTests.test_startProcessc                 C   s2   | j  ddg” | j  d” |  | j  d”” dS )zr
        L{ProcessMonitor.startProcess} silently returns if the named process is
        already started.
        r;   N)r6   rA   r`   ŚassertIsNoner-   r   r   r   Śtest_startProcessAlreadyStarted  s    z,ProcmonTests.test_startProcessAlreadyStartedc                 C   s   |   t| jjd” dS )zy
        L{ProcessMonitor.startProcess} raises a C{KeyError} if the given
        process name isn't recognised.
        r;   N)rU   rV   r6   r`   r-   r   r   r   Ś test_startProcessUnknownKeyError  s    z-ProcmonTests.test_startProcessUnknownKeyErrorc                 C   s   | j  ”  | j  ddg” |  d| j j” d }| j jd j_| j | j j	” | j  
d” | j |” |  | j ” | j jd ” dS )zm
        L{ProcessMonitor.stopProcess} immediately sends a TERM signal to the
        named process.
        r;   r   N)r6   rP   rA   rC   rO   Ś	transportr!   r   rQ   r9   ŚstopProcessrK   Śsecondsra   )r   Z	timeToDier   r   r   Ś"test_stopProcessNaturalTermination  s    

’z/ProcmonTests.test_stopProcessNaturalTerminationc                 C   s“   | j  ”  | j  ddg” |  d| j j” | j | j j” | j jd j}| j j	d |_
| j  d” | j | j j	d ” |  d| j jd ” | j d” |  | j ” | j jd ” dS )z
        L{ProcessMonitor.stopProcess} kills a process which fails to terminate
        naturally within L{ProcessMonitor.killTime} seconds.
        r;   r   g        N)r6   rP   rA   rC   rO   r   rQ   r9   rf   ŚkillTimer!   rg   rK   ra   rh   )r   r0   r   r   r   Śtest_stopProcessForcedKill3  s    
z'ProcmonTests.test_stopProcessForcedKillc                 C   s   |   t| jjd” dS )zx
        L{ProcessMonitor.stopProcess} raises a C{KeyError} if the given process
        name isn't recognised.
        r;   N)rU   rV   r6   rg   r-   r   r   r   Śtest_stopProcessUnknownKeyErrorJ  s    z,ProcmonTests.test_stopProcessUnknownKeyErrorc                 C   s&   | j  ddg” |  | j  d”” dS )zį
        L{ProcessMonitor.stopProcess} silently returns if the named process
        is already stopped. eg Process has crashed and a restart has been
        rescheduled, but in the meantime, the service is stopped.
        r;   N)r6   rA   rc   rg   r-   r   r   r   Śtest_stopProcessAlreadyStoppedR  s    z+ProcmonTests.test_stopProcessAlreadyStoppedc                 C   sŖ   g }|   tj|j” t |j” | j ddg” | j ”  | j 	d” |  
d| jj” | j 	| jj” | jjd  d” |  t|d” |d d }|  |tdg” dS )zI
        Getting a complete output line generates a log message.
        r;   r   s   hello world!
r   Śmessageś[foo] hello world!N)Ś
addCleanupr
   ŚremoveObserverr.   ŚaddObserverr6   rA   rP   r   rQ   rC   rO   r9   ŚoutReceivedŚassertEqualsr\   Śtuple©r   Śeventsrn   r   r   r   Śtest_outputReceivedCompleteLine\  s    
z,ProcmonTests.test_outputReceivedCompleteLinec                 C   sÜ   g }|   tj|j” t |j” | j ddg” | j ”  | j 	d” |  
d| jj” | j 	| jj” | jjd  d” |  t|d” |d d }|  t|d” |d }| dd”\}}|  |d” |  |td” d	S )
zN
        Getting invalid UTF-8 results in the repr of the raw message
        r;   r   s   ’hello world!
r   rn   ś z[foo]s   ’hello world!N)rp   r
   rq   r.   rr   r6   rA   rP   r   rQ   rC   rO   r9   rs   rt   r\   ŚsplitrB   )r   rw   Zmessagesrn   ŚtagŚoutputr   r   r   Ś*test_outputReceivedCompleteLineInvalidUTF8r  s     
z7ProcmonTests.test_outputReceivedCompleteLineInvalidUTF8c                 C   sŌ   g }|   tj|j” t |j” | j ddg” | j ”  | j 	d” |  
d| jj” | j 	| jj” | jjd  d” |  t|d” | jjd  ttd” |  t|d” |d d }|  |tdg” dS )zM
        Getting partial line results in no events until process end
        r;   r   s   hello world!r   rn   ro   N)rp   r
   rq   r.   rr   r6   rA   rP   r   rQ   rC   rO   r9   rs   rt   r\   r#   r	   r   ru   rv   r   r   r   Śtest_outputReceivedPartialLine  s    
z+ProcmonTests.test_outputReceivedPartialLinec                 C   s   | j  ddg” | j  ”  | j d” |  d| j j” | j | j j” | j jd  t	t
d” |  d| j j” | j d” |  d| j j” dS )z§
        L{ProcessMonitor.connectionLost} should immediately restart a process
        if it has been running longer than L{ProcessMonitor.threshold} seconds.
        r;   r   N)r6   rA   rP   r   rQ   rC   rO   r9   r#   r	   r   rH   r-   r   r   r   Ś#test_connectionLostLongLivedProcess£  s    
z0ProcmonTests.test_connectionLostLongLivedProcessc                 C   s   | j  ddg” | j  ”  | j d” | j  d” |  d| j j” | j jd }|  | 	” ” | j | j j
d jj” |  | 	” ” |  d| j j” dS )z”
        L{ProcessMonitor.connectionLost} cancels a scheduled process killer and
        deletes the DelayedCall from the L{ProcessMonitor.murder} list.
        r;   r   N)r6   rA   rP   r   rQ   rg   rC   ZmurderŚ
assertTrueŚactiverO   rf   r!   ŚassertFalserH   )r   ZdelayedCallr   r   r   Śtest_connectionLostMurderCancelø  s    
’z,ProcmonTests.test_connectionLostMurderCancelc                 C   sj   | j  ”  | j  ddg” |  d| j j” | j jd j d” | j | j jd jj	” |  
d| j j” dS )z
        L{ProcessMonitor.connectionLost} removes the corresponding
        ProcessProtocol instance from the L{ProcessMonitor.protocols} list.
        r;   r    N)r6   rP   rA   rC   rO   rf   r&   r   rQ   r!   rH   r-   r   r   r   Ś#test_connectionLostProtocolDeletionĻ  s    
’z0ProcmonTests.test_connectionLostProtocolDeletionc                 C   s   d| j _d| j _| j  ”  | j  ddg” |  | j jd | j j” | j | j j	d ” | j j
d  ttd” |  | j jd | j j” dS )z}
        L{ProcessMonitor.connectionLost} will wait at least minRestartDelay s
        and at most maxRestartDelay s
        r4   é   r;   r   r   N)r6   r7   r8   rP   rA   rK   r$   r   rQ   r9   rO   r#   r	   r   r-   r   r   r   Ś%test_connectionLostMinMaxRestartDelayŻ  s    
z2ProcmonTests.test_connectionLostMinMaxRestartDelayc                 C   s   | j  ”  | j  ddg” | j | j jd ” |  d| j j” |  | j j	d | j j
” | j jd  ttd” |  | j j	d | j j
d ” dS )z|
        L{ProcessMonitor.connectionLost} doubles the restart delay each time
        the process dies too quickly.
        r;   r   r   r4   N)r6   rP   rA   r   rQ   r9   rC   rO   rK   r$   r7   r#   r	   r   r-   r   r   r   Ś&test_connectionLostBackoffDelayDoublesī  s    
z3ProcmonTests.test_connectionLostBackoffDelayDoublesc                 C   s:   | j  ddg” | j  ”  | j d” |  d| j j” dS )zP
        L{ProcessMonitor.startService} starts all monitored processes.
        r;   r   N)r6   rA   rP   r   rQ   rC   rO   r-   r   r   r   Śtest_startServiceż  s    
zProcmonTests.test_startServicec                 C   s   | j  ddg” | j  ddg” | j  ”  | j | j j” |  d| j j” |  d| j j” | j d” | j  ”  | j | j j	d ” |  
i | j j” dS )zT
        L{ProcessMonitor.stopService} should stop all monitored processes.
        r;   Zbarr   N)r6   rA   rP   r   rQ   r9   rC   rO   ŚstopServicerj   rK   r-   r   r   r   Śtest_stopService	  s    

zProcmonTests.test_stopServicec                 C   sl   | j  ddg” | j  ”  | j d” | j  ”  | j d” t| jj}| ” }|  	|g ” |  
|j” dS )zR
        L{ProcessMonitor.restartAll} succeeds when there is one process.
        r;   r   N)r6   rA   rP   r   rQ   Z
restartAllrR   r,   Śpoprt   rc   r"   )r   rJ   Z	myProcessr   r   r   Ś!test_restartAllRestartsOneProcess   s    

z.ProcmonTests.test_restartAllRestartsOneProcessc                 C   s   | j  ddg” | j  ”  | j | j j” |  d| j j” | j d” | j jd  t	t
d” |  | j jd  ” ” | j  ”  |  | j jd  ” ” dS )ze
        L{ProcessMonitor.stopService} should cancel any scheduled process
        restarts.
        r;   r   r   N)r6   rA   rP   r   rQ   r9   rC   rO   r#   r	   r   r   Zrestartr   r   r   r-   r   r   r   Śtest_stopServiceCancelRestarts0  s    

z+ProcmonTests.test_stopServiceCancelRestartsc                 C   sx   d| j _d| j _| j  ”  | j  ddg” | j d” | j  d” | j d” | j  ”  | j d” |  	| j j
i ” dS )ze
        L{ProcessMonitor.stopService} should cancel all scheduled process
        restarts.
        é   r;   r   é   N)r6   r9   r7   rP   rA   r   rQ   rg   r   rK   rO   r-   r   r   r   Ś(test_stopServiceCleanupScheduledRestartsE  s    

z5ProcmonTests.test_stopServiceCleanupScheduledRestartsN)#r'   r(   r)   r*   r:   rE   rI   rM   rN   rT   rW   rY   r[   r^   r_   rb   rd   re   ri   rk   rl   rm   rx   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r2   v   s@   
	

r2   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )ŚDeprecationTestszQ
    Tests that check functionality that should be deprecated is deprecated.
    c                 C   s   t  | _t| jd| _dS )z5
        Create reactor and process monitor.
        r3   N)r+   r   r   r6   r-   r   r   r   r:   d  s    zDeprecationTests.setUpc                 C   sx   | j  ddg” | j j}|  t|d” |  ” }d}|D ]$}|  |d t” d|d kr8d}q8|  |d 	t
|”” d	S )
a   
        _Process.toTuple is deprecated.

        When getting the deprecated processes property, the actual
        data (kept in the class _Process) is converted to a tuple --
        which produces a DeprecationWarning per process so converted.
        r;   r   FŚcategoryZtoTuplern   Tzno tuple deprecation found:{}N)r6   rA   rJ   rt   r\   ŚflushWarningsŚassertIsŚDeprecationWarningr   ŚformatrB   )r   ZmyprocessesŚwarningsZfoundToTupleŚwarningr   r   r   Śtest_toTuplel  s    ’zDeprecationTests.test_toTuplec                 C   sF   | j j}|  |i ” |  ” }| d”}|  |d t” |  |g ” dS )a  
        Accessing L{ProcessMonitor.processes} results in deprecation warning

        Even when there are no processes, and thus no process is converted
        to a tuple, accessing the L{ProcessMonitor.processes} property
        should generate its own DeprecationWarning.
        r   r   N)r6   rJ   rt   r   r   r   r   )r   ZmyProcessesr   Śfirstr   r   r   Śtest_processes  s    
zDeprecationTests.test_processesc                 C   s2   t  | j” |  ” }|D ]}|  |d t” qdS )zO
        Pickling an L{ProcessMonitor} results in deprecation warnings
        r   N)ŚpickleŚdumpsr6   r   r   r   )r   r   r   r   r   r   Śtest_getstate  s    zDeprecationTests.test_getstateN)r'   r(   r)   r*   r:   r   r   r   r   r   r   r   r   ^  s
   r   )r*   r   Ztwisted.trialr   Ztwisted.runner.procmonr   r   Ztwisted.internet.errorr   r   r   Ztwisted.internet.taskr   Ztwisted.python.failurer	   Ztwisted.pythonr
   Ztwisted.test.proto_helpersr   Śobjectr   r+   ZTestCaser2   ZSynchronousTestCaser   r   r   r   r   Ś<module>   s   E   k