U
    .Wj$! ã                   @   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_nameZgr_gidÚtuple)ÚnameÚresult©ÚgidZgrentÚgroup© úcc:\users\psant\downloads\hotstarbackend\school\venv38\Lib\site-packages\twisted/test/test_twistd.pyÚgetgrnamd   s
    z#patchUserDatabase.<locals>.getgrnamÚgetpwnamr2   ÚgetpwuidN)Úpwdr4   ÚosÚgetuidÚgrpÚgetgrgidÚgetgidr   ZaddUserZ	pw_passwdZpw_gecosÚpw_dirZpw_shellr3   )ÚpatchÚuserÚuidr/   r.   ÚpwentZdatabaser2   r0   r-   r1   ÚpatchUserDatabaseC   s           ÿr@   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©ÚselfrC   r0   r0   r1   ÚmakeServicew   s    
zMockServiceMaker.makeServiceN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚtapnamerG   r0   r0   r0   r1   rA   p   s   rA   c                   @   s   e Zd ZdZdd„ ZdS )ÚCrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                 C   s   d S r&   r0   ©rF   Úapplicationr0   r0   r1   Ústart†   s    zCrippledAppLogger.startN)rH   rI   rJ   rK   rP   r0   r0   r0   r1   rM   �   s   rM   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   ©rF   r0   r0   r1   ÚpreApplication“   s    z(CrippledApplicationRunner.preApplicationc                 C   s   d S r&   r0   rR   r0   r0   r1   ÚpostApplication–   s    z)CrippledApplicationRunner.postApplicationN)rH   rI   rJ   rK   rM   ÚloggerFactoryrS   rT   r0   r0   r0   r1   rQ   Š   s   rQ   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 )rL   Ú_optionsÚdescription©rF   r+   r0   r0   r1   Ú__init__¦   s    
z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__c                 S   s   | j S r&   )rX   rR   r0   r0   r1   rC   «   s    z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.optionsN)rH   rI   rJ   r[   rC   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^   r_   r`   rF   r0   r1   Ú
getPlugins³   s
    z7ServerOptionsTests.test_subCommands.<locals>.getPluginsN)r   ÚServerOptionsra   Z_getPluginsr   rc   ÚsubCommandsÚziprL   ÚassertIsNonerX   rY   )rF   r\   rc   Úconfigre   ZexpectedOrderÚ
subCommandZexpectedCommandr+   ZshortcutZparserClassZdocumentationr0   rb   r1   Ú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 rW   ztwisted.internet.default)Ú	shortNamerY   Z
moduleNamerZ   r0   r0   r1   r[   Ð   s    

zPServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstaller.__init__N)rH   rI   rJ   r[   r0   r0   r0   r1   ÚFakeReactorInstallerÏ   s   rl   r]   r^   r_   r`   c                   3   s   ˆV  ˆV  ˆV  ˆ V  d S r&   r0   r0   )r]   r^   r_   r`   r0   r1   ÚgetReactorTypesÚ   s    zBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypesz--help-reactorsc                    s    ˆ  | ˆ ¡ ˆ ˆ  | ¡¡ d S r&   )ÚassertInÚappendr(   )Ús)Ú
helpOutputÚindexesrF   r0   r1   ÚgetIndexê   s    z;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndexz9reactor descriptions were not in alphabetical order: {!r}N)r   rd   ra   Z_getReactorTypesr
   rm   r   ZmessageOutputÚassertRaisesÚ
SystemExitÚparseOptionsÚgetvaluerk   rY   ÚsortedÚformat)rF   rl   rm   rh   Úreactorrs   r0   )r]   r^   r_   r`   rq   rr   rF   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.
        rB   Úno_saveN)r   rd   ri   ÚpostOptionsÚ
