
    Vh$!                       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	 ddlZddl	Z
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      ZG e7d      ZH e7d      ZI e7d      ZJd  ZK G d! d"      ZL G d# d$ej                        ZN G d% d&e=j                        ZP G d' d(eA      ZQ eeB d)       G d* d+eA             ZR G d, d-eA      ZS G d. d/      ZT G d0 d1ej                        ZV G d2 d3eA      ZW eeB d)       G d4 d5eA             ZX eeB d)       G d6 d7eA             ZY eeB d)       G d8 d9eA             ZZ G d: d;      Z[ ee#       G d< d=e[             Z\ G d> d?      Z] G d@ dAeA      Z^dB Z_dC Z` G dD dEeA      Za eeB d)       G dF dGeA             Zb eeB dH       G dI dJeA             Zc ee$       G dK dLe(             Zd G dM dNe=j                        ZedO Zf G dP dQeA      Zgy# e$ r dZ	dZY aw xY w)RzE
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           	         t         j                  t        j                               }t        j                  t        j                               t               }|j                  ||j                  ||j                  |j                  |j                         fd} | t         d|j                          | t        d|        | t         d|j                         y)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                     t              }||j                  j                        <   ||j                  j                        <   t	        |      }|i|    S N)listindexgr_namegr_gidtuple)nameresultgidgrentgroups     H/home/dcms/DCMS/lib/python3.12/site-packages/twisted/test/test_twistd.pygetgrnamz#patchUserDatabase.<locals>.getgrnamd   sR    e.3v||EMM*+-0v||ELL)*vvt$$    getpwnamr5   getpwuidN)pwdr8   osgetuidgrpgetgrgidgetgidr   addUser	pw_passwdpw_gecospw_dirpw_shellr7   )	patchuseruidr3   r1   pwentdatabaser5   r2   s	      ``   @r4   patchUserDatabaserI   C   s    2 LL%ELL%E~HeoosCu~~% 
#z8,,-	#z8$	#z8,,-r6   c                       e Zd ZdZdZd Zy)MockServiceMakerzO
    A non-implementation of L{twisted.application.service.IServiceMaker}.
    ueoac                 Z    || _         t        j                         | _        | j                  S )ze
        Take a L{usage.Options} instance and return a
        L{service.IService} provider.
        )optionsr   ServiceselfrN   s     r4   makeServicezMockServiceMaker.makeServicew   s#    
 (||r6   N)__name__
__module____qualname____doc__tapnamerR    r6   r4   rK   rK   p   s     Gr6   rK   c                       e Zd ZdZd Zy)CrippledAppLoggerz*
    @see: CrippledApplicationRunner.
    c                      y r)   rX   rQ   applications     r4   startzCrippledAppLogger.start       r6   N)rS   rT   rU   rV   r^   rX   r6   r4   rZ   rZ      s    r6   rZ   c                        e Zd ZdZeZd Zd Zy)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                      y r)   rX   rQ   s    r4   preApplicationz(CrippledApplicationRunner.preApplication   r_   r6   c                      y r)   rX   rc   s    r4   postApplicationz)CrippledApplicationRunner.postApplication   r_   r6   N)rS   rT   rU   rV   rZ   loggerFactoryrd   rf   rX   r6   r4   ra   ra      s     &Mr6   ra   c                       e Zd ZdZd Zd Zd Zd Zd Z e	e
 d      d        Z e	e
 d      d	        Z e	e
 d      d
        Zd Zd Zd Zd Zy)ServerOptionsTestszT
    Non-platform-specific tests for the platform-specific ServerOptions class.
    c                 .     G d d      } |d       |d       |d       |d       fd}t        j                         } j                  |j                  t        j
                         ||_        |j                  }g}t        ||      D ]w  \  }}|\  }}	}
} j                  ||j                          j                  |	        j                   |
       |j                        f  j                  ||j                         y y)	zh
        subCommands is built from IServiceMaker plugins, and is sorted
        alphabetically.
        c                       e Zd Zd Zd Zy)7ServerOptionsTests.test_subCommands.<locals>.FakePluginc                 :    || _         d|z   | _        d|z   | _        y )Nzoptions for description of )rW   _optionsdescriptionrQ   r/   s     r4   __init__z@ServerOptionsTests.test_subCommands.<locals>.FakePlugin.__init__   s"    # . 5#4t#; r6   c                     | j                   S r)   )ro   rc   s    r4   rN   z?ServerOptionsTests.test_subCommands.<locals>.FakePlugin.options   s    }}$r6   N)rS   rT   rU   rr   rN   rX   r6   r4   
FakePluginrl      s    <
%r6   rt   applebananacoconutdonutc              3   Z   K   j                  | t                   y wr)   )assertEqualr   )	interfaceru   rv   rw   rx   rQ   s    r4   
getPluginsz7ServerOptionsTests.test_subCommands.<locals>.getPlugins   s+     Y6MLKKs   (+N)r   ServerOptionsrz   _getPluginsr	   r|   subCommandsziprW   assertIsNonero   rp   )rQ   rt   r|   configr   expectedOrder
subCommandexpectedCommandr/   shortcutparserClassdocumentationru   rv   rw   rx   s   `           @@@@r4   test_subCommandsz#ServerOptionsTests.test_subCommands   s   	% 	% 7#H%Y'7#	 	 %%'++V->->?' ((7+.{M+J 	I'J9C6D(KT?#:#:;h'[]O,D,DEF]O,G,GH	Ir6   c                 \   	
  G d d      } |d       |d       |d       |d      		fd}t        j                         } j                  |j                  t        j
                         ||_        t               |_         j                  t        |j                  dg       |j                  j                         
g 	fD ]-  }
 fd	} ||j                          ||j                         /  j                  t              d
j                  
             y)zP
        Reactor names are listed alphabetically by I{--help-reactors}.
        c                       e Zd Zd Zy)GServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstallerc                 :    d|z   | _         d|z   | _        d| _        y )Nzname of rn   ztwisted.internet.default)	shortNamerp   
moduleNamerq   s     r4   rr   zPServerOptionsTests.test_sortedReactorHelp.<locals>.FakeReactorInstaller.__init__   s"    !+d!2#4t#; "<r6   N)rS   rT   rU   rr   rX   r6   r4   FakeReactorInstallerr      s    =r6   r   ru   rv   rw   rx   c               3   .   K        y wr)   rX   )ru   rv   rw   rx   s   r4   getReactorTypeszBServerOptionsTests.test_sortedReactorHelp.<locals>.getReactorTypes   s     MLKKs   z--help-reactorsc                 j    j                  |        j                  j                  |              y r)   )assertInappendr+   )s
helpOutputindexesrQ   s    r4   getIndexz;ServerOptionsTests.test_sortedReactorHelp.<locals>.getIndex   s(    a,z//23r6   z9reactor descriptions were not in alphabetical order: {!r}N)r   r}   rz   _getReactorTypesr   r   r   messageOutputassertRaises
SystemExitparseOptionsgetvaluer   rp   sortedformat)rQ   r   r   r   reactorr   ru   rv   rw   rx   r   r   s   `     @@@@@@r4   test_sortedReactorHelpz)ServerOptionsTests.test_sortedReactorHelp   s   
	= 	= %W-%h/&y1$W-	 %%'00(2J2JK"1'z*f&9&9<M;NO))224
fgu4 	*G4 W&&'W(()	* 	7OGNN	
r6   c                     t        j                         }d|_        |j                          | j	                  |d          y)zS
        postOptions should set no_save to True when a subcommand is used.
        rL   no_saveN)r   r}   r   postOptions
assertTruerQ   r   s     r4   &test_postOptionsSubCommandCausesNoSavez9ServerOptionsTests.test_postOptionsSubCommandCausesNoSave   s7     %%'"y)*r6   c                 t    t        j                         }|j                          | j                  |d          y)zR
        If no sub command is used, postOptions should not touch no_save.
        r   N)r   r}   r   assertFalser   s     r4   (test_postOptionsNoSubCommandSavesAsUsualz;ServerOptionsTests.test_postOptionsNoSubCommandSavesAsUsual  s1     %%'	*+r6   c                     t        j                         }t        |      }t        j                  j
                  D ]  }| j                  ||        y)zq
        All the profilers that can be used in L{app.AppProfiler} are listed in
        the help output.
        N)r   r}   strr
   AppProfiler	profilersr   )rQ   r   r   profilers       r4   test_listAllProfilersz(ServerOptionsTests.test_listAllProfilers
  sB    
 %%'[
11 	0HMM(J/	0r6   twistd unix not availablec                 T    t        j                         }| j                  |d          y)zG
        The default value for the C{umask} option is L{None}.
        umaskN)r   r}   r   r   s     r4   test_defaultUmaskz$ServerOptionsTests.test_defaultUmask  s$    
 %%'&/*r6   c                     t        j                         }|j                  ddg       | j                  |d   d       |j                  ddg       | j                  |d   d       y)zh
        The value given for the C{umask} option is parsed as an octal integer
        literal.
        --umask123r   S   0123N)r   r}   r   rz   r   s     r4   
