o
    Óó·i$! ã                   @   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y1   dZ	dZY nw 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ƒZBeBrà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© ú^C:\Users\psant\Downloads\PAF backend\school\venv\Lib\site-packages\twisted/test/test_twistd.pyÚgetgrnamd   s
   z#patchUserDatabase.<locals>.getgrnamÚgetpwnamr3   ÚgetpwuidN)Úpwdr5   ÚosÚgetuidÚgrpÚgetgrgidÚgetgidr   ZaddUserZ	pw_passwdZpw_gecosÚpw_dirZpw_shellr4   )ÚpatchÚuserÚuidr0   r/   ÚpwentZdatabaser3   r1   r.   r2   ÚpatchUserDatabaseC   s   ÿrA   c                   @   ó   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.
        N)Úoptionsr   ÚService©ÚselfrE   r1   r1   r2   ÚmakeServicew   s   
zMockServiceMaker.makeServiceN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚtapnamerI   r1   r1   r1   r2   rC   p   s    rC   c                   @   s   e Zd ZdZdd„ ZdS )ÚCrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                 C   ó   d S r&   r1   ©rH   Úapplicationr1   r1   r2   Ústart†   ó   zCrippledAppLogger.startN)rJ   rK   rL   rM   rS   r1   r1   r1   r2   rO   �   s    rO   c                   @   s$   e Zd ZdZeZdd„ Zdd„ ZdS )ÚCrippledApplicationRunnerzÃ
    An application runner that cripples the platform-specific runner and
    nasty side-effect-having code so that we can use it without actually
    running any environment-affecting code.
    c                 C   rP   r&   r1   ©rH   r1   r1   r2   ÚpreApplication“   rT   z(CrippledApplicationRunner.preApplicationc                 C   rP   r&   r1   rV   r1   r1   r2   ÚpostApplication–   rT   z)CrippledApplicationRunner.postApplicationN)rJ   rK   rL   rM   rO   Ú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 ]&\}}|\}}	}
}ˆ ||j¡ ˆ 	|	¡ ˆ |
ƒ |j
¡f ˆ ||j¡ q>d	S )
zh
        subCommands is built from IServiceMaker plugins, and is sorted
        alphabetically.
        c                   @   s   e Zd Zdd„ Zdd„ ZdS )z7ServerOptionsTests.test_subCommands.<locals>.FakePluginc                 S   s   || _ d| | _d| | _d S )Nzoptions for údescription of )rN   Ú_optionsÚdescription©rH   r,   r1   r1   r2   Ú__init__¦   s   
z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__c                 S   ó   | j S r&   )r\   rV   r1   r1   r2   rE   «   s   z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.optionsN)rJ   rK   rL   r_   rE   r1   r1   r1   r2   Ú
FakePlugin¥   s    ra   ÚappleÚbananaÚcoconutÚdonutc                 3   s*   � ˆ  | t¡ ˆV  ˆV  ˆV  ˆ V  d S r&   )ÚassertEqualr   )Z	interface©rb   rc   rd   re   rH   r1   r2   Ú
getPlugins³   s   €
z7ServerOptionsTests.test_subCommands.<locals>.getPluginsN)r   ÚServerOptionsrf   Z_getPluginsr   rh   ÚsubCommandsÚziprN   ÚassertIsNoner\   r]   )rH   ra   rh   Úconfigrj   ZexpectedOrderÚ
subCommandZexpectedCommandr,   ZshortcutZparserClassZdocumentationr1   rg   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ƒ qIˆ ˆtˆƒd ˆ¡¡ dS )zP
        Reactor names are listed alphabetically by I{--help-reactors}.
        c                   @   ó   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)rJ   rK   rL   r_   r1   r1   r1   r2   ÚFakeReactorInstallerÏ   ó    rr   rb   rc   rd   re   c                   3   s   � ˆV  ˆV  ˆV  ˆ V  d S r&   r1   r1   )rb   rc   rd   re   r1   r2   ÚgetReactorTypesÚ   s
   €
zBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypesz--help-reactorsc                    s    ˆ  | ˆ ¡ ˆ ˆ  | ¡¡ d S r&   )ÚassertInÚappendr(   )Ús)Ú
helpOutputÚindexesrH   r1   r2   ÚgetIndexê   s   z;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndexz9reactor descriptions were not in alphabetical order: {!r}N)r   ri   rf   Z_getReactorTypesr
   rt   r   ZmessageOutputÚassertRaisesÚ
SystemExitÚparseOptionsÚgetvaluerq   r]   ÚsortedÚformat)rH   rr   rt   rm   Úreactorrz   r1   )rb   rc   rd   re   rx   ry   rH   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.
        rD   Úno_saveN)r   ri   rn   ÚpostOptionsÚ
