U
    
W[Ù! ã                   @   sl  d Z ddlmZmZ ddlZddlZddlZddlZddlZzddl	Z	ddl
Z
W n ek
rl   d Z	Z
Y nX zddlZW n ek
r–   ddlZY nX 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 dd	lmZmZ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* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m*Z7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@ zddl?mAZA W n ek
râ   dZAY n&X ddlBmCZC ddlBmDZD ddlBmEZE zddl4mFZF W n ek
r2   dZFY nX zddlGZGW n ek
rZ   dZGY nX zddlHZHddlIZIW n ek
rŠ   dZIY nX eJeddƒdkr¤dZKndZKd d!„ ZLG d"d#„ d#eMƒZNG d$d%„ d%ejOƒZPG d&d'„ d'e@jQƒZRG d(d)„ d)ejSƒZTG d*d+„ d+ejSƒZUG d,d-„ d-ejSƒZVG d.d/„ d/eMƒZWG d0d1„ d1ejXƒZYG d2d3„ d3ejSƒZZG d4d5„ d5ejSƒZ[G d6d7„ d7ejSƒZ\G d8d9„ d9ejSƒZ]G d:d;„ d;eMƒZ^ee#ƒG d<d=„ d=e^ƒƒZ_G d>d?„ d?eMƒZ`G d@dA„ dAejSƒZadBdC„ ZbdDdE„ ZcG dFdG„ dGejSƒZdG dHdI„ dIejSƒZeG dJdK„ dKejSƒZfee$ƒG dLdM„ dMe.ƒƒZgG dNdO„ dOe@jQƒZhdPdQ„ ZiG dRdS„ dSejSƒZjeAdkrhdTef_kdS )UzE
Tests for L{twisted.application.app} and L{twisted.scripts.twistd}.
é    )Úabsolute_importÚdivisionN)Úimplementer)ÚverifyObject)Úunittest)ÚMockOS)ÚpluginÚloggerÚinternet)ÚserviceÚappÚreactors)ÚIServiceMaker)ÚDeferred)ÚIReactorDaemonizeÚ_ISupportsExitSignalCapturing)ÚAlternateReactor)ÚglobalLogBeginnerÚglobalLogPublisherÚILogObserver)ÚReactorBase)ÚMemoryReactor)ÚNativeStringIOÚ_PY3)ÚComponentized)Úutil)r   ÚtextFromEventDict)ÚplatformType)Ú
UsageError)ÚUserDatabase)Útwistd)Ú_twistd_unix)ÚcheckPID)ÚUnixApplicationRunner)ÚUnixAppLogger)ÚsyslogÚsetuidz5Platform does not support --uid/--gid twistd options.c              	      s|   t  t ¡ ¡}t t ¡ ¡‰tƒ }| ||j	|ˆ |j
|j|j¡ ‡ ‡‡fdd„}| t d|jƒ | td|ƒ | t d|jƒ dS )au  
    Patch L{pwd.getpwnam} so that it behaves as though only one user exists
    and patch L{grp.getgrnam} so that it behaves as though only one group
    exists.

    @param patch: A function like L{TestCase.patch} which will be used to
        install the fake implementations.

    @type user: C{str}
    @param user: The name of the single user which will exist.

    @type uid: C{int}
    @param uid: The UID of the single user which will exist.

    @type group: C{str}
    @param group: The name of the single user which will exist.

    @type gid: C{int}
    @param gid: The GID of the single group which will exist.
    c                    s<   t ˆƒ}ˆ|| ˆj¡< ˆ || ˆj¡< t|ƒ}ˆ|i|  S ©N)ÚlistÚindexZgr_nameZgr_gidÚtuple)ÚnameÚresult©ÚgidZgrentÚgroup© ú:/usr/lib/python3/dist-packages/twisted/test/test_twistd.pyÚgetgrnamy   s
    z#patchUserDatabase.<locals>.getgrnamÚgetpwnamr2   ÚgetpwuidN)Úpwdr4   ÚosÚgetuidÚgrpZgetgrgidÚgetgidr   ZaddUserÚ	pw_passwdÚpw_gecosÚpw_dirÚpw_shellr3   )ÚpatchÚuserÚuidr/   r.   ÚpwentZdatabaser2   r0   r-   r1   ÚpatchUserDatabaseX   s          þrB   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚMockServiceMakerzO
    A non-implementation of L{twisted.application.service.IServiceMaker}.
    Úueoac                 C   s   || _ t ¡ | _| jS )ze
        Take a L{usage.Options} instance and return a
        L{service.IService} provider.
        )Úoptionsr   ÚService©ÚselfrE   r0   r0   r1   ÚmakeServiceŒ   s    
zMockServiceMaker.makeServiceN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚtapnamerI   r0   r0   r0   r1   rC   †   s   rC   c                   @   s   e Zd ZdZdd„ ZdS )ÚCrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                 C   s   d S r'   r0   ©rH   Úapplicationr0   r0   r1   Ústartœ   s    zCrippledAppLogger.startN)rJ   rK   rL   rM   rR   r0   r0   r0   r1   rO   —   s   rO   c                   @   s$   e Zd ZdZeZdd„ Zdd„ ZdS )ÚCrippledApplicationRunnerzÃ
    An application runner that cripples the platform-specific runner and
    nasty side-effect-having code so that we can use it without actually
    running any environment-affecting code.
    c                 C   s   d S r'   r0   ©rH   r0   r0   r1   ÚpreApplication©   s    z(CrippledApplicationRunner.preApplicationc                 C   s   d S r'   r0   rT   r0   r0   r1   ÚpostApplication­   s    z)CrippledApplicationRunner.postApplicationN)rJ   rK   rL   rM   rO   ÚloggerFactoryrU   rV   r0   r0   r0   r1   rS   ¡   s   rS   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edkrjdZe e	_ e
_e_dd„ Zdd„ Zdd„ ZdS )ÚServerOptionsTestszT
    Non-platform-specific tests for the platform-specific ServerOptions class.
    c                    sÐ   G dd„ dt ƒ}|dƒ‰ |dƒ‰|dƒ‰|dƒ‰‡ ‡‡‡‡fdd„}t ¡ }ˆ |jtj¡ ||_|j}ˆ ˆˆˆg}t||ƒD ]L\}}|\}}	}
}ˆ ||j	¡ ˆ 
|	¡ ˆ |
ƒ |j¡f ˆ ||j¡ q~d	S )
zh
        subCommands is built from IServiceMaker plugins, and is sorted
        alphabetically.
        c                   @   s   e Zd Zdd„ Zdd„ ZdS )z7ServerOptionsTests.test_subCommands.<locals>.FakePluginc                 S   s   || _ d| | _d| | _d S )Nzoptions for údescription of )rN   Ú_optionsÚdescription©rH   r+   r0   r0   r1   Ú__init__¼   s    
z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__c                 S   s   | j S r'   )rZ   rT   r0   r0   r1   rE   Á   s    z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.optionsN)rJ   rK   rL   r]   rE   r0   r0   r0   r1   Ú
FakePlugin»   s   r^   ÚappleÚbananaÚcoconutÚdonutc                 3   s(   ˆ  | t¡ ˆV  ˆV  ˆV  ˆ V  d S r'   )ÚassertEqualr   )Z	interface©r_   r`   ra   rb   rH   r0   r1   Ú
getPluginsÉ   s
    z7ServerOptionsTests.test_subCommands.<locals>.getPluginsN)Úobjectr    ÚServerOptionsrc   Z_getPluginsr   re   ÚsubCommandsÚziprN   ÚassertIsNonerZ   r[   )rH   r^   re   Úconfigrh   ZexpectedOrderÚ
subCommandZexpectedCommandr+   ZshortcutZparserClassZdocumentationr0   rd   r1   Útest_subCommands¶   s"    	
z#ServerOptionsTests.test_subCommandsc                    sÚ   G dd„ dt ƒ}|dƒ‰ |dƒ‰|dƒ‰|dƒ‰‡ ‡‡‡fdd„}t ¡ }ˆ |jtj¡ ||_tƒ |_ˆ 	t
|jd	g¡ |j ¡ ‰g ‰ˆ ˆˆˆfD ](}‡‡‡fd
d„}||jƒ ||jƒ q”ˆ ˆtˆƒdˆf ¡ dS )zP
        Reactor names are listed alphabetically by I{--help-reactors}.
        c                   @   s   e Zd Zdd„ ZdS )zGServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstallerc                 S   s   d| | _ d| | _d| _d S )Nzname of rY   ztwisted.internet.default)Ú	shortNamer[   Z
moduleNamer\   r0   r0   r1   r]   æ   s    

zPServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstaller.__init__N)rJ   rK   rL   r]   r0   r0   r0   r1   ÚFakeReactorInstallerå   s   ro   r_   r`   ra   rb   c                   3   s   ˆV  ˆV  ˆV  ˆ V  d S r'   r0   r0   )r_   r`   ra   rb   r0   r1   ÚgetReactorTypesð   s    zBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypesz--help-reactorsc                    s    ˆ  | ˆ ¡ ˆ ˆ  | ¡¡ d S r'   )ÚassertInÚappendr)   )Ús)Ú
helpOutputÚindexesrH   r0   r1   ÚgetIndexÿ   s    z;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndexz7reactor descriptions were not in alphabetical order: %rN)rf   r    rg   rc   Z_getReactorTypesr   rp   r   ZmessageOutputÚassertRaisesÚ
SystemExitÚparseOptionsÚgetvaluern   r[   Úsorted)rH   ro   rp   rk   Úreactorrv   r0   )r_   r`   ra   rb   rt   ru   rH   r1   Útest_sortedReactorHelpá   s0    

 ÿþz)ServerOptionsTests.test_sortedReactorHelpc                 C   s(   t  ¡ }d|_| ¡  |  |d ¡ dS )zS
        postOptions should set no_save to True when a subcommand is used.
        rD   Úno_saveN)r    rg   rl   ÚpostOptionsÚ
assertTrue©rH   rk   r0   r0   r1   Ú&test_postOptionsSubCommandCausesNoSave  s    z9ServerOptionsTests.test_postOptionsSubCommandCausesNoSavec                 C   s"   t  ¡ }| ¡  |  |d ¡ dS )zR
        If no sub command is used, postOptions should not touch no_save.
        r~   N)r    rg   r   ÚassertFalser   r0   r0   r1   Ú(test_postOptionsNoSubCommandSavesAsUsual  s    z;ServerOptionsTests.test_postOptionsNoSubCommandSavesAsUsualc                 C   s.   t  ¡ }t|ƒ}tjjD ]}|  ||¡ qdS )zq
        All the profilers that can be used in L{app.AppProfiler} are listed in
        the help output.
        N)r    rg   Ústrr   ÚAppProfilerZ	profilersrq   )rH   rk   rt   Úprofilerr0   r0   r1   Útest_listAllProfilers  s    z(ServerOptionsTests.test_listAllProfilersc                 C   s   t  ¡ }|  |d ¡ dS )zG
        The default value for the C{umask} option is L{None}.
        ÚumaskN)r    rg   rj   r   r0   r0   r1   Útest_defaultUmask*  s    z$ServerOptionsTests.test_defaultUmaskc                 C   sH   t  ¡ }| ddg¡ |  |d d¡ | ddg¡ |  |d d¡ dS )zh
        The value given for the C{umask} option is parsed as an octal integer
        literal.
        ú--umaskZ123r‰   éS   Z0123N)r    rg   ry   rc   r   r0   r0   r1   Ú
test_umask2  s
    zServerOptionsTests.test_umaskc                 C   s    t  ¡ }|  t|jddg¡ dS )z¥
        If a value is given for the C{umask} option which cannot be parsed as
        an integer, L{UsageError} is raised by L{ServerOptions.parseOptions}.
        r‹   ZabcdefN)r    rg   rw   r   ry   r   r0   r0   r1   Útest_invalidUmask>  s    
ÿz$ServerOptionsTests.test_invalidUmaskNútwistd unix not availablec                 C   sH   t  ¡ }|  t|jddg¡}|  |jd  d¡¡ |  d|jd ¡ dS )zQ
        C{--logger} with an unimportable module raises a L{UsageError}.
        ú--loggerzno.such.module.I.hoper   zeLogger 'no.such.module.I.hope' could not be imported: 'no.such.module.I.hope' does not name an objectÚ
N)	r    rg   rw   r   ry   r€   ÚargsÚ
startswithÚassertNotIn©rH   rk   Úer0   r0   r1   Ú&test_unimportableConfiguredLogObserverL  s     þ
ÿÿz9ServerOptionsTests.test_unimportableConfiguredLogObserverc                 C   sj   t  ¡ }|  t|jddg¡}tjdkr>|  |jd  	d¡¡ n|  |jd  	d¡¡ |  
d|jd ¡ dS )	zP
        C{--logger} with a non-existent object raises a L{UsageError}.
        r   ztwisted.test.test_twistd.FOOBAR)é   é   r   ziLogger 'twisted.test.test_twistd.FOOBAR' could not be imported: 'module' object has no attribute 'FOOBAR'z{Logger 'twisted.test.test_twistd.FOOBAR' could not be imported: module 'twisted.test.test_twistd' has no attribute 'FOOBAR'r‘   N)r    rg   rw   r   ry   ÚsysÚversion_infor€   r’   r“   r”   r•   r0   r0   r1   Ú*test_badAttributeWithConfiguredLogObserver[  s     
ÿ

ÿÿ
ÿÿz=ServerOptionsTests.test_badAttributeWithConfiguredLogObserverc                 C   sv   ddl m} tdkrd}nd}d ||j|j¡}tƒ }tj|d}|  t	|j
dg¡}|  |jd	¡ |  | ¡ |¡ d	S )
z2
        C{--version} prints the version.
        r   )Ú	copyrightZwin32z(the Twisted Windows runner)z(the Twisted daemon)ztwistd {} {}
{}
)Ústdoutz	--versionN)Útwistedr   r   ÚformatÚversionr   r    rg   rw   rx   ry   ÚassertIsÚcoderc   rz   )rH   r   r+   ZexpectedOutputrž   rk   r–   r0   r0   r1   Útest_versionp  s      ÿzServerOptionsTests.test_version)rJ   rK   rL   rM   rm   r}   r‚   r„   rˆ   rŠ   r   rŽ   r!   ÚmsgÚskipr—   rœ   r¤   r0   r0   r0   r1   rX   ²   s   ++
		rX   c                   @   sD   e Zd ZdZedkrdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dS )ÚCheckPIDTestsz 
    Tests for L{checkPID}.
    Nr   c                 C   s    |   tjddd„ ¡ tdƒ dS )z7
        Nonexistent PID file is not an error.
        Úexistsc                 S   s   dS ©NFr0   )Ú_r0   r0   r1   Ú<lambda>‘  ó    z.CheckPIDTests.test_notExists.<locals>.<lambda>znon-existent PID fileN)r>   r6   Úpathr"   rT   r0   r0   r1   Útest_notExists  s    zCheckPIDTests.test_notExistsc              	   C   sH   |   ¡ }t|dƒ}| d¡ W 5 Q R X |  tt|¡}|  d|j¡ dS )zI
        Non-numeric content in a PID file causes a system exit.
        Úwznon-numericznon-numeric valueN)ÚmktempÚopenÚwriterw   rx   r"   rq   r£   )rH   ÚpidfileÚfr–   r0   r0   r1   Útest_nonNumeric•  s
    zCheckPIDTests.test_nonNumericc              	   C   s^   |   ¡ }t|dƒ}| d¡ W 5 Q R X dd„ }|  td|¡ |  tt|¡}|  d|j	¡ dS )zE
        Another running twistd server causes a system exit.
        r¯   Z42c                 S   s   d S r'   r0   ©ÚpidÚsigr0   r0   r1   Úkill§  s    z/CheckPIDTests.test_anotherRunning.<locals>.killr¹   zAnother twistd serverN)
r°   r±   r²   r>   r6   rw   rx   r"   rq   r£   ©rH   r³   r´   r¹   r–   r0   r0   r1   Útest_anotherRunning   s    z!CheckPIDTests.test_anotherRunningc              	   C   sh   |   ¡ }t|dƒ}| tt ¡ d ƒ¡ W 5 Q R X dd„ }|  td|¡ t|ƒ |  tj	 
|¡¡ dS )zJ
        Stale PID file is removed without causing a system exit.
        r¯   é   c                 S   s   t tjdƒ‚d S ©NZfake)ÚOSErrorÚerrnoZESRCHr¶   r0   r0   r1   r¹   µ  s    z&CheckPIDTests.test_stale.<locals>.killr¹   N)r°   r±   r²   r…   r6   Úgetpidr>   r"   rƒ   r­   r¨   )rH   r³   r´   r¹   r0   r0   r1   Ú
test_stale®  s     zCheckPIDTests.test_stalec              	   C   st   |   ¡ }t|dƒ}| d¡ W 5 Q R X dd„ }|  td|¡ |  tt|¡}|  |j	d¡ |  
|jd  d¡¡ dS )	z
        An unexpected L{OSError} when checking the validity of a
        PID in a C{pidfile} terminates the process via L{SystemExit}.
        r¯   Z3581c                 S   s   t tjdƒ‚d S r½   ©r¾   r¿   ZEBADFr¶   r0   r0   r1   r¹   Ä  s    z2CheckPIDTests.test_unexpectedOSError.<locals>.killr¹   Nr   zCan't check status of PID)r°   r±   r²   r>   r6   rw   rx   r"   ZassertIsNotr£   r€   r’   r“   rº   r0   r0   r1   Útest_unexpectedOSError¼  s    z$CheckPIDTests.test_unexpectedOSError)rJ   rK   rL   rM   r!   r¦   r®   rµ   r»   rÁ   rÃ   r0   r0   r0   r1   r§   …  s   r§   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚTapFileTestszM
    Test twistd-related functionality that requires a tap file on disk.
    c              	   C   s8   |   ¡ | _t| jdƒ}t t d¡|¡ W 5 Q R X dS )zP
        Create a trivial Application and put it in a tap file on disk.
        ÚwbúHi!N)r°   Útapfiler±   ÚpickleÚdumpr   ÚApplication)rH   r´   r0   r0   r1   ÚsetUpÑ  s    
zTapFileTests.setUpc                 C   s<   t  ¡ }| d| jg¡ t|ƒ ¡ }|  t |¡j	d¡ dS )zŽ
        Ensure that the createOrGetApplication call that 'twistd -f foo.tap'
        makes will load the Application out of foo.tap.
        z-frÆ   N)
r    rg   ry   rÇ   rS   ZcreateOrGetApplicationrc   r   ÚIServicer+   )rH   rk   rQ   r0   r0   r1   Ú&test_createOrGetApplicationWithTapFileÚ  s    ÿz3TapFileTests.test_createOrGetApplicationWithTapFileN)rJ   rK   rL   rM   rË   rÍ   r0   r0   r0   r1   rÄ   Ì  s   	rÄ   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚTestLoggerFactoryz8
    A logger factory for L{TestApplicationRunner}.
    c                 C   s
   || _ d S r'   )Úrunner)rH   rÏ   r0   r0   r1   r]   ì  s    zTestLoggerFactory.__init__c                 C   s"   | j j d¡ t| j dƒ| j _dS )zC
        Save the logging start on the C{runner} instance.
        ÚlogrQ   N)rÏ   Úorderrr   ÚhasattrÚhadApplicationLogObserverrP   r0   r0   r1   rR   ð  s    ÿzTestLoggerFactory.startc                 C   s   dS )z%
        Don't log anything.
        Nr0   rT   r0   r0   r1   Ústopù  s    zTestLoggerFactory.stopN)rJ   rK   rL   rM   r]   rR   rÔ   r0   r0   r0   r1   rÎ   ç  s   	rÎ   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚTestApplicationRunnerz`
    An ApplicationRunner which tracks the environment in which its methods are
    called.
    c                 C   s"   t j | |¡ g | _t| ƒ| _d S r'   )r   ÚApplicationRunnerr]   rÑ   rÎ   r	   rG   r0   r0   r1   r]     s    zTestApplicationRunner.__init__c                 C   s   | j  d¡ t| dƒ| _d S )NÚprerQ   )rÑ   rr   rÒ   ÚhadApplicationPreApplicationrT   r0   r0   r1   rU     s    z$TestApplicationRunner.preApplicationc                 C   s   | j  d¡ t| dƒ| _d S )NÚpostrQ   )rÑ   rr   rÒ   ÚhadApplicationPostApplicationrT   r0   r0   r1   rV     s    z%TestApplicationRunner.postApplicationN)rJ   rK   rL   rM   r]   rU   rV   r0   r0   r0   r1   rÕ      s   rÕ   c                   @   sl   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Ze	e_
dd„ Ze	e_
dd„ Zdd„ Zdd„ Zdd„ ZdS )ÚApplicationRunnerTestszR
    Non-platform-specific tests for the platform-specific ApplicationRunner.
    c                 C   s4   t  ¡ }tƒ | _d| ji|_tƒ |_d|_|| _d S )NÚtest_command)	r    rg   rC   ÚserviceMakerÚloadedPluginsrf   Ú
subOptionsrl   rk   r   r0   r0   r1   rË     s    zApplicationRunnerTests.setUpc                 C   sL   t | jƒ}| ¡  |  | jj| jjd¡ |  | jjt |j	¡j
d d¡ dS )z·
        Ensure that a twistd plugin gets used in appropriate ways: it
        is passed its Options instance, and the service it returns is
        added to the application.
        zKServiceMaker.makeService needs to be passed the correct sub Command object.r   zPServiceMaker.makeService's result needs to be set as a child of the Application.N)rS   rk   Úrunr¢   rÝ   rE   rß   r   rÌ   rQ   Úservices)rH   Zarunnerr0   r0   r1   Ú,test_applicationRunnerGetsCorrectApplication%  s    
 þýzCApplicationRunnerTests.test_applicationRunnerGetsCorrectApplicationc                 C   sN   t | jƒ}| ¡  |  |j¡ |  |j¡ |  |j¡ |  |j	dddg¡ dS )z†
        Test thet preApplication and postApplication methods are
        called by ApplicationRunner.run() when appropriate.
        r×   rÐ   rÙ   N)
