U
    P|j$! ã                   @   sÀ  d Z ddlZddlZddlZddlZddlZddlZzddlZddl	Z
W n ek
rd   dZ	dZY n
X e
Z	eZddlmZ ddlmZ ddlmZ ddlmZ ddlmZmZmZ ddlmZmZmZ dd	lmZ dd
lmZ ddl m!Z! ddl"m#Z#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. ddl/m0Z0 ddl1m2Z2 ddl3m*Z4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z= ddl>m?Z? ddl@mAZA e7dƒZBeB�rÄddlCmDZDmEZEmFZF e7dƒZGe7dƒZHe7dƒZIe7dƒZJd d!„ ZKG d"d#„ d#ƒZLG d$d%„ d%ejMƒZNG d&d'„ d'e=jOƒZPG d(d)„ d)eAƒZQeeB d*ƒG d+d,„ d,eAƒƒZRG d-d.„ d.eAƒZSG d/d0„ d0ƒZTG d1d2„ d2ejUƒZVG d3d4„ d4eAƒZWeeB d*ƒG d5d6„ d6eAƒƒZXeeB d*ƒG d7d8„ d8eAƒƒZYeeB d*ƒG d9d:„ d:eAƒƒZZG d;d<„ d<ƒZ[ee#ƒG d=d>„ d>e[ƒƒZ\G d?d@„ d@ƒZ]G dAdB„ dBeAƒZ^dCdD„ Z_dEdF„ Z`G dGdH„ dHeAƒZaeeB d*ƒG dIdJ„ dJeAƒƒZbeeB dKƒG dLdM„ dMeAƒƒZcee$ƒG dNdO„ dOe(ƒƒZdG dPdQ„ dQe=jOƒZedRdS„ ZfG dTdU„ dUeAƒZgdS )VzE
Tests for L{twisted.application.app} and L{twisted.scripts.twistd}.
é    N)ÚStringIO)ÚskipIf)Úimplementer)ÚverifyObject)ÚinternetÚloggerÚplugin)ÚappÚreactorsÚservice)ÚIServiceMaker)ÚReactorBase)ÚDeferred)ÚIReactorDaemonizeÚ_ISupportsExitSignalCapturing)ÚAlternateReactor)ÚMemoryReactor)ÚILogObserverÚglobalLogBeginnerÚglobalLogPublisher)Úutil)ÚComponentized)ÚUserDatabase)r   ÚtextFromEventDict)ÚrequireModule)ÚplatformType)Ú
UsageError)Útwistd)ÚMockOS)ÚTestCaseztwisted.scripts._twistd_unix)ÚUnixApplicationRunnerÚUnixAppLoggerÚcheckPIDztwisted.python.syslogÚprofileÚpstatsÚcProfilec              	      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ÚindexÚgr_nameÚgr_gidÚtuple)ÚnameÚresult©ÚgidZgrentÚgroup© ú</tmp/pip-unpacked-wheel-audpp6lv/twisted/test/test_twistd.pyÚgetgrnamd   s
    z#patchUserDatabase.<locals>.getgrnamÚgetpwnamr3   ÚgetpwuidN)Úpwdr5   ÚosÚgetuidÚgrpÚgetgrgidÚgetgidr   ZaddUserÚ	pw_passwdÚpw_gecosÚpw_dirÚpw_shellr4   )ÚpatchÚuserÚuidr0   r/   ÚpwentZdatabaser3   r1   r.   r2   ÚpatchUserDatabaseC   s           ÿrD   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©ÚselfrG   r1   r1   r2   ÚmakeServicew   s    
zMockServiceMaker.makeServiceN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚtapnamerK   r1   r1   r1   r2   rE   p   s   rE   c                   @   s   e Zd ZdZdd„ ZdS )ÚCrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                 C   s   d S r&   r1   ©rJ   Úapplicationr1   r1   r2   Ústart†   s    zCrippledAppLogger.startN)rL   rM   rN   rO   rT   r1   r1   r1   r2   rQ   �   s   rQ   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&   r1   ©rJ   r1   r1   r2   ÚpreApplication“   s    z(CrippledApplicationRunner.preApplicationc                 C   s   d S r&   r1   rV   r1   r1   r2   ÚpostApplication–   s    z)CrippledApplicationRunner.postApplicationN)rL   rM   rN   rO   rQ   ÚloggerFactoryrW   rX   r1   r1   r1   r2   rU   Š   s   rU   c                   @   s”   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d„ ƒZe	e
 dƒdd„ ƒZe	e
 dƒdd„ ƒZdd„ Z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ƒ}|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 )rP   Ú_optionsÚdescription©rJ   r,   r1   r1   r2   Ú__init__¦   s    
z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__c                 S   s   | j S r&   )r\   rV   r1   r1   r2   rG   «   s    z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.optionsN)rL   rM   rN   r_   rG   r1   r1   r1   r2   Ú
FakePlugin¥   s   r`   ÚappleÚbananaÚcoconutÚdonutc                 3   s(   ˆ  | t¡ ˆV  ˆV  ˆV  ˆ V  d S r&   )ÚassertEqualr   )Z	interface©ra   rb   rc   rd   rJ   r1   r2   Ú
getPlugins³   s
    z7ServerOptionsTests.test_subCommands.<locals>.getPluginsN)r   ÚServerOptionsre   Z_getPluginsr   rg   ÚsubCommandsÚziprP   ÚassertIsNoner\   r]   )rJ   r`   rg   Úconfigri   ZexpectedOrderÚ