assertTrue©rH   rm   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   ri   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   ri   Ústrr	   ÚAppProfilerZ	profilersru   )rH   rm   rx   Ú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   ri   rl   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   ri   r}   rf   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   ri   r{   r   r}   r†   r1   r1   r2   Útest_invalidUmask(  s   z$ServerOptionsTests.test_invalidUmaskc                 C   óH   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   ri   r{   r   r}   r…   ÚargsÚ
startswithZassertNotIn©rH   rm   Úer1   r1   r2   Ú&test_unimportableConfiguredLogObserver1  s   ÿ
ÿÿz9ServerOptionsTests.test_unimportableConfiguredLogObserverc                 C   r•   )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   ri   r{   r|   r}   ÚassertIsÚcoderf   r~   )rH   rŸ   r,   ZexpectedOutputr¢   rm   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   ri   r{   r   r}   )rH   r¢   rm   r1   r1   r2   Ú!test_printSubCommandForUsageErrorh  s   z4ServerOptionsTests.test_printSubCommandForUsageErrorN)rJ   rK   rL   rM   ro   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   ó   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   s\   |   ¡ }t|dƒ�}| d¡ W d  ƒ n1 sw   Y  |  tt|¡}|  d|j¡ dS )zI
        Non-numeric content in a PID file causes a system exit.
        Úwznon-numericNznon-numeric value)ÚmktempÚopenÚwriter{   r|   r"   ru   r¦   )rH   ÚpidfileÚfrœ   r1   r1   r2   Útest_nonNumeric  s   ÿzCheckPIDTests.test_nonNumericc                 C   sr   |   ¡ }t|dƒ�}| d¡ W d  ƒ n1 sw   Y  dd„ }|  td|¡ |  tt|¡}|  d|j	¡ dS )zE
        Another running twistd server causes a system exit.
        r³   Z42Nc                 S   rP   r&   r1   ©ÚpidÚsigr1   r1   r2   Úkill‘  rT   z/CheckPIDTests.test_anotherRunning.<locals>.killr½   zAnother twistd server)
r´   rµ   r¶   r=   r7   r{   r|   r"   ru   r¦   ©rH   r·   r¸   r½   rœ   r1   r1   r2   Útest_anotherRunning‰  s   ÿz!CheckPIDTests.test_anotherRunningc                 C   s|   |   ¡ }t|dƒ�}| tt ¡ d ƒ¡ W d  ƒ n1 sw   Y  dd„ }|  td|¡ t|ƒ |  tj	 
|¡¡ dS )zJ
        Stale PID file is removed without causing a system exit.
        r³   é   Nc                 S   ó   t tjdƒ‚©NZfake)ÚOSErrorÚerrnoZESRCHrº   r1   r1   r2   r½      ó   z&CheckPIDTests.test_stale.<locals>.killr½   )r´   rµ   r¶   rŠ   r7   Úgetpidr=   r"   rˆ   r±   r«   )rH   r·   r¸   r½   r1   r1   r2   Ú