rÕ   rk   rà   rƒ   rØ   r€   rÚ   rÓ   rc   rÑ   )rH   rs   r0   r0   r1   Útest_preAndPostApplication9  s    
z1ApplicationRunnerTests.test_preAndPostApplicationc              	      s¨   | j  |¡ g ‰ G ‡ fdd„dtjƒ}ttjtjƒG ‡ fdd„dtƒƒ}|ƒ }t	tj|ƒ t	tj|ƒ || j ƒ}| 
¡  ||_| ¡  |  ˆ dddd||fd	d
g¡ dS )a.  
        Assert that given a particular command line, an application is started
        as a particular UID/GID.

        @param argv: A list of strings giving the options to parse.
        @param uid: An integer giving the expected UID.
        @param gid: An integer giving the expected GID.
        c                       s8   e Zd Z‡ fdd„Z‡ fdd„Z‡ fdd„Zdd„ Zd	S )
z\ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunnerc                    s   ˆ   d¡ d S )NÚenvironment©rr   ©rH   ÚchrootZrundirÚnodaemonr‰   r³   ©Zeventsr0   r1   ÚsetupEnvironmentT  s    zmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironmentc                    s   ˆ   d|||f¡ d S )NÚ
privilegesrå   )rH   Úeuidr@   r.   ré   r0   r1   ÚshedPrivilegesX  s    zkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivilegesc                    s   ˆ   d¡ d S )Nr|   rå   )rH   r|   Ú	oldstdoutÚ	oldstderrré   r0   r1   ÚstartReactor[  s    ziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactorc                 S   s   d S r'   r0   )rH   r³   r0   r0   r1   Ú	removePID^  s    zfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDN)rJ   rK   rL   rê   rí   rð   rñ   r0   ré   r0   r1   ÚFakeUnixApplicationRunnerS  s   rò   c                       s\   e Zd ZdZdZdZdZdZdZdd„ Z	dd„ Z
dd„ Z‡ fdd	„Z‡ fd
d„Zdd„ ZdS )zNApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeServiceNc                 S   s   d S r'   r0   r\   r0   r0   r1   ÚsetNamek  s    zVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNamec                 S   s   d S r'   r0   )rH   Úparentr0   r0   r1   ÚsetServiceParentn  s    z_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentc                 S   s   d S r'   r0   rT   r0   r0   r1   ÚdisownServiceParentq  s    zbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentc                    s   ˆ   d¡ d S )NÚprivilegedStartServicerå   rT   ré   r0   r1   r÷   t  s    zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServicec                    s   ˆ   d¡ d S )NÚstartServicerå   rT   ré   r0   r1   rø   w  s    z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServicec                 S   s   d S r'   r0   rT   r0   r0   r1   ÚstopServicez  s    zZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService)rJ   rK   rL   rô   Úrunningr+   ZprocessNamer@   r.   ró   rõ   rö   r÷   rø   rù   r0   ré   r0   r1   ÚFakeServicea  s   rû   rä   r÷   rë   Frø   r|   N)rk   ry   r    Ú_SomeApplicationRunnerr   r   rÌ   ZIProcessrf   r   rU   rQ   rV   rc   )rH   Úargvr@   r.   rò   rû   rQ   rÏ   r0   ré   r1   Ú"_applicationStartsWithConfiguredIDF  s(    	

  ÿþz9ApplicationRunnerTests._applicationStartsWithConfiguredIDc                 C   s*   d}d}|   dt|ƒdt|ƒg||¡ dS )a  
        L{postApplication} should change the UID and GID to the values
        specified as numeric strings by the configuration after running
        L{service.IService.privilegedStartService} and before running
        L{service.IService.startService}.
        éÒ  éá  ú--uidú--gidN)rþ   r…   )rH   r@   r.   r0   r0   r1   Ú.test_applicationStartsWithConfiguredNumericIDsŒ  s      ÿzEApplicationRunnerTests.test_applicationStartsWithConfiguredNumericIDsc                 C   s<   d}d}d}d}t | j||||ƒ |  d|d|g||¡ dS )a  
        L{postApplication} should change the UID and GID to the values
        specified as user and group names by the configuration after running
        L{service.IService.privilegedStartService} and before running
        L{service.IService.startService}.
        Úfoorÿ   Úbarr   r  r  N)rB   r>   rþ   )rH   r?   r@   r/   r.   r0   r0   r1   Ú+test_applicationStartsWithConfiguredNameIDsš  s    
  ÿzBApplicationRunnerTests.test_applicationStartsWithConfiguredNameIDsc                 C   s8   t ƒ }t ddddœ¡}| |dd¡ |  |jd¡ dS )z7
        L{startReactor} calls L{reactor.run}.
        FÚprofile©r  r‡   ÚdebugNz'startReactor did not call reactor.run())ÚDummyReactorr   rÖ   rð   r€   Úcalled©rH   r|   rÏ   r0   r0   r1   Útest_startReactorRunsTheReactor«  s    ý ÿz6ApplicationRunnerTests.test_startReactorRunsTheReactorc                 C   sD   t ƒ }|  td|¡ t ddddœ¡}| ddd¡ |  |j¡ dS )zN
        L{ApplicationRunner} chooses a reactor if none is specified.
        r|   Fr  r  N)r
  r>   r
   r   rÖ   rð   r€   r  r  r0   r0   r1   Ú*test_applicationRunnerChoosesReactorIfNone¹  s    ýzAApplicationRunnerTests.test_applicationRunnerChoosesReactorIfNonec                 C   sH   G dd„ dt ƒ}|ƒ }t ddddœ¡}| |dd¡ |  d|j¡ dS )zg
        If the reactor exits with a signal, the application runner caches
        the signal.
        c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )z[ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignalú‹
            A dummy reactor, providing a C{run} method, and setting the
            _exitSignal attribute to a nonzero value.
            c                 S   s   dS ©z=
                Dummy method, does nothing.
                Nr0   rT   r0   r0   r1   ÚinstallWakerÓ  s    zhApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.installWakerc                 S   s
   d| _ dS )zZ
                A fake run method setting _exitSignal to a nonzero value
                é   N©Ú_exitSignalrT   r0   r0   r1   rà   Ø  s    z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.runN©rJ   rK   rL   rM   r  rà   r0   r0   r0   r1   ÚDummyReactorWithSignalÍ  s   r  Fr  r  Nr  )r   r   rÖ   rð   ÚassertEqualsr  )rH   r  r|   rÏ   r0   r0   r1   Ú$test_applicationRunnerCapturesSignalÇ  s    ýz;ApplicationRunnerTests.test_applicationRunnerCapturesSignalc                 C   sH   G dd„ dt ƒ}|ƒ }t ddddœ¡}| |dd¡ |  d|j¡ dS )z˜
        The runner sets its _exitSignal instance attribute to None if
        the reactor does not implement L{_ISupportsExitSignalCapturing}.
        c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ziApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttributer  c                 S   s   dS r  r0   rT   r0   r0   r1   r  ó  s    zvApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.installWakerc                 S   s
   d| _ dS )z‚
                A fake run method setting _exitSignal to a nonzero value
                that should be ignored.
                r  Nr  rT   r0   r0   r1   rà   ø  s    zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.runNr  r0   r0   r0   r1   Ú#DummyReactorWithExitSignalAttributeí  s   r  Fr  r  N)rf   r   rÖ   rð   r  r  )rH   r  r|   rÏ   r0   r0   r1   Ú%test_applicationRunnerIgnoresNoSignalç  s    ýz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignalN)rJ   rK   rL   rM   rË   râ   rã   rþ   r  Ú
setuidSkipr¦   r  r  r  r  r  r0   r0   r0   r1   rÛ     s   
F rÛ   c                   @   s‚   e Zd ZdZedkrdZeƒ 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S )Ú*UnixApplicationRunnerSetupEnvironmentTestsaº  
    Tests for L{UnixApplicationRunner.setupEnvironment}.

    @ivar root: The root of the filesystem, or C{unset} if none has been
        specified with a call to L{os.chroot} (patched for this TestCase with
        L{UnixApplicationRunnerSetupEnvironmentTests.chroot}).

    @ivar cwd: The current working directory of the process, or C{unset} if
        none has been specified with a call to L{os.chdir} (patched for this
        TestCase with L{UnixApplicationRunnerSetupEnvironmentTests.chdir}).

    @ivar mask: The current file creation mask of the process, or C{unset} if
        none has been specified with a call to L{os.umask} (patched for this
        TestCase with L{UnixApplicationRunnerSetupEnvironmentTests.umask}).

    @ivar daemon: A boolean indicating whether daemonization has been performed
        by a call to L{_twistd_unix.daemonize} (patched for this TestCase with
        L{UnixApplicationRunnerSetupEnvironmentTests}.
    Nr   c                    s†   ˆ j ˆ _ˆ j ˆ _ˆ j ˆ _dˆ _t ¡ ˆ _ˆ  td‡ fdd„¡ ˆ  td‡ fdd„¡ ˆ  td‡ fdd„¡ t	t
 ¡ ƒˆ _ˆ jˆ j_d S )	NFrç   c                    s   t ˆ d| ƒS )NÚroot©Úsetattr©r­   rT   r0   r1   r«   (  r¬   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>Úchdirc                    s   t ˆ d| ƒS )NÚcwdr  r   rT   r0   r1   r«   )  r¬   r‰   c                    s   t ˆ d| ƒS )NÚmaskr  )r#  rT   r0   r1   r«   *  r¬   )Úunsetr  r"  r#  Údaemonr6   rÀ   r·   r>   r#   r    rg   rÏ   Ú	daemonizerT   r0   rT   r1   rË   "  s    