subCommandZexpectedCommandr,   ZshortcutZparserClassZdocumentationr1   rf   r2   Útest_subCommandsŸ   s"    	
z#ServerOptionsTests.test_subCommandsc                    sØ   G dd„ dƒ}|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 ˆ¡¡ 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 r[   ztwisted.internet.default)Ú	shortNamer]   Z
moduleNamer^   r1   r1   r2   r_   Ð   s    

zPServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstaller.__init__N)rL   rM   rN   r_   r1   r1   r1   r2   ÚFakeReactorInstallerÏ   s   rp   ra   rb   rc   rd   c                   3   s   ˆV  ˆV  ˆV  ˆ V  d S r&   r1   r1   )ra   rb   rc   rd   r1   r2   ÚgetReactorTypesÚ   s    zBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypesz--help-reactorsc                    s    ˆ  | ˆ ¡ ˆ ˆ  | ¡¡ d S r&   )ÚassertInÚappendr(   )Ús)Ú
helpOutputÚindexesrJ   r1   r2   ÚgetIndexê   s    z;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndexz9reactor descriptions were not in alphabetical order: {!r}N)r   rh   re   Z_getReactorTypesr
   rq   r   ZmessageOutputÚassertRaisesÚ
SystemExitÚparseOptionsÚgetvaluero   r]   ÚsortedÚformat)rJ   rp   rq   rl   Úreactorrw   r1   )ra   rb   rc   rd   ru   rv   rJ   r2   Ú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.
        rF   Úno_saveN)r   rh   rm   ÚpostOptionsÚ
assertTrue©rJ   rl   r1   r1   r2   Ú&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   rh   r�   ÚassertFalserƒ   r1   r1   r2   Ú(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   rh   Ústrr	   ÚAppProfilerZ	profilersrr   )rJ   rl   ru   Úprofilerr1   r1   r2   Útest_listAllProfilers
  s    z(ServerOptionsTests.test_listAllProfilersútwistd unix not availablec                 C   s   t  ¡ }|  |d ¡ dS )zG
        The default value for the C{umask} option is L{None}.
        ÚumaskN)r   rh   rk   rƒ   r1   r1   r2   Ú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   rh   rz   re   rƒ   r1   r1   r2   Ú
test_umask  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   rh   rx   r   rz   rƒ   r1   r1   r2   Útest_invalidUmask(  s    z$ServerOptionsTests.test_invalidUmaskc                 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   rh   rx   r   rz   r‚   ÚargsÚ
startswithZassertNotIn©rJ   rl   Úer1   r1   r2   Ú&test_unimportableConfiguredLogObserver1  s      ÿ
ÿÿz9ServerOptionsTests.test_unimportableConfiguredLogObserverc                 C   sH   t  ¡ }|  t|jddg¡}|  |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.FOOBARr   z{Logger 'twisted.test.test_twistd.FOOBAR' could not be imported: module 'twisted.test.test_twistd' has no attribute 'FOOBAR'r“   Nr”   r—   r1   r1   r2   Ú*test_badAttributeWithConfiguredLogObserverA  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   )Ú	copyrightÚwin32z(the Twisted Windows runner)z(the Twisted daemon)ztwistd {} {}
{}
©Ústdoutz	--versionN)Útwistedr›   r   r}   Úversionr   r   rh   rx   ry   rz   ÚassertIsÚcodere   r{   )rJ   r›   r,   ZexpectedOutputrž   rl   r˜   r1   r1   r2   Útest_versionT  s      ÿzServerOptionsTests.test_versionc                 C   s(   t ƒ }tj|d�}|  t|jdg¡ dS )zI
        Command is printed when an invalid option is requested.
        r�   z	web --fooN)r   r   rh   rx   r   rz   )rJ   rž   rl   r1   r1   r2   Ú!test_printSubCommandForUsageErrorh  s    z4ServerOptionsTests.test_printSubCommandForUsageErrorN)rL   rM   rN   rO   rn   r   r„   r†   rŠ   r   Ú_twistd_unixr�   r�   r‘   r™   rš   r£   r¤   r1   r1   r1   r2   rZ   š   s    +/	






rZ   r‹   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )ÚCheckPIDTestsz 
    Tests for L{checkPID}.
    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 ©NFr1   )Ú_r1   r1   r2   Ú<lambda>|  ó    z.CheckPIDTests.test_notExists.<locals>.<lambda>znon-existent PID fileN)r@   r7   Úpathr"   rV   r1   r1   r2   Útest_notExistsx  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Úwriterx   ry   r"   rr   r¢   )rJ   ÚpidfileÚfr˜   r1   r1   r2   Ú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&   r1   ©ÚpidÚsigr1   r1   r2   Úkill‘  s    z/CheckPIDTests.test_anotherRunning.<locals>.killr¸   zAnother twistd serverN)
