o
    ¯b(  ã                   @   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(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m(Z2m3Z3 ddl4m5Z5 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 e5dƒZBeBràddlCmDZDmEZEmFZF e5dƒZGe5dƒZHe5dƒZIe5dƒ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)ÚILogObserverÚglobalLogBeginnerÚglobalLogPublisher)Úutil)ÚComponentized)ÚUserDatabase)r   ÚtextFromEventDict)ÚrequireModule)ÚplatformType)Ú
UsageError)Útwistd)ÚMemoryReactor)ÚMockOS)ÚTestCaseztwistd.scripts._twistd_unix)ÚUnixApplicationRunnerÚUnixAppLoggerÚcheckPIDztwistd.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©ÚgidÚgrentÚgroup© ú:/usr/lib/python3/dist-packages/twisted/test/test_twistd.pyÚgetgrnamd   s
   z#patchUserDatabase.<locals>.getgrnamÚgetpwnamr4   ÚgetpwuidN)Úpwdr6   ÚosÚgetuidÚgrpÚgetgrgidÚgetgidr   ÚaddUserÚ	pw_passwdÚpw_gecosÚpw_dirÚpw_shellr5   )ÚpatchÚuserÚuidr1   r/   ÚpwentÚdatabaser4   r2   r.   r3   ÚpatchUserDatabaseC   s   ÿrG   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.
        )Úoptionsr   ÚService©ÚselfrK   r2   r2   r3   ÚmakeServicew   s   
zMockServiceMaker.makeServiceN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚtapnamerO   r2   r2   r2   r3   rI   p   s    rI   c                   @   s   e Zd ZdZdd„ ZdS )ÚCrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                 C   ó   d S r&   r2   ©rN   Úapplicationr2   r2   r3   Ústart†   ó   zCrippledAppLogger.startN)rP   rQ   rR   rS   rY   r2   r2   r2   r3   rU      s    rU   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   rV   r&   r2   ©rN   r2   r2   r3   ÚpreApplication“   rZ   z(CrippledApplicationRunner.preApplicationc                 C   rV   r&   r2   r\   r2   r2   r3   ÚpostApplication–   rZ   z)CrippledApplicationRunner.postApplicationN)rP   rQ   rR   rS   rU   ÚloggerFactoryr]   r^   r2   r2   r2   r3   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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 )rT   Ú_optionsÚdescription©rN   r,   r2   r2   r3   Ú__init__¦   s   
z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__c                 S   ó   | j S r&   )rb   r\   r2   r2   r3   rK   «   s   z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.optionsN)rP   rQ   rR   re   rK   r2   r2   r2   r3   Ú
FakePlugin¥   s    rg   ÚappleÚbananaÚcoconutÚdonutc                 3   s*    ˆ  | t¡ ˆV  ˆV  ˆV  ˆ V  d S r&   )ÚassertEqualr   )Ú	interface©rh   ri   rj   rk   rN   r2   r3   Ú
getPlugins³   s   €
z7ServerOptionsTests.test_subCommands.<locals>.getPluginsN)r   ÚServerOptionsrl   Ú_getPluginsr   ro   ÚsubCommandsÚziprT   ÚassertIsNonerb   rc   )rN   rg   ro   Úconfigrr   ÚexpectedOrderÚ
subCommandÚexpectedCommandr,   ÚshortcutÚparserClassÚdocumentationr2   rn   r3   Ú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 ra   ztwisted.internet.default)Ú	shortNamerc   Ú
moduleNamerd   r2   r2   r3   re   Ð   s   


zPServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstaller.__init__N)rP   rQ   rR   re   r2   r2   r2   r3   ÚFakeReactorInstallerÏ   ó    r€   rh   ri   rj   rk   c                   3   s    ˆV  ˆV  ˆV  ˆ V  d S r&   r2   r2   )rh   ri   rj   rk   r2   r3   ÚgetReactorTypesÚ   s
   €
zBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypesz--help-reactorsc                    s    ˆ  | ˆ ¡ ˆ ˆ  | ¡¡ d S r&   )ÚassertInÚappendr(   )Ús)Ú
helpOutputÚindexesrN   r2   r3   ÚgetIndexê   s   z;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndexz9reactor descriptions were not in alphabetical order: {!r}N)r   rp   rl   Ú_getReactorTypesr
   r‚   r   ÚmessageOutputÚassertRaisesÚ
SystemExitÚparseOptionsÚgetvaluer~   rc   ÚsortedÚformat)rN   r€   r‚   ru   Úreactorrˆ   r2   )rh   ri   rj   rk   r†   r‡   rN   r3   Ú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.
        rJ   Úno_saveN)r   rp   rw   ÚpostOptionsÚ