test_umaskzServerOptionsTests.test_umask  s`     %%'Y./"-Y/0"-r6   c                 r    t        j                         }| j                  t        |j                  ddg       y)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   r}   r   r   r   r   s     r4   test_invalidUmaskz$ServerOptionsTests.test_invalidUmask(  s/     %%'*f&9&9Ix;PQr6   c                 
   t        j                         }| j                  t        |j                  ddg      }| j                  |j                  d   j                  d             | j                  d|j                  d          y)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   r}   r   r   r   r   args
startswithassertNotInrQ   r   es      r4   &test_unimportableConfiguredLogObserverz9ServerOptionsTests.test_unimportableConfiguredLogObserver1  sy     %%'++j:Q-R
 	FF1I  B	
 	qvvay)r6   c                 
   t        j                         }| j                  t        |j                  ddg      }| j                  |j                  d   j                  d             | j                  d|j                  d          y)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   s      r4   *test_badAttributeWithConfiguredLogObserverz=ServerOptionsTests.test_badAttributeWithConfiguredLogObserverA  sz     %%':;

 	FF1I  ,	
 	qvvay)r6   c                 v   ddl m} t        dk(  rd}nd}dj                  ||j                  |j                        }t               }t        j                  |      }| j                  t        |j                  dg      }| j                  |j                  d	       | j                  |j                         |       y	)
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   r}   r   r   r   assertIscoderz   r   )rQ   r   r/   expectedOutputr   r   r   s          r4   test_versionzServerOptionsTests.test_versionT  s     	&7"1D)D-44)##Y%8%8
 %%V4j&*=*=}Maffd#*N;r6   c                     t               }t        j                  |      }| j                  t        |j
                  dg       y)zI
        Command is printed when an invalid option is requested.
        r   z	web --fooN)r   r   r}   r   r   r   )rQ   r   r   s      r4   !test_printSubCommandForUsageErrorz4ServerOptionsTests.test_printSubCommandForUsageErrorh  s5     %%V4*f&9&9K=Ir6   N)rS   rT   rU   rV   r   r   r   r   r   r   _twistd_unixr   r   r   r   r   r   r   rX   r6   r4   ri   ri      s    )IV-
^+,0 9:+ ;+ 9:	. ;	. 9:R ;R* *&<(Jr6   ri   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)CheckPIDTestsz 
    Tests for L{checkPID}.
    c                 ^    | j                  t        j                  dd        t        d       y)z7
        Nonexistent PID file is not an error.
        existsc                      yNFrX   )_s    r4   <lambda>z.CheckPIDTests.test_notExists.<locals>.<lambda>|      r6   znon-existent PID fileN)rD   r:   pathr#   rc   s    r4   test_notExistszCheckPIDTests.test_notExistsx  s!     	

277Ho6()r6   c                     | j                         }t        |d      5 }|j                  d       ddd       | j                  t        t
        |      }| j                  d|j                         y# 1 sw Y   AxY w)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   )rQ   pidfilefr   s       r4   test_nonNumericzCheckPIDTests.test_nonNumeric  sc     ++-'3 	#1GGM"	#j(G<)1662	# 	#s   A//A8c                 *   | j                         }t        |d      5 }|j                  d       ddd       d }| j                  t        d|       | j                  t        t        |      }| j                  d|j                         y# 1 sw Y   [xY w)zE
        Another running twistd server causes a system exit.
        r   42Nc                      y r)   rX   pidsigs     r4   killz/CheckPIDTests.test_anotherRunning.<locals>.kill  s    r6   r   zAnother twistd server)
r   r   r   rD   r:   r   r   r#   r   r   rQ   r   r   r   r   s        r4   test_anotherRunningz!CheckPIDTests.test_anotherRunning  sy     ++-'3 	1GGDM		 	

2vt$j(G<-qvv6	 	s   B		Bc                 j   | j                         }t        |d      5 }|j                  t        t	        j
                         dz                ddd       d }| j                  t        d|       t        |       | j                  t        j                  j                  |             y# 1 sw Y   ]xY w)zJ
        Stale PID file is removed without causing a system exit.
        r      Nc                 6    t        t        j                  d      Nfake)OSErrorerrnoESRCHr   s     r4   r   z&CheckPIDTests.test_stale.<locals>.kill      %++v..r6   r   )r   r   r   r   r:   getpidrD   r#   r   r   r   )rQ   r   r   r   s       r4   
test_stalezCheckPIDTests.test_stale  s     ++-'3 	*1GGC		a()	*	/ 	

2vt$01	* 	*s   0B))B2c                    | j                         }t        |d      5 }|j                  d       ddd       d }| j                  t        d|       | j                  t        t        |      }| j                  |j                  d       | j                  |j                  d   j                  d             y# 1 sw Y   xY w)z
        An unexpected L{OSError} when checking the validity of a
        PID in a C{pidfile} terminates the process via L{SystemExit}.
        r   3581Nc                 6    t        t        j                  d      r   r   r   EBADFr   s     r4   r   z2CheckPIDTests.test_unexpectedOSError.<locals>.kill  r   r6   r   r   zCan't check status of PID)r   r   r   rD   r:   r   r   r#   assertIsNotr   r   r   r   r   s        r4   test_unexpectedOSErrorz$CheckPIDTests.test_unexpectedOSError  s    
 ++-'3 	1GGFO		/ 	

2vt$j(G<&q	,,-HIJ	 	s   B66B?N)	rS   rT   rU   rV   r   r   r   r   r  rX   r6   r4   r   r   r  s!    *372Kr6   r   c                       e Zd ZdZd Zd Zy)TapFileTestszM
    Test twistd-related functionality that requires a tap file on disk.
    c                     | j                         | _        t        | j                  d      5 }t        j                  t        j                  d      |       ddd       y# 1 sw Y   yxY w)zP
        Create a trivial Application and put it in a tap file on disk.
        wbHi!N)r   tapfiler   pickledumpr   Application)rQ   r   s     r4   setUpzTapFileTests.setUp  sO     {{}$,,% 	7KK++E2A6	7 	7 	7s   *AA(c                     t        j                         }|j                  d| j                  g       t	        |      j                         }| j                  t        j                  |      j                  d       y)z
        Ensure that the createOrGetApplication call that 'twistd -f foo.tap'
        makes will load the Application out of foo.tap.
        z-fr  N)
r   r}   r   r  ra   createOrGetApplicationrz   r   IServicer/   )rQ   r   r]   s      r4   &test_createOrGetApplicationWithTapFilez3TapFileTests.test_createOrGetApplicationWithTapFile  s]    
 %%'T4<<01/7NNP))+6;;UCr6   N)rS   rT   rU   rV   r  r  rX   r6   r4   r	  r	    s    7Dr6   r	  c                   "    e Zd ZdZd Zd Zd Zy)TestLoggerFactoryz8
    A logger factory for L{TestApplicationRunner}.
    c                     || _         y r)   )runner)rQ   r  s     r4   rr   zTestLoggerFactory.__init__  s	    r6   c                     | j                   j                  j                  d       t        | j                   d      | j                   _        y)zC
        Save the logging start on the C{runner} instance.
        logr]   N)r  orderr   hasattrhadApplicationLogObserverr\   s     r4   r^   zTestLoggerFactory.start  s3     	  '07]0S-r6   c                      y)z%
        Don't log anything.
        NrX   rc   s    r4   stopzTestLoggerFactory.stop  r   r6   N)rS   rT   rU   rV   rr   r^   r   rX   r6   r4   r  r    s    Tr6   r  c                   "    e Zd ZdZd Zd Zd Zy)TestApplicationRunnerz`
    An ApplicationRunner which tracks the environment in which its methods are
    called.
    c                 r    t         j                  j                  | |       g | _        t	        |       | _        y r)   )r
   ApplicationRunnerrr   r  r  r   rP   s     r4   rr   zTestApplicationRunner.__init__  s+    &&tW5
'-r6   c                 \    | j                   j                  d       t        | d      | _        y )Nprer]   )r  r   r  hadApplicationPreApplicationrc   s    r4   rd   z$TestApplicationRunner.preApplication  s#    

% ,3D-,H)r6   c                 \    | j                   j                  d       t        | d      | _        y )Npostr]   )r  r   r  hadApplicationPostApplicationrc   s    r4   rf   z%TestApplicationRunner.postApplication  s#    

&!-4T=-I*r6   N)rS   rT   rU   rV   rr   rd   rf   rX   r6   r4   r"  r"    s    
.
IJr6   r"  c                       e Zd ZdZd Zd Zd Zd Z e e	e
dd       d      d	        Z e e	e
dd       d      d
        Zd Zd Zd Zd Zy)ApplicationRunnerTestszR
    Non-platform-specific tests for the platform-specific ApplicationRunner.
    c                     t        j                         }t               | _        d| j                  i|_        t               |_        d|_        || _        y )Ntest_command)	r   r}   rK   serviceMakerloadedPluginsobject