r¯   r°   r±   r@   r7   rx   ry   r"   rr   r¢   ©rJ   r²   r³   r¸   r˜   r1   r1   r2   Ú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µ   r1   r1   r2   r¸      s    z&CheckPIDTests.test_stale.<locals>.killr¸   N)r¯   r°   r±   r‡   r7   Úgetpidr@   r"   r…   r¬   r§   )rJ   r²   r³   r¸   r1   r1   r2   Ú
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¾   ÚEBADFrµ   r1   r1   r2   r¸   °  s    z2CheckPIDTests.test_unexpectedOSError.<locals>.killr¸   Nr   zCan't check status of PID)r¯   r°   r±   r@   r7   rx   ry   r"   ZassertIsNotr¢   r‚   r•   r–   r¹   r1   r1   r2   Útest_unexpectedOSError§  s    z$CheckPIDTests.test_unexpectedOSErrorN)	rL   rM   rN   rO   r­   r´   rº   rÀ   rÃ   r1   r1   r1   r2   r¦   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)rJ   r³   r1   r1   r2   Ú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   rh   rz   rÇ   rU   ZcreateOrGetApplicationre   r   ÚIServicer,   )rJ   rl   rS   r1   r1   r2   Ú&test_createOrGetApplicationWithTapFileÆ  s    z3TapFileTests.test_createOrGetApplicationWithTapFileN)rL   rM   rN   rO   rË   rÍ   r1   r1   r1   r2   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)rJ   rÏ   r1   r1   r2   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.
        ÚlogrS   N)rÏ   Úorderrs   ÚhasattrÚhadApplicationLogObserverrR   r1   r1   r2   rT   Ù  s    zTestLoggerFactory.startc                 C   s   dS )z%
        Don't log anything.
        Nr1   rV   r1   r1   r2   Ústopà  s    zTestLoggerFactory.stopN)rL   rM   rN   rO   r_   rT   rÔ   r1   r1   r1   r2   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   rI   r1   r1   r2   r_   ì  s    zTestApplicationRunner.__init__c                 C   s   | j  d¡ t| dƒ| _d S )NÚprerS   )rÑ   rs   rÒ   ÚhadApplicationPreApplicationrV   r1   r1   r2   rW   ñ  s    z$TestApplicationRunner.preApplicationc                 C   s   | j  d¡ t| dƒ| _d S )NÚpostrS   )rÑ   rs   rÒ   ÚhadApplicationPostApplicationrV   r1   r1   r2   rX   õ  s    z%TestApplicationRunner.postApplicationN)rL   rM   rN   rO   r_   rW   rX   r1   r1   r1   r2   rÕ   æ  s   rÕ   c                   @   sˆ   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zee	e
d
dƒ dƒdd„ ƒZee	e
d
dƒ dƒdd„ ƒZ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   rh   rE   ÚserviceMakerÚloadedPluginsÚobjectÚ
subOptionsrm   rl   rƒ   r1   r1   r2   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)rU   rl   Úrunr¡   rÝ   rG   rà   r   rÌ   rS   Zservices)rJ   Zarunnerr1   r1   r2   Ú,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Õ   rl   rá   r…   rØ   r‚   rÚ   rÓ   re   rÑ   )rJ   rt   r1   r1   r2   Útest_preAndPostApplication  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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©rs   ©rJ   ÚchrootZrundirÚnodaemonrŒ   r²   ©Úeventsr1   r2   ÚsetupEnvironment8  s    zmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironmentc                    s   ˆ   d|||f¡ d S )NÚ
privilegesrå   )rJ   ÚeuidrB   r/   ré   r1   r2   ÚshedPrivileges;  s    zkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivilegesc                    s   ˆ   d¡ d S )Nr~   rå   )rJ   r~   Ú	oldstdoutÚ	oldstderrré   r1   r2   ÚstartReactor>  s    ziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactorc                 S   s   d S r&   r1   )rJ   r²   r1   r1   r2   Ú	removePIDA  s    zfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDN)rL   rM   rN   rë   rî   rñ   rò   r1   ré   r1   r2   ÚFakeUnixApplicationRunner7  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&   r1   r^   r1   r1   r2   ÚsetNameM  s    zVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNamec                 S   s   d S r&   r1   )rJ   Úparentr1   r1   r2   ÚsetServiceParentP  s    z_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentc                 S   s   d S r&   r1   rV   r1   r1   r2   ÚdisownServiceParentS  s    zbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentc                    s   ˆ   d¡ d S )NÚprivilegedStartServicerå   rV   ré   r1   r2   rø   V  s    zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServicec                    s   ˆ   d¡ d S )NÚstartServicerå   rV   ré   r1   r2   rù   Y  s    z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServicec                 S   s   d S r&   r1   rV   r1   r1   r2   ÚstopService\  s    zZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService)rL   rM   rN   rõ   Zrunningr,   ÚprocessNamerB   r/   rô   rö   r÷   rø   rù   rú   r1   ré   r1   r2   ÚFakeServiceD  s   rü   rä   rø   rì   Frù   r~   N)rl   rz   r   Ú_SomeApplicationRunnerr   r   rÌ   ZIProcessr   rW   rS   rX   re   )rJ   ÚargvrB   r/   ró   rü   rS   rÏ   r1   ré   r2   Ú"_applicationStartsWithConfiguredID*  s*    	

ûþz9ApplicationRunnerTests._applicationStartsWithConfiguredIDÚsetuidNz5Platform does not support --uid/--gid twistd options.c                 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‡   )rJ   rB   r/   r1   r1   r2   Ú.test_applicationStartsWithConfiguredNumericIDss  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)rD   r@   rÿ   )rJ   rA   rB   r0   r/   r1   r1   r2   Ú+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}.
        Fr#   ©r#   r‰   ÚdebugNz'startReactor did not call reactor.run())ÚDummyReactorr	   rÖ   rñ   r‚   Úcalled©rJ   r~   rÏ   r1   r1   r2   Ú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  r1   r1   r2   Ú*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.
                Nr1   rV   r1   r1   r2   Ú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©Ú_exitSignalrV   r1   r1   r2   rá   À  s    z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.runN©rL   rM   rN   rO   r  rá   r1   r1   r1   r2   ÚDummyReactorWithSignalµ  s   r  Fr#   r	  Nr  )r   r	   rÖ   rñ   ÚassertEqualsr  )rJ   r  r~   rÏ   r1   r1   r2   Ú$test_applicationRunnerCapturesSignal¯  s    