z0UnixApplicationRunnerSetupEnvironmentTests.setUpc                    s    dˆ _ ˆ  td‡ fdd„¡ dS )z§
        Indicate that daemonization has happened and change the PID so that the
        value written to the pidfile can be tested in the daemonization case.
        TrÀ   c                      s
   ˆ j d S ©Nr¼   )r·   r0   rT   r0   r1   r«   5  r¬   zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>N)r%  r>   r6   ©rH   r|   r0   rT   r1   r&  /  s    z4UnixApplicationRunnerSetupEnvironmentTests.daemonizec                 C   s&   | j  ddddd¡ |  | jd¡ dS )z¡
        L{UnixApplicationRunner.setupEnvironment} changes the root of the
        filesystem if passed a non-L{None} value for the C{chroot} parameter.
        ú/foo/barÚ.TN)rÏ   rê   rc   r  rT   r0   r0   r1   Útest_chroot8  s    z6UnixApplicationRunnerSetupEnvironmentTests.test_chrootc                 C   s(   | j  ddddd¡ |  | j| j¡ dS )z
        L{UnixApplicationRunner.setupEnvironment} does not change the root of
        the filesystem if passed L{None} for the C{chroot} parameter.
        Nr*  T)rÏ   rê   r¢   r  r$  rT   r0   r0   r1   Útest_noChrootA  s    z8UnixApplicationRunnerSetupEnvironmentTests.test_noChrootc                 C   s&   | j  ddddd¡ |  | jd¡ dS )zŸ
        L{UnixApplicationRunner.setupEnvironment} changes the working directory
        of the process to the path given for the C{rundir} parameter.
        Nr)  T)rÏ   rê   rc   r"  rT   r0   r0   r1   Útest_changeWorkingDirectoryJ  s    zFUnixApplicationRunnerSetupEnvironmentTests.test_changeWorkingDirectoryc              	   C   s:   t tƒ ƒ | j ddddd¡ W 5 Q R X |  | j¡ dS )z
        L{UnixApplicationRunner.setupEnvironment} daemonizes the process if
        C{False} is passed for the C{nodaemon} parameter.
        Nr*  F)r   ÚFakeDaemonizingReactorrÏ   rê   r€   r%  rT   r0   r0   r1   Útest_daemonizeS  s    z9UnixApplicationRunnerSetupEnvironmentTests.test_daemonizec                 C   s$   | j  ddddd¡ |  | j¡ dS )z–
        L{UnixApplicationRunner.setupEnvironment} does not daemonize the
        process if C{True} is passed for the C{nodaemon} parameter.
        Nr*  T)rÏ   rê   rƒ   r%  rT   r0   r0   r1   Útest_noDaemonize]  s    z;UnixApplicationRunnerSetupEnvironmentTests.test_noDaemonizec              	   C   sP   |   ¡ }| j dddd|¡ t|dƒ}t| ¡ ƒ}W 5 Q R X |  || j¡ dS )z
        L{UnixApplicationRunner.setupEnvironment} writes the process's PID to
        the file specified by the C{pidfile} parameter.
        Nr*  TÚrb)r°   rÏ   rê   r±   ÚintÚreadrc   r·   ©rH   r³   r´   r·   r0   r0   r1   Útest_nonDaemonPIDFilef  s
    z@UnixApplicationRunnerSetupEnvironmentTests.test_nonDaemonPIDFilec              	   C   sj   |   ¡ }ttƒ ƒ | j dddd|¡ W 5 Q R X t|dƒ}t| ¡ ƒ}W 5 Q R X |  || j	d ¡ dS )z½
        L{UnixApplicationRunner.setupEnvironment} writes the daemonized
        process's PID to the file specified by the C{pidfile} parameter if
        C{nodaemon} is C{False}.
        Nr*  Fr1  r¼   )
r°   r   r.  rÏ   rê   r±   r2  r3  rc   r·   r4  r0   r0   r1   Útest_daemonPIDFiler  s    z=UnixApplicationRunnerSetupEnvironmentTests.test_daemonPIDFilec              	   C   s<   t tƒ ƒ | j ddddd¡ W 5 Q R X |  | jd¡ dS )z
        L{UnixApplicationRunner.setupEnvironment} changes the process umask to
        the value specified by the C{umask} parameter.
        Nr*  Fé{   ©r   r.  rÏ   rê   rc   r#  rT   r0   r0   r1   r   €  s    z5UnixApplicationRunnerSetupEnvironmentTests.test_umaskc                 C   s(   | j  ddddd¡ |  | j| j¡ dS )zÑ
        L{UnixApplicationRunner.setupEnvironment} doesn't change the process
        umask if L{None} is passed for the C{umask} parameter and C{True} is
        passed for the C{nodaemon} parameter.
        Nr*  T)rÏ   rê   r¢   r#  r$  rT   r0   r0   r1   Útest_noDaemonizeNoUmaskŠ  s    zBUnixApplicationRunnerSetupEnvironmentTests.test_noDaemonizeNoUmaskc              	   C   s<   t tƒ ƒ | j ddddd¡ W 5 Q R X |  | jd¡ dS )zÖ
        L{UnixApplicationRunner.setupEnvironment} changes the process umask to
        C{0077} if L{None} is passed for the C{umask} parameter and C{False} is
        passed for the C{nodaemon} parameter.
        Nr*  Fé?   r8  rT   r0   r0   r1   Útest_daemonizedNoUmask”  s    zAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmask)rJ   rK   rL   rM   r!   r¦   rf   r$  rË   r&  r+  r,  r-  r/  r0  r5  r6  r   r9  r;  r0   r0   r0   r1   r  	  s    				
	

r  c                   @   sL   e Zd ZdZedkrdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dd„ ZdS )Ú*UnixApplicationRunnerStartApplicationTestsz>
    Tests for L{UnixApplicationRunner.startApplication}.
    Nr   c                    sü   t  ¡ }| ddddddddd	g	¡ t d
¡}t|ƒ| _g ‰ ‡ fdd„}trˆt 	| jj
¡j}t 	|¡j}| ¡ }| d¡ |  ||¡ n|  t | jj
¡t |¡¡ |  td|¡ |  tddd„ ¡ |  tddd„ ¡ | j |¡ |  ˆ ddddd	g¡ dS )zó
        L{UnixApplicationRunner.startApplication} calls
        L{UnixApplicationRunner.setupEnvironment} with the chroot, rundir,
        nodaemon, umask, and pidfile parameters from the configuration it is
        constructed with.
        ú
--nodaemonr‹   Z0070z--chrootz/foo/chrootz--rundirz/foo/rundirz	--pidfilez/foo/pidfileÚtest_setupEnvironmentc                    s   ˆ   |||||f¡ d S r'   )Úextendræ   ©r’   r0   r1   ÚfakeSetupEnvironment¹  s    z^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironmentrH   rê   rí   c                  _   s   d S r'   r0   ©ÚaÚkwr0   r0   r1   r«   Ô  r¬   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>ÚstartApplicationc                  _   s   d S r'   r0   rB  r0   r0   r1   r«   Õ  r¬   Té8   N)r    rg   ry   r   rÊ   r#   rÏ   r   ÚinspectZ	signaturerê   Z
parametersÚcopyÚpoprc   Z
getargspecr>   r   rE  )rH   rE   rQ   rA  ZsetupEnvironmentParametersZfakeSetupEnvironmentParametersr0   r@  r1   r>  §  sT        û

ÿ
ÿ
ÿþÿÿþz@UnixApplicationRunnerStartApplicationTests.test_setupEnvironmentc                    s4   ‡ fdd„}ˆ   td|¡ ti ƒ}| ddd¡ dS )zf
        L{UnixApplicationRunner.shedPrivileges} switches the user ID
        of the process.
        c                    s(   ˆ   | d¡ ˆ   |d¡ ˆ   |d¡ d S )NéÈ   é6   é#   ©rc   ©r@   r.   rì   rT   r0   r1   ÚswitchUIDPassâ  s    zUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPassÚ	switchUIDrL  rJ  rK  N)r>   r!   r#   rí   )rH   rO  rÏ   r0   rT   r1   Útest_shedPrivilegesÝ  s    z>UnixApplicationRunnerStartApplicationTests.test_shedPrivilegesc                 C   sD   dd„ }t i ƒ}|  td|¡ |  t|jddd¡}|  |jd¡ dS )z 
        An unexpected L{OSError} when calling
        L{twisted.scripts._twistd_unix.shedPrivileges}
        terminates the process via L{SystemExit}.
        c                 S   s   t tjdƒ‚d S r½   rÂ   rN  r0   r0   r1   ÚswitchUIDFailò  s    zZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFailrP  rL  rJ  Nr¼   )r#   r>   r!   rw   rx   rí   rc   r£   )rH   rR  rÏ   Úexcr0   r0   r1   Útest_shedPrivilegesErrorì  s     ÿzCUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesErrorc                    s®   t ˆ j|ˆ|ˆƒ ‡ ‡‡fdd„}‡ ‡fdd„}‡ ‡fdd„}ˆ  td|¡ ˆ  td|¡ ˆ  td	|¡ t ¡ }| d
dtˆƒg¡ t 	d¡}	t
|ƒˆ _t
|ƒ}
|
 |	¡ dS )zj
        Common code for tests which try to pass the the UID to
        L{UnixApplicationRunner}.
        c                    s   ˆ   | ˆ¡ ˆ   |ˆ¡ d S r'   rM  )r@   r.   ©rH   Ú	wantedGidÚ	wantedUidr0   r1   Ú
initgroups  s    zFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroupsc                    s   ˆ   | ˆ¡ d S r'   rM  )r@   )rH   rW  r0   r1   r&     s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuidc                    s   ˆ   | ˆ¡ d S r'   rM  )r.   )rH   rV  r0   r1   Úsetgid  s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgidrX  r&   rY  r=  r  r>  N)rB   r>   r   r6   r    rg   ry   r…   r   rÊ   r#   rÏ   rE  )rH   Z
wantedUserrW  ZwantedGrouprV  rX  r&   rY  rE   rQ   rÏ   r0   rU  r1   Ú_setUIDü  s&    ÿ þ

z2UnixApplicationRunnerStartApplicationTests._setUIDc                 C   s   |   dddd¡ dS )z½
        Starting an application with L{UnixApplicationRunner} configured
        with a UID and no GUID will result in the GUID being
        set to the default GUID for that UID.
        r  i  r  i’  N)rZ  rT   r0   r0   r1   Útest_setUidWithoutGid  s    z@UnixApplicationRunnerStartApplicationTests.test_setUidWithoutGidc                 C   sT   t  ¡ }|  d|dd¡ |  ¡ }|  dt|ƒ¡ d ||¡}|  ||d d ¡ dS )	zz
        If the specified UID is the same as the current UID of the process,
        then a warning is displayed.
        ZmorefooZmorebari÷  r¼   z\tried to drop privileges and setuid {} but uid is already {}; should we be root? Continuing.r   ÚmessageN)r6   r7   rZ  ÚflushWarningsrc   Úlenr    )rH   Z
currentUidZwarningsShownZexpectedWarningr0   r0   r1   Útest_setUidSameAsCurrentUid%  s     ÿÿzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUid)rJ   rK   rL   rM   r!   r¦   r>  rQ  rT  rZ  r[  r_  r0   r0   r0   r1   r<  Ÿ  s   6 	r<  c                   @   s,   e Zd ZdZedkrdZdd„ Zdd„ ZdS )Ú#UnixApplicationRunnerRemovePIDTestsz7
    Tests for L{UnixApplicationRunner.removePID}.
    Nr   c                 C   sV   t i ƒ}|  ¡ }t |¡ tj |d¡}t|dƒ ¡  | |¡ |  	tj 
|¡¡ dS )zp
        L{UnixApplicationRunner.removePID} deletes the file the name of
        which is passed to it.
        zfoo.pidr¯   N)r#   r°   r6   Úmakedirsr­   Újoinr±   Úcloserñ   rƒ   r¨   )rH   rÏ   r­   r³   r0   r0   r1   Útest_removePID=  s    

z2UnixApplicationRunnerRemovePIDTests.test_removePIDc                 C   sF   t i ƒ}| d¡ |  t¡}|  t|ƒd¡ |  |d jjtj¡ dS )zr
        Calling L{UnixApplicationRunner.removePID} with a non-existent filename
        logs an OSError.
        Zfakepidr¼   r   N)	r#   rñ   ZflushLoggedErrorsr¾   rc   r^  Úvaluer¿   ZENOENT)rH   rÏ   Úerrorsr0   r0   r1   Útest_removePIDErrorsK  s
    