assertTrue©rF   rh   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   rd   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   rd   Ústrr	   ÚAppProfilerZ	profilersrn   )rF   rh   rq   Úprofilerr0   r0   r1   Ú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   rd   rg   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   rd   rv   ra   r   r0   r0   r1   Ú
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   rd   rt   r   rv   r   r0   r0   r1   Ú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   rd   rt   r   rv   r~   ÚargsÚ
startswithZassertNotIn©rF   rh   Úer0   r0   r1   Ú&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“   r0   r0   r1   Ú*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   ry   Úversionr   r   rd   rt   ru   rv   ÚassertIsÚcodera   rw   )rF   r—   r+   ZexpectedOutputrš   rh   r”   r0   r0   r1   Ú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   rd   rt   r   rv   )rF   rš   rh   r0   r0   r1   Ú!test_printSubCommandForUsageErrorh  s    z4ServerOptionsTests.test_printSubCommandForUsageErrorN)rH   rI   rJ   rK   rj   r{   r€   r‚   r†   r   Ú_twistd_unixr‰   rŒ   r�   r•   r–   rŸ   r    r0   r0   r0   r1   rV   š   s    +/	






rV   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 ©NFr0   )Ú_r0   r0   r1   Ú<lambda>|  ó    z.CheckPIDTests.test_notExists.<locals>.<lambda>znon-existent PID fileN)r<   r6   Úpathr"   rR   r0   r0   r1   Ú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Úwritert   ru   r"   rn   rž   )rF   Ú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   rt   ru   r"   rn   rž   ©rF   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£   )rF   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º   ÚEBADFr±   r0   r0   r1   r´   °  s    z2CheckPIDTests.test_unexpectedOSError.<locals>.killr´   Nr   zCan't check status of PID)r«   r¬   r­   r<   r6   rt   ru   r"   ZassertIsNotrž   r~   r‘   r’   rµ   r0   r0   r1   Útest_unexpectedOSError§  s    z$CheckPIDTests.test_unexpectedOSErrorN)	rH   rI   rJ   rK   r©   r°   r¶   r¼   r¿   r0   r0   r0   r1   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)rF   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   rd   rv   rÃ   rQ   ZcreateOrGetApplicationra   r   ÚIServicer+   )rF   rh   rO   r0   r0   r1   Ú&test_createOrGetApplicationWithTapFileÆ  s    z3TapFileTests.test_createOrGetApplicationWithTapFileN)rH   rI   rJ   rK   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)rF   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.
        ÚlogrO   N)rË   Úorderro   ÚhasattrÚhadApplicationLogObserverrN   r0   r0   r1   rP   Ù  s    zTestLoggerFactory.startc                 C   s   dS )z%
        Don't log anything.
        Nr0   rR   r0   r0   r1   Ústopà  s    zTestLoggerFactory.stopN)rH   rI   rJ   rK   r[   rP   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   rE   r0   r0   r1   r[   ì  s    zTestApplicationRunner.__init__c                 C   s   | j  d¡ t| dƒ| _d S )NÚprerO   )rÍ   ro   rÎ   ÚhadApplicationPreApplicationrR   r0   r0   r1   rS   ñ  s    z$TestApplicationRunner.preApplicationc                 C   s   | j  d¡ t| dƒ| _d S )NÚpostrO   )rÍ   ro   rÎ   ÚhadApplicationPostApplicationrR   r0   r0   r1   rT   õ  s    z%TestApplicationRunner.postApplicationN)rH   rI   rJ   rK   r[   rS   rT   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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   rd   rA   ÚserviceMakerÚloadedPluginsÚobjectÚ
subOptionsri   rh   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)rQ   rh   Úrunr�   rÙ   rC   rÜ   r   rÈ   rO   Zservices)rF   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Ñ   rh   rÝ   r�   rÔ   r~   rÖ   rÏ   ra   rÍ   )rF   rp   r0   r0   r1   Ú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©ro   ©rF   ÚchrootZrundirÚnodaemonrˆ   r®   ©Úeventsr0   r1   ÚsetupEnvironment8  s    zmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironmentc                    s   ˆ   d|||f¡ d S )NÚ
privilegesrá   )rF   Úeuidr>   r.   rå   r0   r1   ÚshedPrivileges;  s    zkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivilegesc                    s   ˆ   d¡ d S )Nrz   rá   )rF   rz   Ú	oldstdoutÚ	oldstderrrå   r0   r1   ÚstartReactor>  s    ziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactorc                 S   s   d S r&   r0   )rF   r®   r0   r0   r1   Ú	removePIDA  s    zfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDN)rH   rI   rJ   rç   rê   rí   rî   r0   rå   r0   r1   Ú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&   r0   rZ   r0   r0   r1   ÚsetNameM  s    zVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNamec                 S   s   d S r&   r0   )rF   Úparentr0   r0   r1   ÚsetServiceParentP  s    z_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentc                 S   s   d S r&   r0   rR   r0   r0   r1   ÚdisownServiceParentS  s    zbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentc                    s   ˆ   d¡ d S )NÚprivilegedStartServicerá   rR   rå   r0   r1   rô   V  s    zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServicec                    s   ˆ   d¡ d S )NÚstartServicerá   rR   rå   r0   r1   rõ   Y  s    z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServicec                 S   s   d S r&   r0   rR   r0   r0   r1   ÚstopService\  s    zZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService)rH   rI   rJ   rñ   Úrunningr+   ÚprocessNamer>   r.   rð   rò   ró   rô   rõ   rö   r0   rå   r0   r1   ÚFakeServiceD  s   rù   rà   rô   rè   Frõ   rz   N)rh   rv   r   Ú_SomeApplicationRunnerr   r   rÈ   ZIProcessr   rS   rO   rT   ra   )rF   Úargvr>   r.   rï   rù   rO   rË   r0   rå   r1   Ú"_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ƒ   )rF   r>   r.   r0   r0   r1   Ú.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)r@   r<   rü   )rF   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}.
        Fr#   ©r#   r…   ÚdebugNz'startReactor did not call reactor.run())ÚDummyReactorr	   rÒ   rí   r~   Úcalled©rF   rz   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.
        rz   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   rR   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©Ú_exitSignalrR   r0   r0   r1   rÝ   À  s    z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.runN©rH   rI   rJ   rK   r  rÝ   r0   r0   r0   r1   ÚDummyReactorWithSignalµ  s   r  Fr#   r  Nr  )r   r	   rÒ   rí   ÚassertEqualsr  )rF   r  rz   rË   r0   r0   r1   Ú$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  r0   rR   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  rR   r0   r0   r1   rÝ   Þ  s    zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.runNr  r0   r0   r0   r1   Ú#DummyReactorWithExitSignalAttributeÓ  s   r  Fr#   r  N)r	   rÒ   rí   r  r  )rF   r  rz   rË   r0   r0   r1   Ú%test_applicationRunnerIgnoresNoSignalÍ  s    