ÿz;ApplicationRunnerTests.test_applicationRunnerCapturesSignalc                 C   sF   G dd„ dƒ}|ƒ }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  r1   rV   r1   r1   r2   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  rV   r1   r1   r2   rá   Þ  s    zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.runNr  r1   r1   r1   r2   Ú#DummyReactorWithExitSignalAttributeÓ  s   r  Fr#   r	  N)r	   rÖ   rñ   r  r  )rJ   r  r~   rÏ   r1   r1   r2   Ú%test_applicationRunnerIgnoresNoSignalÍ  s    
ÿz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal)rL   rM   rN   rO   rË   râ   rã   rÿ   r   Úgetattrr7   r  r  r  r  r  r  r1   r1   r1   r2   rÛ   ú  s&   	Iþ
þ
rÛ   c                   @   sv   e Zd Z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}.
    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¬   rV   r1   r2   rª     r«   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>Úchdirc                    s   t ˆ d| ƒS )NÚcwdr  r!  rV   r1   r2   rª     r«   rŒ   c                    s   t ˆ d| ƒS )NÚmaskr  )r$  rV   r1   r2   rª     r«   )Úunsetr  r#  r$  Údaemonr7   r¿   r¶   r@   r    r   rh   rÏ   Ú	daemonizerV   r1   rV   r2   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¶   r1   rV   r1   r2   rª     r«   zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>N)r&  r@   r7   ©rJ   r~   r1   rV   r2   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ë   re   r  rV   r1   r1   r2   Útest_chroot  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%  rV   r1   r1   r2   Útest_noChroot!  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ë   re   r#  rV   r1   r1   r2   Útest_changeWorkingDirectory)  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&  rV   r1   r1   r2   Útest_daemonize1  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&  rV   r1   r1   r2   Ú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Úreadre   r¶   ©rJ   r²   r³   r¶   r1   r1   r2   Útest_nonDaemonPIDFileB  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+  Fr2  r»   )
r¯   r   r/  rÏ   rë   r°   r3  r4  re   r¶   r5  r1   r1   r2   Útest_daemonPIDFileM  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ë   re   r$  rV   r1   r1   r2   r�   Z  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%  rV   r1   r1   r2   Útest_noDaemonizeNoUmaskc  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é?   r9  rV   r1   r1   r2   Útest_daemonizedNoUmaskl  s    zAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmaskN)rL   rM   rN   rO   rß   r%  rË   r'  r,  r-  r.  r0  r1  r6  r7  r�   r:  r<  r1   r1   r1   r2   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S )Ú*UnixApplicationRunnerStartApplicationTestsz>
    Tests for L{UnixApplicationRunner.startApplication}.
    c                    sÚ   t  ¡ }| ddddddddd	g	¡ t d
¡}t|ƒ| _g ‰ ‡ fdd„}t | jj	¡j
}t |¡j
}| ¡ }| d¡ |  ||¡ |  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/rundirú	--pidfilez/foo/pidfileÚtest_setupEnvironmentc                    s   ˆ   |||||f¡ d S r&   )Úextendræ   ©r•   r1   r2   ÚfakeSetupEnvironment—  s    z^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironmentrJ   rë   rî   c                  _   s   d S r&   r1   ©ÚaÚkwr1   r1   r2   rª   «  r«   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>ÚstartApplicationc                  _   s   d S r&   r1   rD  r1   r1   r2   rª   ¬  r«   Té8   N)r   rh   rz   r   rÊ   r    rÏ   ÚinspectÚ	signaturerë   Ú
parametersÚcopyÚpopre   r@   r	   rG  )rJ   rG   rS   rC  ZsetupEnvironmentParametersZfakeSetupEnvironmentParametersr1   rB  r2   r@  }  s>    ÷ÿ

ÿÿ
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   é#   ©re   ©rB   r/   rí   rV   r1   r2   ÚswitchUIDPass·  s    zUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPassÚ	switchUIDrP  rN  rO  N)r@   r¥   r    rî   )rJ   rS  rÏ   r1   rV   r2   Ú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Á   rR  r1   r1   r2   ÚswitchUIDFailÇ  s    zZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFailrT  rP  rN  Nr»   )r    r@   r¥   rx   ry   rî   re   r¢   )rJ   rV  rÏ   Úexcr1   r1   r2   Ú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ˆƒd|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&   rQ  )rB   r/   ©rJ   Ú	wantedGidÚ	wantedUidr1   r2   Ú
initgroupsÖ  s    zFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroupsc                    s   ˆ   | ˆ¡ d S r&   rQ  )rB   )rJ   r[  r1   r2   r   Ú  s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuidc                    s   ˆ   | ˆ¡ d S r&   rQ  )r/   )rJ   rZ  r1   r2   ÚsetgidÝ  s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgidr\  r   r]  r>  r  r?  r@  N)rD   r@   r   r7   r   rh   rz   r‡   r   rÊ   r    rÏ   rG  )rJ   Z
wantedUserr[  ZwantedGrouprZ  ZpidFiler\  r   r]  rG   rS   rÏ   r1   rY  r2   Ú_setUIDÏ  s    ÿ