subOptionsr   r   r   s     r4   r  zApplicationRunnerTests.setUp  sG    %%',. .0A0AB"H*r6   c                 f   t        | j                        }|j                          | j                  | j                  j
                  | j                  j                  d       | j                  | j                  j                  t        j                  |j                        j                  d   d       y)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)ra   r   runr   r/  rN   r2  r   r  r]   services)rQ   arunners     r4   ,test_applicationRunnerGetsCorrectApplicationzCApplicationRunnerTests.test_applicationRunnerGetsCorrectApplication  s     ,DKK8%%KK"""	
 	%%W001::1="	
r6   c                 ,   t        | j                        }|j                          | j                  |j                         | j                  |j                         | j                  |j                         | j                  |j                  g d       y)z
        Test thet preApplication and postApplication methods are
        called by ApplicationRunner.run() when appropriate.
        )r&  r  r)  N)
r"  r   r4  r   r'  r   r*  r  rz   r  )rQ   r   s     r4   test_preAndPostApplicationz1ApplicationRunnerTests.test_preAndPostApplication  sh    
 "$++.	778778334"89r6   c           	         | j                   j                  |       g  G fddt        j                        }t	        t
        j                  t
        j                         G fdd             } |       }t        t
        j                  |       t        t
        j                  |        || j                         }|j                          ||_
        |j                          | j                  dddd||fd	d
g       y)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                   2    e Zd Z fdZ fdZ fdZd Zy)\ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunnerc                 (    j                  d       y )Nenvironmentr   )rQ   chrootrundirnodaemonr   r   eventss         r4   setupEnvironmentzmApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.setupEnvironment8  s    m,r6   c                 0    j                  d|||f       y )N
privilegesr?  )rQ   euidrF   r1   rC  s       r4   shedPrivilegeszkApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.shedPrivileges;  s    |T3<=r6   c                 (    j                  d       y )Nr   r?  )rQ   r   	oldstdout	oldstderrrC  s       r4   startReactorziApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.startReactor>  s    i(r6   c                      y r)   rX   )rQ   r   s     r4   	removePIDzfApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeUnixApplicationRunner.removePIDA      r6   N)rS   rT   rU   rD  rH  rL  rN  rC  s   r4   FakeUnixApplicationRunnerr<  7  s    ->)r6   rQ  c                   R    e Zd ZdZdZdZdZdZdZd Z	d Z
d Z fdZ fdZd Zy)NApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeServiceNc                      y r)   rX   rq   s     r4   setNamezVApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setNameM  rO  r6   c                      y r)   rX   )rQ   parents     r4   setServiceParentz_ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.setServiceParentP  rO  r6   c                      y r)   rX   rc   s    r4   disownServiceParentzbApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.disownServiceParentS  rO  r6   c                 (    j                  d       y )NprivilegedStartServicer?  rQ   rC  s    r4   r\  zeApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.privilegedStartServiceV  s    67r6   c                 (    j                  d       y )NstartServicer?  r]  s    r4   r_  z[ApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.startServiceY  s    n-r6   c                      y r)   rX   rc   s    r4   stopServicezZApplicationRunnerTests._applicationStartsWithConfiguredID.<locals>.FakeService.stopService\  rO  r6   )rS   rT   rU   rW  runningr/   processNamerF   r1   rU  rX  rZ  r\  r_  ra  rP  s   r4   FakeServicerS  D  s?    FGDKCC8.r6   rd  r>  r\  rF  Fr_  r   N)r   r   r   _SomeApplicationRunnerr   r   r  IProcessr   rd   r]   rf   rz   )	rQ   argvrF   r1   rQ  rd  r]   r  rC  s	           @r4   "_applicationStartsWithConfiguredIDz9ApplicationRunnerTests._applicationStartsWithConfiguredID*  s     	  &	(E(E 	 
W%%w'7'7	8	 	 
9	4 "mW%%{3W%%{3*4;;7( (uc3/		
r6   setuidNz5Platform does not support --uid/--gid twistd options.c                 ^    d}d}| j                  dt        |      dt        |      g||       y)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)rh  r   )rQ   rF   r1   s      r4   .test_applicationStartsWithConfiguredNumericIDszEApplicationRunnerTests.test_applicationStartsWithConfiguredNumericIDss  s4     //c#hS2C	
r6   c                 t    d}d}d}d}t        | j                  ||||       | j                  d|d|g||       y)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}.
        foork  barrl  rm  rn  N)rI   rD   rh  )rQ   rE   rF   r3   r1   s        r4   +test_applicationStartsWithConfiguredNameIDszBApplicationRunnerTests.test_applicationStartsWithConfiguredNameIDs  sJ     $**dC<//dGU+S#	
r6   c                     t               }t        j                  dddd      }|j                  |dd       | j	                  |j
                  d       y)z7
        L{startReactor} calls L{reactor.run}.
        Fr$   r$   r   debugNz'startReactor did not call reactor.run())DummyReactorr
   r$  rL  r   calledrQ   r   r  s      r4   test_startReactorRunsTheReactorz6ApplicationRunnerTests.test_startReactorRunsTheReactor  sL     .&&9uE
 	GT40(QRr6   c                     t               }| j                  t        d|       t        j                  dddd      }|j                  ddd       | j                  |j                         y)zN
        L{ApplicationRunner} chooses a reactor if none is specified.
        r   Fr$   ru  N)rw  rD   r   r
   r$  rL  r   rx  ry  s      r4   *test_applicationRunnerChoosesReactorIfNonezAApplicationRunnerTests.test_applicationRunnerChoosesReactorIfNone  sY     .

8Y0&&9uE
 	D$-'r6   c                      G d dt               } |       }t        j                  dddd      }|j                  |dd       | j	                  d|j
                         y)zg
        If the reactor exits with a signal, the application runner caches
        the signal.
        c                       e Zd ZdZd Zd Zy)[ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal
            A dummy reactor, providing a C{run} method, and setting the
            _exitSignal attribute to a nonzero value.
            c                      yz=
                Dummy method, does nothing.
                NrX   rc   s    r4   installWakerzhApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.installWaker  r   r6   c                     d| _         y)zZ
                A fake run method setting _exitSignal to a nonzero value
                   N_exitSignalrc   s    r4   r4  z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal.<locals>.DummyReactorWithSignal.run  s     $% r6   NrS   rT   rU   rV   r  r4  rX   r6   r4   DummyReactorWithSignalr    s    

%r6   r  Fr$   ru  Nr  )r   r
   r$  rL  assertEqualsr  )rQ   r  r   r  s       r4   $test_applicationRunnerCapturesSignalz;ApplicationRunnerTests.test_applicationRunnerCapturesSignal  s\    	%[ 	%" )*&&9uE
 	GT40!V//0r6   c                      G d d      } |       }t        j                  dddd      }|j                  |dd       | j                  d|j                         y)z
        The runner sets its _exitSignal instance attribute to None if
        the reactor does not implement L{_ISupportsExitSignalCapturing}.
        c                       e Zd ZdZd Zd Zy)iApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttributer  c                      yr  rX   rc   s    r4   r  zvApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.installWaker  r   r6   c                     d| _         y)z
                A fake run method setting _exitSignal to a nonzero value
                that should be ignored.
                r  Nr  rc   s    r4   r4  zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal.<locals>.DummyReactorWithExitSignalAttribute.run  s    
 $% r6   Nr  rX   r6   r4   #DummyReactorWithExitSignalAttributer    s    

%r6   r  Fr$   ru  N)r
   r$  rL  r  r  )rQ   r  r   r  s       r4   %test_applicationRunnerIgnoresNoSignalz<ApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal  sZ    	% 	%$ 67&&9uE
 	GT40$ 2 23r6   )rS   rT   rU   rV   r  r7  r9  rh  r   getattrr:   ro  rs  rz  r|  r  r  rX   r6   r4   r,  r,    s    
,
:G
R B$''?
	
 B$''?
	
 	S
(1<4r6   r,  c                   f    e Zd ZdZ e       Zd Zd Zd Zd Z	d Z
d Zd Zd	 Zd
 Zd Zd Zd Zy)*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                      j                    _         j                    _         j                    _        d _        t        j                          _         j                  t
        d fd        j                  t
        d fd        j                  t
        d fd       t        t        j                                _         j                   j                  _        y )NFr@  c                     t        d|       S )Nrootsetattrr   rQ   s    r4   r   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>  s    gdFD.I r6   chdirc                     t        d|       S )Ncwdr  r  s    r4   r   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>  s    WT5$-G r6   r   c                     t        d|       S )Nmaskr  )r  rQ   s    r4   r   zBUnixApplicationRunnerSetupEnvironmentTests.setUp.<locals>.<lambda>  s    WT64-H r6   )unsetr  r  r  daemonr:   r   r   rD   r!   r   r}   r  	daemonizerc   s   `r4   r  z0UnixApplicationRunnerSetupEnvironmentTests.setUp  s    JJ	::JJ	99;

2x!IJ

2w GH

2w HI+F,@,@,BC $r6   c                 H     d _          j                  t        d fd       y)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                  "     j                   dz   S Nr   )r   rc   s   r4   r   zFUnixApplicationRunnerSetupEnvironmentTests.daemonize.<locals>.<lambda>  s    A r6   N)r  rD   r:   rQ   r   s   ` r4   r  z4UnixApplicationRunnerSetupEnvironmentTests.daemonize  s    
 

2x!56r6   c                 z    | j                   j                  ddddd       | j                  | j                  d       y)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  rD  rz   r  rc   s    r4   test_chrootz6UnixApplicationRunnerSetupEnvironmentTests.test_chroot  s2    
 	$$ZdD$GJ/r6   c                     | j                   j                  ddddd       | j                  | j                  | j                         y)z
        L{UnixApplicationRunner.setupEnvironment} does not change the root of
        the filesystem if passed L{None} for the C{chroot} parameter.
        Nr  T)r  rD  r   r  r  rc   s    r4   test_noChrootz8UnixApplicationRunnerSetupEnvironmentTests.test_noChroot!  s4    
 	$$T3dDAdii,r6   c                 z    | j                   j                  ddddd       | j                  | j                  d       y)z
        L{UnixApplicationRunner.setupEnvironment} changes the working directory
        of the process to the path given for the C{rundir} parameter.
        Nr  T)r  rD  rz   r  rc   s    r4   test_changeWorkingDirectoryzFUnixApplicationRunnerSetupEnvironmentTests.test_changeWorkingDirectory)  s2    
 	$$T:tT4H:.r6   c                     t        t                     5  | j                  j                  ddddd       ddd       | j	                  | j
                         y# 1 sw Y   %xY w)z
        L{UnixApplicationRunner.setupEnvironment} daemonizes the process if
        C{False} is passed for the C{nodaemon} parameter.
        Nr  F)r   FakeDaemonizingReactorr  rD  r   r  rc   s    r4   test_daemonizez9UnixApplicationRunnerSetupEnvironmentTests.test_daemonize1  sS    
 467 	GKK((sE4F	G$	G 	Gs    AA!c                 x    | j                   j                  ddddd       | j                  | j                         y)z
        L{UnixApplicationRunner.setupEnvironment} does not daemonize the
        process if C{True} is passed for the C{nodaemon} parameter.
        Nr  T)r  rD  r   r  rc   s    r4   test_noDaemonizez;UnixApplicationRunnerSetupEnvironmentTests.test_noDaemonize:  s0    
 	$$T3dDA%r6   c                    | j                         }| j                  j                  dddd|       t        |d      5 }t	        |j                               }ddd       | j                  | j                         y# 1 sw Y   &xY w)z
        L{UnixApplicationRunner.setupEnvironment} writes the process's PID to
        the file specified by the C{pidfile} parameter.
        Nr  Trb)r   r  rD  r   intreadrz   r   rQ   r   r   r   s       r4   test_nonDaemonPIDFilez@UnixApplicationRunnerSetupEnvironmentTests.test_nonDaemonPIDFileB  sm    
 ++-$$T3dGD'4  	 Aaffh-C	 dhh'	  	 s   A;;Bc                 d   | j                         }t        t                     5  | j                  j	                  dddd|       ddd       t        |d      5 }t        |j                               }ddd       | j                  | j                  dz          y# 1 sw Y   WxY w# 1 sw Y   5xY w)z
        L{UnixApplicationRunner.setupEnvironment} writes the daemonized
        process's PID to the file specified by the C{pidfile} parameter if
        C{nodaemon} is C{False}.
        Nr  Fr  r   )
r   r   r  r  rD  r   r  r  rz   r   r  s       r4   test_daemonPIDFilez=UnixApplicationRunnerSetupEnvironmentTests.test_daemonPIDFileM  s     ++-467 	JKK((sE4I	J'4  	 Aaffh-C	 dhhl+		J 	J	  	 s    BB&B#&B/c                     t        t                     5  | j                  j                  ddddd       ddd       | j	                  | j
                  d       y# 1 sw Y   &xY w)z
        L{UnixApplicationRunner.setupEnvironment} changes the process umask to
        the value specified by the C{umask} parameter.
        Nr  F{   r   r  r  rD  rz   r  rc   s    r4   r   z5UnixApplicationRunnerSetupEnvironmentTests.test_umaskZ  sW    
 467 	FKK((sE3E	FC(	F 	F    AA"c                     | j                   j                  ddddd       | j                  | j                  | j                         y)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  rD  r   r  r  rc   s    r4   test_noDaemonizeNoUmaskzBUnixApplicationRunnerSetupEnvironmentTests.test_noDaemonizeNoUmaskc  s4     	$$T3dDAdii,r6   c                     t        t                     5  | j                  j                  ddddd       ddd       | j	                  | j
                  d       y# 1 sw Y   &xY w)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?   r  rc   s    r4   test_daemonizedNoUmaskzAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmaskl  sW     467 	GKK((sE4F	GE*	G 	Gr  N)rS   rT   rU   rV   r1  r  r  r  r  r  r  r  r  r  r  r   r  r  rX   r6   r4   r  r    sL    ( HE
/70-/%&	(,)-+r6   r  c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	*UnixApplicationRunnerStartApplicationTestsz>
    Tests for L{UnixApplicationRunner.startApplication}.
    c                    t        j                         }|j                  g d       t        j                  d      }t        |      | _        g fd}t        j                  | j                  j                        j                  }t        j                  |      j                  }|j                         }|j                  d       | j                  ||       | j                  t
        d|       | j                  t
        dd        | j                  t        dd	        | j                  j!                  |       | j                  g d
       y)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/rundir	--pidfile/foo/pidfiletest_setupEnvironmentc                 2    j                  |||||f       y r)   )extend)rQ   r@  rA  rB  r   r   r   s         r4   fakeSetupEnvironmentz^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.fakeSetupEnvironment  s    KK5'BCr6   rQ   rD  rH  c                       y r)   rX   akws     r4   r   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>  r   r6   startApplicationc                       y r)   rX   r  s     r4   r   zRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment.<locals>.<lambda>  r   r6   )r  r  T8   r  N)r   r}   r   r   r  r!   r  inspect	signaturerD  
parameterscopypoprz   rD   r
   r  )rQ   rN   r]   r  setupEnvironmentParametersfakeSetupEnvironmentParametersr   s         @r4   r  z@UnixApplicationRunnerStartApplicationTests.test_setupEnvironment}  s!    &&(
	
 ))*AB+G4	D &-%6%6KK((&

* 	# *1):): *

* 	' *H)L)L)N&&**6235ST

(*<>RS

(*:<QR

3*,AB$$[1WXr6   c                 z      fd} j                  t        d|       t        i       }|j                  ddd       y)zf
        L{UnixApplicationRunner.shedPrivileges} switches the user ID
        of the process.
        c                 r    j                  | d       j                  |d       j                  |d       y )N   6   #   rz   )rF   r1   rG  rQ   s      r4   switchUIDPasszUUnixApplicationRunnerStartApplicationTests.test_shedPrivileges.<locals>.switchUIDPass  s3    S#&S"%T2&r6   	switchUIDr  r  r  N)rD   r   r!   rH  )rQ   r  r  s   `  r4   test_shedPrivilegesz>UnixApplicationRunnerStartApplicationTests.test_shedPrivileges  s6    	'
 	

<m<&r*b#r*r6   c                     d }t        i       }| j                  t        d|       | j                  t        |j
                  ddd      }| j                  |j                  d       y)z
        An unexpected L{OSError} when calling
        L{twisted.scripts._twistd_unix.shedPrivileges}
        terminates the process via L{SystemExit}.
        c                 6    t        t        j                  d      r   r  )rF   r1   rG  s      r4   switchUIDFailzZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError.<locals>.switchUIDFail  r   r6   r  r  r  Nr   )r!   rD   r   r   r   rH  rz   r   )rQ   r  r  excs       r4   test_shedPrivilegesErrorzCUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError  sU    	/ 'r*

<m<
F,A,A2sDQ1%r6   c                     t         j                  ||        fd} fd} fd} j                  t        d|        j                  t        d|        j                  t        d|       t	        j
                         }	|	j                  ddt              d	|g       t        j                  d
      }
t        |	       _        t        |	      }|j                  |
       y)zj
        Common code for tests which try to pass the the UID to
        L{UnixApplicationRunner}.
        c                 N    j                  |        j                  |       y r)   r  )rF   r1   rQ   	wantedGid	wantedUids     r4   
initgroupszFUnixApplicationRunnerStartApplicationTests._setUID.<locals>.initgroups  s#    S),S),r6   c                 *    j                  |        y r)   r  )rF   rQ   r  s    r4   ri  zBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setuid      S),r6   c                 *    j                  |        y r)   r  )r1   rQ   r  s    r4   setgidzBUnixApplicationRunnerStartApplicationTests._setUID.<locals>.setgid  r  r6   r  ri  r  r  rm  r  r  N)rI   rD   r   r:   r   r}   r   r   r   r  r!   r  r  )rQ   
wantedUserr  wantedGroupr  pidFiler  ri  r  rN   r]   r  s   ` ` `       r4   _setUIDz2UnixApplicationRunnerStartApplicationTests._setUID  s    
 	$**j)[)T	-	-	- 	

4z2

2x(

2x(&&(7C	NKI	
 ))*AB+G4&w/,r6   c                 P    | j                  dddd| j                         dz          y)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.
        rq  i  rr  i  z_test_setUidWithoutGid.pidN)r  r   rc   s    r4   test_setUidWithoutGidz@UnixApplicationRunnerStartApplicationTests.test_setUidWithoutGid  s'     	4dkkm6R&R	
r6   c                    t        j                         }| j                  d|ddd       | j                         }dj	                  ||      }| j                  ||d   d          | j                  dt        |      |       y	)
zz
        If the specified UID is the same as the current UID of the process,
        then a warning is displayed.
        morefoomorebari  ztest_setUidSameAsCurrentUid.pidz\tried to drop privileges and setuid {} but uid is already {}; should we be root? Continuing.r   messager   N)r:   r;   r  flushWarningsr   rz   len)rQ   
currentUidwarningsShownexpectedWarnings       r4   test_setUidSameAsCurrentUidzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUid  s    
 YY[
z9d4U	
 **,--3VJ
-K 	 	-*:9*EFC.>r6   N)
rS   rT   rU   rV   r  r  r  r  r  r  rX   r6   r4   r  r  w  s'    2Yh+&-<
?r6   r  c                       e Zd ZdZd Zd Zy)#UnixApplicationRunnerRemovePIDTestsz7
    Tests for L{UnixApplicationRunner.removePID}.
    c                 V   t        i       }| j                         }t        j                  |       t        j                  j                  |d      }t        |d      j                          |j                  |       | j                  t        j                  j                  |             y)zp
        L{UnixApplicationRunner.removePID} deletes the file the name of
        which is passed to it.
        zfoo.pidr   N)r!   r   r:   makedirsr   joinr   closerN  r   r   )rQ   r  r   r   s       r4   test_removePIDz2UnixApplicationRunnerRemovePIDTests.test_removePID  su    
 'r*{{}
D'',,tY/Wc  "!01r6   c                 
   t        i       }|j                  d       | j                  t              }| j	                  t        |      d       | j	                  |d   j                  j                  t        j                         y)zr
        Calling L{UnixApplicationRunner.removePID} with a non-existent filename
        logs an OSError.
        fakepidr   r   N)	r!   rN  flushLoggedErrorsr   rz   r  valuer   ENOENT)rQ   r  errorss      r4   test_removePIDErrorsz8UnixApplicationRunnerRemovePIDTests.test_removePIDErrors  sb    
 'r*#''0Va(..=r6   N)rS   rT   rU   rV   r  r  rX   r6   r4   r	  r	  
  s    2	>r6   r	  c                   (    e Zd ZdZd Zd Zd Zd Zy)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                      d| _         d| _        y r   )_beforeDaemonizeCalled_afterDaemonizeCalledrc   s    r4   rr   z"FakeNonDaemonizingReactor.__init__5  s    &+#%*"r6   c                     d| _         y NT)r  rc   s    r4   beforeDaemonizez)FakeNonDaemonizingReactor.beforeDaemonize9  s
    &*#r6   c                     d| _         y r  )r  rc   s    r4   afterDaemonizez(FakeNonDaemonizingReactor.afterDaemonize<  s
    %)"r6   c                      y)z*
        Skip event registration.
        NrX   )rQ   r   r  s      r4   addSystemEventTriggerz/FakeNonDaemonizingReactor.addSystemEventTrigger?  r   r6   N)rS   rT   rU   rV   rr   r  r  r!  rX   r6   r4   r  r  )  s    	++*r6   r  c                       e Zd ZdZy)r  z
    A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize}
    methods, announcing this, and logging whether the methods have been called.
    N)rS   rT   rU   rV   rX   r6   r4   r  r  E  s    r6   r  c                       e Zd ZdZdZd Zy)rw  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                 @    | j                   rt        d      d| _         y)zV
        A fake run method, checking that it's been called one and only time.
        zAlready calledTN)rx  RuntimeErrorrc   s    r4   r4  zDummyReactor.runX  s     ;;/00r6   N)rS   rT   rU   rV   rx  r4  rX   r6   r4   rw  rw  M  s     Fr6   rw  c                       e Zd ZdZ ee d      d        Zd Z ee d      d        Zd Z	 ee d      d        Z
 ee d      d	        Z ee d      d
        Zd Zd Zd Zd Zy)AppProfilingTestsz'
    Tests for L{app.AppProfiler}.
    zprofile module not availablec                    t        j                         }| j                         |d<   d|d<   t        j                  |      }t               }|j                  |       | j                  |j                         t        |d         5 }|j                         }ddd       | j                  d       | j                  d|       y# 1 sw Y   .xY w)z
        L{app.ProfileRunner.run} should call the C{run} method of the reactor
        and save profile data in the specified file.
        r$   r   NzDummyReactor.runfunction callsr   r}   r   r
   r   rw  r4  r   rx  r   r  r   rQ   r   r   r   r   datas         r4   test_profilezAppProfilingTests.test_profilef  s     %%' KKMy&z??6*.W'&#$ 	668D	($/&-	 	   CCc                     t               }| j                  t        d|      } ||      }|j                          |j	                          |j                         }| j                  d|       | j                  d|       y )Nr   r)  z(run))r   rD   sysprint_statsrestorer   r   )rQ   
statsClassr$   outr   statsr,  s          r4   
_testStatszAppProfilingTests._testStatsz  sg    j C3/ 7#||~&-gt$r6   c                 B   t        j                         }| j                         |d<   d|d<   d|d<   t        j                  |      }t               }|j                  |       | j                  |j                         | j                  t        j                  |d          y)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   r}   r   r
   r   rw  r4  r   rx  r6  r%   StatsrQ   r   r   r   s       r4   test_profileSaveStatsz'AppProfilingTests.test_profileSaveStats  s~     %%' KKMy&z"{??6*.W'fY&78r6   c                    t         j                  j                         }t        j                         }d|d<   t        j                  |      }dt         j                  d<   	 | j                  t        |j                  d       t         j                  j                          t         j                  j                  |       y# t         j                  j                          t         j                  j                  |       w xY w)z
        When the C{profile} module is not present, L{app.ProfilerRunner.run}
        should raise a C{SystemExit} exception.
        r$   r   Nr0  modulesr  r   r}   r
   r   r   r   r4  clearupdaterQ   savedModulesr   r   s       r4   test_withoutProfilez%AppProfilingTests.test_withoutProfile  s    
 {{'')%%'&z??6*!%I	-j(,,=KKKK|, KKKK|,   !!C   ?C?c                     G d dt         j                        }| j                  t         d|       t        j                         }| j                         |d<   d|d<   t        j                  |      }t               }t        j                  }| j                  t        |j                  |       | j                  t        j                  |       y)z
        When an error happens during the print of the stats, C{sys.stdout}
        should be restored to its initial value.
        c                       e Zd Zd Zy)GAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfilec                     t        d      )NBoomr%  rc   s    r4   r1  zSAppProfilingTests.test_profilePrintStatsError.<locals>.ErroneousProfile.print_stats  s    "6**r6   N)rS   rT   rU   r1  rX   r6   r4   ErroneousProfilerH    s    +r6   rL  Profiler$   r   N)r$   rM  rD   r   r}   r   r
   r   rw  r0  r   r   r%  r4  r   )rQ   rL  r   r   r   	oldStdouts         r4   test_profilePrintStatsErrorz-AppProfilingTests.test_profilePrintStatsError  s    	+w 	+ 	

7I'78%%' KKMy&z??6*.JJ	,g>cjj),r6   zcProfile module not availablec                    t        j                         }| j                         |d<   d|d<   t        j                  |      }t               }|j                  |       | j                  |j                         t        |d         5 }|j                         }ddd       | j                  d       | j                  d|       y# 1 sw Y   .xY w)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   Nr4  r)  r*  r+  s         r4   test_cProfilezAppProfilingTests.test_cProfile  s     %%' KKMy'z??6*.W'&#$ 	668D	eT"&-	 	r.  c                 B   t        j                         }| j                         |d<   d|d<   d|d<   t        j                  |      }t               }|j                  |       | j                  |j                         | j                  t        j                  |d          y)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   Tr8  Nr9  r;  s       r4   test_cProfileSaveStatsz(AppProfilingTests.test_cProfileSaveStats  s~     %%' KKMy'z"{??6*.W'fY&78r6   c                    t         j                  j                         }dt         j                  d<   t        j                         }d|d<   t        j                  |      }	 | j                  t        |j                  d       t         j                  j                          t         j                  j                  |       y# t         j                  j                          t         j                  j                  |       w xY 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>  rB  s       r4   test_withoutCProfilez&AppProfilingTests.test_withoutCProfile  s     {{'')"&J%%''z??6*	-j(,,=KKKK|, KKKK|,rE  c                     t        j                         }| j                         |d<   d|d<   | j                  t        t
        j                  |      }| j                  t        |      d       y)zq
        Check that L{app.AppProfiler} raises L{SystemExit} when given an
        unknown profiler name.
        r$   foobarr   z!Unsupported profiler name: foobarN)	r   r}   r   r   r   r
   r   rz   r   )rQ   r   errors      r4   test_unknownProfilerz&AppProfilingTests.test_unknownProfiler  sY    
 %%' KKMy%z!!*coovFU%HIr6   c                 f    t        j                  i       }| j                  |j                  d       y)zU
        L{app.Profiler} defaults to the cprofile profiler if not specified.
        cprofileNr
   r   rz   r   rQ   r   s     r4   test_defaultProfilerz&AppProfilingTests.test_defaultProfiler  s(     ??2&**J7r6   c                 j    t        j                  ddi      }| j                  |j                  d       y)ze
        The case of the profiler name passed to L{app.AppProfiler} is not
        relevant.
        r   CprOfiler[  Nr\  r]  s     r4   test_profilerNameCaseInsentivez0AppProfilingTests.test_profilerNameCaseInsentive  s-    
 ??J
#;<**J7r6   N)rS   rT   rU   rV   r   r$   r-  r6  r<  rD  rO  r&   rQ  rS  rU  rY  r^  ra  rX   r6   r4   r'  r'  a  s     K78. 9.&%" K789 99"-$ K78- 9-, L9:. ;.& L9:9 ;9$-$
J88r6   r'  c                 V    g t         j                  f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                 >    j                  |         | g|i |S r)   r?  )logFiler   kwargslogFilesoldFileLogObservers      r4   observerz+_patchTextFileLogObserver.<locals>.observer(  s$     !';D;F;;r6   textFileLogObserver)r   ri  )rD   rh  rf  rg  s     @@r4   _patchTextFileLogObserverrj    s/     H33< 
&'2Or6   c                 R    g  G fdd      }| j                  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                   "    e Zd Z fdZ fdZy)(_setupSyslog.<locals>.fakesyslogobserverc                 (    j                  |       y r)   r?  )rQ   prefixlogMessagess     r4   rr   z1_setupSyslog.<locals>.fakesyslogobserver.__init__8  s    v&r6   c                 (    j                  |       y r)   r?  )rQ   	eventDictrp  s     r4   emitz-_setupSyslog.<locals>.fakesyslogobserver.emit;  s    y)r6   N)rS   rT   rU   rr   rs  )rp  s   r4   fakesyslogobserverrm  7  s    	'	*r6   rt  SyslogObserver)rD   syslog)testCasert  rp  s     @r4   _setupSyslogrx  0  s.    
 K* * NN6+-?@r6   c                       e Zd ZdZd Zd Zd Zd Zd Zd Z	i e
j                  fdZd	 Zd
 Zd Zd Z ee d       ee d      d               Zd Zd Zd Zd Zd Zd Zy)AppLoggerTestsz
    Tests for L{app.AppLogger}.

    @ivar observers: list of observers installed during the tests.
    @type observers: C{list}
    c                 L     g  _          fd} j                  t        d|       y)z
        Override L{globaLogBeginner.beginLoggingTo} so that we can trace the
        observers installed in C{self.observers}.
        c                 t    | D ]2  }j                   j                  |       t        j                  |       4 y r)   )	observersr   r   addObserver)r}  rh  rQ   s     r4   beginLoggingToz,AppLoggerTests.setUp.<locals>.beginLoggingToQ  s2    % 9%%h/"..x89r6   r  N)r}  rD   r   )rQ   r  s   ` r4   r  zAppLoggerTests.setUpJ  s%    
 	9
 	

$&6Gr6   c                 P    | j                   D ]  }t        j                  |        y)z1
        Remove all installed observers.
        N)r}  r   removeObserverrQ   rh  s     r4   tearDownzAppLoggerTests.tearDownX  s%      	8H--h7	8r6   c                 H    t        t               G 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                       e Zd Zg Zd Zy)2AppLoggerTests._makeObserver.<locals>.TestObserverc                 :    | j                   j                  |       y r)   )_logsr   )rQ   events     r4   __call__z;AppLoggerTests._makeObserver.<locals>.TestObserver.__call__k  s    

!!%(r6   N)rS   rT   rU   r  r  rX   r6   r4   TestObserverr  g  s    E)r6   r  )r   r   )rQ   r  s     r4   _makeObserverzAppLoggerTests._makeObserver_  s*     
\	"	) 	) 
#	) ~r6   c                     | j                  | j                  |g       | j                  d|j                  d   d          | j                  d|j                  d   d          y)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)rz   r}  r   r  r  s     r4   _checkObserverzAppLoggerTests._checkObserverp  sR     	(4mX^^A%6|%DEox~~a'8'FGr6   c                     t        j                  i       }| j                         fd|_         |j                  t                      | j                         y)z
        L{app.AppLogger.start} calls L{globalLogBeginner.addObserver}, and then
        writes some messages about twistd and the reactor.
        c                       S r)   rX   rh  s   r4   r   z+AppLoggerTests.test_start.<locals>.<lambda>  s     r6   N)r
   	AppLoggerr  _getLogObserverr^   r   r  )rQ   r   rh  s     @r4   
test_startzAppLoggerTests.test_startz  sG    
 r"%%'!1]_%H%r6   c                     t               }| j                         }|j                  t        |       t	        j
                  i       } |j                  |       | j                  |       y)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  r^   r  )rQ   r]   rh  r   s       r4   $test_startUsesApplicationLogObserverz3AppLoggerTests.test_startUsesApplicationLogObserver  sS     $o%%'  x8r"[!H%r6   c                     | j                         dfdi}|j                  |        ||      } |j                  |       S )a  
        Set up an AppLogger which exercises the C{logger} configuration option.

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

        @rtype: C{list}
        @return: The logs accumulated by the log observer.
        r   c                       S r)   rX   r  s   r4   r   z7AppLoggerTests._setupConfiguredLogger.<locals>.<lambda>  s    X r6   )r  rA  r^   )rQ   r]   extraLogArgs	appLoggerlogArgsr   rh  s         @r4   _setupConfiguredLoggerz%AppLoggerTests._setupConfiguredLogger  sG    " %%'-.|$7#[!r6   c                 X    t               }| j                  | j                  |             y)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  r\   s     r4   #test_startUsesConfiguredLogObserverz2AppLoggerTests.test_startUsesConfiguredLogObserver  s$     $oD77DEr6   c                     | j                         }t               }|j                  t        |       | j	                  | j                  |             | j                  |j                  g        y)zk
        C{--logger} takes precedence over a L{ILogObserver} component set on
        Application.
        N)r  r   r  r   r  r  rz   r  )rQ   rh  r]   s      r4   (test_configuredLogObserverBeatsComponentz7AppLoggerTests.test_configuredLogObserverBeatsComponent  sV    
 %%'#o  x8D77DE,r6   c                     g }t               }|j                  t        |j                         | j	                  | j                  |             | j                  |g        y)zq
        C{--logger} takes precedence over a L{LegacyILogObserver} component
        set on Application.
        N)r   r  LegacyILogObserverr   r  r  rz   )rQ   nonlogsr]   s      r4   .test_configuredLogObserverBeatsLegacyComponentz=AppLoggerTests.test_configuredLogObserverBeatsLegacyComponent  sN    
 #o  !3W^^DD77DE"%r6   c                 <   g }| j                         }t               }|j                  t        |       |j                  t        |j
                         t        j                  i       } |j                  |       | j                  |       | j                  |g        y)zw
        A L{ILogObserver} takes precedence over a L{LegacyILogObserver}
        component set on Application.
        N)r  r   r  r   r  r   r
   r  r^   r  rz   )rQ   r  rh  r]   r   s        r4   .test_loggerComponentBeatsLegacyLoggerComponentz=AppLoggerTests.test_loggerComponentBeatsLegacyLoggerComponent  s}    
 %%'#o  x8  !3W^^Dr"[!H%"%r6   r   zsyslog not availablec                     t        |       }t               }| j                  | j                  |ddit                     | j                  |g        y)z`
        C{--logger} takes precedence over a C{--syslog} command line
        argument.
        rv  TN)rx  r   r  r  r"   rz   )rQ   logsr]   s      r4   %test_configuredLogObserverBeatsSyslogz4AppLoggerTests.test_configuredLogObserverBeatsSyslog  sL     D!#o''h5E}U	
 	r"r6   c                     t               }| j                         }| j                  | j                  |ddi             | j	                  t
        j                  j                  |             y)za
        C{--logger} takes precedence over a C{--logfile} command line
        argument.
        logfiler   N)r   r   r  r  r   r:   r   r   )rQ   r]   r   s      r4   &test_configuredLogObserverBeatsLogfilez5AppLoggerTests.test_configuredLogObserverBeatsLogfile  sV    
 $o{{}''i5HI	
 	-.r6   c                    t        j                  ddi      }t        | j                        } |j                          | j                  t        |      d       | j                  |d   t        j                         t        j                  ddi      } |j                          | j                  t        |      d       | j                  |d   t        j                         y)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  rj  rD   r  rz   r  r   r0  r   )rQ   r   rf  s      r4   test_getLogObserverStdoutz(AppLoggerTests.test_getLogObserverStdout  s    
 	3/0,TZZ8 X*hqk3::.	2/ X*hqk3::.r6   c                    t        | j                        }| j                         }t        j                  d|i      }|j                         }| j                  |j                  j                         | j                  t        |      d       | j                  |d   j                  t        j                  j                  |             y)z
        When passing the C{logfile} option, L{app.AppLogger._getLogObserver}
        returns a log observer pointing at the specified path.
        r  r   r   N)rj  rD   r   r
   r  r  
addCleanup_outFiler  rz   r  r   r:   abspath)rQ   rf  filenamesutrh  s        r4   test_getLogObserverFilez&AppLoggerTests.test_getLogObserverFile  s    
 -TZZ8;;=mmY12&&())//0X*!))277??8+DEr6   c                 T   g t               }fd}| j                  t        d|       t        j                  i       }||_         |j                          | j                  |g        |j                          | j                  |g       | j                  |j
                         y)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                 (    j                  |        y r)   r?  )rh  removeds    r4   removez(AppLoggerTests.test_stop.<locals>.remove   s    NN8$r6   r  N)	r1  rD   r   r
   r  	_observerr   rz   r   )rQ   rh  r  r   r  s       @r4   	test_stopzAppLoggerTests.test_stop  s     8	% 	

%'7@r"#8*-8*-&**+r6   c                 f   g t        j                  i       }t        t               G fdd             fd|_         |j
                  t                      | j                  dt        d                | j                  | j                  g      }| j                  t        |      d|       y)zt
        L{app.AppLogger} using a legacy logger observer still works, wrapping
        it in a compat shim.
        c                       e Zd ZdZ fdZy);AppLoggerTests.test_legacyObservers.<locals>.LoggerObserverzX
            An observer which implements the legacy L{LegacyILogObserver}.
            c                 (    j                  |       y)z<
                Add C{x} to the logs list.
                Nr?  )rQ   xr  s     r4   r  zDAppLoggerTests.test_legacyObservers.<locals>.LoggerObserver.__call__:  s     Ar6   N)rS   rT   rU   rV   r  r  s   r4   LoggerObserverr  4  s    r6   r  c                               S r)   rX   )r  s   r4   r   z5AppLoggerTests.test_legacyObservers.<locals>.<lambda>@  s
    .*: r6   r  r   N)r
   r  r   r  _observerFactoryr^   r   r   r   r  test_legacyObserversrz   r  )rQ   r   warningsr  r  s      @@r4   r  z#AppLoggerTests.test_legacyObservers,  s    
 r"	'	(		 		 
)		 #;]_%m%6tAw%?@%%t'@'@&ABX84r6   c                 X   g t        j                  i       }fd|_         |j                  t	                      | j                  dt        d                | j                  | j                  g      }| j                  |d   d   d       | j                  t        |      d|       y)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                       j                   S r)   r?  r  s   r4   r   zAAppLoggerTests.test_unmarkedObserversDeprecated.<locals>.<lambda>O  s     r6   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  r^   r   r   r   r   test_unmarkedObserversDeprecatedrz   r  )rQ   r   r  r  s      @r4   r  z/AppLoggerTests.test_unmarkedObserversDeprecatedG  s     r"!4]_%m%6tAw%?@%%t'L'L&MNQK	"0	
 	X84r6   N)rS   rT   rU   rV   r  r  r  r  r  r  r
   r  r  r  r  r  r  r   r   rv  r  r  r  r  r  r  r  rX   r6   r4   rz  rz  B  s    H8"H	&& )+cmm0F	-	&&" 9:J./
# 0 ;
#
//&F,*565r6   rz  c                   T    e Zd ZdZd Zd Zd Zd Zd Zd Z	 e
e d      d	        Zy
)UnixAppLoggerTestszw
    Tests for L{UnixAppLogger}.

    @ivar signals: list of signal handlers installed.
    @type signals: C{list}
    c                 L     g  _          fd} j                  t        d|       y)zs
        Fake C{signal.signal} for not installing the handlers but saving them
        in C{self.signals}.
        c                 @    j                   j                  | |f       y r)   )signalsr   )r   r   rQ   s     r4   
fakeSignalz,UnixAppLoggerTests.setUp.<locals>.fakeSignalu  s    LLa)r6   signalN)r  rD   r  )rQ   r  s   ` r4   r  zUnixAppLoggerTests.setUpn  s#    
 	* 	

68Z0r6   c                    t        | j                        }t        ddd      } |j                          | j	                  t        |      d       | j                  |d   t        j                         t        ddd      } |j                          | j	                  t        |      d       | j                  |d   t        j                         y)	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  rB  r   r   r  r  N)	rj  rD   r"   r  rz   r  r   r0  r   )rQ   rf  r   s      r4   r  z,UnixAppLoggerTests.test_getLogObserverStdoutz  s     -TZZ83DAB X*hqk3::.24@A X*hqk3::.r6   c                     t        ddd      }| j                  t        |j                        }| j	                  t        |      d       y)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  rz   r   )rQ   r   rX  s      r4   test_getLogObserverStdoutDaemonz2UnixAppLoggerTests.test_getLogObserverStdoutDaemon  s@    
 3EBC!!*f.D.DEU%MNr6   c                    t        | j                        }| j                         }t        d|i      }|j	                         }| j                  |j                  j                         | j                  t        |      d       | j                  |d   j                  t        j                  j                  |             | j                  t        | j                        d       | j                  | j                  d   d   t        j                         t!               f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                  (     j                  d        y r)   )callback)ds   r4   rotatez:UnixAppLoggerTests.test_getLogObserverFile.<locals>.rotate  s    JJtr6   N)rj  rD   r   r"   r  r  r  r  rz   r  r   r:   r  r  r  SIGUSR1r   r  )rQ   rf  r  r  rh  r  	rotateLogr  s          @r4   r  z*UnixAppLoggerTests.test_getLogObserverFile  s    -TZZ8;;=Y12&&())//0X*!))277??8+DET\\*A.a+V^^<J	 $LLOA&	$r6   c                      fd} j                  t        d|        j                         }t        d|i      }|j	                         } j                  |j                  j                          j                   j                  g        y)zy
        If a signal handler is already installed,
        L{UnixAppLogger._getLogObserver} doesn't override it.
        c                 X    j                  | t        j                         t               S r)   )rz   r  r  r1  )r   rQ   s    r4   fakeGetSignalzVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler.<locals>.fakeGetSignal  s    S&..18Or6   	getsignalr  N)
rD   r  r   r"   r  r  r  r  rz   r  )rQ   r  r  r  rh  s   `    r4   ,test_getLogObserverDontOverrideSignalHandlerz?UnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler  sn    	 	

6;6;;=Y12&&())//0r*r6   c                 d   t        | j                        }t        ddd      } |j                         }| j	                  |j
                  j                         | j                  t        |      d       | j                  |d   j                  t        j                  j                  d             y)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)rj  rD   r"   r  r  r  r  rz   r  r   r:   r  )rQ   rf  r   rh  s       r4   test_getLogObserverDefaultFilez1UnixAppLoggerTests.test_getLogObserverDefaultFile  s     -TZZ825AB)6))+))//0X*!))277??<+HIr6   r   c                     t        |       }t        ddd      } |j                         }| j                  |dg        |ddi       | j                  |dddig       y)z
        If C{syslog} is set to C{True}, L{UnixAppLogger._getLogObserver} starts
        a L{syslog.SyslogObserver} with given C{prefix}.
        Tztest-prefix)rv  ro  r  bN)rx  r"   r  rz   )rQ   r  r   rh  s       r4   test_getLogObserverSyslogz,UnixAppLoggerTests.test_getLogObserverSyslog  sd     D!$-HI)6))+/#sSz:;r6   N)rS   rT   rU   rV   r  r  r  r  r  r  r   r   r  rX   r6   r4   r  r  e  sF    
1/$O<+&J 9:
< ;
<r6   r  z!twistd unix support not availablec                   p    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zy)DaemonizeTestszH
    Tests for L{_twistd_unix.UnixApplicationRunner} daemonization.
    c                    t               | _        t        j                         | _        | j                  t        d| j                         t        j                  | j                        | _        t        j                  d      | j                  _        t        j                  | j                  _        t        j                  | j                  _        d | j                  _        y )Nr:   r  c                       y r)   rX   )r   s    r4   r   z&DaemonizeTests.setUp.<locals>.<lambda>  r   r6   )r   mockosr   r}   r   rD   r   r!   r  r   r  r]   r0  r   rJ  stderrrK  rL  rc   s    r4   r  zDaemonizeTests.setUp  s    h**,

<t{{3"88E")"5"5e"< #

 #

#5 r6   c                 (   t        t                     5  | j                  j                          ddd       | j	                  | j
                  j                  g d       | j	                  | j
                  j                  ddg       y# 1 sw Y   ZxY w)zw
        When double fork succeeded in C{daemonize}, the child process writes
        B{0} to the status pipe.
        N)r  r  r   r  forkTsetsidr  )r      0unlinkz
twistd.pidr  )r   r  r  rf   rz   r  actionsclosedrc   s    r4   test_successzDaemonizeTests.test_success  su    
 467 	*KK'')	*KK	
 	++b"X6	* 	*s   BBc                    d| j                   _        d| j                   _        t        t	                     5  | j                  t        | j                  j                         ddd       | j                  | j                   j                  g d       | j                  | j                   j                  dg       y# 1 sw Y   YxY w)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  r  d   exitr   r  r  )r  childreadDatar   r  r   SystemErrorr  rf   rz   r  r  rc   s    r4   test_successInParentz#DaemonizeTests.test_successInParent  s    
 "#467 	Hk4;;+F+FG	HKK
	
 	++bT2	H 	Hs   +B99Cc                    g fd}|| j                   _        t        t                     5  | j                  j                          ddd       | j                  | j                   j                  g d       | j                  | j                   j                  ddg       | j                  ddg       y# 1 sw Y   nxY w)z
        If the C{os.write} call to the status pipe raises an B{EINTR} error,
        the process child retries to write.
        c                 z    j                  | |f       t              dk(  rt        t        j                        y r  r   r  r   r   EINTR)fdr,  writtens     r4   raisingWritez6DaemonizeTests.test_successEINTR.<locals>.raisingWrite$  s3    NNB:&7|q ekk** !r6   N)r  r  r  r  r  r  r  r  )r  r  )	r  r   r   r  r  rf   rz   r  r  )rQ   r  r  s     @r4   test_successEINTRz DaemonizeTests.test_successEINTR  s    
 	+
 )467 	*KK'')	*KK
	
 	++b"X6*j17;	* 	*s   B55B>c                    g fd}|| j                   _        d| j                   _        t        t	                     5  | j                  t        | j                  j                         ddd       | j                  | j                   j                  g d       | j                  | j                   j                  dg       | j                  ddg       y# 1 sw Y   mxY w)z
        If the C{os.read} call on the status pipe raises an B{EINTR} error, the
        parent child retries to read.
        c                 z    j                  | |f       t              dk(  rt        t        j                        y)Nr   r  r  )r  sizer  s     r4   raisingReadz=DaemonizeTests.test_successInParentEINTR.<locals>.raisingReadA  s0    KKT
#4yA~ekk**r6   FN)r  r  r  r  r  r  )r  r  )r  r  r  r   r  r   r  r  rf   rz   r  r  )rQ   r  r  s     @r4   test_successInParentEINTRz(DaemonizeTests.test_successInParentEINTR:  s    
 	 '!467 	Hk4;;+F+FG	HKK		
 	++bT2)Y/6	H 	Hs   +CCc                     G fddt         j                        } |       }|j                  | j                  j                         t        t                     5  | j                  t        | j                  j                         ddd       | j                  | j                  j                  ddddddd	|fd
g       | j                  | j                  j                  dd	g       y# 1 sw Y   bxY w)z
        Assert L{UnixApplicationRunner.postApplication} writes
        C{reported} to its status pipe if the service raises an
        exception whose message is C{raised}.
        c                       e Zd Z fdZy)6DaemonizeTests.assertErrorWritten.<locals>.FakeServicec                     t              r)   rK  )rQ   raiseds    r4   r_  zCDaemonizeTests.assertErrorWritten.<locals>.FakeService.startService`  s    "6**r6   N)rS   rT   rU   r_  )r  s   r4   rd  r  _  s    +r6   rd  Nr  r  r  r  r   r  r  r  )r   rO   rX  r  r]   r   r  r   r%  rf   rz   r  r  r  )rQ   r  reportedrd  errorServices    `   r4   assertErrorWrittenz!DaemonizeTests.assertErrorWrittenX  s    	+'// 	+ #}%%dkk&=&=>467 	IlDKK,G,GH	IKK "h'(	
 	++b"X6	I 	Is   +C((C1c                 *    | j                  dd       y)z
        If an error happens during daemonization, the child process writes the
        exception error to the status pipe.
        zSomething is wrongs"   1 RuntimeError: Something is wrongr  r  Nr  rc   s    r4   
test_errorzDaemonizeTests.test_errorv  s    
 	'2W 	  	
r6   c                 *    | j                  dd       y)z
        If an error happens during daemonization, and that error's
        message is Unicode, the child encodes the message as ascii
        with backslash Unicode code points.
        u   •s   1 RuntimeError: \u2022r  Nr   rc   s    r4   test_unicodeErrorz DaemonizeTests.test_unicodeError  s     	x:TUr6   c                    d| j                   _        || j                   _        t               }| j	                  t
        d|       t        t                     5  | j                  t        | j                  j                         ddd       | j                  |j                         |       | j                  | j                   j                  |       | j                  | j                   j                  dg       y# 1 sw Y   wxY w)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   rD   r0  r   r  r   r  r  rf   rz   r   r  r  )rQ   r  errorMessagemockOSActionserrorIOs        r4   assertErrorInParentBehaviorz*DaemonizeTests.assertErrorInParentBehavior  s     "'*

3g.467 	Hk4;;+F+FG	H))+\:,,m<++bT2		H 	Hs   +C88Dc                 0    | j                  ddg d       y)z
        When the child writes an error message to the status pipe
        during daemonization, the parent writes the repr of the
        message to C{stderr} and exits with non-zero status code.
        s    1 Exception: An identified errorzgAn error has occurred: b'Exception: An identified error'
Please look at log file for more information.
r  r  r  r   )r  r   r  r  r&  r'  Nr)  rc   s    r4   test_errorInParentz!DaemonizeTests.test_errorInParent  s%     	((8B 	) 	
r6   c                 0    | j                  ddg d       y)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-  rc   s    r4   test_nonASCIIErrorInParentz)DaemonizeTests.test_nonASCIIErrorInParent  s%     	(()B 	) 	
r6   c                 t    d}dj                  d      }| j                  |dj                  |      g d       y)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)  )rQ   truncatedMessagereportedMessages      r4   &test_errorInParentWithTruncatedUnicodez5DaemonizeTests.test_errorInParentWithTruncatedUnicode  sL     A 066G((%BBH&#C 	) 	
r6   c                 *    | j                  dd       y)z{
        If an error occurs during daemonization and its message is too
        long, it's truncated by the child.
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsd   1 RuntimeError: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxr  Nr   rc   s    r4   test_errorMessageTruncatedz)DaemonizeTests.test_errorMessageTruncated  s    
 	'F 	  	
r6   c                 *    | j                  dd       y)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   ••••••••••••••••••••••••••••••r2  r  Nr   rc   s    r4   !test_unicodeErrorMessageTruncatedz0DaemonizeTests.test_unicodeErrorMessageTruncated  s     	 : 	  	
r6   c                     t               }| j                  j                  |       | j                  |j                         | j                  |j
                         y)z
        C{daemonize} indeed calls L{IReactorDaemonize.beforeDaemonize} and
        L{IReactorDaemonize.afterDaemonize} if the reactor implements
        L{IReactorDaemonize}.
        N)r  r  r  r   r  r  r  s     r4   test_hooksCalledzDaemonizeTests.test_hooksCalled  sB     )*g&667556r6   c                     t               }| j                  j                  |       | j                  |j                         | j                  |j
                         y)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  s     r4   test_hooksNotCalledz"DaemonizeTests.test_hooksNotCalled   sF     ,-g&778667r6   N)rS   rT   rU   rV   r  r  r  r  r  r  r!  r#  r)  r.  r0  r5  r8  r:  r<  r>  rX   r6   r4   r  r    sX    67*3,<:7<7<
V3"
,
,
:
	
	7	8r6   r  c                   D    e Zd ZdZed        Zej                  d        Zy)SignalCapturingMemoryReactorz
    MemoryReactor that implements the _ISupportsExitSignalCapturing interface,
    all other operations identical to MemoryReactor.
    c                     | j                   S r)   _valrc   s    r4   r  z(SignalCapturingMemoryReactor._exitSignal  s    yyr6   c                     || _         y r)   rB  )rQ   vals     r4   r  z(SignalCapturingMemoryReactor._exitSignal  s	    	r6   N)rS   rT   rU   rV   propertyr  setterrX   r6   r4   r@  r@    s5    
    r6   r@  c                   2     e Zd ZdZeZ fdZd Zd Z x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                 2    t         |   |       d | _        y r)   )superrr   _signalValue)rQ   r   	__class__s     r4   rr   z(StubApplicationRunnerWithSignal.__init__'  s      r6   c                      y)z
        Does nothing.
        NrX   rc   s    r4   rd   z.StubApplicationRunnerWithSignal.preApplication+  r   r6   c                     t               }| j                  |_        | j                  |t        j
                  t        j                         y)z`
        Instantiate a SignalCapturingMemoryReactor and start it
        in the runner.
        N)r@  rL  r  rL  r0  r   r  r  s     r4   rf   z/StubApplicationRunnerWithSignal.postApplication0  s4    
 /0"//'3::szz:r6   )
rS   rT   rU   rV   rZ   rg   rr   rd   rf   __classcell__)rM  s   @r4   rI  rI    s     &M!
;r6   rI  c                       f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                 ,    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
        )rI  rL  )r   r  signums     r4   stubApplicationRunnerFactoryzIstubApplicationRunnerFactoryCreator.<locals>.stubApplicationRunnerFactoryG  s     18$r6   rX   )rS  rT  s   ` r4   #stubApplicationRunnerFactoryCreatorrU  :  s      ('r6   c                   (    e Zd ZdZd Zd Zd Zd Zy)ExitWithSignalTestsz?
    Tests for L{twisted.application.app._exitWithSignal}.
    c                     t        j                          _        dt               i j                  _        t                j                  _        d j                  _        ddg _         fd} j                  t        d|       y)zM
        Set up the server options and a fake for use by test cases.
        r.  Nc                 B    | j                   d<   |j                   d<   y)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)fakeKillArgs)r   r   rQ   s     r4   fakeKillz+ExitWithSignalTests.setUp.<locals>.fakeKillj  s%     $'Da #&Da r6   r   )r   r}   r   rK   r0  r1  r2  r   rZ  rD   r:   )rQ   r[  s   ` r4   r  zExitWithSignalTests.setUp`  sg     **,%35E5G$H!!'!/!4L		' 	

2vx(r6   c                    ddgfd}| j                  t        d|       t        j                  t        j                         | j                  d   t        j                         | j                  d   t        j                         | j                  | j                  d   t        j                                | j                  | j                  d   t        j                         y)z
        exitWithSignal replaces the existing signal handler with the default
        handler and sends the replaced signal to the current process.
        Nc                     | d<   |d<   y )Nr   r   rX   )r   handlerfakeSignalArgss     r4   fake_signalz<ExitWithSignalTests.test_exitWithSignal.<locals>.fake_signal  s     #N1 'N1r6   r  r   r   )
rD   r  r
   _exitWithSignalSIGINTr  SIG_DFLrZ  r:   r   )rQ   r`  r_  s     @r4   test_exitWithSignalz'ExitWithSignalTests.test_exitWithSignalw  s     	( 	

68[1FMM*.+V]];.+V^^<$++A.		<$++A.>r6   c                     | j                  t        dt        d             t        j                  | j                         | j                  | j                  d          | j                  | j                  d          y)zb
        _exitWithSignal is not called if the runner does not exit with a
        signal.
        re  Nr   r   )rD   r   rU  runAppr   r   rZ  rc   s    r4   test_normalExitz#ExitWithSignalTests.test_normalExit  sc    
 	

,.QRV.W	
 	dkk"$++A./$++A./r6   c                 Z   | j                  t        dt        t        j                               t        j
                  | j                         | j                  | j                  d   t        j                                | j                  | j                  d   t        j                         y)zP
        _exitWithSignal is called when the runner exits with a signal.
        re  r   r   N)rD   r   rU  r  rb  rf  r   r  rZ  r:   r   rc   s    r4   test_runnerExitsWithSignalz.ExitWithSignalTests.test_runnerExitsWithSignal  st     	

$/>	

 	dkk"$++A.		<$++A.>r6   N)rS   rT   rU   rV   r  rd  rg  ri  rX   r6   r4   rW  rW  Z  s    ).?(
0?r6   rW  )hrV   r   r  r:   r  r  r0  r<   _grpr9   _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.internet.testingr   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.test_processr   twisted.trial.unittestr    r   twisted.scripts._twistd_unixr!   r"   r#   rv  r$   r%   r&   rI   rK   r  rZ   re  ra   ri   r   r	  r  r$  r"  r,  r  r  r	  r  r  rw  r'  rj  rx  rz  r  r  r@  rI  rU  rW  rX   r6   r4   <module>r     s  
   	   

 C
C   & . , , 6 6 5 - + X @ 2 N N  3 / T 0 / + " , +;<  
.	/
	
"	x	 $*.Z "  = =  UJ UJp L56CKH CK 7CKLD8 D0 *JC11 J(p4X p4f L56F+ F+ 7F+R L56O? O? 7O?d L56>( > 7>< 8 6    (w8 w8t*$`5X `5F	 L56y< y< 7y<x L=>f8X f8 ?f8R	 *+=  ,;f&C&C ;<(@H?( H?OB  
C
Cs   I= =	J
	J