z8UnixApplicationRunnerRemovePIDTests.test_removePIDErrors)rJ   rK   rL   rM   r!   r¦   rd  rg  r0   r0   r0   r1   r`  5  s
   r`  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚFakeNonDaemonizingReactora›  
    A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize}
    methods, but not announcing this, and logging whether the methods have been
    called.

    @ivar _beforeDaemonizeCalled: if C{beforeDaemonize} has been called or not.
    @type _beforeDaemonizeCalled: C{bool}
    @ivar _afterDaemonizeCalled: if C{afterDaemonize} has been called or not.
    @type _afterDaemonizeCalled: C{bool}
    c                 C   s   d| _ d| _d S r©   )Ú_beforeDaemonizeCalledÚ_afterDaemonizeCalledrT   r0   r0   r1   r]   d  s    z"FakeNonDaemonizingReactor.__init__c                 C   s
   d| _ d S ©NT)ri  rT   r0   r0   r1   ÚbeforeDaemonizei  s    z)FakeNonDaemonizingReactor.beforeDaemonizec                 C   s
   d| _ d S rk  )rj  rT   r0   r0   r1   ÚafterDaemonizem  s    z(FakeNonDaemonizingReactor.afterDaemonizec                 O   s   dS )z*
        Skip event registration.
        Nr0   )rH   r’   rD  r0   r0   r1   ÚaddSystemEventTriggerq  s    z/FakeNonDaemonizingReactor.addSystemEventTriggerN)rJ   rK   rL   rM   r]   rl  rm  rn  r0   r0   r0   r1   rh  X  s
   rh  c                   @   s   e Zd ZdZdS )r.  z
    A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize}
    methods, announcing this, and logging whether the methods have been called.
    N©rJ   rK   rL   rM   r0   r0   r0   r1   r.  x  s   r.  c                   @   s   e Zd ZdZdZdd„ ZdS )r
  z²
    A dummy reactor, only providing a C{run} method and checking that it
    has been called.

    @ivar called: if C{run} has been called or not.
    @type called: C{bool}
    Fc                 C   s   | j rtdƒ‚d| _ dS )zV
        A fake run method, checking that it's been called one and only time.
        zAlready calledTN)r  ÚRuntimeErrorrT   r0   r0   r1   rà   ‹  s    úDummyReactor.runN)rJ   rK   rL   rM   r  rà   r0   r0   r0   r1   r
    s   r
  c                   @   s®   e Zd ZdZdd„ Zedkr"de_dd„ Zdd	„ Zedkr@de_d
d„ Z	dd„ Z
edkr^de
_dd„ Zedkrtde_dd„ ZedkrŠde_dd„ Zdd„ Zdd„ Zdd„ ZdS )ÚAppProfilingTestsz'
    Tests for L{app.AppProfiler}.
    c              	   C   s~   t  ¡ }|  ¡ |d< d|d< t |¡}tƒ }| |¡ |  |j¡ t	|d ƒ}| 
¡ }W 5 Q R X |  d|¡ |  d|¡ dS )zŒ
        L{app.ProfileRunner.run} should call the C{run} method of the reactor
        and save profile data in the specified file.
        r  r‡   rq  úfunction callsN©r    rg   r°   r   r†   r
  rà   r€   r  r±   r3  rq   ©rH   rk   r‡   r|   r´   Údatar0   r0   r1   Útest_profileš  s    

zAppProfilingTests.test_profileNzprofile module not availablec                 C   sP   t ƒ }|  td|¡}||ƒ}| ¡  | ¡  | ¡ }|  d|¡ |  d|¡ d S )Nrž   rs  z(run))r   r>   rš   Úprint_statsZrestorerz   rq   )rH   Z
statsClassr  Úoutrž   Zstatsrv  r0   r0   r1   Ú
_testStats±  s    zAppProfilingTests._testStatsc                 C   s`   t  ¡ }|  ¡ |d< d|d< d|d< t |¡}tƒ }| |¡ |  |j¡ |  	t
j|d ¡ dS )z˜
        With the C{savestats} option specified, L{app.ProfileRunner.run}
        should save the raw stats object instead of a summary output.
        r  r‡   TÚ	savestatsN©r    rg   r°   r   r†   r
  rà   r€   r  rz  ÚpstatsZStats©rH   rk   r‡   r|   r0   r0   r1   Útest_profileSaveStatsÃ  s    

z'AppProfilingTests.test_profileSaveStatsc              	   C   s`   t j ¡ }t ¡ }d|d< t |¡}dt jd< z|  	t
|jd¡ W 5 t j ¡  t j |¡ X dS )z†
        When the C{profile} module is not present, L{app.ProfilerRunner.run}
        should raise a C{SystemExit} exception.
        r  r‡   N©rš   ÚmodulesrH  r    rg   r   r†   ÚclearÚupdaterw   rx   rà   ©rH   ZsavedModulesrk   r‡   r0   r0   r1   Útest_withoutProfileØ  s    



z%AppProfilingTests.test_withoutProfilec                 C   st   G dd„ dt jƒ}|  t d|¡ t ¡ }|  ¡ |d< d|d< t |¡}tƒ }t	j
}|  t|j|¡ |  t	j
|¡ dS )z…
        When an error happens during the print of the stats, C{sys.stdout}
        should be restored to its initial value.
        c                   @   s   e Zd Zdd„ ZdS )zGAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfilec                 S   s   t dƒ‚d S )NZBoom©rp  rT   r0   r0   r1   rx  ñ  s    zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_statsN)rJ   rK   rL   rx  r0   r0   r0   r1   ÚErroneousProfileð  s   r‡  ÚProfiler  r‡   N)r  rˆ  r>   r    rg   r°   r   r†   r
  rš   rž   rw   rp  rà   r¢   )rH   r‡  rk   r‡   r|   Z	oldStdoutr0   r0   r1   Útest_profilePrintStatsErrorë  s    
z-AppProfilingTests.test_profilePrintStatsErrorc              	   C   s~   t  ¡ }|  ¡ |d< d|d< t |¡}tƒ }| |¡ |  |j¡ t	|d ƒ}| 
¡ }W 5 Q R X |  d|¡ |  d|¡ dS )z
        L{app.CProfileRunner.run} should call the C{run} method of the
        reactor and save profile data in the specified file.
        r  ÚcProfiler‡   rà   rs  Nrt  ru  r0   r0   r1   Útest_cProfile  s    

zAppProfilingTests.test_cProfilezcProfile module not availablec                 C   s`   t  ¡ }|  ¡ |d< d|d< d|d< t |¡}tƒ }| |¡ |  |j¡ |  	t
j|d ¡ dS )z¡
        With the C{savestats} option specified,
        L{app.CProfileRunner.run} should save the raw stats object
        instead of a summary output.
        r  rŠ  r‡   Tr{  Nr|  r~  r0   r0   r1   Útest_cProfileSaveStats  s    

z(AppProfilingTests.test_cProfileSaveStatsc              	   C   s`   t j ¡ }dt jd< t ¡ }d|d< t |¡}z|  	t
|jd¡ W 5 t j ¡  t j |¡ X dS )zª
        When the C{cProfile} module is not present,
        L{app.CProfileRunner.run} should raise a C{SystemExit}
        exception and log the C{ImportError}.
        NrŠ  r‡   r€  r„  r0   r0   r1   Útest_withoutCProfile0  s    



z&AppProfilingTests.test_withoutCProfilec                 C   s@   t  ¡ }|  ¡ |d< d|d< |  ttj|¡}|  t|ƒd¡ dS )zq
        Check that L{app.AppProfiler} raises L{SystemExit} when given an
        unknown profiler name.
        r  Zfoobarr‡   z!Unsupported profiler name: foobarN)	r    rg   r°   rw   rx   r   r†   rc   r…   )rH   rk   Úerrorr0   r0   r1   Útest_unknownProfilerC  s
    z&AppProfilingTests.test_unknownProfilerc                 C   s   t  i ¡}|  |jd¡ dS )zU
        L{app.Profiler} defaults to the cprofile profiler if not specified.
        ÚcprofileN©r   r†   rc   r‡   ©rH   r‡   r0   r0   r1   Útest_defaultProfilerP  s    
z&AppProfilingTests.test_defaultProfilerc                 C   s    t  ddi¡}|  |jd¡ dS )ze
        The case of the profiler name passed to L{app.AppProfiler} is not
        relevant.
        r‡   ZCprOfiler  Nr‘  r’  r0   r0   r1   Útest_profilerNameCaseInsentiveX  s    z0AppProfilingTests.test_profilerNameCaseInsentive)rJ   rK   rL   rM   rw  r  r¦   rz  r  r…  r‰  r‹  rŠ  rŒ  r  r  r“  r”  r0   r0   r0   r1   rr  •  s,   rr  c                    s(   g ‰ t j‰‡ ‡fdd„}| t d|ƒ ˆ S )a  
    Patch L{logger.textFileLogObserver} to record every call and keep a
    reference to the passed log file for tests.

    @param patch: a callback for patching (usually L{unittest.TestCase.patch}).

    @return: the list that keeps track of the log files.
    @rtype: C{list}
    c                    s   ˆ   | ¡ ˆ| f|ž|ŽS r'   rå   )ZlogFiler’   Úkwargs©ÚlogFilesZoldFileLogObserverr0   r1   Úobservero  s    
z+_patchTextFileLogObserver.<locals>.observerÚtextFileLogObserver)r	   r™  )r>   r˜  r0   r–  r1   Ú_patchTextFileLogObserverb  s
    
rš  c                    s*   g ‰ G ‡ fdd„dt ƒ}|  td|¡ ˆ S )zu
    Make fake syslog, and return list to which prefix and then log
    messages will be appended if it is used.
    c                       s$   e Zd Z‡ fdd„Z‡ fdd„ZdS )z(_setupSyslog.<locals>.fakesyslogobserverc                    s   ˆ   |¡ d S r'   rå   )rH   Úprefix©ZlogMessagesr0   r1   r]   €  s    z1_setupSyslog.<locals>.fakesyslogobserver.__init__c                    s   ˆ   |¡ d S r'   rå   )rH   Z	eventDictrœ  r0   r1   Úemitƒ  s    z-_setupSyslog.<locals>.fakesyslogobserver.emitN)rJ   rK   rL   r]   r  r0   rœ  r0   r1   Úfakesyslogobserver  s   rž  ZSyslogObserver)rf   r>   r%   )ZtestCaserž  r0   rœ  r1   Ú_setupSyslogx  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	i e
jfdd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedks„edkrŠde_dd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ ZdS )(ÚAppLoggerTestsz†
    Tests for L{app.AppLogger}.

    @ivar observers: list of observers installed during the tests.
    @type observers: C{list}
    c                    s$   g ˆ _ ‡ fdd„}ˆ  td|¡ dS )zˆ
        Override L{globaLogBeginner.beginLoggingTo} so that we can trace the
        observers installed in C{self.observers}.
        c                    s$   | D ]}ˆ j  |¡ t |¡ qd S r'   )Ú	observersrr   r   ZaddObserver)r¡  r˜  rT   r0   r1   ÚbeginLoggingToš  s    z,AppLoggerTests.setUp.<locals>.beginLoggingTor¢  N)r¡  r>   r   )rH   r¢  r0   rT   r1   rË   “  s    zAppLoggerTests.setUpc                 C   s   | j D ]}t |¡ qdS )z1
        Remove all installed observers.
        N)r¡  r   ÚremoveObserver©rH   r˜  r0   r0   r1   ÚtearDown¢  s    