z2UnixApplicationRunnerStartApplicationTests._setUIDc                 C   s   |   d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’  z_test_setUidWithoutGid.pidN)r^  r¯   rV   r1   r1   r2   Útest_setUidWithoutGidí  s        
ÿz@UnixApplicationRunnerStartApplicationTests.test_setUidWithoutGidc                 C   sX   t  ¡ }|  d|ddd¡ |  ¡ }d ||¡}|  ||d d ¡ |  dt|ƒ|¡ 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÷  ztest_setUidSameAsCurrentUid.pidz\tried to drop privileges and setuid {} but uid is already {}; should we be root? Continuing.r   Úmessager»   N)r7   r8   r^  ÚflushWarningsr}   re   Úlen)rJ   Z
currentUidZwarningsShownZexpectedWarningr1   r1   r2   Útest_setUidSameAsCurrentUid÷  s         ÿ ÿÿzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUidN)
rL   rM   rN   rO   r@  rU  rX  r^  r_  rc  r1   r1   r1   r2   r=  w  s   4
r=  c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )Ú#UnixApplicationRunnerRemovePIDTestsz7
    Tests for L{UnixApplicationRunner.removePID}.
    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¯   r7   Úmakedirsr¬   Újoinr°   Úcloserò   r…   r§   )rJ   rÏ   r¬   r²   r1   r1   r2   Ú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½   re   rb  Úvaluer¾   ÚENOENT)rJ   rÏ   Úerrorsr1   r1   r2   Útest_removePIDErrors  s
    

z8UnixApplicationRunnerRemovePIDTests.test_removePIDErrorsN)rL   rM   rN   rO   rh  rl  r1   r1   r1   r2   rd  
  s   rd  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Ú_afterDaemonizeCalledrV   r1   r1   r2   r_   5  s    z"FakeNonDaemonizingReactor.__init__c                 C   s
   d| _ d S ©NT)rn  rV   r1   r1   r2   ÚbeforeDaemonize9  s    z)FakeNonDaemonizingReactor.beforeDaemonizec                 C   s
   d| _ d S rp  )ro  rV   r1   r1   r2   ÚafterDaemonize<  s    z(FakeNonDaemonizingReactor.afterDaemonizec                 O   s   dS )z*
        Skip event registration.
        Nr1   )rJ   r•   rF  r1   r1   r2   ÚaddSystemEventTrigger?  s    z/FakeNonDaemonizingReactor.addSystemEventTriggerN)rL   rM   rN   rO   r_   rq  rr  rs  r1   r1   r1   r2   rm  )  s
   rm  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)rL   rM   rN   rO   r1   r1   r1   r2   r/  E  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  ÚRuntimeErrorrV   r1   r1   r2   rá   X  s    úDummyReactor.runN)rL   rM   rN   rO   r  rá   r1   r1   r1   r2   r  M  s   r  c                   @   s¤   e Zd ZdZee dƒdd„ ƒZdd„ Zee dƒdd„ ƒZd	d
„ Z	ee dƒdd„ ƒZ
ee dƒdd„ ƒZee dƒdd„ ƒZdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚAppProfilingTestsz'
    Tests for L{app.AppProfiler}.
    zprofile module not availablec              	   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‰   ru  úfunction callsN©r   rh   r¯   r	   rˆ   r  rá   r‚   r  r°   r4  rr   ©rJ   rl   r‰   r~   r³   Údatar1   r1   r2   Útest_profilef  s    

zAppProfilingTests.test_profilec                 C   sP   t ƒ }|  td|¡}||ƒ}| ¡  | ¡  | ¡ }|  d|¡ |  d|¡ d S )Nrž   rw  z(run))r   r@   ÚsysÚprint_statsÚrestorer{   rr   )rJ   Z
statsClassr#   Úoutrž   Ústatsrz  r1   r1   r2   Ú
_testStatsz  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   rh   r¯   r	   rˆ   r  rá   r‚   r  r�  r$   ZStats©rJ   rl   r‰   r~   r1   r1   r2   Ú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|  ÚmodulesrL  r   rh   r	   rˆ   ÚclearÚupdaterx   ry   rá   ©rJ   ZsavedModulesrl   r‰   r1   r1   r2   Ú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©rt  rV   r1   r1   r2   r}  ·  s    zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_statsN)rL   rM   rN   r}  r1   r1   r1   r2   ÚErroneousProfile¶  s   r�  ÚProfiler#   r‰   N)r#   rŽ  r@   r   rh   r¯   r	   rˆ   r  r|  rž   rx   rt  rá   r¡   )rJ   r�  rl   r‰   r~   Z	oldStdoutr1   r1   r2   Útest_profilePrintStatsError¯  s    
z-AppProfilingTests.test_profilePrintStatsErrorzcProfile module not availablec              	   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#   r%   r‰   rá   rw  Nrx  ry  r1   r1   r2   Útest_cProfileÆ  s    

zAppProfilingTests.test_cProfilec                 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„  r1   r1   r2   Ú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Š  r1   r1   r2   Útest_withoutCProfileí  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   rh   r¯   rx   ry   r	   rˆ   re   r‡   )rJ   rl   Úerrorr1   r1   r2   Útest_unknownProfilerÿ  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ˆ   re   r‰   ©rJ   r‰   r1   r1   r2   Útest_defaultProfiler  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—  r1   r1   r2   Útest_profilerNameCaseInsentive  s    z0AppProfilingTests.test_profilerNameCaseInsentiveN)rL   rM   rN   rO   r   r#   r{  r�  r…  r‹  r�  r%   r�  r‘  r’  r”  r˜  r™  r1   r1   r1   r2   rv  a  s"   