assertTrue©rN   ru   r2   r2   r3   Ú&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   rp   r”   ÚassertFalser–   r2   r2   r3   Ú(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   rp   Ústrr	   ÚAppProfilerÚ	profilersrƒ   )rN   ru   r†   Úprofilerr2   r2   r3   Ú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   rp   rt   r–   r2   r2   r3   Ú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.
        ú--umaskÚ123r    éS   Ú0123N)r   rp   r   rl   r–   r2   r2   r3   Ú
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¢   ÚabcdefN)r   rp   r‹   r   r   r–   r2   r2   r3   Ú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   rp   r‹   r   r   r•   ÚargsÚ
startswithÚassertNotIn©rN   ru   Úer2   r2   r3   Ú&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°   r2   r2   r3   Ú*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   rp   r‹   rŒ   r   ÚassertIsÚcoderl   rŽ   )rN   r´   r,   ÚexpectedOutputr·   ru   r±   r2   r2   r3   Ú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   rp   r‹   r   r   )rN   r·   ru   r2   r2   r3   Ú!test_printSubCommandForUsageErrorh  s   z4ServerOptionsTests.test_printSubCommandForUsageErrorN)rP   rQ   rR   rS   r|   r’   r—   r™   rž   r   Ú_twistd_unixr¡   r¦   r¨   r²   r³   r½   r¾   r2   r2   r2   r3   r`   š   s"    +/	






r`   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 ©NFr2   )Ú_r2   r2   r3   Ú<lambda>|  ó    z.CheckPIDTests.test_notExists.<locals>.<lambda>znon-existent PID fileN)rB   r8   Úpathr"   r\   r2   r2   r3   Ú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"   rƒ   r»   )rN   ÚpidfileÚfr±   r2   r2   r3   Ú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É   Ú42Nc                 S   rV   r&   r2   ©ÚpidÚsigr2   r2   r3   Úkill‘  rZ   z/CheckPIDTests.test_anotherRunning.<locals>.killrÔ   zAnother twistd server)
rÊ   rË   rÌ   rB   r8   r‹   rŒ   r"   rƒ   r»   ©rN   rÍ   rÎ   rÔ   r±   r2   r2   r3   Ú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ƒ‚©NÚfake)ÚOSErrorÚerrnoÚESRCHrÑ   r2   r2   r3   rÔ      ó   z&CheckPIDTests.test_stale.<locals>.killrÔ   )rÊ   rË   rÌ   rš   r8   ÚgetpidrB   r"   r˜   rÇ   rÁ   )rN   rÍ   rÎ   rÔ   r2   r2   r3   Ú
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É   Ú3581Nc                 S   rØ   rÙ   ©rÛ   rÜ   ÚEBADFrÑ   r2   r2   r3   rÔ   °  rÞ   z2CheckPIDTests.test_unexpectedOSError.<locals>.killrÔ   r   zCan't check status of PID)rÊ   rË   rÌ   rB   r8   r‹   rŒ   r"   ÚassertIsNotr»   r•   r­   r®   rÕ   r2   r2   r3   Útest_unexpectedOSError§  s   ÿz$CheckPIDTests.test_unexpectedOSErrorN)	rP   rQ   rR   rS   rÈ   rÏ   rÖ   rà   rå   r2   r2   r2   r3   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)rN   rÎ   r2   r2   r3   Ú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   rp   r   rê   r[   ÚcreateOrGetApplicationrl   r   ÚIServicer,   )rN   ru   rX   r2   r2   r3   Ú&test_createOrGetApplicationWithTapFileÆ  s   z3TapFileTests.test_createOrGetApplicationWithTapFileN)rP   rQ   rR   rS   rî   rñ   r2   r2   r2   r3   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)rN   rõ   r2   r2   r3   re   Ö  ó   
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.
        ÚlogrX   N)rõ   Úorderr„   ÚhasattrÚhadApplicationLogObserverrW   r2   r2   r3   rY   Ù  s   zTestLoggerFactory.startc                 C   rÂ   )z%
        Don't log anything.
        Nr2   r\   r2   r2   r3   Ústopà  rÆ   zTestLoggerFactory.stopN)rP   rQ   rR   rS   re   rY   rû   r2   r2   r2   r3   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	   ÚApplicationRunnerre   rø   ró   r   rM   r2   r2   r3   re   ì  s   zTestApplicationRunner.__init__c                 C   ó   | j  d¡ t| dƒ| _d S )NÚprerX   )rø   r„   rù   ÚhadApplicationPreApplicationr\   r2   r2   r3   r]   ñ  ó   z$TestApplicationRunner.preApplicationc                 C   rþ   )NÚpostrX   )rø   r„   rù   ÚhadApplicationPostApplicationr\   r2   r2   r3   r^   õ  r  z%TestApplicationRunner.postApplicationN)rP   rQ   rR   rS   re   r]   r^   r2   r2   r2   r3   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   rp   rI   ÚserviceMakerÚloadedPluginsÚobjectÚ