zAppLoggerTests.tearDownc                 C   s   t tƒG dd„ dtƒƒ}|ƒ S )zÂ
        Make a new observer which captures all logs sent to it.

        @return: An observer that stores all logs sent to it.
        @rtype: Callable that implements L{ILogObserver}.
        c                   @   s   e Zd Zg Zdd„ ZdS )z2AppLoggerTests._makeObserver.<locals>.TestObserverc                 S   s   | j  |¡ d S r'   )Ú_logsrr   )rH   Zeventr0   r0   r1   Ú__call__µ  s    z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__N)rJ   rK   rL   r¦  r§  r0   r0   r0   r1   ÚTestObserver±  s   r¨  )r   r   rf   )rH   r¨  r0   r0   r1   Ú_makeObserverª  s    zAppLoggerTests._makeObserverc                 C   s@   |   | j|g¡ |  d|jd d ¡ |  d|jd d ¡ dS )z
        Ensure that initial C{twistd} logs are written to logs.

        @param observer: The observer made by L{self._makeObserver).
        ústarting upr   Z
log_formatzreactor classr¼   N)rc   r¡  rq   r¦  r¤  r0   r0   r1   Ú_checkObserver»  s    zAppLoggerTests._checkObserverc                    s:   t  i ¡}|  ¡ ‰ ‡ fdd„|_| tƒ ¡ |  ˆ ¡ dS )z”
        L{app.AppLogger.start} calls L{globalLogBeginner.addObserver}, and then
        writes some messages about twistd and the reactor.
        c                      s   ˆ S r'   r0   r0   ©r˜  r0   r1   r«   Í  r¬   z+AppLoggerTests.test_start.<locals>.<lambda>N)r   Ú	AppLoggerr©  Ú_getLogObserverrR   r   r«  )rH   r	   r0   r¬  r1   Ú
test_startÆ  s
    
zAppLoggerTests.test_startc                 C   s<   t ƒ }|  ¡ }| t|¡ t i ¡}| |¡ |  |¡ dS )zµ
        When the L{ILogObserver} component is available on the application,
        that object will be used as the log observer instead of constructing a
        new one.
        N)r   r©  ÚsetComponentr   r   r­  rR   r«  )rH   rQ   r˜  r	   r0   r0   r1   Ú$test_startUsesApplicationLogObserverÒ  s    

z3AppLoggerTests.test_startUsesApplicationLogObserverc                    s8   |   ¡ ‰ d‡ fdd„i}| |¡ ||ƒ}| |¡ ˆ S )a  
        Set up an AppLogger which exercises the C{logger} configuration option.

        @type application: L{Componentized}
        @param application: The L{Application} object to pass to
            L{app.AppLogger.start}.
        @type extraLogArgs: C{dict}
        @param extraLogArgs: extra values to pass to AppLogger.
        @type appLogger: L{AppLogger} class, or a subclass
        @param appLogger: factory for L{AppLogger} instances.

        @rtype: C{list}
        @return: The logs accumulated by the log observer.
        r	   c                      s   ˆ S r'   r0   r0   r¬  r0   r1   r«   ñ  r¬   z7AppLoggerTests._setupConfiguredLogger.<locals>.<lambda>)r©  rƒ  rR   )rH   rQ   ZextraLogArgsZ	appLoggerZlogArgsr	   r0   r¬  r1   Ú_setupConfiguredLoggerà  s    

z%AppLoggerTests._setupConfiguredLoggerc                 C   s   t ƒ }|  |  |¡¡ dS )a  
        When the C{logger} key is specified in the configuration dictionary
        (i.e., when C{--logger} is passed to twistd), the initial log observer
        will be the log observer returned from the callable which the value
        refers to in FQPN form.
        N)r   r«  r²  rP   r0   r0   r1   Ú#test_startUsesConfiguredLogObserverø  s    z2AppLoggerTests.test_startUsesConfiguredLogObserverc                 C   s<   |   ¡ }tƒ }| t|¡ |  |  |¡¡ |  |jg ¡ dS )zk
        C{--logger} takes precedence over a L{ILogObserver} component set on
        Application.
        N)r©  r   r°  r   r«  r²  rc   r¦  )rH   r˜  rQ   r0   r0   r1   Ú(test_configuredLogObserverBeatsComponent  s
    z7AppLoggerTests.test_configuredLogObserverBeatsComponentc                 C   s8   g }t ƒ }| t|j¡ |  |  |¡¡ |  |g ¡ dS )zq
        C{--logger} takes precedence over a L{LegacyILogObserver} component
        set on Application.
        N)r   r°  ÚLegacyILogObserverrr   r«  r²  rc   )rH   ÚnonlogsrQ   r0   r0   r1   Ú.test_configuredLogObserverBeatsLegacyComponent  s
    z=AppLoggerTests.test_configuredLogObserverBeatsLegacyComponentc                 C   sZ   g }|   ¡ }tƒ }| t|¡ | t|j¡ t i ¡}| |¡ |  	|¡ |  
|g ¡ dS )zw
        A L{ILogObserver} takes precedence over a L{LegacyILogObserver}
        component set on Application.
        N)r©  r   r°  r   rµ  rr   r   r­  rR   r«  rc   )rH   r¶  r˜  rQ   r	   r0   r0   r1   Ú.test_loggerComponentBeatsLegacyLoggerComponent  s    


