o
    ¯b¥8  ã                   @   sd  d 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	m
Z
mZmZmZmZmZmZmZ ddlmZmZmZ ddl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"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z)m*Z* ddl%m+Z+ G dd„ dej,j-j.ƒZ/edd�G dd„ de+ƒƒZ0G dd„ de)ƒZ1G dd„ dƒZ2G dd„ dƒZ3G dd„ dƒZ4G dd „ d ƒZ5dS )!z2
Tests for L{twisted.application.runner._runner}.
é    N)ÚStringIO)ÚSIGTERM)ÚTracebackType)	ÚAnyÚIterableÚListÚOptionalÚTextIOÚTupleÚTypeÚUnionÚcast)ÚFactoryÚattribÚattrs)ÚMemoryReactor)ÚFileLogObserverÚFilteringLogObserverÚILogObserverÚLogBeginnerÚLogLevelÚLogLevelFilterPredicateÚLogPublisher)ÚFilePathé   )Ú_runneré   )Ú
ExitStatus)ÚNonePIDFileÚPIDFile)ÚRunnerc                   @   sÚ   e Zd ZdZd)dee defdd„Zd*dd„Zd*d	d
„Z	d*dd„Z
d*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd„Zd*dd „Zd*d!d"„Zd*d#d$„Zd)d%ed&ee ddfd'd(„ZdS )+ÚRunnerTestsz
    Tests for L{Runner}.
    NÚcontentÚreturnc                 C   s"   t |  ¡ ƒ}|d ur| |¡ |S ©N)r   ÚmktempÚ
setContent)Úselfr"   ÚfilePath© r)   úM/usr/lib/python3/dist-packages/twisted/application/runner/test/test_runner.pyr(   '   s   
zRunnerTests.filePathc                 C   s¶   t ƒ | _tƒ | _|  td| j¡ |  td| j¡ d| _| j› d� ¡ | _t	ƒ | _
t	ƒ | _t| j
| jƒ| _tƒ | _tƒ | _t| j| jj| j| jƒ| _|  td| j¡ |  td| j¡ d S )NÚexitÚkilli9  Ú
ÚstderrÚglobalLogBeginner)Ú	DummyExitr+   Ú	DummyKillr,   Úpatchr   ÚpidÚencodeÚpidFileContentr   Ústdoutr.   ÚDummyStandardIOÚstdioÚDummyWarningsModuleÚwarningsr   ÚglobalLogPublisherr   r/   ©r'   r)   r)   r*   ÚsetUp-   s&   üzRunnerTests.setUpc                 C   s*   t tƒ d�}| ¡  |  |jg d¢¡ dS )zD
        L{Runner.run} calls the expected methods in order.
        ©Úreactor)ÚkillIfRequestedÚstartLoggingÚstartReactorÚreactorExitedN)ÚDummyRunnerr   ÚrunÚassertEqualÚcalledMethods©r'   Úrunnerr)   r)   r*   Útest_runInOrderO   s   þzRunnerTests.test_runInOrderc                 C   sP   t ƒ }ttƒ |d�}|  |j¡ |  |j¡ | ¡  |  |j¡ |  |j¡ dS )z;
        L{Runner.run} uses the provided PID file.
        ©r?   ÚpidFileN)ÚDummyPIDFiler    r   ÚassertFalseÚenteredÚexitedrE   Ú
assertTrue©r'   rL   rI   r)   r)   r*   Útest_runUsesPIDFile`   s   zRunnerTests.test_runUsesPIDFilec                 C   sV   t |  | j¡ƒ}dd„ |_ttƒ |d�}| ¡  |  | jj	t
j¡ |  | jjd¡ dS )z²
        L{Runner.run} exits with L{ExitStatus.EX_USAGE} and the expected
        message if a process is already running that corresponds to the given
        PID file.
        c                   S   ó   dS ©NTr)   r)   r)   r)   r*   Ú<lambda>w   ó    z4RunnerTests.test_runAlreadyRunning.<locals>.<lambda>rK   zAlready running.N)r   r(   r5   Ú	isRunningr    r   rE   rF   r+   Ústatusr   Ú	EX_CONFIGÚmessagerR   r)   r)   r*   Útest_runAlreadyRunningp   s   
z"RunnerTests.test_runAlreadyRunningc                 C   s6   t tƒ d�}| ¡  |  | jjg ¡ |  | jj¡ dS )z‚
        L{Runner.killIfRequested} when C{kill} is false doesn't exit and
        doesn't indiscriminately murder anyone.
        r>   N)	r    r   r@   rF   r,   ÚcallsrN   r+   rP   rH   r)   r)   r*   Útest_killNotRequested   s   z!RunnerTests.test_killNotRequestedc                 C   sL   t tƒ dd�}| ¡  |  | jjg ¡ |  | jjtj	¡ |  | jj