subOptionsrw   ru   r–   r2   r2   r3   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)r[   ru   Úrunrº   r  rK   r	  r   rð   rX   Úservices)rN   Úarunnerr2   r2   r3   Ú,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ü   ru   r
  r˜   r   r•   r  rú   rl   rø   )rN   r…   r2   r2   r3   Ú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©r„   ©rN   ÚchrootÚrundirÚnodaemonr    rÍ   ©Úeventsr2   r3   ÚsetupEnvironment8  ó   zmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironmentc                    s   ˆ   d|||f¡ d S )NÚ
privilegesr  )rN   ÚeuidrD   r/   r  r2   r3   ÚshedPrivileges;  s   zkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivilegesc                    r  )Nr‘   r  )rN   r‘   Ú	oldstdoutÚ	oldstderrr  r2   r3   ÚstartReactor>  r  ziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactorc                 S   rV   r&   r2   )rN   rÍ   r2   r2   r3   Ú	removePIDA  rZ   zfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDN)rP   rQ   rR   r  r  r  r   r2   r  r2   r3   Ú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   rV   r&   r2   rd   r2   r2   r3   ÚsetNameN  rZ   zVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNamec                 S   rV   r&   r2   )rN   Úparentr2   r2   r3   ÚsetServiceParentQ  rZ   z_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentc                 S   rV   r&   r2   r\   r2   r2   r3   ÚdisownServiceParentT  rZ   zbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentc                    r  )NÚprivilegedStartServicer  r\   r  r2   r3   r&  W  r  zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServicec                    r  )NÚstartServicer  r\   r  r2   r3   r'  Z  r  z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServicec                 S   rV   r&   r2   r\   r2   r2   r3   ÚstopService]  rZ   zZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService)rP   rQ   rR   r#  Úrunningr,   ÚprocessNamerD   r/   r"  r$  r%  r&  r'  r(  r2   r  r2   r3   ÚFakeServiceD  s    r+  r  r&  r  Fr'  r‘   N)ru   r   r   Ú_SomeApplicationRunnerr   r   rð   ÚIProcessr   r]   rX   r^   rl   )rN   ÚargvrD   r/   r!  r+  rX   rõ   r2   r  r3   Ú"_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š   )rN   rD   r/   r2   r2   r3   Ú.test_applicationStartsWithConfiguredNumericIDst  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}.
        Úfoor1  Úbarr2  r3  r4  N)rG   rB   r/  )rN   rC   rD   r1   r/   r2   r2   r3   Ú+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©rN   r‘   rõ   r2   r2   r3   Ú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#   r9  N)r;  rB   r   r	   rý   r  r•   r<  r=  r2   r2   r3   Ú*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.
                Nr2   r\   r2   r2   r3   ÚinstallWaker¼  rÆ   zhApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.installWakerc                 S   ó
   d| _ dS )zZ
                A fake run method setting _exitSignal to a nonzero value
                é   N©Ú_exitSignalr\   r2   r2   r3   r
  Á  s   
z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.runN©rP   rQ   rR   rS   rB  r
  r2   r2   r2   r3   ÚDummyReactorWithSignal¶  ó    rH  Fr#   r9  NrD  )r   r	   rý   r  ÚassertEqualsrF  )rN   rH  r‘   rõ   r2   r2   r3   Ú$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Â   rA  r2   r\   r2   r2   r3   rB  Ú  rÆ   zvApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.installWakerc                 S   rC  )z‚
                A fake run method setting _exitSignal to a nonzero value
                that should be ignored.
                rD  NrE  r\   r2   r2   r3   r
  ß  s   
zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.runNrG  r2   r2   r2   r3   Ú#DummyReactorWithExitSignalAttributeÔ  rI  rL  Fr#   r9  N)r	   rý   r  rJ  rF  )rN   rL  r‘   rõ   r2   r2   r3   Ú%test_applicationRunnerIgnoresNoSignalÎ  s   
ÿz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal)rP   rQ   rR   rS   rî   r  r  r/  r   Úgetattrr8   r5  r8  r>  r?  rK  rM  r2   r2   r2   r3   r  ú  s(    	Jþ
þ
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Ç   r\   r2   r3   rÅ     ó    zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>Úchdirc                    rP  )NÚcwdrR  rT  r\   r2   r3   rÅ     rU  r    c                    rP  )NÚmaskrR  )rX  r\   r2   r3   rÅ     rU  )ÚunsetrQ  rW  rX  Údaemonr8   rß   rÒ   rB   r    r   rp   rõ   Ú	daemonizer\   r2   r\   r3   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Ò   r2   r\   r2   r3   rÅ     s   
 zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>N)rZ  rB   r8   ©rN   r‘   r2   r\   r3   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  rl   rQ  r\   r2   r2   r3   Ú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º   rQ  rY  r\   r2   r2   r3   Ú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  rl   rW  r\   r2   r2   r3   Ú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•   rZ  r\   r2   r2   r3   Útest_daemonize2  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˜   rZ  r\   r2   r2   r3   Ú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Úreadrl   rÒ   ©rN   rÍ   rÎ   rÒ   r2   r2   r3   Útest_nonDaemonPIDFileC  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  rl   rÒ   rk  r2   r2   r3   Útest_daemonPIDFileN  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  rl   rX  r\   r2   r2   r3   r¦   [  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º   rX  rY  r\   r2   r2   r3   Útest_noDaemonizeNoUmaskd  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  r\   r2   r2   r3   Útest_daemonizedNoUmaskm  s   ÿzAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmaskN)rP   rQ   rR   rS   r  rY  rî   r[  r`  rc  rd  rf  rg  rl  rm  r¦   rp  rr  r2   r2   r2   r3   rO  î  s    			rO  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¢   Ú0070z--chrootú/foo/chrootz--rundirú/foo/rundirz	--pidfileú/foo/pidfileÚtest_setupEnvironmentc                    s   ˆ   |||||f¡ d S r&   )Úextendr  ©r­   r2   r3   ÚfakeSetupEnvironment˜  s   z^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironmentrN   r  r  c                  _   rV   r&   r2   ©ÚaÚkwr2   r2   r3   rÅ   ¬  rÆ   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>ÚstartApplicationc                  _   rV   r&   r2   r}  r2   r2   r3   rÅ   ­  rÆ   )rv  rw  Té8   rx  N)r   rp   r   r   rí   r    rõ   ÚinspectÚ	signaturer  Ú
parametersÚcopyÚpoprl   rB   r	   r€  )rN   rK   rX   r|  ÚsetupEnvironmentParametersÚfakeSetupEnvironmentParametersr2   r{  r3   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   é#   ©rl   ©rD   r/   r  r\   r2   r3   ÚswitchUIDPass¸  s   zUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPassÚ	switchUIDr‹  r‰  rŠ  N)rB   r¿   r    r  )rN   rŽ  rõ   r2   r\   r3   Ú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â   r  r2   r2   r3   ÚswitchUIDFailÈ  rÞ   zZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFailr  r‹  r‰  Nr×   )r    rB   r¿   r‹   rŒ   r  rl   r»   )rN   r‘  rõ   Úexcr2   r2   r3   Útest_shedPrivilegesErrorÁ  s
   zCUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesErrorc                    s®   t ˆ j|ˆ|ˆƒ ‡ ‡‡fdd„}‡ ‡fdd„}‡ ‡fdd„}ˆ  td|¡ ˆ  td|¡ ˆ  td	|¡ t ¡ }| d
dtˆƒg¡ t 	d¡}	t
|ƒˆ _t
|ƒ}
|
 |	¡ dS )zj
        Common code for tests which try to pass the the UID to
        L{UnixApplicationRunner}.
        c                    s   ˆ   | ˆ¡ ˆ   |ˆ¡ d S r&   rŒ  )rD   r/   ©rN   Ú	wantedGidÚ	wantedUidr2   r3   Ú
initgroups×  r  zFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroupsc                    ó   ˆ   | ˆ¡ d S r&   rŒ  )rD   )rN   r–  r2   r3   r0  Û  ó   zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuidc                    r˜  r&   rŒ  )r/   )rN   r•  r2   r3   ÚsetgidÞ  r™  zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgidr—  r0  rš  rt  r3  ry  N)rG   rB   r   r8   r   rp   r   rš   r   rí   r    rõ   r€  )rN   Ú
wantedUserr–  ÚwantedGroupr•  r—  r0  rš  rK   rX   rõ   r2   r”  r3   Ú_setUIDÐ  s   

z2UnixApplicationRunnerStartApplicationTests._setUIDc                 C   s   |   dddd¡ dS )z½
        Starting an application with L{UnixApplicationRunner} configured
        with a UID and no GUID will result in the GUID being
        set to the default GUID for that UID.
        r6  i  r7  i’  N)r  r\   r2   r2   r3   Útest_setUidWithoutGidì  s   z@UnixApplicationRunnerStartApplicationTests.test_setUidWithoutGidc                 C   sT   t  ¡ }|  d|dd¡ |  ¡ }|  dt|ƒ¡ d ||¡}|  ||d d ¡ dS )	zz
        If the specified UID is the same as the current UID of the process,
        then a warning is displayed.
        ÚmorefooÚmorebari÷  r×   z\tried to drop privileges and setuid {} but uid is already {}; should we be root? Continuing.r   ÚmessageN)r8   r9   r  ÚflushWarningsrl   Úlenr   )rN   Ú
currentUidÚwarningsShownÚexpectedWarningr2   r2   r3   Útest_setUidSameAsCurrentUidô  s   þzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUidN)
rP   rQ   rR   rS   ry  r  r“  r  rž  r§  r2   r2   r2   r3   rs  x  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Ê   r8   ÚmakedirsrÇ   ÚjoinrË   Úcloser   r˜   rÁ   )rN   rõ   rÇ   rÍ   r2   r2   r3   Ú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.
        Úfakepidr×   r   N)	r    r   ÚflushLoggedErrorsrÛ   rl   r£  ÚvaluerÜ   ÚENOENT)rN   rõ   Úerrorsr2   r2   r3   Útest_removePIDErrors  s
   

z8UnixApplicationRunnerRemovePIDTests.test_removePIDErrorsN)rP   rQ   rR   rS   r¬  r²  r2   r2   r2   r3   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Ú_afterDaemonizeCalledr\   r2   r2   r3   re   0  s   
z"FakeNonDaemonizingReactor.__init__c                 C   ó
   d| _ d S ©NT)rµ  r\   r2   r2   r3   ÚbeforeDaemonize4  rö   z)FakeNonDaemonizingReactor.beforeDaemonizec                 C   r·  r¸  )r¶  r\   r2   r2   r3   ÚafterDaemonize7  rö   z(FakeNonDaemonizingReactor.afterDaemonizec                 O   rÂ   )z*
        Skip event registration.
        Nr2   )rN   r­   r  r2   r2   r3   ÚaddSystemEventTrigger:  rÆ   z/FakeNonDaemonizingReactor.addSystemEventTriggerN)rP   rQ   rR   rS   re   r¹  rº  r»  r2   r2   r2   r3   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)rP   rQ   rR   rS   r2   r2   r2   r3   re  @  s    re  c                   @   rH   )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<  ÚRuntimeErrorr\   r2   r2   r3   r
  S  s   
úDummyReactor.runN)rP   rQ   rR   rS   r<  r
  r2   r2   r2   r3   r;  H  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   rp   rÊ   r	   r›   r;  r
  r•   r<  rË   rj  rƒ   ©rN   ru   r   r‘   rÎ   Údatar2   r2   r3   Útest_profilea  ó   


ÿzAppProfilingTests.test_profilec                 C   sP   t ƒ }|  td|¡}||ƒ}| ¡  | ¡  | ¡ }|  d|¡ |  d|¡ d S )Nr·   r¿  z(run))r   rB   ÚsysÚprint_statsÚrestorerŽ   rƒ   )rN   Ú
statsClassr#   Úoutr·   ÚstatsrÂ  r2   r2   r3   Ú
_testStatsu  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   rp   rÊ   r	   r›   r;  r
  r•   r<  rË  r$   ÚStats©rN   ru   r   r‘   r2   r2   r3   Ú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Å  Úmodulesr…  r   rp   r	   r›   r‹   rŒ   r
  ÚclearÚupdate©rN   ÚsavedModulesru   r   r2   r2   r3   Ú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                   @   r}   )zGAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfilec                 S   s   t dƒ‚)NÚBoom©r¼  r\   r2   r2   r3   rÆ  ²  ó   zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_statsN)rP   rQ   rR   rÆ  r2   r2   r2   r3   ÚErroneousProfile±  r   rÛ  ÚProfiler#   r   N)r#   rÜ  rB   r   rp   rÊ   r	   r›   r;  rÅ  r·   r‹   r¼  r
  rº   )rN   rÛ  ru   r   r‘   Ú	oldStdoutr2   r2   r3   Ú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Á  r2   r2   r3   Ú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Ï  r2   r2   r3   Ú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Õ  r2   r2   r3   Ú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#   Úfoobarr   z!Unsupported profiler name: foobarN)	r   rp   rÊ   r‹   rŒ   r	   r›   rl   rš   )rN   ru   Úerrorr2   r2   r3   Ú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›   rl   r   ©rN   r   r2   r2   r3   Ú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   ÚCprOfilerå  Nræ  rç  r2   r2   r3   Útest_profilerNameCaseInsentive  s   z0AppProfilingTests.test_profilerNameCaseInsentiveN)rP   rQ   rR   rS   r   r#   rÃ  rË  rÐ  r×  rÞ  r%   rß  rà  rá  rä  rè  rê  r2   r2   r2   r3   r¾  \  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  )ÚlogFiler­   Úkwargs©ÚlogFilesÚoldFileLogObserverr2   r3   Úobserver#  s   
z+_patchTextFileLogObserver.<locals>.observerÚtextFileLogObserver)r   rñ  )rB   rð  r2   rí  r3   Ú_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  )rN   Úprefix©ÚlogMessagesr2   r3   re   3  r  z1_setupSyslog.<locals>.fakesyslogobserver.__init__c                    ró  r&   r  )rN   Ú	eventDictrõ  r2   r3   Úemit6  r  z-_setupSyslog.<locals>.fakesyslogobserver.emitN)rP   rQ   rR   re   rø  r2   rõ  r2   r3   Úfakesyslogobserver2  s    rù  ÚSyslogObserver)rB   Úsyslog)ÚtestCaserù  r2   rõ  r3   Ú_setupSyslog+  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&   )Ú	observersr„   r   ÚaddObserver)r   rð  r\   r2   r3   ÚbeginLoggingToL  s   þz,AppLoggerTests.setUp.<locals>.beginLoggingTor  N)r   rB   r   )rN   r  r2   r\   r3   rî   E  s   zAppLoggerTests.setUpc                 C   s   | j D ]}t |¡ qdS )z1
        Remove all installed observers.
        N)r   r   ÚremoveObserver©rN   rð  r2   r2   r3   ÚtearDownS  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&   )Ú_logsr„   )rN   Úeventr2   r2   r3   Ú__call__f  r™  z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__N)rP   rQ   rR   r  r  r2   r2   r2   r3   ÚTestObserverb  s    r	  )r   r   )rN   r	  r2   r2   r3   Ú_makeObserverZ  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   Ú
log_formatzreactor classr×   N)rl   r   rƒ   r  r  r2   r2   r3   Ú_checkObserverk  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&   r2   r2   ©rð  r2   r3   rÅ   |  rÆ   z+AppLoggerTests.test_start.<locals>.<lambda>N)r	   Ú	AppLoggerr
  Ú_getLogObserverrY   r   r  )rN   r   r2   r  r3   Ú
test_startu  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  rY   r  )rN   rX   rð  r   r2   r2   r3   Ú$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&   r2   r2   r  r2   r3   rÅ   Ÿ  rÆ   z7AppLoggerTests._setupConfiguredLogger.<locals>.<lambda>)r
  rÔ  rY   )rN   rX   ÚextraLogArgsÚ	appLoggerÚlogArgsr   r2   r  r3   Ú_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  rW   r2   r2   r3   Ú#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  rl   r  )rN   rð  rX   r2   r2   r3   Ú(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  ÚLegacyILogObserverr„   r  r  rl   )rN   ÚnonlogsrX   r2   r2   r3   Ú.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  r„   r	   r  rY   r  rl   )rN   r  rð  rX   r   r2   r2   r3   Ú.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!   rl   )rN   ÚlogsrX   r2   r2   r3   Ú%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˜   r8   rÇ   rÁ   )rN   rX   rÇ   r2   r2   r3   Ú&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   Ú rD  N)
r	   r  rò  rB   r  rl   r£  rº   rÅ  r·   )rN   r   rî  r2   r2   r3   Ú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ò  rB   rÊ   r	   r  r  Ú
addCleanupÚ_outFiler«  rl   r£  rÇ   r8   Úabspath)rN   rî  ÚfilenameÚsutrð  r2   r2   r3   Ú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  ©Úremovedr2   r3   Úremove  r  z(AppLoggerTests.test_stop.<locals>.remover  N)	r  rB   r   r	   r  Ú	_observerrû   rl   rt   )rN   rð  r.  r   r2   r,  r3   Ú	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  )rN   Úx©r  r2   r3   r  5  s   zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__N)rP   rQ   rR   rS   r  r2   r2  r2   r3   ÚLoggerObserver/  s    r3  c                      s   ˆ ƒ S r&   r2   r2   )r3  r2   r3   rÅ   ;  ó    z5AppLoggerTests.test_legacyObservers.<locals>.<lambda>r  r   N)r	   r  r   r  Ú_observerFactoryrY   r   rƒ   r   r¢  Útest_legacyObserversrl   r£  ©rN   r   Úwarningsr2   )r3  r  r3   r6  '  s   
z#AppLoggerTests.test_legacyObserversc                    st   g ‰ t  i ¡}‡ fdd„|_| tƒ ¡ |  dtˆ d ƒ¡ |  | jg¡}|  	t
|ƒd|¡ |  	|d d d¡ dS )	zÐ
        L{app.AppLogger} using a logger observer which does not implement
        L{ILogObserver} or L{LegacyILogObserver} will be wrapped in a compat
        shim and raise a L{DeprecationWarning}.
        c                      s   ˆ j S r&   r  r2   r2  r2   r3   rÅ   J  r4  zAAppLoggerTests.test_unmarkedObserversDeprecated.<locals>.<lambda>r  r   r×   r¡  aZ  Passing a logger factory which makes log observers which do not implement twisted.logger.ILogObserver or twisted.python.log.ILogObserver to twisted.application.app.AppLogger was deprecated in Twisted 16.2. Please use a factory that produces twisted.logger.ILogObserver (or the legacy twisted.python.log.ILogObserver) implementing objects instead.N)r	   r  r  rY   r   rƒ   r   r¢  Ú test_unmarkedObserversDeprecatedrl   r£  r7  r2   r2  r3   r9  B  s   

ýz/AppLoggerTests.test_unmarkedObserversDeprecatedN)rP   rQ   rR   rS   rî   r  r
  r  r  r  r	   r  r  r  r  r  r  r   r¿   rû  r   r"  r%  r+  r0  r6  r9  r2   r2   r2   r3   rþ  =  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&   )Úsignalsr„   )rÓ   rÎ   r\   r2   r3   Ú
fakeSignalp  s   z,UnixAppLoggerTests.setUp.<locals>.fakeSignalÚsignalN)r;  rB   r=  )rN   r<  r2   r\   r3   rî   i  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$  rD  N)	rò  rB   r!   r  rl   r£  rº   rÅ  r·   ©rN   rî  r   r2   r2   r3   r%  u  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  rl   rš   )rN   r   rã  r2   r2   r3   Ú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&   )Úcallbackr2   ©Údr2   r3   Úrotate¥  r  z:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotateN)rò  rB   rÊ   r!   r  r&  r'  r«  rl   r£  rÇ   r8   r(  r;  r=  ÚSIGUSR1r   rD  )rN   rî  r)  r*  rð  rD  Ú	rotateLogr2   rB  r3   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&   )rl   r=  rE  r  )rÓ   r\   r2   r3   ÚfakeGetSignal´  s   zVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignalÚ	getsignalr!  N)
rB   r=  rÊ   r!   r  r&  r'  r«  rl   r;  )rN   rG  r)  r*  rð  r2   r\   r3   Ú,test_getLogObserverDontOverrideSignalHandler®  s   z?UnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandlerc                 C   sN   t | jƒ}tdddœƒ}| ¡  |  t|ƒd¡ |  |d jtj d¡¡ dS )z¶
        When daemonized and C{logfile} is empty, the observer returned by
        L{UnixAppLogger._getLogObserver} points at C{twistd.log} in the current
        directory.
        r$  Fr>  r×   r   z
twistd.logN)	rò  rB   r!   r  rl   r£  rÇ   r8   r(  r?  r2   r2   r3   Ú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  rl   )rN   r  r   rð  r2   r2   r3   Útest_getLogObserverSyslogÎ  s   z,UnixAppLoggerTests.test_getLogObserverSyslogN)rP   rQ   rR   rS   rî   r%  r@  r+  rI  rJ  r   r¿   rL  r2   r2   r2   r3   r:  `  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 )Nr8   ré   c                  W   rV   r&   r2   r{  r2   r2   r3   rÅ   ê  rÆ   z&DaemonizeTests.setUp.<locals>.<lambda>)r   Úmockosr   rp   ru   rB   r¿   r    rõ   r   rí   rX   rÅ  r·   r  Ústderrr  r  r\   r2   r2   r3   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)©rV  r_  ©r    rq  ©ÚforkTÚsetsidrR  )rÌ   éþÿÿÿó   0©Úunlinkz
twistd.pidéýÿÿÿrU  )r   re  rõ   r^   rl   rN  ÚactionsÚclosedr\   r2   r2   r3   Ú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.
        FrV  N)rP  rQ  rR  ©rj  éÿÿÿÿéd   ©Úexitr   rW  r^  )rN  ÚchildÚreadDatar   re  r‹   ÚSystemErrorrõ   r^   rl   rZ  r[  r\   r2   r2   r3   Ú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\  ©r„   r£  rÛ   rÜ   ÚEINTR)ÚfdrÂ  ©Úwrittenr2   r3   ÚraisingWrite  s   