rv  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{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oldFileLogObserverr1   r2   Úobserver(  s    
z+_patchTextFileLogObserver.<locals>.observerÚtextFileLogObserver)r   rž  )r@   r�  r1   r›  r2   Ú_patchTextFileLogObserver  s
    
rŸ  c                    s(   g ‰ G ‡ fdd„dƒ}|   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å   )rJ   Úprefix©ZlogMessagesr1   r2   r_   8  s    z1_setupSyslog.<locals>.fakesyslogobserver.__init__c                    s   ˆ   |¡ d S r&   rå   )rJ   Z	eventDictr¡  r1   r2   Úemit;  s    z-_setupSyslog.<locals>.fakesyslogobserver.emitN)rL   rM   rN   r_   r¢  r1   r¡  r1   r2   Úfakesyslogobserver7  s   r£  ZSyslogObserver)r@   Úsyslog)ZtestCaser£  r1   r¡  r2   Ú_setupSyslog0  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ee dƒee dƒdd„ ƒƒZ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&   )Ú	observersrs   r   ZaddObserver)r§  r�  rV   r1   r2   ÚbeginLoggingToQ  s    z,AppLoggerTests.setUp.<locals>.beginLoggingTor¨  N)r§  r@   r   )rJ   r¨  r1   rV   r2   rË   J  s    zAppLoggerTests.setUpc                 C   s   | j D ]}t |¡ qdS )z1
        Remove all installed observers.
        N)r§  r   ÚremoveObserver©rJ   r�  r1   r1   r2   ÚtearDownX  s    
zAppLoggerTests.tearDownc                 C   s   t tƒG dd„ dƒƒ}|ƒ 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&   )Ú_logsrs   )rJ   Úeventr1   r1   r2   Ú__call__k  s    z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__N)rL   rM   rN   r¬  r®  r1   r1   r1   r2   ÚTestObserverg  s   r¯  )r   r   )rJ   r¯  r1   r1   r2   Ú_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)re   r§  rr   r¬  rª  r1   r1   r2   Ú_checkObserverp  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&   r1   r1   ©r�  r1   r2   rª   �  r«   z+AppLoggerTests.test_start.<locals>.<lambda>N)r	   Ú	AppLoggerr°  Ú_getLogObserverrT   r   r²  )rJ   r   r1   r³  r2   Ú
test_startz  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´  rT   r²  )rJ   rS   r�  r   r1   r1   r2   Ú$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&   r1   r1   r³  r1   r2   rª   ¤  r«   z7AppLoggerTests._setupConfiguredLogger.<locals>.<lambda>)r°  r‰  rT   )rJ   rS   ZextraLogArgsZ	appLoggerZlogArgsr   r1   r³  r2   Ú_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¹  rR   r1   r1   r2   Ú#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¹  re   r¬  )rJ   r�  rS   r1   r1   r2   Ú(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·  ÚLegacyILogObserverrs   r²  r¹  re   )rJ   ÚnonlogsrS   r1   r1   r2   Ú.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¼  rs   r	   r´  rT   r²  re   )rJ   r½  r�  rS   r   r1   r1   r2   Ú.test_loggerComponentBeatsLegacyLoggerComponentÊ  s    


z=AppLoggerTests.test_loggerComponentBeatsLegacyLoggerComponentr‹   zsyslog not availablec                 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!   re   )rJ   ÚlogsrS   r1   r1   r2   Ú%test_configuredLogObserverBeatsSyslogÛ  s    ÿz4AppLoggerTests.test_configuredLogObserverBeatsSyslogc                 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…   r7   r¬   r§   )rJ   rS   r¬   r1   r1   r2   Ú&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µ  re   rb  r¡   r|  rž   )rJ   r   rœ  r1   r1   r2   Útest_getLogObserverStdoutõ  s    
z(AppLoggerTests.test_getLogObserverStdoutc                 C   sd   t | jƒ}|  ¡ }t d|i¡}| ¡ }|  |jj¡ |  	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µ  Ú
addCleanupÚ_outFilerg  re   rb  r¬   r7   Úabspath)rJ   rœ  ÚfilenameÚsutr�  r1   r1   r2   Ú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³  ©Úremovedr1   r2   Úremove   s    z(AppLoggerTests.test_stop.<locals>.remover©  N)	rß   r@   r   r	   r´  Z	_observerrÔ   re   rk   )rJ   r�  rÏ  r   r1   rÍ  r2   Ú	test_stop  s    
zAppLoggerTests.test_stopc                    sz   g ‰t  i ¡}ttƒG ‡fdd„dƒƒ‰ ‡ 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å   )rJ   Úx©rÀ  r1   r2   r®  :  s    zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__N)rL   rM   rN   rO   r®  r1   rÒ  r1   r2   ÚLoggerObserver4  s   rÓ  c                      s   ˆ ƒ S r&   r1   r1   )rÓ  r1   r2   rª   @  r«   z5AppLoggerTests.test_legacyObservers.<locals>.<lambda>r±  r   N)r	   r´  r   r¼  Z_observerFactoryrT   r   rr   r   ra  Útest_legacyObserversre   rb  ©rJ   r   Úwarningsr1   )rÓ  rÀ  r2   rÔ  ,  s    
z#AppLoggerTests.test_legacyObserversc                    st   g ‰ t  i ¡}‡ fdd„|_| tƒ ¡ |  dtˆ d ƒ¡ |  | jg¡}|  	|d d d¡ |  	t
|ƒ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å   r1   rÒ  r1   r2   rª   O  r«   zAAppLoggerTests.test_unmarkedObserversDeprecated.<locals>.<lambda>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.r»   N)r	   r´  rµ  rT   r   rr   r   ra  Ú test_unmarkedObserversDeprecatedre   rb  rÕ  r1   rÒ  r2   r×  G  s    