test_stale˜  s   ÿzCheckPIDTests.test_stalec                 C   sˆ   |   ¡ }t|dƒ�}| d¡ W d  ƒ n1 sw   Y  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3581Nc                 S   rÁ   rÂ   ©rÃ   rÄ   ÚEBADFrº   r1   r1   r2   r½   °  rÅ   z2CheckPIDTests.test_unexpectedOSError.<locals>.killr½   r   zCan't check status of PID)r´   rµ   r¶   r=   r7   r{   r|   r"   ZassertIsNotr¦   r…   r™   rš   r¾   r1   r1   r2   Útest_unexpectedOSError§  s   ÿz$CheckPIDTests.test_unexpectedOSErrorN)	rJ   rK   rL   rM   r²   r¹   r¿   rÇ   rÊ   r1   r1   r1   r2   rª   r  s    
rª   c                   @   ó    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   sN   |   ¡ | _t| jdƒ�}t t d¡|¡ W d  ƒ dS 1 s w   Y  dS )zP
        Create a trivial Application and put it in a tap file on disk.
        ÚwbúHi!N)r´   Útapfilerµ   ÚpickleÚdumpr   ÚApplication)rH   r¸   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   ri   r}   rÏ   rU   ZcreateOrGetApplicationrf   r   ÚIServicer,   )rH   rm   rR   r1   r1   r2   Ú&test_createOrGetApplicationWithTapFileÆ  s   z3TapFileTests.test_createOrGetApplicationWithTapFileN)rJ   rK   rL   rM   rÓ   rÕ   r1   r1   r1   r2   rÌ   ¹  s    rÌ   c                   @   ó(   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   ó
   || _ d S r&   )Úrunner)rH   rÙ   r1   r1   r2   r_   Ö  ó   
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.
        ÚlogrR   N)rÙ   Úorderrv   ÚhasattrÚhadApplicationLogObserverrQ   r1   r1   r2   rS   Ù  s   zTestLoggerFactory.startc                 C   r¬   )z%
        Don't log anything.
        Nr1   rV   r1   r1   r2   Ústopà  r°   zTestLoggerFactory.stopN)rJ   rK   rL   rM   r_   rS   rß   r1   r1   r1   r2   r×   Ñ  s
    r×   c                   @   rÖ   )	ÚTestApplicationRunnerz`
    An ApplicationRunner which tracks the environment in which its methods are
    called.
    c                 C   s"   t j | |¡ g | _t| ƒ| _d S r&   )r	   ÚApplicationRunnerr_   rÜ   r×   r   rG   r1   r1   r2   r_   ì  s   zTestApplicationRunner.__init__c                 C   ó   | j  d¡ t| dƒ| _d S )NÚprerR   )rÜ   rv   rÝ   ÚhadApplicationPreApplicationrV   r1   r1   r2   rW   ñ  ó   z$TestApplicationRunner.preApplicationc                 C   râ   )NÚpostrR   )rÜ   rv   rÝ   ÚhadApplicationPostApplicationrV   r1   r1   r2   rX   õ  rå   z%TestApplicationRunner.postApplicationN)rJ   rK   rL   rM   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   ri   rC   ÚserviceMakerÚloadedPluginsÚobjectÚ
subOptionsrn   rm   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   rm   Úrunr¥   rê   rE   rí   r   rÔ   rR   Zservices)rH   Zarunnerr1   r1   r2   Ú,test_applicationRunnerGetsCorrectApplication  s   
ýýzCApplicationRunnerTests.test_applicationRunnerGetsCorrectApplicationc                 C   sL   t | jƒ}| ¡  |  |j¡ |  |j¡ |  |j¡ |  |j	g d¢¡ dS )z†
        Test thet preApplication and postApplication methods are
        called by ApplicationRunner.run() when appropriate.
        )rã   rÛ   ræ   N)
rà   rm   rî   rˆ   rä   r…   rç   rÞ   rf   rÜ   )rH   rw   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                    ó   ˆ   d¡ d S )NÚenvironment©rv   ©rH   ÚchrootZrundirÚnodaemonr�   r·   ©Úeventsr1   r2   ÚsetupEnvironment8  ó   zmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironmentc                    s   ˆ   d|||f¡ d S )NÚ
privilegesró   )rH   Úeuidr?   r/   r÷   r1   r2   ÚshedPrivileges;  s   zkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivilegesc                    rñ   )Nr�   ró   )rH   r�   Ú	oldstdoutÚ	oldstderrr÷   r1   r2   ÚstartReactor>  rú   ziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactorc                 S   rP   r&   r1   )rH   r·   r1   r1   r2   Ú	removePIDA  rT   zfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDN)rJ   rK   rL   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   rP   r&   r1   r^   r1   r1   r2   ÚsetNameM  rT   zVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNamec                 S   rP   r&   r1   )rH   Úparentr1   r1   r2   ÚsetServiceParentP  rT   z_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentc                 S   rP   r&   r1   rV   r1   r1   r2   ÚdisownServiceParentS  rT   zbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentc                    rñ   )NÚprivilegedStartServiceró   rV   r÷   r1   r2   r  V  rú   zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServicec                    rñ   )NÚstartServiceró   rV   r÷   r1   r2   r  Y  rú   z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServicec                 S   rP   r&   r1   rV   r1   r1   r2   ÚstopService\  rT   zZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService)rJ   rK   rL   r  Úrunningr,   ÚprocessNamer?   r/   r  r  r  r  r  r	  r1   r÷   r1   r2   ÚFakeServiceD  s    r  rò   r  rû   Fr  r�   N)rm   r}   r   Ú_SomeApplicationRunnerr   r   rÔ   ZIProcessr   rW   rR   rX   rf   )rH   Úargvr?   r/   r  r  rR   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Š   )rH   r?   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)rA   r=   r  )rH   r>   r?   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©rH   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                   @   rË   )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   r¬   ©z=
                Dummy method, does nothing.
                Nr1   rV   r1   r1   r2   ÚinstallWaker»  r°   zhApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.installWakerc                 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©rJ   rK   rL   rM   r"  rî   r1   r1   r1   r2   ÚDummyReactorWithSignalµ  ó    r(  Fr#   r  Nr$  )r   r	   rá   r   ÚassertEqualsr&  )rH   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                   @   rË   )ziApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttributer   c                 S   r¬   r!  r1   rV   r1   r1   r2   r"  Ù  r°   zvApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.installWakerc                 S   r#  )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Ó  r)  r,  Fr#   r  N)r	   rá   r   r*  r&  )rH   r,  r�   rÙ   r1   r1   r2   Ú%test_applicationRunnerIgnoresNoSignalÍ  s   
ÿz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal)rJ   rK   rL   rM   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                    ó   t ˆ d| ƒS )NÚroot©Úsetattr©r±   rV   r1   r2   r¯     ó    zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>Úchdirc                    r0  )NÚcwdr2  r4  rV   r1   r2   r¯     r5  r�   c                    r0  )NÚmaskr2  )r8  rV   r1   r2   r¯     r5  )Úunsetr1  r7  r8  Údaemonr7   rÆ   r»   r=   r    r   ri   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¯     s   
 zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>N)r:  r=   r7   ©rH   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ù   rf   r1  rV   r1   r1   r2   Útest_chroot  ó   z6UnixApplicationRunnerSetupEnvironmentTests.test_chrootc                 C   ó(   | 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¥   r1  r9  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ù   rf   r7  rV   r1   r1   r2   Útest_changeWorkingDirectory)  rA  zFUnixApplicationRunnerSetupEnvironmentTests.test_changeWorkingDirectoryc                 C   sN   t tƒ ƒ� | j ddddd¡ W d  ƒ n1 sw   Y  |  | 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   sd   |   ¡ }| j dddd|¡ t|dƒ�}t| ¡ ƒ}W d  ƒ n1 s$w   Y  |  || 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Úreadrf   r»   ©rH   r·   r¸   r»   r1   r1   r2   Útest_nonDaemonPIDFileB  s   ÿz@UnixApplicationRunnerSetupEnvironmentTests.test_nonDaemonPIDFilec                 C   s’   |   ¡ }ttƒ ƒ� | j dddd|¡ W d  ƒ n1 sw   Y  t|dƒ�}t| ¡ ƒ}W d  ƒ n1 s9w   Y  |  || 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?  FrH  rÀ   )
r´   r   rE  rÙ   rù   rµ   rI  rJ  rf   r»   rK  r1   r1   r2   Útest_daemonPIDFileM  s   ÿÿz=UnixApplicationRunnerSetupEnvironmentTests.test_daemonPIDFilec                 C   sP   t tƒ ƒ� | j ddddd¡ W d  ƒ n1 sw   Y  |  | jd¡ dS )z�
        L{UnixApplicationRunner.setupEnvironment} changes the process umask to
        the value specified by the C{umask} parameter.
        Nr?  Fé{   ©r   rE  rÙ   rù   rf   r8  rV   r1   r1   r2   r“   Z  s   ÿz5UnixApplicationRunnerSetupEnvironmentTests.test_umaskc                 C   rB  )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¥   r8  r9  rV   r1   r1   r2   Útest_noDaemonizeNoUmaskc  s   zBUnixApplicationRunnerSetupEnvironmentTests.test_noDaemonizeNoUmaskc                 C   sP   t tƒ ƒ� | j ddddd¡ W d  ƒ n1 sw   Y  |  | 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é?   rO  rV   r1   r1   r2   Útest_daemonizedNoUmaskl  s   ÿzAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmaskN)rJ   rK   rL   rM   rì   r9  rÓ   r;  r@  rC  rD  rF  rG  rL  rM  r“   rP  rR  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  ¡ }| g d¢¡ 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 |¡ |  ˆ g d¢¡ 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--chrootú/foo/chrootz--rundirú/foo/rundirú	--pidfileú/foo/pidfileÚtest_setupEnvironmentc                    s   ˆ   |||||f¡ d S r&   )Úextendrô   ©r™   r1   r2   ÚfakeSetupEnvironment—  s   z^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironmentrH   rù   rý   c                  _   rP   r&   r1   ©ÚaÚkwr1   r1   r2   r¯   «  r°   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>ÚstartApplicationc                  _   rP   r&   r1   r]  r1   r1   r2   r¯   ¬  r°   )rU  rV  Té8   rX  N)r   ri   r}   r   rÒ   r    rÙ   ÚinspectÚ	signaturerù   Ú
parametersÚcopyÚpoprf   r=   r	   r`  )rH   rE   rR   r\  ZsetupEnvironmentParametersZfakeSetupEnvironmentParametersr1   r[  r2   rY  }  s4   ÿ