ÿz6DaemonizeTests.test_successEINTR.<locals>.raisingWriteN)rP  rQ  rR  rT  rR  rW  rY  rU  )rU  rV  )	rN  rÌ   r   re  rõ   r^   rl   rZ  r[  )rN   rk  r2   ri  r3   Ú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×   rV  rf  )rh  Úsize©rj  r2   r3   ÚraisingRead;  s   
z=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadFN)rP  rQ  rR  r`  rW  r^  )r^  r_  )rN  rj  rb  r   re  r‹   rd  rõ   r^   rl   rZ  r[  )rN   ro  r2   rn  r3   Útest_successInParentEINTR4  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Ù  r\   ©Úraisedr2   r3   r'  Z  rÚ  zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startServiceN)rP   rQ   rR   r'  r2   rq  r2   r3   r+  Y  s    r+  NrP  rQ  rR  rT  rÌ   rU  rW  rY  )r   rL   r$  rõ   rX   r   re  r‹   r¼  r^   rl   rN  rZ  r[  )rN   rr  Úreportedr+  ÚerrorServicer2   rq  r3   ÚassertErrorWrittenR  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©rr  rs  N©ru  r\   r2   r2   r3   Ú
test_errorp  ó   
ÿzDaemonizeTests.test_errorc                 C   rv  )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: \u2022rw  Nrx  r\   r2   r2   r3   Útest_unicodeErrory  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^  )rN  rb  rc  r   rB   rÅ  r   re  r‹   rd  rõ   r^   rl   rŽ   rZ  r[  )rN   rc  ÚerrorMessageÚmockOSActionsÚerrorIOr2   r2   r3   Ú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.
©rP  rQ  rR  r]  )ra  r×   rW  ©rc  r}  r~  N©r€  r\   r2   r2   r3   Ú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„  r\   r2   r2   r3   Ú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€  )rN   ÚtruncatedMessageÚreportedMessager2   r2   r3   Ú&test_errorInParentWithTruncatedUnicode¾  s   
ÿ
øz5DaemonizeTests.test_errorInParentWithTruncatedUnicodec                 C   rv  )z{
        If an error occurs during daemonization and its message is too
        long, it's truncated by the child.
        ÚÈxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsd   1 RuntimeError: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrw  Nrx  r\   r2   r2   r3   Útest_errorMessageTruncatedÛ  rz  z)DaemonizeTests.test_errorMessageTruncatedc                 C   rv  )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ˆ  rw  Nrx  r\   r2   r2   r3   Ú!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]  r2   r2   r3   Útest_hooksCalledï  ó   zDaemonizeTests.test_hooksCalledc                 C   r  )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]  r2   r2   r3   Útest_hooksNotCalledú  r‘  z"DaemonizeTests.test_hooksNotCalledN)rP   rQ   rR   rS   rî   r\  re  rl  rp  ru  ry  r{  r€  r…  r‡  r‹  r  rŽ  r  r’  r2   r2   r2   r3   rM  Ü  s$    
		rM  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   rf   r&   ©Ú_valr\   r2   r2   r3   rF    s   z(SignalCapturingMemoryReactor._exitSignalc                 C   rô   r&   r”  )rN   Úvalr2   r2   r3   rF    s   
N)rP   rQ   rR   rS   ÚpropertyrF  Úsetterr2   r2   r2   r3   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&   )Úsuperre   Ú_signalValuer–   ©Ú	__class__r2   r3   re   !  s   
z(StubApplicationRunnerWithSignal.__init__c                 C   rÂ   )z
        Does nothing.
        Nr2   r\   r2   r2   r3   r]   %  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)r“  r›  rF  r  rÅ  r·   rO  r]  r2   r2   r3   r^   *  s   z/StubApplicationRunnerWithSignal.postApplication)
rP   rQ   rR   rS   rU   r_   re   r]   r^   Ú__classcell__r2   r2   rœ  r3   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›  )ru   rõ   ©Úsignumr2   r3   ÚstubApplicationRunnerFactoryA  s   zIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryr2   )r   r¡  r2   rŸ  r3   Ú#stubApplicationRunnerFactoryCreator4  s   r¢  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Ñ   r\   r2   r3   ÚfakeKilld  s   
z+ExitWithSignalTests.setUp.<locals>.fakeKillrÔ   )r   rp   ru   rI   r  r  r	  rw   r¤  rB   r8   )rN   r¥  r2   r\   r3   rî   Z  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×   r2   )rÓ   Úhandler©ÚfakeSignalArgsr2   r3   Úfake_signaly  s   z<ExitWithSignalTests.test_exitWithSignal.<locals>.fake_signalr=  r   r×   )
rB   r=  r	   Ú_exitWithSignalÚSIGINTrJ  ÚSIG_DFLr¤  r8   rß   )rN   r©  r2   r§  r3   Útest_exitWithSignalq  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×   )rB   r   r¢  ÚrunAppru   rt   r¤  r\   r2   r2   r3   Ú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)rB   r   r¢  r=  r«  r®  ru   rJ  r¤  r8   rß   r\   r2   r2   r3   Útest_runnerExitsWithSignal‘  s   ýz.ExitWithSignalTests.test_runnerExitsWithSignalN)rP   rQ   rR   rS   rî   r­  r¯  r°  r2   r2   r2   r3   r£  T  s    r£  )hrS   rÜ   r‚  r8   rë   r=  rÅ  r:   Ú_grpr7   Ú_pwdÚImportErrorÚior   Úunittestr   Úzope.interfacer   Úzope.interface.verifyr   r¸   r   r   r   Útwisted.applicationr	   r
   r   Útwisted.application.servicer   Útwisted.internet.baser   Útwisted.internet.deferr   Útwisted.internet.interfacesr   r   Ú#twisted.internet.test.modulehelpersr   Útwisted.loggerr   r   r   Útwisted.pythonr   Útwisted.python.componentsr   Útwisted.python.fakepwdr   Útwisted.python.logr  r   Útwisted.python.reflectr   Útwisted.python.runtimer   Útwisted.python.usager   Útwisted.scriptsr   Útwisted.test.proto_helpersr   Útwisted.test.test_processr   Útwisted.trial.unittestr   r¿   Útwisted.scripts._twistd_unixr    r!   r"   rû  r#   r$   r%   rG   rI   r  rU   r,  r[   r`   rÀ   rç   ró   rý   rü   r  rO  rs  r¨  r´  re  r;  r¾  rò  rý  rþ  r:  rM  r“  r™  r¢  r£  r2   r2   r2   r3   Ú<module>   s²   þ-	 
YF 
u 

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