ÿz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal)rH   rI   rJ   rK   rÇ   rÞ   rß   rü   r   Úgetattrr6   r  r  r  r  r  r  r0   r0   r0   r1   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¨   rR   r0   r1   r¦     r§   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>Úchdirc                    s   t ˆ d| ƒS )NÚcwdr  r  rR   r0   r1   r¦     r§   rˆ   c                    s   t ˆ d| ƒS )NÚmaskr  )r!  rR   r0   r1   r¦     r§   )Úunsetr  r   r!  Údaemonr6   r»   r²   r<   r    r   rd   rË   Ú	daemonizerR   r0   rR   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   rR   r0   r1   r¦     r§   zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>N)r#  r<   r6   ©rF   rz   r0   rR   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ç   ra   r  rR   r0   r0   r1   Ú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"  rR   r0   r0   r1   Ú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ç   ra   r   rR   r0   r0   r1   Ú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#  rR   r0   r0   r1   Ú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#  rR   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Úreadra   r²   ©rF   r®   r¯   r²   r0   r0   r1   Ú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(  Fr/  r·   )
r«   r   r,  rË   rç   r¬   r0  r1  ra   r²   r2  r0   r0   r1   Ú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ç   ra   r!  rR   r0   r0   r1   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"  rR   r0   r0   r1   Ú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é?   r6  rR   r0   r0   r1   Útest_daemonizedNoUmaskl  s    zAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmaskN)rH   rI   rJ   rK   rÛ   r"  rÇ   r$  r)  r*  r+  r-  r.  r3  r4  rŒ   r7  r9  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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‘   r0   r1   ÚfakeSetupEnvironment—  s    z^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironmentrF   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   rA  r0   r0   r1   r¦   ¬  r§   Té8   N)r   rd   rv   r   rÆ   r    rË   ÚinspectÚ	signaturerç   Ú
parametersÚcopyÚpopra   r<   r	   rD  )rF   rC   rO   r@  ZsetupEnvironmentParametersZfakeSetupEnvironmentParametersr0   r?  r1   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   é#   ©ra   ©r>   r.   ré   rR   r0   r1   ÚswitchUIDPass·  s    zUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPassÚ	switchUIDrM  rK  rL  N)r<   r¡   r    rê   )rF   rP  rË   r0   rR   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½   rO  r0   r0   r1   ÚswitchUIDFailÇ  s    zZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFailrQ  rM  rK  Nr·   )r    r<   r¡   rt   ru   rê   ra   rž   )rF   rS  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ˆƒ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&   rN  )r>   r.   ©rF   Ú	wantedGidÚ	wantedUidr0   r1   Ú
initgroupsÖ  s    zFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroupsc                    s   ˆ   | ˆ¡ d S r&   rN  )r>   )rF   rX  r0   r1   rý   Ú  s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuidc                    s   ˆ   | ˆ¡ d S r&   rN  )r.   )rF   rW  r0   r1   ÚsetgidÝ  s    zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgidrY  rý   rZ  r;  r   r<  r=  N)r@   r<   r   r6   r   rd   rv   rƒ   r   rÆ   r    rË   rD  )rF   Z
wantedUserrX  ZwantedGrouprW  ZpidFilerY  rý   rZ  rC   rO   rË   r0   rV  r1   Ú_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«   rR   r0   r0   r1   Ú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)r6   r7   r[  ÚflushWarningsry   ra   Úlen)rF   Z
currentUidZwarningsShownZexpectedWarningr0   r0   r1   Útest_setUidSameAsCurrentUid÷  s         ÿ ÿÿzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUidN)
rH   rI   rJ   rK   r=  rR  rU  r[  r\  r`  r0   r0   r0   r1   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«   r6   Úmakedirsr¨   Újoinr¬   Úcloserî   r�   r£   )rF   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¹   ra   r_  Úvaluerº   ÚENOENT)rF   rË   Úerrorsr0   r0   r1   Útest_removePIDErrors  s
    

z8UnixApplicationRunnerRemovePIDTests.test_removePIDErrorsN)rH   rI   rJ   rK   re  ri  r0   r0   r0   r1   ra  
  s   ra  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Ú_afterDaemonizeCalledrR   r0   r0   r1   r[   5  s    z"FakeNonDaemonizingReactor.__init__c                 C   s
   d| _ d S ©NT)rk  rR   r0   r0   r1   ÚbeforeDaemonize9  s    z)FakeNonDaemonizingReactor.beforeDaemonizec                 C   s
   d| _ d S rm  )rl  rR   r0   r0   r1   ÚafterDaemonize<  s    z(FakeNonDaemonizingReactor.afterDaemonizec                 O   s   dS )z*
        Skip event registration.
        Nr0   )rF   r‘   rC  r0   r0   r1   ÚaddSystemEventTrigger?  s    z/FakeNonDaemonizingReactor.addSystemEventTriggerN)rH   rI   rJ   rK   r[   rn  ro  rp  r0   r0   r0   r1   rj  )  s
   rj  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)rH   rI   rJ   rK   r0   r0   r0   r1   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	  ÚRuntimeErrorrR   r0   r0   r1   rÝ   X  s    úDummyReactor.runN)rH   rI   rJ   rK   r	  rÝ   r0   r0   r0   r1   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…   rr  úfunction callsN©r   rd   r«   r	   r„   r  rÝ   r~   r	  r¬   r1  rn   ©rF   rh   r…   rz   r¯   Údatar0   r0   r1   Útest_profilef  s    

zAppProfilingTests.test_profilec                 C   sP   t ƒ }|  td|¡}||ƒ}| ¡  | ¡  | ¡ }|  d|¡ |  d|¡ d S )Nrš   rt  z(run))r   r<   ÚsysÚprint_statsÚrestorerw   rn   )rF   Z
statsClassr#   Úoutrš   Ústatsrw  r0   r0   r1   Ú
_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   rd   r«   r	   r„   r  rÝ   r~   r	  r~  r$   ZStats©rF   rh   r…   rz   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©ry  ÚmodulesrI  r   rd   r	   r„   ÚclearÚupdatert   ru   rÝ   ©rF   ZsavedModulesrh   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©rq  rR   r0   r0   r1   rz  ·  s    zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_statsN)rH   rI   rJ   rz  r0   r0   r0   r1   ÚErroneousProfile¶  s   rŠ  ÚProfiler#   r…   N)r#   r‹  r<   r   rd   r«   r	   r„   r  ry  rš   rt   rq  rÝ   r�   )rF   rŠ  rh   r…   rz   Z	oldStdoutr0   r0   r1   Ú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Ý   rt  Nru  rv  r0   r0   r1   Ú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�  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_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   rd   r«   rt   ru   r	   r„   ra   rƒ   )rF   rh   Úerrorr0   r0   r1   Ú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„   ra   r…   ©rF   r…   r0   r0   r1   Ú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”  r0   r0   r1   Útest_profilerNameCaseInsentive  s    z0AppProfilingTests.test_profilerNameCaseInsentiveN)rH   rI   rJ   rK   r   r#   rx  r~  r‚  rˆ  rŒ  r%   r�  rŽ  r�  r‘  r•  r–  r0   r0   r0   r1   rs  a  s"   









rs  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oldFileLogObserverr0   r1   Úobserver(  s    
z+_patchTextFileLogObserver.<locals>.observerÚtextFileLogObserver)r   r›  )r<   rš  r0   r˜  r1   Ú_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á   )rF   Úprefix©ZlogMessagesr0   r1   r[   8  s    z1_setupSyslog.<locals>.fakesyslogobserver.__init__c                    s   ˆ   |¡ d S r&   rá   )rF   Z	eventDictrž  r0   r1   Úemit;  s    z-_setupSyslog.<locals>.fakesyslogobserver.emitN)rH   rI   rJ   r[   rŸ  r0   rž  r0   r1   Úfakesyslogobserver7  s   r   ZSyslogObserver)r<   Úsyslog)ZtestCaser   r0   rž  r1   Ú_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&   )Ú	observersro   r   ZaddObserver)r¤  rš  rR   r0   r1   ÚbeginLoggingToQ  s    z,AppLoggerTests.setUp.<locals>.beginLoggingTor¥  N)r¤  r<   r   )rF   r¥  r0   rR   r1   rÇ   J  s    zAppLoggerTests.setUpc                 C   s   | j D ]}t |¡ qdS )z1
        Remove all installed observers.
        N)r¤  r   ÚremoveObserver©rF   rš  r0   r0   r1   Ú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&   )Ú_logsro   )rF   Úeventr0   r0   r1   Ú__call__k  s    z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__N)rH   rI   rJ   r©  r«  r0   r0   r0   r1   ÚTestObserverg  s   r¬  )r   r   )rF   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)ra   r¤  rn   r©  r§  r0   r0   r1   Ú_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&   r0   r0   ©rš  r0   r1   r¦   �  r§   z+AppLoggerTests.test_start.<locals>.<lambda>N)r	   Ú	AppLoggerr­  Ú_getLogObserverrP   r   r¯  )rF   r   r0   r°  r1   Ú
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±  rP   r¯  )rF   rO   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†  rP   )rF   rO   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¶  rN   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¶  ra   r©  )rF   rš  rO   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´  ÚLegacyILogObserverro   r¯  r¶  ra   )rF   ÚnonlogsrO   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¹  ro   r	   r±  rP   r¯  ra   )rF   rº  rš  rO   r   r0   r0   r1   Ú.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!   ra   )rF   ÚlogsrO   r0   r0   r1   Ú%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�   r6   r¨   r£   )rF   rO   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²  ra   r_  r�   ry  rš   )rF   r   r™  r0   r0   r1   Ú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Ú_outFilerd  ra   r_  r¨   r6   Úabspath)rF   r™  ÚfilenameÚsutrš  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°  ©Úremovedr0   r1   Úremove   s    z(AppLoggerTests.test_stop.<locals>.remover¦  N)	rÛ   r<   r   r	   r±  Z	_observerrÐ   ra   rg   )rF   rš  rÌ  r   r0   rÊ  r1   Ú	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á   )rF   Úx©r½  r0   r1   r«  :  s    zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__N)rH   rI   rJ   rK   r«  r0   rÏ  r0   r1   ÚLoggerObserver4  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¹  Z_observerFactoryrP   r   rn   r   r^  Útest_legacyObserversra   r_  ©rF   r   Úwarningsr0   )rÐ  r½  r1   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á   r0   rÏ  r0   r1   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²  rP   r   rn   r   r^  Ú test_unmarkedObserversDeprecatedra   r_  rÒ  r0   rÏ  r1   rÔ  G  s    

ýz/AppLoggerTests.test_unmarkedObserversDeprecatedN)rH   rI   rJ   rK   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£  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&   )Úsignalsro   )r³   r¯   rR   r0   r1   Ú
fakeSignalu  s    z,UnixAppLoggerTests.setUp.<locals>.fakeSignalÚsignalN)rÖ  r<   rØ  )rF   r×  r0   rR   r1   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²  ra   r_  r�   ry  rš   )rF   r™  r   r0   r0   r1   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!   rt   ru   r²  ra   rƒ   )rF   r   r�  r0   r0   r1   Ú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&   )Úcallbackr0   ©Údr0   r1   Úrotateª  s    z:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotateN)rœ  r<   r«   r!   r²  rÄ  rÅ  rd  ra   r_  r¨   r6   rÆ  rÖ  rØ  ÚSIGUSR1r   rÞ  )rF   r™  rÇ  rÈ  rš  rÞ  Z	rotateLogr0   rÜ  r1   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&   )ra   rØ  rß  rÛ   )r³   rR   r0   r1   ÚfakeGetSignal¹  s    zVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignalÚ	getsignalr¿  N)
r<   rØ  r«   r!   r²  rÄ  rÅ  rd  ra   rÖ  )rF   rà  rÇ  rÈ  rš  r0   rR   r1   Ú,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Å  rd  ra   r_  r¨   r6   rÆ  )rF   r™  r   rš  r0   r0   r1   Ú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�  rB  ÚbN)r¢  r!   r²  ra   )rF   r½  r   rš  r0   r0   r1   Útest_getLogObserverSyslogÔ  s    z,UnixAppLoggerTests.test_getLogObserverSyslogN)rH   rI   rJ   rK   rÇ   rÃ  rÚ  rÉ  râ  rã  r   r¡   rå  r0   r0   r0   r1   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 )Nr6   rÂ   c                  W   s   d S r&   r0   r?  r0   r0   r1   r¦   ð  r§   z&DaemonizeTests.setUp.<locals>.<lambda>)r   Úmockosr   rd   rh   r<   r¡   r    rË   r   rÆ   rO   ry  rš   rë   Ústderrrì   rí   rR   r0   r0   r1   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ˆ   r8  ©ÚforkTÚsetsid)r­   éþÿÿÿó   0©Úunlinkz
twistd.pidéýÿÿÿrî  N)r   r,  rË   rT   ra   rç  ÚactionsÚclosedrR   r0   r0   r1   Ú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ë  ©r1  éÿÿÿÿéd   ©Úexitr   rð  r÷  N)rç  ÚchildÚreadDatar   r,  rt   ÚSystemErrorrË   rT   ra   ró  rô  rR   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%  ©ro   r_  r¹   rº   ZEINTR)Úfdrw  ©Zwrittenr0   r1   ÚraisingWrite$  s    z6DaemonizeTests.test_successEINTR.<locals>.raisingWriteré  rê  rë  rí  rð  rò  rî  )rî  rï  N)	rç  r­   r   r,  rË   rT   ra   ró  rô  )rF   r  r0   r  r1   Ú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©r1  r0   r1   ÚraisingReadA  s    
z=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadFré  rê  rë  rù  rð  r÷  )r÷  rø  N)rç  r1  rû  r   r,  rt   rý  rË   rT   ra   ró  rô  )rF   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‰  rR   ©Úraisedr0   r1   rõ   `  s    zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startServiceN)rH   rI   rJ   rõ   r0   r  r0   r1   rù   _  s   rù   ré  rê  rë  rí  r­   rî  rð  rò  N)r   rD   rò   rË   rO   r   r,  rt   rq  rT   ra   rç  ró  rô  )rF   r	  Úreportedrù   ZerrorServicer0   r  r1   Ú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  rR   r0   r0   r1   Ú
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  rR   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<   ry  r   r,  rt   rý  rË   rT   ra   rw   ró  rô  )rF   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  rR   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  rR   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)ry   r  )rF   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  rR   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  rR   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~   rk  rl  r&  r0   r0   r1   Ú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)rj  rË   r$  r�   rk  rl  r&  r0   r0   r1   Útest_hooksNotCalled   s    z"DaemonizeTests.test_hooksNotCalledN)rH   rI   rJ   rK   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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_valrR   r0   r0   r1   r    s    z(SignalCapturingMemoryReactor._exitSignalc                 C   s
   || _ d S r&   r   )rF   Úvalr0   r0   r1   r    s    N)rH   rI   rJ   rK   Úpropertyr  Úsetterr0   r0   r0   r1   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__r0   r1   r[   '  s    z(StubApplicationRunnerWithSignal.__init__c                 C   s   dS )z
        Does nothing.
        Nr0   rR   r0   r0   r1   rS   +  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í   ry  rš   rè  r&  r0   r0   r1   rT   0  s    z/StubApplicationRunnerWithSignal.postApplication)