d¡ dS )zÞ
        L{Runner.killIfRequested} when C{kill} is true but C{pidFile} is
        L{nonePIDFile} exits with L{ExitStatus.EX_USAGE} and the expected
        message; and also doesn't indiscriminately murder anyone.
        T)r?   r,   zNo PID file specified.N)r    r   r@   rF   r,   r]   r+   rY   r   ÚEX_USAGEr[   rH   r)   r)   r*   Ú test_killRequestedWithoutPIDFileŠ   s
   z,RunnerTests.test_killRequestedWithoutPIDFilec                 C   sf   t |  | j¡ƒ}ttƒ d|d�}| ¡  |  | jj| j	t
fg¡ |  | jjtj¡ |  | jjd¡ dS )z—
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        performs a targeted killing of the appropriate process.
        T©r?   r,   rL   N)r   r(   r5   r    r   r@   rF   r,   r]   r3   r   r+   rY   r   ÚEX_OKÚassertIdenticalr[   rR   r)   r)   r*   Útest_killRequestedWithPIDFile—   s   z)RunnerTests.test_killRequestedWithPIDFilec                 C   s`   t |  d¡ƒ}dtfdd„}||_ttƒ d|d�}| ¡  |  | jj	t
j¡ |  | jjd¡ dS )z•
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        that it can't read exits with L{ExitStatus.EX_IOERR}.
        Nr#   c                   S   s   t tjdƒ‚)NzPermission denied)ÚOSErrorÚerrnoÚEACCESr)   r)   r)   r*   Úread«   s   z?RunnerTests.test_killRequestedWithPIDFileCantRead.<locals>.readTra   zUnable to read PID file.)r   r(   Úintrh   r    r   r@   rF   r+   rY   r   ÚEX_IOERRr[   )r'   rL   rh   rI   r)   r)   r*   Ú%test_killRequestedWithPIDFileCantRead¤   s   z1RunnerTests.test_killRequestedWithPIDFileCantReadc                 C   óL   t |  d¡ƒ}ttƒ d|d�}| ¡  |  | jjtj	¡ |  | jj
d¡ dS )z˜
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        containing no value exits with L{ExitStatus.EX_DATAERR}.
        ó    Tra   úInvalid PID file.N©r   r(   r    r   r@   rF   r+   rY   r   Ú
EX_DATAERRr[   rR   r)   r)   r*   Ú"test_killRequestedWithPIDFileEmpty¶   ó
   z.RunnerTests.test_killRequestedWithPIDFileEmptyc                 C   rl   )z£
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        containing a non-integer value exits with L{ExitStatus.EX_DATAERR}.
        s    ** totally not a number, dude **Tra   rn   Nro   rR   r)   r)   r*   Ú%test_killRequestedWithPIDFileNotAnIntÂ   rr   z1RunnerTests.test_killRequestedWithPIDFileNotAnIntc                    s  t ƒ }G ‡ fdd„dƒ‰ |  tdˆ ƒ ¡ G ‡fdd„dtƒ‰|  tdˆ¡ G ‡fdd„dtƒ‰ttƒ tj|ˆd	�}| 	¡  |  
tˆ jƒd
¡ |  ˆ jd t¡ |  
tˆjƒd
¡ |  ˆjd t¡ |  ˆjd jtj¡ tˆˆjƒ}|  |ˆ¡ |  |j|¡ dS )zÛ
        L{Runner.startLogging} sets up a filtering observer with a log level
        predicate set to the given log level that contains a file observer of
        the given type which writes to the given file.
        c                       s8   e Zd ZU g Zee ed< dee ddf‡ fdd„ZdS )z2RunnerTests.test_startLogging.<locals>.LogBeginnerÚ	observersr#   Nc                    s   t |ƒˆ _d S r$   )Úlistrt   )r'   rt   ©r   r)   r*   ÚbeginLoggingToÜ   ó   zARunnerTests.test_startLogging.<locals>.LogBeginner.beginLoggingTo)	Ú__name__Ú
__module__Ú__qualname__rt   r   r   Ú__annotations__r   rw   r)   rv   r)   r*   r   Ù   s   
 r   r/   c                       sZ   e Zd ZU dZee ed< g Zee	 ed< e
edd„ ƒfdedee	 def‡ fdd„ZdS )	z?RunnerTests.test_startLogging.<locals>.MockFilteringLogObserverNÚobserverÚ
predicatesc                 S   s   d S r$   r)   )Úeventr)   r)   r*   rV   ë   rW   zHRunnerTests.test_startLogging.<locals>.MockFilteringLogObserver.<lambda>ÚnegativeObserverc                    s$   |ˆ _ t|ƒˆ _t | |||¡ d S r$   )r}   ru   r~   r   Ú__init__)r'   r}   r~   r€   ©ÚMockFilteringLogObserverr)   r*   r�   ç   s
   
ÿzHRunnerTests.test_startLogging.<locals>.MockFilteringLogObserver.__init__)ry   rz   r{   r}   r   r   r|   r~   r   r   r   r   r�   r)   r‚   r)   r*   rƒ   ã   s   
 üþýürƒ   r   c                       s4   e Zd ZU dZee ed< deddf‡ fdd„ZdS )z:RunnerTests.test_startLogging.<locals>.MockFileLogObserverNÚoutFiler#   c                    s   |ˆ _ t | |t¡ d S r$   )r„   r   r�   Ústr)r'   r„   ©ÚMockFileLogObserverr)   r*   r�   ú   s   zCRunnerTests.test_startLogging.<locals>.MockFileLogObserver.__init__)ry   rz   r{   r„   r   r	   r|   r�   r)   r†   r)   r*   r‡   ÷   s   
 r‡   )r?   ÚdefaultLogLevelÚlogFileÚfileLogObserverFactoryé   r   N)r   r2   r   r   r   r    r   r   ÚcriticalrA   rF   Úlenrt   ÚassertIsInstancer~   r   rc   rˆ   r   r}   r„   )r'   r‰   rI   r}   r)   )r   r‡   rƒ   r*   Útest_startLoggingÎ   s2   ü
ÿÿzRunnerTests.test_startLoggingc                 C   s(   t ƒ }t|d�}| ¡  |  |j¡ dS )ze
        L{Runner.startReactor} with the C{reactor} argument runs the given
        reactor.
        r>   N)r   r    rB   rQ   ÚhasRun)r'   r?   rI   r)   r)   r*   Útest_startReactorWithReactor  s   
z(RunnerTests.test_startReactorWithReactorc                 C   s   |   dd¡ dS )z�
        L{Runner.startReactor} ensures that C{whenRunning} is called with
        C{whenRunningArguments} when the reactor is running.
        ÚwhenRunningrB   N©Ú	_testHookr<   r)   r)   r*   Útest_startReactorWhenRunning&  s   z(RunnerTests.test_startReactorWhenRunningc                 C   ó   |   d¡ dS )zb
        L{Runner.whenRunning} calls C{whenRunning} with
        C{whenRunningArguments}.
        r’   Nr“   r<   r)   r)   r*   Útest_whenRunningWithArguments-  ó   z)RunnerTests.test_whenRunningWithArgumentsc                 C   r–   )zf
        L{Runner.whenRunning} calls C{reactorExited} with
        C{reactorExitedArguments}.
        rC   Nr“   r<   r)   r)   r*   Útest_reactorExitedWithArguments4  r˜   z+RunnerTests.test_reactorExitedWithArgumentsÚ
methodNameÚ
callerNamec                    s˜   |du r|}t tƒ tƒ tƒ d�}g ‰ dtddf‡ fdd„}|||› d�| ¡ i}tddtƒ i|¤Ž}t||ƒ}|ƒ  |  tˆ ƒd	¡ |  ˆ d
 |¡ dS )aÊ  
        Verify that the named hook is run with the expected arguments as
        specified by the arguments used to create the L{Runner}, when the
        specified caller is invoked.

        @param methodName: The name of the hook to verify.

        @param callerName: The name of the method that is expected to cause the
            hook to be called.
            If C{None}, use the L{Runner} method with the same name as the
            hook.
        N)ÚaÚbÚcÚ	argumentsr#   c                     s   ˆ   | ¡ d S r$   )Úappend)rŸ   ©ÚargumentsSeenr)   r*   ÚhookN  rx   z#RunnerTests._testHook.<locals>.hookÚ	Argumentsr?   r‹   r   r)   )ÚdictÚobjectÚcopyr    r   ÚgetattrrF   r�   )r'   rš   r›   rŸ   r£   ÚrunnerArgumentsrI   Ú
hookCallerr)   r¡   r*   r”   ;  s"   þÿÿ
zRunnerTests._testHookr$   ©r#   N)ry   rz   r{   Ú__doc__r   Úbytesr   r(   r=   rJ   rS   r\   r^   r`   rd   rk   rq   rs   r�   r‘   r•   r—   r™   r…   r”   r)   r)   r)   r*   r!   "   s&    