ÿþÿþ
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   é#   ©rf   ©r?   r/   rü   rV   r1   r2   ÚswitchUIDPass·  s   zUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPassÚ	switchUIDri  rg  rh  N)r=   r©   r    rý   )rH   rl  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   rÁ   rÂ   rÈ   rk  r1   r1   r2   ÚswitchUIDFailÇ  rÅ   zZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFailrm  ri  rg  NrÀ   )r    r=   r©   r{   r|   rý   rf   r¦   )rH   ro  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&   rj  )r?   r/   ©rH   Ú	wantedGidÚ	wantedUidr1   r2   Ú
initgroupsÖ  rå   zFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroupsc                    ó   ˆ   | ˆ¡ d S r&   rj  )r?   )rH   rt  r1   r2   r  Ú  ó   zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuidc                    rv  r&   rj  )r/   )rH   rs  r1   r2   ÚsetgidÝ  rw  zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgidru  r  rx  rT  r  rW  rY  N)rA   r=   r   r7   r   ri   r}   rŠ   r   rÒ   r    rÙ   r`  )rH   Z
wantedUserrt  ZwantedGrouprs  ZpidFileru  r  rx  rE   rR   rÙ   r1   rr  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)ry  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   ry  ÚflushWarningsr€   rf   Úlen)rH   Z
currentUidZwarningsShownZexpectedWarningr1   r1   r2   Útest_setUidSameAsCurrentUid÷  s   
ÿþzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUidN)
rJ   rK   rL   rM   rY  rn  rq  ry  rz  r~  r1   r1   r1   r2   rS  w  s    4
rS  c                   @   rË   )Ú#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«   )rH   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Ã   rf   r}  ÚvaluerÄ   ÚENOENT)rH   rÙ   Úerrorsr1   r1   r2   Útest_removePIDErrors  s
   

z8UnixApplicationRunnerRemovePIDTests.test_removePIDErrorsN)rJ   rK   rL   rM   rƒ  r‡  r1   r1   r1   r2   r  
  s    r  c                   @   ó0   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   ó
   d| _ d S ©NT)rŠ  rV   r1   r1   r2   ÚbeforeDaemonize9  rÚ   z)FakeNonDaemonizingReactor.beforeDaemonizec                 C   rŒ  r�  )r‹  rV   r1   r1   r2   ÚafterDaemonize<  rÚ   z(FakeNonDaemonizingReactor.afterDaemonizec                 O   r¬   )z*
        Skip event registration.
        Nr1   )rH   r™   r_  r1   r1   r2   ÚaddSystemEventTrigger?  r°   z/FakeNonDaemonizingReactor.addSystemEventTriggerN)rJ   rK   rL   rM   r_   rŽ  r�  r�  r1   r1   r1   r2   r‰  )  s    r‰  c                   @   s   e Zd ZdZdS )rE  z�
    A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize}
    methods, announcing this, and logging whether the methods have been called.
    N)rJ   rK   rL   rM   r1   r1   r1   r2   rE  E  s    rE  c                   @   rB   )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)rJ   rK   rL   rM   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 d  ƒ n1 s6w   Y  |  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Œ   Nr’  úfunction calls©r   ri   r´   r	   r‹   r  rî   r…   r  rµ   rJ  ru   ©rH   rm   rŒ   r�   r¸   Údatar1   r1   r2   Útest_profilef  ó   


ÿzAppProfilingTests.test_profilec                 C   sP   t ƒ }|  td|¡}||ƒ}| ¡  | ¡  | ¡ }|  d|¡ |  d|¡ d S )Nr¢   r”  z(run))r   r=   ÚsysÚprint_statsÚrestorer~   ru   )rH   Z
statsClassr#   Úoutr¢   Ústatsr—  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   ri   r´   r	   r‹   r  rî   r…   r  rŸ  r$   ZStats©rH   rm   rŒ   r�   r1   r1   r2   Útest_profileSaveStats‹  s   

z'AppProfilingTests.test_profileSaveStatsc              	   C   st   t j ¡ }t ¡ }d|d< t |¡}dt jd< z|  t|j	d¡ W t j 
¡  t j |¡ dS t j 
¡  t j |¡ w )z†
        When the C{profile} module is not present, L{app.ProfilerRunner.run}
        should raise a C{SystemExit} exception.
        r#   rŒ   N©rš  Úmodulesre  r   ri   r	   r‹   r{   r|   rî   ÚclearÚupdate©rH   ZsavedModulesrm   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                   @   rp   )zGAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfilec                 S   s   t dƒ‚)NZBoom©r‘  rV   r1   r1   r2   r›  ·  ó   zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_statsN)rJ   rK   rL   r›  r1   r1   r1   r2   ÚErroneousProfile¶  rs   r¬  ÚProfiler#   rŒ   N)r#   r­  r=   r   ri   r´   r	   r‹   r  rš  r¢   r{   r‘  rî   r¥   )rH   r¬  rm   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 d  ƒ n1 s6w   Y  |  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Œ   Nrî   r”  r•  r–  r1   r1   r2   Útest_cProfileÆ  r™  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   st   t j ¡ }dt jd< t ¡ }d|d< t |¡}z|  t|j	d¡ W t j 
¡  t j |¡ dS t j 
¡  t j |¡ w )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   ri   r´   r{   r|   r	   r‹   rf   rŠ   )rH   rm   Ú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‹   rf   rŒ   ©rH   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)rJ   rK   rL   rM   r   r#   r˜  rŸ  r£  r©  r®  r%   r¯  r°  r±  r³  r·  r¸  r1   r1   r1   r2   r“  a  s$    









r“  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    ˆ   | ¡ ˆ| g|¢R i |¤ŽS r&   ró   )ZlogFiler™   Úkwargs©ÚlogFilesZoldFileLogObserverr1   r2   Úobserver(  s   
z+_patchTextFileLogObserver.<locals>.observerÚtextFileLogObserverN)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                    ó   ˆ   |¡ d S r&   ró   )rH   Úprefix©ZlogMessagesr1   r2   r_   8  rú   z1_setupSyslog.<locals>.fakesyslogobserver.__init__c                    r¿  r&   ró   )rH   Z	eventDictrÁ  r1   r2   Úemit;  rú   z-_setupSyslog.<locals>.fakesyslogobserver.emitN)rJ   rK   rL   r_   rÂ  r1   rÁ  r1   r2   Úfakesyslogobserver7  s    rÃ  ZSyslogObserverN)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                    ó$   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&   )Ú	observersrv   r   ZaddObserver)rÈ  r¼  rV   r1   r2   ÚbeginLoggingToQ  s   þz,AppLoggerTests.setUp.<locals>.beginLoggingTorÉ  N)rÈ  r=   r   )rH   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©rH   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&   )Ú_logsrv   )rH   Úeventr1   r1   r2   Ú__call__k  rw  z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__N)rJ   rK   rL   rÍ  rÏ  r1   r1   r1   r2   ÚTestObserverg  s    rÐ  N)r   r   )rH   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)rf   rÈ  ru   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 r&   r1   r1   ©r¼  r1   r2   r¯   �  r°   z+AppLoggerTests.test_start.<locals>.<lambda>N)r	   Ú	AppLoggerrÑ  Ú_getLogObserverrS   r   rÓ  )rH   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Ö  rS   rÓ  )rH   rR   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                      rÔ  r&   r1   r1   rÕ  r1   r2   r¯   ¤  r°   z7AppLoggerTests._setupConfiguredLogger.<locals>.<lambda>N)rÑ  r§  rS   )rH   rR   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Û  rQ   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Û  rf   rÍ  )rH   r¼  rR   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Ù  ÚLegacyILogObserverrv   rÓ  rÛ  rf   )rH   ÚnonlogsrR   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Þ  rv   r	   rÖ  rS   rÓ  rf   )rH   rß  r¼  rR   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!   rf   )rH   ÚlogsrR   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«   )rH   rR   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×  rf   r}  r¥   rš  r¢   )rH   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Ú_outFiler‚  rf   r}  r±   r7   Úabspath)rH   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   rú   z(AppLoggerTests.test_stop.<locals>.removerÊ  N)	rì   r=   r   r	   rÖ  Z	_observerrß   rf   rl   )rH   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ó   )rH   Úx©râ  r1   r2   rÏ  :  s   zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__N)rJ   rK   rL   rM   rÏ  r1   rô  r1   r2   ÚLoggerObserver4  s    rõ  c                      s   ˆ ƒ S r&   r1   r1   )rõ  r1   r2   r¯   @  ó    z5AppLoggerTests.test_legacyObservers.<locals>.<lambda>rÒ  r   N)r	   rÖ  r   rÞ  Z_observerFactoryrS   r   ru   r   r|  Útest_legacyObserversrf   r}  ©rH   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×  rS   r   ru   r   r|  Ú test_unmarkedObserversDeprecatedrf   r}  rø  r1   rô  r2   rú  G  s   

ýz/AppLoggerTests.test_unmarkedObserversDeprecatedN)rJ   rK   rL   rM   rÓ   rÌ  rÑ  rÓ  rØ  rÚ  r	   rÖ  rÛ  rÜ  rÝ  rà  rá  r   r©   rÄ  rã  rå  rè  rî  rò  r÷  rú  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                    rÇ  )zs
        Fake C{signal.signal} for not installing the handlers but saving them
        in C{self.signals}.
        c                    s   ˆ j  | |f¡ d S r&   )Úsignalsrv   )r¼   r¸   rV   r1   r2   Ú
fakeSignalu  s   z,UnixAppLoggerTests.setUp.<locals>.fakeSignalÚsignalN)rü  r=   rþ  )rH   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×  rf   r}  r¥   rš  r¢   )rH   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!   r{   r|   r×  rf   rŠ   )rH   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ª  rú   z:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotateN)r¾  r=   r´   r!   r×  ré  rê  r‚  rf   r}  r±   r7   rë  rü  rþ  ÚSIGUSR1r   r  )rH   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&   )rf   rþ  r  rì   )r¼   rV   r1   r2   ÚfakeGetSignal¹  s   zVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignalÚ	getsignalrä  N)
r=   rþ  r´   r!   r×  ré  rê  r‚  rf   rü  )rH   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ê  r‚  rf   r}  r±   r7   rë  )rH   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À  r^  ÚbN)rÅ  r!   r×  rf   )rH   râ  r   r¼  r1   r1   r2   Útest_getLogObserverSyslogÔ  s   z,UnixAppLoggerTests.test_getLogObserverSyslogN)rJ   rK   rL   rM   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   rP   r&   r1   r[  r1   r1   r2   r¯   ð  r°   z&DaemonizeTests.setUp.<locals>.<lambda>)r   Úmockosr   ri   rm   r=   r©   r    rÙ   r   rÒ   rR   rš  r¢   rþ   Ústderrrÿ   r   rV   r1   r1   r2   rÓ   è  s   


zDaemonizeTests.setUpc                 C   s`   t tƒ ƒ� | j ¡  W d  ƒ n1 sw   Y  |  | jjg d¢¡ |  | 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.
        N)©r6  r?  ©r�   rQ  ©ZforkTÚsetsidr  )r¶   éþÿÿÿó   0©Úunlinkz