ýz/AppLoggerTests.test_unmarkedObserversDeprecatedN)rL   rM   rN   rO   rË   r«  r°  r²  r¶  r¸  r	   r´  r¹  rº  r»  r¾  r¿  r   r¥   r¤  rÁ  rÃ  rÆ  rÌ  rÐ  rÔ  r×  r1   r1   r1   r2   r¦  B  s.   
 ÿ



r¦  c                   @   sT   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	e
e dƒdd„ ƒZdS )ÚUnixAppLoggerTestszw
    Tests for L{UnixAppLogger}.

    @ivar signals: list of signal handlers installed.
    @type signals: C{list}
    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&   )Úsignalsrs   )r·   r³   rV   r1   r2   Ú
fakeSignalu  s    z,UnixAppLoggerTests.setUp.<locals>.fakeSignalÚsignalN)rÙ  r@   rÛ  )rJ   rÚ  r1   rV   r2   rË   n  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µ  re   rb  r¡   r|  rž   )rJ   rœ  r   r1   r1   r2   rÆ  z  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!   rx   ry   rµ  re   r‡   )rJ   r   r“  r1   r1   r2   Útest_getLogObserverStdoutDaemonŒ  s    z2UnixAppLoggerTests.test_getLogObserverStdoutDaemonc                    sÀ   t | jƒ}|  ¡ }td|iƒ}| ¡ }|  |jj¡ |  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&   )Úcallbackr1   ©Údr1   r2   Úrotateª  s    z:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotateN)rŸ  r@   r¯   r!   rµ  rÇ  rÈ  rg  re   rb  r¬   r7   rÉ  rÙ  rÛ  ÚSIGUSR1r   rá  )rJ   rœ  rÊ  rË  r�  rá  Z	rotateLogr1   rß  r2   rÌ  •  s    