z=AppLoggerTests.test_loggerComponentBeatsLegacyLoggerComponentc                 C   s6   t | ƒ}tƒ }|  |  |ddit¡¡ |  |g ¡ dS )z`
        C{--logger} takes precedence over a C{--syslog} command line
        argument.
        r%   TN)rŸ  r   r«  r²  r$   rc   )rH   ÚlogsrQ   r0   r0   r1   Ú%test_configuredLogObserverBeatsSyslog-  s    
þz4AppLoggerTests.test_configuredLogObserverBeatsSyslogNz&Not on POSIX, or syslog not available.c                 C   s:   t ƒ }|  ¡ }|  |  |ddi¡¡ |  tj |¡¡ dS )za
        C{--logger} takes precedence over a C{--logfile} command line
        argument.
        Úlogfiler­   N)r   r°   r«  r²  rƒ   r6   r­   r¨   )rH   rQ   r­   r0   r0   r1   Ú&test_configuredLogObserverBeatsLogfile?  s    
ÿz5AppLoggerTests.test_configuredLogObserverBeatsLogfilec                 C   s~   t  ddi¡}t| jƒ}| ¡  |  t|ƒd¡ |  |d tj	¡ t  ddi¡}| ¡  |  t|ƒd¡ |  |d tj	¡ dS )z’
        When logfile is empty or set to C{-}, L{app.AppLogger._getLogObserver}
        returns a log observer pointing at C{sys.stdout}.
        r»  ú-r¼   r   Ú r  N)
r   r­  rš  r>   r®  rc   r^  r¢   rš   rž   )rH   r	   r—  r0   r0   r1   Útest_getLogObserverStdoutK  s    
z(AppLoggerTests.test_getLogObserverStdoutc                 C   sV   t | jƒ}|  ¡ }t d|i¡}| ¡  |  t|ƒd¡ |  |d jt	j 
|¡¡ dS )z•
        When passing the C{logfile} option, L{app.AppLogger._getLogObserver}
        returns a log observer pointing at the specified path.
        r»  r¼   r   N)rš  r>   r°   r   r­  r®  rc   r^  r­   r6   Úabspath)rH   r—  Úfilenamer	   r0   r0   r1   Útest_getLogObserverFile_  s    

ÿz&AppLoggerTests.test_getLogObserverFilec                    sp   g ‰ t ƒ }‡ fdd„}|  td|¡ t i ¡}||_| ¡  |  ˆ |g¡ | ¡  |  ˆ |g¡ |  |j¡ dS )zÀ
        L{app.AppLogger.stop} removes the observer created in C{start}, and
        reinitialize its C{_observer} so that if C{stop} is called several
        times it doesn't break.
        c                    s   ˆ   | ¡ d S r'   rå   r¬  ©Zremovedr0   r1   Úremovex  s    z(AppLoggerTests.test_stop.<locals>.remover£  N)	rf   r>   r   r   r­  Z	_observerrÔ   rc   rj   )rH   r˜  rÄ  r	   r0   rÃ  r1   Ú	test_stopo  s    
zAppLoggerTests.test_stopc                    sz   g ‰t  i ¡}ttƒG ‡fdd„dtƒƒ‰ ‡ fdd„|_| tƒ ¡ |  dt	ˆd ƒ¡ |  
| jg¡}|  t|ƒd¡ dS )zt
        L{app.AppLogger} using a legacy logger observer still works, wrapping
        it in a compat shim.
        c                       s   e Zd ZdZ‡ fdd„ZdS )z;AppLoggerTests.test_legacyObservers.<locals>.LoggerObserverzX
            An observer which implements the legacy L{LegacyILogObserver}.
            c                    s   ˆ   |¡ dS )z<
                Add C{x} to the logs list.
                Nrå   )rH   Úx©r¹  r0   r1   r§  ’  s    zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__N)rJ   rK   rL   rM   r§  r0   rÇ  r0   r1   ÚLoggerObserver  s   rÈ  c                      s   ˆ ƒ S r'   r0   r0   )rÈ  r0   r1   r«   ˜  r¬   z5AppLoggerTests.test_legacyObservers.<locals>.<lambda>rª  r   N)r   r­  r   rµ  rf   Z_observerFactoryrR   r   rq   r   r]  Útest_legacyObserversrc   r^  ©rH   r	   Úwarningsr0   )rÈ  r¹  r1   rÉ  …  s    

ÿz#AppLoggerTests.test_legacyObserversc                    sr   g ‰ t  i ¡}‡ fdd„|_| tƒ ¡ |  dtˆ d ƒ¡ |  | jg¡}|  	t
|ƒd¡ |  	|d d d¡ dS )	zÐ
        L{app.AppLogger} using a logger observer which does not implement
        L{ILogObserver} or L{LegacyILogObserver} will be wrapped in a compat
        shim and raise a L{DeprecationWarning}.
        c                      s   ˆ j S r'   rå   r0   rÇ  r0   r1   r«   ©  r¬   zAAppLoggerTests.test_unmarkedObserversDeprecated.<locals>.<lambda>rª  r   r¼   r\  aZ  Passing a logger factory which makes log observers which do not implement twisted.logger.ILogObserver or twisted.python.log.ILogObserver to twisted.application.app.AppLogger was deprecated in Twisted 16.2. Please use a factory that produces twisted.logger.ILogObserver (or the legacy twisted.python.log.ILogObserver) implementing objects instead.N)r   r­  r®  rR   r   rq   r   r]  Ú test_unmarkedObserversDeprecatedrc   r^  rÊ  r0   rÇ  r1   rÌ  ¡  s    
ÿÿz/AppLoggerTests.test_unmarkedObserversDeprecated)rJ   rK   rL   rM   rË   r¥  r©  r«  r¯  r±  r   r­  r²  r³  r´  r·  r¸  rº  r!   r%   r¦   r¼  r¿  rÂ  rÅ  rÉ  rÌ  r0   r0   r0   r1   r   ‹  s0   ÿ
ÿr   c                   @   sb   e Zd ZdZedkr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kr^de_dS )ÚUnixAppLoggerTestszw
    Tests for L{UnixAppLogger}.

    @ivar signals: list of signal handlers installed.
    @type signals: C{list}
    Nr   c                    s$   g ˆ _ ‡ fdd„}ˆ  td|¡ dS )zs
        Fake C{signal.signal} for not installing the handlers but saving them
        in C{self.signals}.
        c                    s   ˆ j  | |f¡ d S r'   )Úsignalsrr   )r¸   r´   rT   r0   r1   Ú
fakeSignalÏ  s    z,UnixAppLoggerTests.setUp.<locals>.fakeSignalÚsignalN)rÎ  r>   rÐ  )rH   rÏ  r0   rT   r1   rË   È  s    zUnixAppLoggerTests.setUpc                 C   s~   t | jƒ}tdddœƒ}| ¡  |  t|ƒd¡ |  |d tj¡ tdddœƒ}| ¡  |  t|ƒd¡ |  |d tj¡ dS )	z°
        When non-daemonized and C{logfile} is empty or set to C{-},
        L{UnixAppLogger._getLogObserver} returns a log observer pointing at
        C{sys.stdout}.
        r½  T©r»  rè   r¼   r   r¾  r  N)	rš  r>   r$   r®  rc   r^  r¢   rš   rž   ©rH   r—  r	   r0   r0   r1   r¿  Õ  s    
z,UnixAppLoggerTests.test_getLogObserverStdoutc                 C   s0   t dddœƒ}|  t|j¡}|  t|ƒd¡ dS )z
        When daemonized and C{logfile} is set to C{-},
        L{UnixAppLogger._getLogObserver} raises C{SystemExit}.
        r½  FrÑ  z&Daemons cannot log to stdout, exiting!N)r$   rw   rx   r®  rc   r…   )rH   r	   rŽ  r0   r0   r1   Útest_getLogObserverStdoutDaemonè  s    z2UnixAppLoggerTests.test_getLogObserverStdoutDaemonc                    s²   t | jƒ}|  ¡ }td|iƒ}| ¡  |  t|ƒd¡ |  |d jtj 	|¡¡ |  t| j
ƒd¡ |  | j
d d tj¡ tƒ ‰ ‡ fdd„}||d _| j
d d }|ddƒ ˆ S )zÓ
        When C{logfile} contains a file name, L{app.AppLogger._getLogObserver}
        returns a log observer pointing at the specified path, and a signal
        handler rotating the log is installed.
        r»  r¼   r   c                      s   ˆ   d ¡ d S r'   )Úcallbackr0   ©Údr0   r1   Úrotate  s    z:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotateN)rš  r>   r°   r$   r®  rc   r^  r­   r6   rÀ  rÎ  rÐ  ÚSIGUSR1r   r×  )rH   r—  rÁ  r	   r×  Z	rotateLogr0   rÕ  r1   rÂ  ò  s    


z*UnixAppLoggerTests.test_getLogObserverFilec                    sH   ‡ fdd„}ˆ   td|¡ ˆ  ¡ }td|iƒ}| ¡  ˆ  ˆ jg ¡ dS )zy
        If a signal handler is already installed,
        L{UnixAppLogger._getLogObserver} doesn't override it.
        c                    s   ˆ   | tj¡ tƒ S r'   )rc   rÐ  rØ  rf   )r¸   rT   r0   r1   ÚfakeGetSignal  s    zVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignalÚ	getsignalr»  N)r>   rÐ  r°   r$   r®  rc   rÎ  )rH   rÙ  rÁ  r	   r0   rT   r1   Ú,test_getLogObserverDontOverrideSignalHandler  s    z?UnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandlerc                 C   sN   t | jƒ}tdddœƒ}| ¡  |  t|ƒd¡ |  |d jtj d¡¡ dS )z¶
        When daemonized and C{logfile} is empty, the observer returned by
        L{UnixAppLogger._getLogObserver} points at C{twistd.log} in the current
        directory.
        r¾  FrÑ  r¼   r   z
twistd.logN)	rš  r>   r$   r®  rc   r^  r­   r6   rÀ  rÒ  r0   r0   r1   Útest_getLogObserverDefaultFile  s
    
z1UnixAppLoggerTests.test_getLogObserverDefaultFilec                 C   sP   t | ƒ}tdddœƒ}| ¡ }|  |dg¡ |ddiƒ |  |dddig¡ dS )z’
        If C{syslog} is set to C{True}, L{UnixAppLogger._getLogObserver} starts
        a L{syslog.SyslogObserver} with given C{prefix}.
        Tztest-prefix)r%   r›  rC  ÚbN)rŸ  r$   r®  rc   )rH   r¹  r	   r˜  r0   r0   r1   Útest_getLogObserverSyslog-  s    z,UnixAppLoggerTests.test_getLogObserverSyslogzSyslog not available)rJ   rK   rL   rM   r!   r¦   rË   r¿  rÓ  rÂ  rÛ  rÜ  rÞ  r%   r0   r0   r0   r1   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„ Zdd„ Zdd„ Zd d!„ Zd"S )#ÚDaemonizeTestszH
    Tests for L{_twistd_unix.UnixApplicationRunner} daemonization.
    c                 C   sb   t ƒ | _t ¡ | _|  td| j¡ t | j¡| _t	 
d¡| j_tj| j_tj| j_dd„ | j_d S )Nr6   rÆ   c                  W   s   d S r'   r0   r@  r0   r0   r1   r«   K  r¬   z&DaemonizeTests.setUp.<locals>.<lambda>)r   Úmockosr    rg   rk   r>   r!   r#   rÏ   r   rÊ   rQ   rš   rž   rî   Ústderrrï   rð   rT   r0   r0   r1   rË   C  s    


zDaemonizeTests.setUpc              
   C   sV   t tƒ ƒ | j ¡  W 5 Q R X |  | jjdddddddg¡ |  | jjddg¡ d	S )
zw
        When double fork succeeded in C{daemonize}, the child process writes
        B{0} to the status pipe.
        ©r!  r*  ©r‰   r:  ©ÚforkTÚsetsid)r²   éþÿÿÿó   0©Úunlinkz
twistd.pidéýÿÿÿrç  N)r   r.  rÏ   rV   rc   rà  ÚactionsÚclosedrT   r0   r0   r1   Útest_successN  s      ÿþzDaemonizeTests.test_successc              	   C   sh   d| j _d| j _ttƒ ƒ |  t| jj¡ W 5 Q R X |  	| j j
ddddddg¡ |  	| j jd	g¡ d
S )zˆ
        The parent process initiating the C{daemonize} call reads data from the
        status pipe and then exit the process.
        Frè  râ  rã  rä  ©r3  éÿÿÿÿéd   ©Úexitr   ré  rð  N)rà  ÚchildÚreadDatar   r.  rw   ÚSystemErrorrÏ   rV   rc   rì  rí  rT   r0   r0   r1   Útest_successInParent\  s      ÿþz#DaemonizeTests.test_successInParentc              	      s|   g ‰ ‡ fdd„}|| j _ttƒ ƒ | j ¡  W 5 Q R X |  | j jddddddg¡ |  | j jdd	g¡ |  d
d
gˆ ¡ dS )z‚
        If the C{os.write} call to the status pipe raises an B{EINTR} error,
        the process child retries to write.
        c                    s(   ˆ   | |f¡ tˆ ƒdkr$ttjƒ‚d S r'  ©rr   r^  ÚIOErrorr¿   ZEINTR)Úfdrv  ©Zwrittenr0   r1   ÚraisingWrites  s    z6DaemonizeTests.test_successEINTR.<locals>.raisingWriterâ  rã  rä  ræ  ré  rë  rç  )rç  rè  N)	rà  r²   r   r.  rÏ   rV   rc   rì  rí  )rH   rü  r0   rû  r1   Útest_successEINTRl  s     ÿþz DaemonizeTests.test_successEINTRc              	      s†   g ‰ ‡ fdd„}|| j _d| j _ttƒ ƒ |  t| jj¡ W 5 Q R X |  	| j j
dddddg¡ |  	| j jd	g¡ |  	d
d
gˆ ¡ dS )z
        If the C{os.read} call on the status pipe raises an B{EINTR} error, the
        parent child retries to read.
        c                    s(   ˆ   | |f¡ tˆ ƒdkr$ttjƒ‚dS )Nr¼   rè  rø  )rú  Úsize©r3  r0   r1   ÚraisingReadŠ  s    
z=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadFrâ  rã  rä  rò  ré  rð  )rð  rñ  N)rà  r3  rô  r   r.  rw   rö  rÏ   rV   rc   rì  rí  )rH   r   r0   rÿ  r1   Útest_successInParentEINTRƒ  s     ÿþz(DaemonizeTests.test_successInParentEINTRc                    sŒ   G ‡ fdd„dt jƒ}|ƒ }| | jj¡ ttƒ ƒ |  t| jj	¡ W 5 Q R X |  
| jjddddddd|fd	g¡ |  
| jjd
dg¡ dS )z¶
        Assert L{UnixApplicationRunner.postApplication} writes
        C{reported} to its status pipe if the service raises an
        exception whose message is C{raised}.
        c                       s   e Zd Z‡ fdd„ZdS )z6DaemonizeTests.assertErrorWritten.<locals>.FakeServicec                    s   t ˆ ƒ‚d S r'   r†  rT   ©Úraisedr0   r1   rø   ¥  s    zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startServiceN)rJ   rK   rL   rø   r0   r  r0   r1   rû   £  s   rû   râ  rã  rä  ræ  r²   rç  ré  rë  N)r   rF   rõ   rÏ   rQ   r   r.  rw   rp  rV   rc   rà  rì  rí  )rH   r  Úreportedrû   ZerrorServicer0   r  r1   ÚassertErrorWritten  s     þþz!DaemonizeTests.assertErrorWrittenc                 C   s   | j ddd dS )z„
        If an error happens during daemonization, the child process writes the
        exception error to the status pipe.
        zSomething is wrongs"   1 RuntimeError: Something is wrong©r  r  N©r  rT   r0   r0   r1   Ú
test_error¶  s    ÿzDaemonizeTests.test_errorc                 C   s   | j ddd dS )z»
        If an error happens during daemonization, and that error's
        message is Unicode, the child encodes the message as ascii
        with backslash Unicode code points.
        u   â€¢s   1 RuntimeError: \u2022r  Nr  rT   r0   r0   r1   Útest_unicodeErrorÀ  s    ÿz DaemonizeTests.test_unicodeErrorc              	   C   s€   d| j _|| j _tƒ }|  td|¡ ttƒ ƒ |  t	| j
j¡ W 5 Q R X |  | ¡ |¡ |  | j j|¡ |  | j jdg¡ dS )a  
        Make L{os.read} appear to return C{readData}, and assert that
        L{UnixApplicationRunner.postApplication} writes
        C{errorMessage} to standard error and executes the calls
        against L{os} functions specified in C{mockOSActions}.
        FÚ
__stderr__rð  N)rà  rô  rõ  r   r>   rš   r   r.  rw   rö  rÏ   rV   rc   rz   rì  rí  )rH   rõ  ÚerrorMessageÚmockOSActionsZerrorIOr0   r0   r1   ÚassertErrorInParentBehaviorË  s    z*DaemonizeTests.assertErrorInParentBehaviorc              	   C   s    | j ddddddddgd	 d
S )zÍ
        When the child writes an error message to the status pipe
        during daemonization, the parent writes the repr of the
        message to C{stderr} and exits with non-zero status code.
        s    1 Exception: An identified errorzgAn error has occurred: b'Exception: An identified error'
Please look at log file for more information.
râ  rã  rä  rï  ©ró  r¼   ré  ©rõ  r  r  N©r  rT   r0   r0   r1   Útest_errorInParentÞ  s        þûz!DaemonizeTests.test_errorInParentc              	   C   s    | j ddddddddgd	 d
S )zØ
        When the child writes a non-ASCII error message to the status
        pipe during daemonization, the parent writes the repr of the
        message to C{stderr} and exits with a non-zero status code.
        s   1 Exception: ÿzXAn error has occurred: b'Exception: \xff'
Please look at log file for more information.
râ  rã  rä  rï  r  ré  r  Nr  rT   r0   r0   r1   Útest_nonASCIIErrorInParentï  s        þúz)DaemonizeTests.test_nonASCIIErrorInParentc              	   C   s4   d}d  d¡}| j|d  |¡ddddd	d
gd dS )a
  
        When the child writes a non-ASCII error message to the status
        pipe during daemonization, and that message is too longer, the
        parent writes the repr of the truncated message to C{stderr}
        and exits with a non-zero status code.
        ód   1 RuntimeError: \u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022zb'RuntimeError: {}'zb\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022\\u2022zHAn error has occurred: {}
Please look at log file for more information.
râ  rã  rä  rï  r  ré  r  N)r    r  )rH   ZtruncatedMessageZreportedMessager0   r0   r1   Ú&test_errorInParentWithTruncatedUnicode  s    
þ    þùz5DaemonizeTests.test_errorInParentWithTruncatedUnicodec                 C   s   | j ddd dS )z{
        If an error occurs during daemonization and its message is too
        long, it's truncated by the child.
        ZÈxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsd   1 RuntimeError: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr  Nr  rT   r0   r0   r1   Útest_errorMessageTruncated  s    þz)DaemonizeTests.test_errorMessageTruncatedc                 C   s   | j ddd dS )z¾
        If an error occurs during daemonization and its message is
        unicode and too long, it's truncated by the child, even if
        this splits a unicode escape sequence.
        uZ   â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢r  r  Nr  rT   r0   r0   r1   Ú!test_unicodeErrorMessageTruncated%  s    þz0DaemonizeTests.test_unicodeErrorMessageTruncatedc                 C   s.   t ƒ }| j |¡ |  |j¡ |  |j¡ dS )z¸
        C{daemonize} indeed calls L{IReactorDaemonize.beforeDaemonize} and
        L{IReactorDaemonize.afterDaemonize} if the reactor implements
        L{IReactorDaemonize}.
        N)r.  rÏ   r&  r€   ri  rj  r(  r0   r0   r1   Útest_hooksCalled1  s    zDaemonizeTests.test_hooksCalledc                 C   s.   t ƒ }| j |¡ |  |j¡ |  |j¡ dS )zÀ
        C{daemonize} does NOT call L{IReactorDaemonize.beforeDaemonize} or
        L{IReactorDaemonize.afterDaemonize} if the reactor does NOT implement
        L{IReactorDaemonize}.
        N)rh  rÏ   r&  rƒ   ri  rj  r(  r0   r0   r1   Útest_hooksNotCalled=  s    z"DaemonizeTests.test_hooksNotCalledN)rJ   rK   rL   rM   rË   rî  r÷  rý  r  r  r  r	  r  r  r  r  r  r  r  r  r0   r0   r0   r1   rß  >  s"   

rß  c                   @   s   e Zd ZdZdS )ÚSignalCapturingMemoryReactorz‰
    MemoryReactor that implements the _ISupportsExitSignalCapturing interface,
    all other operations identical to MemoryReactor.
    Nro  r0   r0   r0   r1   r  J  s   r  c                       s4   e Zd ZdZeZ‡ fdd„Zdd„ Zdd„ Z‡  Z	S )ÚStubApplicationRunnerWithSignalzï
    An application runner that uses a SignalCapturingMemoryReactor and
    has a _signalValue attribute that it will set in the reactor.

    @ivar _signalValue: The signal value to set on the reactor's _exitSignal
        attribute.
    c                    s   t t| ƒ |¡ d | _d S r'   )Úsuperr  r]   Ú_signalValuer   ©Ú	__class__r0   r1   r]   ]  s    z(StubApplicationRunnerWithSignal.__init__c                 C   s   dS )z
        Does nothing.
        Nr0   rT   r0   r0   r1   rU   b  s    z.StubApplicationRunnerWithSignal.preApplicationc                 C   s$   t ƒ }| j|_|  |tjtj¡ dS )z`
        Instantiate a SignalCapturingMemoryReactor and start it
        in the runner.
        N)r  r  r  rð   rš   rž   rá  r(  r0   r0   r1   rV   g  s    z/StubApplicationRunnerWithSignal.postApplication)