"









M


 r!   T)Úfrozenc                   @   sL   e Zd ZdZeee eeƒd�Z	ddd„Z
ddd„Zdd	d
„Zddd„ZdS )rD   zg
    Stub for L{Runner}.

    Keep track of calls to some methods without actually doing anything.
    )ÚtypeÚdefaultr#   Nc                 C   ó   | j  d¡ d S )Nr@   ©rG   r    r<   r)   r)   r*   r@   j  ó   zDummyRunner.killIfRequestedc                 C   r±   )NrA   r²   r<   r)   r)   r*   rA   m  r³   zDummyRunner.startLoggingc                 C   r±   )NrB   r²   r<   r)   r)   r*   rB   p  r³   zDummyRunner.startReactorc                 C   r±   )NrC   r²   r<   r)   r)   r*   rC   s  r³   zDummyRunner.reactorExitedr«   )ry   rz   r{   r¬   r   r   r…   r   ru   rG   r@   rA   rB   rC   r)   r)   r)   r*   rD   `  s    


rD   c                   @   sN   e Zd ZdZddd„Zddd„Zdeee  d	ee d
ee	 ddfdd„Z
dS )rM   z]
    Stub for L{PIDFile}.

    Tracks context manager entry/exit without doing anything.
    r#   Nc                 C   s   t  | ¡ d| _d| _d S ©NF)r   r�   rO   rP   r<   r)   r)   r*   r�   ~  s   