z*UnixAppLoggerTests.test_getLogObserverFilec                    sV   ‡ fdd„}ˆ   td|¡ ˆ  ¡ }td|iƒ}| ¡ }ˆ  |jj¡ ˆ  ˆ 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&   )re   rÛ  râ  rß   )r·   rV   r1   r2   ÚfakeGetSignal¹  s    zVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignalÚ	getsignalrÂ  N)
r@   rÛ  r¯   r!   rµ  rÇ  rÈ  rg  re   rÙ  )rJ   rã  rÊ  rË  r�  r1   rV   r2   Ú,test_getLogObserverDontOverrideSignalHandler³  s    z?UnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandlerc                 C   s\   t | jƒ}tdddœƒ}| ¡ }|  |jj¡ |  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µ  rÇ  rÈ  rg  re   rb  r¬   r7   rÉ  )rJ   rœ  r   r�  r1   r1   r2   Útest_getLogObserverDefaultFileÆ  s    
z1UnixAppLoggerTests.test_getLogObserverDefaultFiler‹   c                 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   rE  ÚbN)r¥  r!   rµ  re   )rJ   rÀ  r   r�  r1   r1   r2   Útest_getLogObserverSyslogÔ  s    z,UnixAppLoggerTests.test_getLogObserverSyslogN)rL   rM   rN   rO   rË   rÆ  rÝ  rÌ  rå  ræ  r   r¥   rè  r1   r1   r1   r2   rØ  e  s   	
rØ  z!twistd unix support not availablec                   @   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 )Nr7   rÆ   c                  W   s   d S r&   r1   rB  r1   r1   r2   rª   ð  r«   z&DaemonizeTests.setUp.<locals>.<lambda>)r   Úmockosr   rh   rl   r@   r¥   r    rÏ   r   rÊ   rS   r|  rž   rï   Ústderrrð   rñ   rV   r1   r1   r2   rË   è  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Ï   rX   re   rê  ÚactionsÚclosedrV   r1   r1   r2   Útest_successò  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î  ©r4  éÿÿÿÿéd   ©Úexitr   ró  rú  N)rê  ÚchildÚreadDatar   r/  rx   ÚSystemErrorrÏ   rX   re   rö  r÷  rV   r1   r1   r2   Ú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(  ©rs   rb  r½   r¾   ZEINTR)Úfdrz  ©Zwrittenr1   r2   ÚraisingWrite$  s    z6DaemonizeTests.test_successEINTR.<locals>.raisingWriterì  rí  rî  rð  ró  rõ  rñ  )rñ  rò  N)	rê  r±   r   r/  rÏ   rX   re   rö  r÷  )rJ   r  r1   r  r2   Útest_successEINTR  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©r4  r1   r2   ÚraisingReadA  s    
z=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadFrì  rí  rî  rü  ró  rú  )rú  rû  N)rê  r4  rþ  r   r/  rx   r   rÏ   rX   re   rö  r÷  )rJ   r	  r1   r  r2   Ú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Œ  rV   ©Úraisedr1   r2   rù   `  s    zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startServiceN)rL   rM   rN   rù   r1   r  r1   r2   rü   _  s   rü   rì  rí  rî  rð  r±   rñ  ró  rõ  N)r   rH   rö   rÏ   rS   r   r/  rx   rt  rX   re   rê  rö  r÷  )rJ   r  Úreportedrü   ZerrorServicer1   r  r2   ÚassertErrorWrittenX  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  rV   r1   r1   r2   Ú
test_errorv  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  rV   r1   r1   r2   Ú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/  rx   r   rÏ   rX   re   r{   rö  r÷  )rJ   rÿ  ÚerrorMessageÚmockOSActionsZerrorIOr1   r1   r2   Ú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  rV   r1   r1   r2   Ú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  rV   r1   r1   r2   Ú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  )rJ   ZtruncatedMessageZreportedMessager1   r1   r2   Ú&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  rV   r1   r1   r2   Ú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  rV   r1   r1   r2   Ú!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‚   rn  ro  r)  r1   r1   r2   Útest_hooksCalledõ  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)rm  rÏ   r'  r…   rn  ro  r)  r1   r1   r2   Útest_hooksNotCalled   s    z"DaemonizeTests.test_hooksNotCalledN)rL   rM   rN   rO   rË   rø  r  r  r
  r  r  r  r  r  r  r  r  r  r   r!  r1   r1   r1   r2   ré  â  s"   
		ré  c                   @   s*   e Zd ZdZedd„ ƒZejdd„ ƒZdS )ÚSignalCapturingMemoryReactorz‰
    MemoryReactor that implements the _ISupportsExitSignalCapturing interface,
    all other operations identical to MemoryReactor.
    c                 C   s   | j S r&   ©Z_valrV   r1   r1   r2   r    s    z(SignalCapturingMemoryReactor._exitSignalc                 C   s
   || _ d S r&   r#  )rJ   Úvalr1   r1   r2   r    s    N)rL   rM   rN   rO   Úpropertyr  Úsetterr1   r1   r1   r2   r"    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 ƒ  |¡ d | _d S r&   )Úsuperr_   Ú_signalValuerƒ   ©Ú	__class__r1   r2   r_   '  s    z(StubApplicationRunnerWithSignal.__init__c                 C   s   dS )z
        Does nothing.
        Nr1   rV   r1   r1   r2   rW   +  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)  r1   r1   r2   rX   0  s    z/StubApplicationRunnerWithSignal.postApplication)
rL   rM   rN   rO   rQ   rY   r_   rW   rX   Ú__classcell__r1   r1   r*  r2   r'    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)  )rl   rÏ   ©Úsignumr1   r2   ÚstubApplicationRunnerFactoryG  s    zIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryr1   )r.  r/  r1   r-  r2   Ú#stubApplicationRunnerFactoryCreator:  s    r0  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µ   rV   r1   r2   ÚfakeKillj  s    
z+ExitWithSignalTests.setUp.<locals>.fakeKillr¸   )r   rh   rl   rE   rÞ   rß   rà   rm   r2  r@   r7   )rJ   r3  r1   rV   r2   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»   r1   )r·   Úhandler©ZfakeSignalArgsr1   r2   Úfake_signal  s    z<ExitWithSignalTests.test_exitWithSignal.<locals>.fake_signalrÛ  r   r»   )
r@   rÛ  r	   Z_exitWithSignalÚSIGINTr  ÚSIG_DFLr2  r7   r¿   )rJ   r6  r1   r5  r2   Útest_exitWithSignalw  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   r0  ÚrunApprl   rk   r2  rV   r1   r1   r2   Ú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   r0  rÛ  r7  r:  rl   r  r2  r7   r¿   rV   r1   r1   r2   Útest_runnerExitsWithSignal—  s    ýz.ExitWithSignalTests.test_runnerExitsWithSignalN)rL   rM   rN   rO   rË   r9  r;  r<  r1   r1   r1   r2   r1  Z  s
   r1  )hrO   r¾   rI  r7   rÈ   rÛ  r|  r9   Z_grpr6   Ú_pwdÚImportErrorÚior   Zunittestr   Zzope.interfacer   Zzope.interface.verifyr   rŸ   r   r   r   Ztwisted.applicationr	   r
   r   Ztwisted.application.servicer   Ztwisted.internet.baser   Ztwisted.internet.deferr   Ztwisted.internet.interfacesr   r   Z#twisted.internet.test.modulehelpersr   Ztwisted.internet.testingr   Ztwisted.loggerr   r   r   Ztwisted.pythonr   Ztwisted.python.componentsr   Ztwisted.python.fakepwdr   Ztwisted.python.logr¼  r   Ztwisted.python.reflectr   Ztwisted.python.runtimer   Ztwisted.python.usager   Ztwisted.scriptsr   Ztwisted.test.test_processr   Ztwisted.trial.unittestr   r¥   Ztwisted.scripts._twistd_unixr    r!   r"   r¤  r#   r$   r%   rD   rE   r´  rQ   rý   rU   rZ   r¦   rÄ   rÎ   rÖ   rÕ   rÛ   r  r=  rd  rm  r/  r  rv  rŸ  r¥  r¦  rØ  ré  r"  r'  r0  r1  r1   r1   r1   r2   Ú<module>   s®   
-	 Y
F t
 

 
 ;  %
|
  + 