rJ   rK   rL   rM   rO   rW   r]   rU   rV   Ú__classcell__r0   r0   r  r1   r  S  s
   r  c                    s   ‡ fdd„}|S )aI  
    Create a factory function to instantiate a
    StubApplicationRunnerWithSignal that will report signum as the captured
    signal..

    @param signum: The integer signal number or None
    @type signum: C{int} or C{None}

    @return: A factory function to create stub runners.
    @rtype: stubApplicationRunnerFactory
    c                    s   t | ƒ}ˆ |_|S )a·  
        Create a StubApplicationRunnerWithSignal using a reactor that
        implements _ISupportsExitSignalCapturing and whose _exitSignal
        attribute is set to signum.

        @param config: The runner configuration, platform dependent.
        @type config: L{twisted.scripts.twistd.ServerOptions}

        @return: A runner to use for the test.
        @rtype: twisted.test.test_twistd.StubApplicationRunnerWithSignal
        )r  r  )rk   rÏ   ©Úsignumr0   r1   ÚstubApplicationRunnerFactory  s    zIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryr0   )r!  r"  r0   r   r1   Ú#stubApplicationRunnerFactoryCreatorr  s    r#  c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚExitWithSignalTestsz?
    Tests for L{twisted.application.app._exitWithSignal}.
    c                    sR   t  ¡ ˆ _dtƒ iˆ j_tƒ ˆ j_dˆ j_ddgˆ _‡ fdd„}ˆ  	t
d|¡ dS )zM
        Set up the server options and a fake for use by test cases.
        rÜ   Nc                    s   | ˆ j d< |ˆ j d< dS )zÄ
            Fake method to capture arguments passed to os.kill.

            @param pid: The pid of the process being killed.

            @param sig: The signal sent to the process.
            r   r¼   N)ÚfakeKillArgsr¶   rT   r0   r1   ÚfakeKill£  s    
z+ExitWithSignalTests.setUp.<locals>.fakeKillr¹   )r    rg   rk   rC   rÞ   rf   rß   rl   r%  r>   r6   )rH   r&  r0   rT   r1   rË   ™  s    


zExitWithSignalTests.setUpc                    s€   ddg‰ ‡ fdd„}|   td|¡ t tj¡ |  ˆ d tj¡ |  ˆ d tj¡ |  | jd t 	¡ ¡ |  | jd tj¡ dS )zœ
        exitWithSignal replaces the existing signal handler with the default
        handler and sends the replaced signal to the current process.
        Nc                    s   | ˆ d< |ˆ d< d S )Nr   r¼   r0   )r¸   Zhandler©ZfakeSignalArgsr0   r1   Úfake_signal¹  s    z<ExitWithSignalTests.test_exitWithSignal.<locals>.fake_signalrÐ  r   r¼   )
r>   rÐ  r   Z_exitWithSignalÚSIGINTr  ÚSIG_DFLr%  r6   rÀ   )rH   r(  r0   r'  r1   Útest_exitWithSignal±  s    z'ExitWithSignalTests.test_exitWithSignalc                 C   sB   |   tdtdƒ¡ t | j¡ |  | jd ¡ |  | jd ¡ dS )zb
        _exitWithSignal is not called if the runner does not exit with a
        signal.
        rü   Nr   r¼   )r>   r    r#  ÚrunApprk   rj   r%  rT   r0   r0   r1   Útest_normalExitÆ  s    ýz#ExitWithSignalTests.test_normalExitc                 C   sN   |   tdttjƒ¡ t | j¡ |  | jd t	 
¡ ¡ |  | jd tj¡ dS )zP
        _exitWithSignal is called when the runner exits with a signal.
        rü   r   r¼   N)r>   r    r#  rÐ  r)  r,  rk   r  r%  r6   rÀ   rT   r0   r0   r1   Útest_runnerExitsWithSignalÕ  s    ýz.ExitWithSignalTests.test_runnerExitsWithSignalN)rJ   rK   rL   rM   rË   r+  r-  r.  r0   r0   r0   r1   r$  “  s
   r$  z!twistd unix support not available)lrM   Z
__future__r   r   r¿   rG  rÐ  r6   rš   r5   r8   ÚImportErrorZcPicklerÈ   Zzope.interfacer   Zzope.interface.verifyr   Ztwisted.trialr   Ztwisted.test.test_processr   rŸ   r   r	   r
   Ztwisted.applicationr   r   r   Ztwisted.application.servicer   Ztwisted.internet.deferr   Ztwisted.internet.interfacesr   r   Z#twisted.internet.test.modulehelpersr   Ztwisted.loggerr   r   r   Ztwisted.internet.baser   Ztwisted.test.proto_helpersr   Ztwisted.python.compatr   r   Ztwisted.python.componentsr   Ztwisted.pythonr   Ztwisted.python.logrµ  r   Ztwisted.python.runtimer   Ztwisted.python.usager   Ztwisted.python.fakepwdr   Ztwisted.scriptsr    r!   Ztwisted.scripts._twistd_unixr"   r#   r$   r%   r  r}  rŠ  Úgetattrr  rB   rf   rC   r­  rO   rü   rS   ZTestCaserX   r§   rÄ   rÎ   rÖ   rÕ   rÛ   r  r<  r`  rh  r.  r
  rr  rš  rŸ  r   rÍ  rß  r  r  r#  r$  r¦   r0   r0   r0   r1   Ú<module>   sÆ   



.
 TG s  #  N  4   !Q