rH   rI   rJ   rK   rM   rU   r[   rS   rT   Ú__classcell__r0   r0   r'  r1   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&  )rh   rË   ©Úsignumr0   r1   ÚstubApplicationRunnerFactoryG  s    zIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryr0   )r+  r,  r0   r*  r1   Ú#stubApplicationRunnerFactoryCreator:  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±   rR   r0   r1   ÚfakeKillj  s    
z+ExitWithSignalTests.setUp.<locals>.fakeKillr´   )r   rd   rh   rA   rÚ   rÛ   rÜ   ri   r/  r<   r6   )rF   r0  r0   rR   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³   Ú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»   )rF   r3  r0   r2  r1   Ú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   r-  ÚrunApprh   rg   r/  rR   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Ø  r4  r7  rh   r  r/  r6   r»   rR   r0   r0   r1   Útest_runnerExitsWithSignal—  s    ýz.ExitWithSignalTests.test_runnerExitsWithSignalN)rH   rI   rJ   rK   rÇ   r6  r8  r9  r0   r0   r0   r1   r.  Z  s
   r.  )hrK   rº   rF  r6   rÄ   rØ  ry  r8   Z_grpr5   Ú_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%   r@   rA   r±  rM   rú   rQ   rV   r¢   rÀ   rÊ   rÒ   rÑ   r×   r  r:  ra  rj  r,  r  rs  rœ  r¢  r£  rÕ  ræ  r  r$  r-  r.  r0   r0   r0   r1   Ú<module>   s®   
-	 Y
F t
 

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