twistd.pidéýÿÿÿr  )r   rE  rÙ   rX   rf   r  ÚactionsÚclosedrV   r1   r1   r2   Útest_successò  s   ÿþzDaemonizeTests.test_successc                 C   st   d| j _d| j _ttƒ ƒ� |  t| jj¡ W d  ƒ n1 s w   Y  |  	| j j
g d¢¡ |  	| 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  N)r  r  r  ©rJ  éÿÿÿÿéd   ©Úexitr   r  r  )r  ÚchildÚreadDatar   rE  r{   ÚSystemErrorrÙ   rX   rf   r  r  rV   r1   r1   r2   Útest_successInParent  s   ÿþz#DaemonizeTests.test_successInParentc                    sˆ   g ‰ ‡ fdd„}|| j _ttƒ ƒ� | j ¡  W d  ƒ n1 s!w   Y  |  | j jg d¢¡ |  | 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<  ©rv   r}  rÃ   rÄ   ZEINTR)Úfdr—  ©Zwrittenr1   r2   ÚraisingWrite$  s   
ÿz6DaemonizeTests.test_successEINTR.<locals>.raisingWriteN)r  r  r  r  r  r  r  r  )r  r  )	r  r¶   r   rE  rÙ   rX   rf   r  r  )rH   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 d  ƒ n1 s(w   Y  |  	| j j
g d¢¡ |  	| 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©rJ  r1   r2   ÚraisingReadA  s   
z=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadFN)r  r  r  r  r  r  )r  r  )r  rJ  r   r   rE  r{   r"  rÙ   rX   rf   r  r  )rH   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 d  ƒ n1 s-w   Y  |  
| 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 ˆ ƒ‚r&   rª  rV   ©Úraisedr1   r2   r  `  r«  zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startServiceN)rJ   rK   rL   r  r1   r-  r1   r2   r  _  s    r  Nr  r  r  r  r¶   r  r  r  )r   rF   r  rÙ   rR   r   rE  r{   r‘  rX   rf   r  r  r  )rH   r.  Úreportedr  ZerrorServicer1   r-  r2   ÚassertErrorWrittenX  s$   ÿùþz!DaemonizeTests.assertErrorWrittenc                 C   ó   | 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©r0  rV   r1   r1   r2   Ú
test_errorv  ó   
ÿzDaemonizeTests.test_errorc                 C   r1  )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: \u2022r2  Nr3  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 d  ƒ n1 s*w   Y  |  | ¡ |¡ |  | 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__Nr  )r  r   r!  r   r=   rš  r   rE  r{   r"  rÙ   rX   rf   r~   r  r  )rH   r!  ÚerrorMessageÚmockOSActionsZerrorIOr1   r1   r2   ÚassertErrorInParentBehavior‡  s   ÿz*DaemonizeTests.assertErrorInParentBehaviorc                 C   ó   | j ddg d¢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!  r8  r9  N©r:  rV   r1   r1   r2   Útest_errorInParent˜  ó
   
úz!DaemonizeTests.test_errorInParentc                 C   r;  )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=  Nr>  rV   r1   r1   r2   Útest_nonASCIIErrorInParent®  r@  z)DaemonizeTests.test_nonASCIIErrorInParentc                 C   s,   d}d  d¡}| j|d  |¡g d¢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=  N)r€   r:  )rH   ZtruncatedMessageZreportedMessager1   r1   r2   Ú&test_errorInParentWithTruncatedUnicodeÄ  s   
ÿ
øz5DaemonizeTests.test_errorInParentWithTruncatedUnicodec                 C   r1  )z{
        If an error occurs during daemonization and its message is too
        long, it's truncated by the child.
        ZÈxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsd   1 RuntimeError: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr2  Nr3  rV   r1   r1   r2   Útest_errorMessageTruncatedá  r5  z)DaemonizeTests.test_errorMessageTruncatedc                 C   r1  )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   â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢rB  r2  Nr3  rV   r1   r1   r2   Ú!test_unicodeErrorMessageTruncatedê  s   
þz0DaemonizeTests.test_unicodeErrorMessageTruncatedc                 C   ó.   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)rE  rÙ   r;  r…   rŠ  r‹  r=  r1   r1   r2   Útest_hooksCalledõ  ó   zDaemonizeTests.test_hooksCalledc                 C   rF  )zÀ
        C{daemonize} does NOT call L{IReactorDaemonize.beforeDaemonize} or
        L{IReactorDaemonize.afterDaemonize} if the reactor does NOT implement
        L{IReactorDaemonize}.
        N)r‰  rÙ   r;  rˆ   rŠ  r‹  r=  r1   r1   r2   Útest_hooksNotCalled   rH  z"DaemonizeTests.test_hooksNotCalledN)rJ   rK   rL   rM   rÓ   r  r#  r(  r,  r0  r4  r6  r:  r?  rA  rC  rD  rE  rG  rI  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   r`   r&   ©Z_valrV   r1   r1   r2   r&    s   z(SignalCapturingMemoryReactor._exitSignalc                 C   rØ   r&   rK  )rH   Úvalr1   r1   r2   r&    s   
N)rJ   rK   rL   rM   Úpropertyr&  Úsetterr1   r1   r1   r2   rJ    s    
rJ  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   r¬   )z
        Does nothing.
        Nr1   rV   r1   r1   r2   rW   +  r°   z.StubApplicationRunnerWithSignal.preApplicationc                 C   s$   t ƒ }| j|_|  |tjtj¡ dS )z`
        Instantiate a SignalCapturingMemoryReactor and start it
        in the runner.
        N)rJ  rQ  r&  r   rš  r¢   r  r=  r1   r1   r2   rX   0  s   z/StubApplicationRunnerWithSignal.postApplication)
rJ   rK   rL   rM   rO   rY   r_   rW   rX   Ú__classcell__r1   r1   rR  r2   rO    s    rO  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
        N)rO  rQ  )rm   rÙ   ©Úsignumr1   r2   ÚstubApplicationRunnerFactoryG  s   zIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryNr1   )rV  rW  r1   rU  r2   Ú#stubApplicationRunnerFactoryCreator:  s   rX  c                   @   rˆ  )Ú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   ri   rm   rC   rë   rì   rí   rn   rZ  r=   r7   )rH   r[  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_DFLrZ  r7   rÆ   )rH   r^  r1   r]  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   rX  ÚrunApprm   rl   rZ  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   rX  rþ  r_  rb  rm   r*  rZ  r7   rÆ   rV   r1   r1   r2   Útest_runnerExitsWithSignal—  s   ýz.ExitWithSignalTests.test_runnerExitsWithSignalN)rJ   rK   rL   rM   rÓ   ra  rc  rd  r1   r1   r1   r2   rY  Z  s    rY  )hrM   rÄ   rb  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%   rA   rC   rÖ  rO   r  rU   rZ   rª   rÌ   r×   rá   rà   rè   r/  rS  r  r‰  rE  r  r“  r¾  rÅ  rÆ  rû  r  rJ  rO  rX  rY  r1   r1   r1   r2   Ú<module>   s²   þ-	 
YF 
t 

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