zDummyPIDFile.__init__c                 C   s
   d| _ | S rU   )rO   r<   r)   r)   r*   Ú	__enter__„  s   zDummyPIDFile.__enter__ÚexcTypeÚexcValueÚ	tracebackc                 C   ó
   d| _ d S rU   ©rP   )r'   r¶   r·   r¸   r)   r)   r*   Ú__exit__ˆ  s   
zDummyPIDFile.__exit__r«   )r#   rM   )ry   rz   r{   r¬   r�   rµ   r   r   ÚBaseExceptionr   r»   r)   r)   r)   r*   rM   w  s    


þýüûrM   c                   @   s@   e Zd ZdZd
dd„Z	ddeeef dee	 ddfdd	„Z
dS )r0   zy
    Stub for L{_exit.exit} that remembers whether it's been called and, if it has,
    what arguments it was given.
    r#   Nc                 C   r¹   r´   rº   r<   r)   r)   r*   r�   —  ó   
zDummyExit.__init__rY   r[   c                 C   s    | j rJ ‚|| _|| _d| _ d S rU   )rP   rY   r[   )r'   rY   r[   r)   r)   r*   Ú__call__š  s   

zDummyExit.__call__r«   r$   )ry   rz   r{   r¬   r�   r   ri   r   r   r…   r¾   r)   r)   r)   r*   r0   ‘  s    
ÿ
ÿÿþr0   c                   @   s0   e Zd ZdZd
dd„Zdededdfdd	„ZdS )r1   zv
    Stub for L{os.kill} that remembers whether it's been called and, if it has,
    what arguments it was given.
    r#   Nc                 C   s
   g | _ d S r$   )r]   r<   r)   r)   r*   r�   ª  r½   zDummyKill.__init__r3   Úsigc                 C   s   | j  ||f¡ d S r$   )r]   r    )r'   r3   r¿   r)   r)   r*   r¾   ­  s   zDummyKill.__call__r«   )ry   rz   r{   r¬   r�   ri   r¾   r)   r)   r)   r*   r1   ¤  s    
r1   c                   @   ó&   e Zd ZdZdededdfdd„ZdS )r7   zR
    Stub for L{sys} which provides L{StringIO} streams as stdout and stderr.
    r6   r.   r#   Nc                 C   s   || _ || _d S r$   )r6   r.   )r'   r6   r.   r)   r)   r*   r�   ¶  s   
zDummyStandardIO.__init__)ry   rz   r{   r¬   r	   r�   r)   r)   r)   r*   r7   ±  ó    r7   c                   @   rÀ   )r9   zV
    Stub for L{warnings} which provides a C{showwarning} method that is a no-op.
    ÚargsÚkwargsr#   Nc                  O   rT   )z\
        Do nothing.

        @param args: ignored.
        @param kwargs: ignored.
        Nr)   )rÂ   rÃ   r)   r)   r*   ÚshowwarningÀ  rW   zDummyWarningsModule.showwarning)ry   rz   r{   r¬   r   rÄ   r)   r)   r)   r*   r9   »  rÁ   r9   )6r¬   rf   Úior   Úsignalr   Útypesr   Útypingr   r   r   r   r	   r
   r   r   r   Úattrr   r   r   Útwisted.trial.unittestÚtwistedÚtwisted.internet.testingr   Útwisted.loggerr   r   r   r   r   r   r   Útwisted.python.filepathr   rI   r   Ú_exitr   Ú_pidfiler   r   r    ÚtrialÚunittestÚTestCaser!   rD   rM   r0   r1   r7   r9   r)   r)   r)   r*   Ú<module>   s2   ,$	  @
