Ϫf$!dZddlZddlZddlZddlZddlZddlZ ddlZddl Z e Z eZddl m Z ddlmZddlmZddlmZddlmZmZmZddlmZmZmZdd lmZdd lmZdd l m!Z!dd l"m#Z#m$Z$dd l%m&Z&ddl'm(Z(ddl)m*Z*m+Z+m,Z,ddl-m.Z.ddl/m0Z0ddl1m2Z2ddl3m*Z4m5Z5ddl6m7Z7ddl8m9Z9ddl:m;Z;ddlm?Z?ddl@mAZAe7dZBeBr ddlCmDZDmEZEmFZFe7dZGe7dZHe7dZIe7dZJd ZKGd!d"ZLGd#d$ejZNGd%d&e=jZPGd'd(eAZQeeB d)Gd*d+eAZRGd,d-eAZSGd.d/ZTGd0d1ejZVGd2d3eAZWeeB d)Gd4d5eAZXeeB d)Gd6d7eAZYeeB d)Gd8d9eAZZGd:d;Z[ee#Gd<d=e[Z\Gd>d?Z]Gd@dAeAZ^dBZ_dCZ`GdDdEeAZaeeB d)GdFdGeAZbeeB dHGdIdJeAZcee$GdKdLe(ZdGdMdNe=jZedOZfGdPdQeAZgy#e $rdZ dZYawxYw)RzE Tests for L{twisted.application.app} and L{twisted.scripts.twistd}. N)StringIO)skipIf) implementer) verifyObject)internetloggerplugin)appreactorsservice) IServiceMaker) ReactorBase)Deferred)IReactorDaemonize_ISupportsExitSignalCapturing)AlternateReactor) MemoryReactor) ILogObserverglobalLogBeginnerglobalLogPublisher)util) Componentized) UserDatabase)rtextFromEventDict) requireModule) platformType) UsageError)twistd)MockOS)TestCaseztwisted.scripts._twistd_unix)UnixApplicationRunner UnixAppLoggercheckPIDztwisted.python.syslogprofilepstatscProfilec tjtj}tj tj t}|j||j||j|j|jfd}|td|j|td||td|jy)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. ct}||jj<||jj<t |}|i|SN)listindexgr_namegr_gidtuple)nameresultgidgrentgroups :/usr/lib/python3/dist-packages/twisted/test/test_twistd.pygetgrnamz#patchUserDatabase..getgrnamdsRe.3v||EMM*+-0v||ELL)*vvt$$getpwnamr5getpwuidN)pwdr8osgetuidgrpgetgrgidgetgidraddUser pw_passwdpw_gecospw_dirpw_shellr7) patchuseruidr3r1pwentdatabaser5r2s `` @r4patchUserDatabaserICs2 LL %E LL %E~H  eoosCu~~% #z8,,- #z8$ #z8,,-r6ceZdZdZdZdZy)MockServiceMakerzO A non-implementation of L{twisted.application.service.IServiceMaker}. ueoacZ||_tj|_|jS)ze Take a L{usage.Options} instance and return a L{service.IService} provider. )optionsr ServiceselfrNs r4 makeServicezMockServiceMaker.makeServicews#  ( ||r6N)__name__ __module__ __qualname____doc__tapnamerRr6r4rKrKpsGr6rKceZdZdZdZy)CrippledAppLoggerz* @see: CrippledApplicationRunner. cyr)rXrQ applications r4startzCrippledAppLogger.start r6N)rSrTrUrVr^rXr6r4rZrZs  r6rZc eZdZdZeZdZdZy)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. cyr)rXrQs r4preApplicationz(CrippledApplicationRunner.preApplicationr_r6cyr)rXrcs r4postApplicationz)CrippledApplicationRunner.postApplicationr_r6N)rSrTrUrVrZ loggerFactoryrdrfrXr6r4raras &M  r6raceZdZdZdZdZdZdZdZe e ddZ e e dd Z e e dd Z d Zd Zd ZdZy)ServerOptionsTestszT Non-platform-specific tests for the platform-specific ServerOptions class. c. Gdd}|d |d |d|d fd}tj}j|jtj ||_|j } g}t||D]w\}}|\}} } } j||jj| j| |jfj| |jyy) zh subCommands is built from IServiceMaker plugins, and is sorted alphabetically. ceZdZdZdZy)7ServerOptionsTests.test_subCommands..FakePluginc:||_d|z|_d|z|_y)Nz options for description of )rW_options descriptionrQr/s r4__init__z@ServerOptionsTests.test_subCommands..FakePlugin.__init__s"# . 5 #4t#; r6c|jSr))rorcs r4rNz?ServerOptionsTests.test_subCommands..FakePlugin.optionss }}$r6N)rSrTrUrrrNrXr6r4 FakePluginrls  <  %r6rtapplebananacoconutdonutc3ZKj|tywr)) assertEqualr ) interfacerurvrwrxrQs r4 getPluginsz7ServerOptionsTests.test_subCommands..getPluginss+   Y 6MLKKs(+N) r ServerOptionsrz _getPluginsr r| subCommandsziprW assertIsNonerorp)rQrtr|configr expectedOrder subCommandexpectedCommandr/shortcut parserClass documentationrurvrwrxs` @@@@r4test_subCommandsz#ServerOptionsTests.test_subCommandss  % %7#H%Y'7#  %%' ++V->->?'(( 7 +.{M+J I 'J9C 6D(K   T?#:#: ;   h '   []O,D,D E F   ]O,G,G H  Ir6c\ Gdd}|d|d|d|d  fd}tj}j|jtj ||_t |_jt|jdg|jj g  fD]-} fd }||j||j/j t d j y ) zP Reactor names are listed alphabetically by I{--help-reactors}. ceZdZdZy)GServerOptionsTests.test_sortedReactorHelp..FakeReactorInstallerc:d|z|_d|z|_d|_y)Nzname of rnztwisted.internet.default) shortNamerp moduleNamerqs r4rrzPServerOptionsTests.test_sortedReactorHelp..FakeReactorInstaller.__init__s"!+d!2#4t#; "<r6N)rSrTrUrrrXr6r4FakeReactorInstallerrs =r6rrurvrwrxc3.Kywr)rX)rurvrwrxsr4getReactorTypeszBServerOptionsTests.test_sortedReactorHelp..getReactorTypessMLKKsz--help-reactorscjj|jj|yr))assertInappendr+)s helpOutputindexesrQs r4getIndexz;ServerOptionsTests.test_sortedReactorHelp..getIndexs( a,z//23r6z9reactor descriptions were not in alphabetical order: {!r}N)rr}rz_getReactorTypesr rr messageOutput assertRaises SystemExit parseOptionsgetvaluerrpsortedformat) rQrrrreactorrrurvrwrxrrs ` @@@@@@r4test_sortedReactorHelpz)ServerOptionsTests.test_sortedReactorHelps  = = %W-%h/&y1$W-  %%' 00(2J2JK"1'z *f&9&9z.CheckPIDTests.test_notExists..|r6znon-existent PID fileN)rDr:pathr#rcs r4test_notExistszCheckPIDTests.test_notExistsxs! 277Ho6()r6c|j}t|d5}|jdddd|jtt |}|j d|jy#1swYAxYw)zI Non-numeric content in a PID file causes a system exit. wz non-numericNznon-numeric value)mktempopenwriterrr#rr)rQpidfilefrs r4test_nonNumericzCheckPIDTests.test_nonNumericsc++- '3  #1 GGM " #   j(G < )1662 # #s A//A8c*|j}t|d5}|jddddd}|jtd||j t t|}|jd|jy#1swY[xYw)zE Another running twistd server causes a system exit. r42Ncyr)rXpidsigs r4killz/CheckPIDTests.test_anotherRunning..kills r6rzAnother twistd server) rrrrDr:rrr#rrrQrrrrs r4test_anotherRunningz!CheckPIDTests.test_anotherRunningsy++- '3  1 GGDM   2vt$   j(G < -qvv6  s B  Bcj|j}t|d5}|jtt j dzdddd}|j td|t||jtjj|y#1swY]xYw)zJ Stale PID file is removed without causing a system exit. rNc6ttjdNfake)OSErrorerrnoESRCHrs r4rz&CheckPIDTests.test_stale..kill%++v. .r6r) rrrrr:getpidrDr#rrr)rQrrrs r4 test_stalezCheckPIDTests.test_stales++- '3  *1 GGC a( ) * / 2vt$ 01 * *s 0B))B2c|j}t|d5}|jddddd}|jtd||j t t|}|j|jd|j|jdjdy#1swYxYw)z An unexpected L{OSError} when checking the validity of a PID in a C{pidfile} terminates the process via L{SystemExit}. r3581Nc6ttjdrrrEBADFrs r4rz2CheckPIDTests.test_unexpectedOSError..killrr6rrzCan't check status of PID) rrrrDr:rrr# assertIsNotrrrrrs r4test_unexpectedOSErrorz$CheckPIDTests.test_unexpectedOSErrors ++- '3  1 GGFO  / 2vt$   j(G < & q ,,-HIJ  s B66B?N) rSrTrUrVrrrrrrXr6r4rrrs!*3 7 2Kr6rceZdZdZdZdZy) TapFileTestszM Test twistd-related functionality that requires a tap file on disk. c|j|_t|jd5}tjt j d|dddy#1swYyxYw)zP Create a trivial Application and put it in a tap file on disk. wbHi!N)rtapfilerpickledumpr Application)rQrs r4setUpzTapFileTests.setUpsO{{} $,, % 7 KK++E2A 6 7 7 7s *AA(ctj}|jd|jgt |j }|j tj|jdy)z Ensure that the createOrGetApplication call that 'twistd -f foo.tap' makes will load the Application out of foo.tap. z-fr N) rr}rr racreateOrGetApplicationrzr IServicer/)rQrr]s r4&test_createOrGetApplicationWithTapFilez3TapFileTests.test_createOrGetApplicationWithTapFiles] %%'T4<<01/7NNP  ))+6;;UCr6N)rSrTrUrVrrrXr6r4r r s7Dr6r c"eZdZdZdZdZdZy)TestLoggerFactoryz8 A logger factory for L{TestApplicationRunner}. c||_yr))runner)rQrs r4rrzTestLoggerFactory.__init__s  r6c|jjjdt|jd|j_y)zC Save the logging start on the C{runner} instance. logr]N)rorderrhasattrhadApplicationLogObserverr\s r4r^zTestLoggerFactory.starts3   '07 ]0S -r6cy)z% Don't log anything. NrXrcs r4stopzTestLoggerFactory.stoprr6N)rSrTrUrVrrr^r rXr6r4rrsT r6rc"eZdZdZdZdZdZy)TestApplicationRunnerz` An ApplicationRunner which tracks the environment in which its methods are called. crtjj||g|_t ||_yr))r ApplicationRunnerrrrrrrPs r4rrzTestApplicationRunner.__init__s+ &&tW5 '- r6c\|jjdt|d|_y)Nprer])rrrhadApplicationPreApplicationrcs r4rdz$TestApplicationRunner.preApplications# % ,3D-,H)r6c\|jjdt|d|_y)Npostr])rrrhadApplicationPostApplicationrcs r4rfz%TestApplicationRunner.postApplications# &!-4T=-I*r6N)rSrTrUrVrrrdrfrXr6r4r"r"s . IJr6r"ceZdZdZdZdZdZdZee e dd dd Z ee e dd dd Z d Z d Zd ZdZy)ApplicationRunnerTestszR Non-platform-specific tests for the platform-specific ApplicationRunner. ctj}t|_d|ji|_t |_d|_||_y)N test_command) rr}rK serviceMaker loadedPluginsobject subOptionsrrrs r4rzApplicationRunnerTests.setUpsG%%',. .0A0AB"H* r6cft|j}|j|j|jj |jj d|j|jjtj|jjddy)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.rzPServiceMaker.makeService's result needs to be set as a child of the Application.N) rarrunrr/rNr2r rr]services)rQarunners r4,test_applicationRunnerGetsCorrectApplicationzCApplicationRunnerTests.test_applicationRunnerGetsCorrectApplications ,DKK8     % % KK " " "    % %   W00 1 : :1 = " r6c,t|j}|j|j|j|j |j |j |j|j|jgdy)z Test thet preApplication and postApplication methods are called by ApplicationRunner.run() when appropriate. )r&rr)N) r"rr4rr'rr*rrzr)rQrs r4test_preAndPostApplicationz1ApplicationRunnerTests.test_preAndPostApplicationsh "$++ .  778 778 334 "89r6c |jj|gGfddtj}t t j t jGfdd}|}tt j |tt j|||j}|j||_ |j|jdddd||fd d gy ) 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. c2eZdZfdZfdZfdZdZy)\ApplicationRunnerTests._applicationStartsWithConfiguredID..FakeUnixApplicationRunnerc(jdy)N environmentr)rQchrootrundirnodaemonrreventss r4setupEnvironmentzmApplicationRunnerTests._applicationStartsWithConfiguredID..FakeUnixApplicationRunner.setupEnvironment8s m,r6c0jd|||fy)N privilegesr?)rQeuidrFr1rCs r4shedPrivilegeszkApplicationRunnerTests._applicationStartsWithConfiguredID..FakeUnixApplicationRunner.shedPrivileges;s |T3<=r6c(jdy)Nrr?)rQr oldstdout oldstderrrCs r4 startReactorziApplicationRunnerTests._applicationStartsWithConfiguredID..FakeUnixApplicationRunner.startReactor>s i(r6cyr)rX)rQrs r4 removePIDzfApplicationRunnerTests._applicationStartsWithConfiguredID..FakeUnixApplicationRunner.removePIDAr6N)rSrTrUrDrHrLrNrCsr4FakeUnixApplicationRunnerr<7s - > ) r6rQcReZdZdZdZdZdZdZdZdZ dZ dZ fdZ fdZ dZy)NApplicationRunnerTests._applicationStartsWithConfiguredID..FakeServiceNcyr)rXrqs r4setNamezVApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.setNameMrOr6cyr)rX)rQparents r4setServiceParentz_ApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.setServiceParentPrOr6cyr)rXrcs r4disownServiceParentzbApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.disownServiceParentSrOr6c(jdy)NprivilegedStartServicer?rQrCs r4r\zeApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.privilegedStartServiceVs 67r6c(jdy)N startServicer?r]s r4r_z[ApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.startServiceYs n-r6cyr)rXrcs r4 stopServicezZApplicationRunnerTests._applicationStartsWithConfiguredID..FakeService.stopService\rOr6)rSrTrUrWrunningr/ processNamerFr1rUrXrZr\r_rarPsr4 FakeServicerSDs?FGDKCC    8 . r6rdr>r\rFFr_rN) rrr_SomeApplicationRunnerrr rIProcessrrdr]rfrz) rQargvrFr1rQrdr]rrCs @r4"_applicationStartsWithConfiguredIDz9ApplicationRunnerTests._applicationStartsWithConfiguredID*s   & (E(E  W%%w'7'7 8   9 4"m W%%{3W%%{3*4;;7(   (uc3/   r6setuidNz5Platform does not support --uid/--gid twistd options.c^d}d}|jdt|dt|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)rhr)rQrFr1s r4.test_applicationStartsWithConfiguredNumericIDszEApplicationRunnerTests.test_applicationStartsWithConfiguredNumericIDsss4 // c#hS 2C r6ctd}d}d}d}t|j|||||jd|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}. foorkbarrlrmrnN)rIrDrh)rQrErFr3r1s r4+test_applicationStartsWithConfiguredNameIDszBApplicationRunnerTests.test_applicationStartsWithConfiguredNameIDssJ$**dC< // dGU +S# r6ct}tjdddd}|j|dd|j |j dy)z7 L{startReactor} calls L{reactor.run}. Fr$r$rdebugNz'startReactor did not call reactor.run()) DummyReactorr r$rLrcalledrQrrs r4test_startReactorRunsTheReactorz6ApplicationRunnerTests.test_startReactorRunsTheReactorsL.&&9u E  GT40 (QRr6ct}|jtd|tjdddd}|j ddd|j |jy)zN L{ApplicationRunner} chooses a reactor if none is specified. rFr$ruN)rwrDrr r$rLrrxrys r4*test_applicationRunnerChoosesReactorIfNonezAApplicationRunnerTests.test_applicationRunnerChoosesReactorIfNonesY. 8Y0&&9u E  D$- 'r6cGddt}|}tjdddd}|j|dd|j d|j y)zg If the reactor exits with a signal, the application runner caches the signal. ceZdZdZdZdZy)[ApplicationRunnerTests.test_applicationRunnerCapturesSignal..DummyReactorWithSignal A dummy reactor, providing a C{run} method, and setting the _exitSignal attribute to a nonzero value. cyz= Dummy method, does nothing. NrXrcs r4 installWakerzhApplicationRunnerTests.test_applicationRunnerCapturesSignal..DummyReactorWithSignal.installWakerrr6cd|_y)zZ A fake run method setting _exitSignal to a nonzero value N _exitSignalrcs r4r4z_ApplicationRunnerTests.test_applicationRunnerCapturesSignal..DummyReactorWithSignal.runs $% r6NrSrTrUrVrr4rXr6r4DummyReactorWithSignalrs     %r6rFr$ruNr)rr r$rL assertEqualsr)rQrrrs r4$test_applicationRunnerCapturesSignalz;ApplicationRunnerTests.test_applicationRunnerCapturesSignals\  %[ %")*&&9u E  GT40 !V//0r6cGdd}|}tjdddd}|j|dd|jd|jy)z The runner sets its _exitSignal instance attribute to None if the reactor does not implement L{_ISupportsExitSignalCapturing}. ceZdZdZdZdZy)iApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal..DummyReactorWithExitSignalAttributercyrrXrcs r4rzvApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal..DummyReactorWithExitSignalAttribute.installWakerrr6cd|_y)z A fake run method setting _exitSignal to a nonzero value that should be ignored. rNrrcs r4r4zmApplicationRunnerTests.test_applicationRunnerIgnoresNoSignal..DummyReactorWithExitSignalAttribute.runs $% r6NrrXr6r4#DummyReactorWithExitSignalAttributers     %r6rFr$ruN)r r$rLrr)rQrrrs r4%test_applicationRunnerIgnoresNoSignalz. sgdFD.Ir6chdirctd|S)Ncwdrrs r4rzBUnixApplicationRunnerSetupEnvironmentTests.setUp.. sWT5$-Gr6rctd|S)Nmaskr)rrQs r4rzBUnixApplicationRunnerSetupEnvironmentTests.setUp.. sWT64-Hr6)unsetrrrdaemonr:rrrDr!rr}r daemonizercs`r4rz0UnixApplicationRunnerSetupEnvironmentTests.setUpsJJ ::JJ  99; 2x!IJ 2w GH 2w HI+F,@,@,BC $ r6cHd_jtdfdy)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. Trc"jdzSNr)rrcsr4rzFUnixApplicationRunnerSetupEnvironmentTests.daemonize..sAr6N)rrDr:rQrs` r4rz4UnixApplicationRunnerSetupEnvironmentTests.daemonizes   2x!56r6cz|jjddddd|j|jdy)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)rrDrzrrcs r4 test_chrootz6UnixApplicationRunnerSetupEnvironmentTests.test_chroots2 $$ZdD$G J/r6c|jjddddd|j|j|jy)z L{UnixApplicationRunner.setupEnvironment} does not change the root of the filesystem if passed L{None} for the C{chroot} parameter. NrT)rrDrrrrcs r4 test_noChrootz8UnixApplicationRunnerSetupEnvironmentTests.test_noChroot!s4 $$T3dDA dii,r6cz|jjddddd|j|jdy)z L{UnixApplicationRunner.setupEnvironment} changes the working directory of the process to the path given for the C{rundir} parameter. NrT)rrDrzrrcs r4test_changeWorkingDirectoryzFUnixApplicationRunnerSetupEnvironmentTests.test_changeWorkingDirectory)s2 $$T:tT4H :.r6ctt5|jjdddddddd|j |j y#1swY%xYw)z L{UnixApplicationRunner.setupEnvironment} daemonizes the process if C{False} is passed for the C{nodaemon} parameter. NrF)rFakeDaemonizingReactorrrDrrrcs r4test_daemonizez9UnixApplicationRunnerSetupEnvironmentTests.test_daemonize1sS 46 7 G KK ( (sE4 F G  $ G Gs AA!cx|jjddddd|j|jy)z L{UnixApplicationRunner.setupEnvironment} does not daemonize the process if C{True} is passed for the C{nodaemon} parameter. NrT)rrDrrrcs r4test_noDaemonizez;UnixApplicationRunnerSetupEnvironmentTests.test_noDaemonize:s0 $$T3dDA %r6c|j}|jjdddd|t|d5}t |j }ddd|j |jy#1swY&xYw)z L{UnixApplicationRunner.setupEnvironment} writes the process's PID to the file specified by the C{pidfile} parameter. NrTrb)rrrDrintreadrzrrQrrrs r4test_nonDaemonPIDFilez@UnixApplicationRunnerSetupEnvironmentTests.test_nonDaemonPIDFileBsm ++- $$T3dGD '4  Aaffh-C  dhh'  s A;;Bcd|j}tt5|jj dddd|dddt |d5}t |j}ddd|j|jdzy#1swYWxYw#1swY5xYw)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}. NrFrr) rrrrrDrrrrzrrs r4test_daemonPIDFilez=UnixApplicationRunnerSetupEnvironmentTests.test_daemonPIDFileMs ++- 46 7 J KK ( (sE4 I J '4  Aaffh-C  dhhl+  J J  s BB&B#&B/ctt5|jjdddddddd|j |j dy#1swY&xYw)z L{UnixApplicationRunner.setupEnvironment} changes the process umask to the value specified by the C{umask} parameter. NrF{rrrrDrzrrcs r4rz5UnixApplicationRunnerSetupEnvironmentTests.test_umaskZsW 46 7 F KK ( (sE3 E F C( F F AA"c|jjddddd|j|j|jy)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. NrT)rrDrrrrcs r4test_noDaemonizeNoUmaskzBUnixApplicationRunnerSetupEnvironmentTests.test_noDaemonizeNoUmaskcs4 $$T3dDA dii,r6ctt5|jjdddddddd|j |j dy#1swY&xYw)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. NrF?rrcs r4test_daemonizedNoUmaskzAUnixApplicationRunnerSetupEnvironmentTests.test_daemonizedNoUmasklsW 46 7 G KK ( (sE4 F G E* G GrN)rSrTrUrVr1rrrrrrrrrrrrrrXr6r4rrsL( HE /70-/%& ( ,)-+r6rc4eZdZdZdZdZdZdZdZdZ y) *UnixApplicationRunnerStartApplicationTestsz> Tests for L{UnixApplicationRunner.startApplication}. ctj}|jgdtjd}t ||_gfd}tj|j jj}tj|j}|j}|jd|j|||jt d||jt dd|jtdd |j j!||jgd 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. ) --nodaemonr0070z--chroot /foo/chrootz--rundir /foo/rundir --pidfile /foo/pidfiletest_setupEnvironmentc2j|||||fyr))extend)rQr@rArBrrrs r4fakeSetupEnvironmentz^UnixApplicationRunnerStartApplicationTests.test_setupEnvironment..fakeSetupEnvironments KK5'B Cr6rQrDrHcyr)rXakws r4rzRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment..rr6startApplicationcyr)rXrs r4rzRUnixApplicationRunnerStartApplicationTests.test_setupEnvironment..rr6)rrT8rN)rr}rr rr!rinspect signaturerD parameterscopypoprzrDr r)rQrNr]rsetupEnvironmentParametersfakeSetupEnvironmentParametersrs @r4rz@UnixApplicationRunnerStartApplicationTests.test_setupEnvironment}s!&&(  ))*AB +G4  D&-%6%6 KK ( (& * #*1):): * * '*H)L)L)N&&**62 35ST (*<>RS (*:.switchUIDPasss3   S# &   S" %   T2 &r6 switchUIDrrrN)rDrr!rH)rQrrs` r4test_shedPrivilegesz>UnixApplicationRunnerStartApplicationTests.test_shedPrivilegess6  ' <m<&r*b#r*r6cd}ti}|jtd||jt|j ddd}|j |jdy)z An unexpected L{OSError} when calling L{twisted.scripts._twistd_unix.shedPrivileges} terminates the process via L{SystemExit}. c6ttjdrr)rFr1rGs r4 switchUIDFailzZUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesError..switchUIDFailrr6rrrNr)r!rDrrrrHrzr)rQrrexcs r4test_shedPrivilegesErrorzCUnixApplicationRunnerStartApplicationTests.test_shedPrivilegesErrorsU /'r* <m< F,A,A2sDQ 1%r6ctj||fd}fd}fd}jtd|jtd|jtd|t j } | j ddtd |gtjd } t| _ t| } | j| y ) zj Common code for tests which try to pass the the UID to L{UnixApplicationRunner}. cNj|j|yr)r)rFr1rQ wantedGid wantedUids r4 initgroupszFUnixApplicationRunnerStartApplicationTests._setUID..initgroupss#   S) ,   S) ,r6c*j|yr)r)rFrQrs r4rizBUnixApplicationRunnerStartApplicationTests._setUID..setuid   S) ,r6c*j|yr)r)r1rQrs r4setgidzBUnixApplicationRunnerStartApplicationTests._setUID..setgidrr6rrirrrmrrN) rIrDrr:rr}rrr rr!rr) rQ wantedUserr wantedGrouprpidFilerrirrNr]rs ` ` ` r4_setUIDz2UnixApplicationRunnerStartApplicationTests._setUIDs $**j)[)T - - - 4z2 2x( 2x(&&( 7C NK I ))*AB +G4 &w/ ,r6cP|jdddd|jdzy)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. rqirriz_test_setUidWithoutGid.pidN)rrrcs r4test_setUidWithoutGidz@UnixApplicationRunnerStartApplicationTests.test_setUidWithoutGids' 4dkkm6R&R r6ctj}|jd|ddd|j}dj ||}|j ||dd|j dt ||y ) zz If the specified UID is the same as the current UID of the process, then a warning is displayed. morefoomorebariztest_setUidSameAsCurrentUid.pidz\tried to drop privileges and setuid {} but uid is already {}; should we be root? Continuing.rmessagerN)r:r;r flushWarningsrrzlen)rQ currentUid warningsShownexpectedWarnings r4test_setUidSameAsCurrentUidzFUnixApplicationRunnerStartApplicationTests.test_setUidSameAsCurrentUids YY[  z9d4U **,  --3VJ -K  -*:9*EF C . >r6N) rSrTrUrVrrrrrrrXr6r4rrws'2Yh + &-< ?r6rceZdZdZdZdZy)#UnixApplicationRunnerRemovePIDTestsz7 Tests for L{UnixApplicationRunner.removePID}. cVti}|j}tj|tjj |d}t |dj|j||jtjj|y)zp L{UnixApplicationRunner.removePID} deletes the file the name of which is passed to it. zfoo.pidrN) r!rr:makedirsrjoinrcloserNrr)rQrrrs r4test_removePIDz2UnixApplicationRunnerRemovePIDTests.test_removePIDsu 'r*{{} D'',,tY/ Wc  "! 01r6c ti}|jd|jt}|j t |d|j |dj jtjy)zr Calling L{UnixApplicationRunner.removePID} with a non-existent filename logs an OSError. fakepidrrN) r!rNflushLoggedErrorsrrzrvaluerENOENT)rQrerrorss r4test_removePIDErrorsz8UnixApplicationRunnerRemovePIDTests.test_removePIDErrorssb 'r*#''0 Va( .. =r6N)rSrTrUrVrrrXr6r4r r  s 2 >r6r c(eZdZdZdZdZdZdZy)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|_yr)_beforeDaemonizeCalled_afterDaemonizeCalledrcs r4rrz"FakeNonDaemonizingReactor.__init__5s&+#%*"r6cd|_yNT)rrcs r4beforeDaemonizez)FakeNonDaemonizingReactor.beforeDaemonize9s &*#r6cd|_yr)rrcs r4afterDaemonizez(FakeNonDaemonizingReactor.afterDaemonize<s %)"r6cy)z* Skip event registration. NrX)rQrrs r4addSystemEventTriggerz/FakeNonDaemonizingReactor.addSystemEventTrigger?rr6N)rSrTrUrVrrrrr!rXr6r4rr)s ++* r6rceZdZdZy)rz A dummy reactor, providing C{beforeDaemonize} and C{afterDaemonize} methods, announcing this, and logging whether the methods have been called. N)rSrTrUrVrXr6r4rrEsr6rceZdZdZdZdZy)rwz 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@|jr tdd|_y)zV A fake run method, checking that it's been called one and only time. zAlready calledTN)rx RuntimeErrorrcs r4r4zDummyReactor.runXs ;;/0 0 r6N)rSrTrUrVrxr4rXr6r4rwrwMsFr6rwceZdZdZee ddZdZee ddZdZ ee ddZ ee dd Z ee dd Z d Zd Zd ZdZy)AppProfilingTestsz' Tests for L{app.AppProfiler}. zprofile module not availablectj}|j|d<d|d<tj|}t }|j ||j|jt|d5}|j}ddd|jd|jd|y#1swY.xYw)z L{app.ProfileRunner.run} should call the C{run} method of the reactor and save profile data in the specified file. r$rNzDummyReactor.runfunction calls rr}rr rrwr4rrxrrrrQrrrrdatas r4 test_profilezAppProfilingTests.test_profilefs %%' KKMy&z??6*. W ' &# $ 668D  ($/ &-   CC ct}|jtd|}||}|j|j |j }|j d||j d|y)Nrr)z(run))rrDsys print_statsrestorerr)rQ statsClassr$outrstatsr,s r4 _testStatszAppProfilingTests._testStatszsgjC3/7# ||~ &- gt$r6cBtj}|j|d<d|d<d|d<tj|}t }|j ||j|j|jtj|dy)z With the C{savestats} option specified, L{app.ProfileRunner.run} should save the raw stats object instead of a summary output. r$rT savestatsN rr}rr rrwr4rrxr6r%StatsrQrrrs r4test_profileSaveStatsz'AppProfilingTests.test_profileSaveStatss~ %%' KKMy&z"{??6*. W '  fY&78r6ctjj}tj}d|d<t j |}dtjd< |jt|jdtjjtjj|y#tjjtjj|wxYw)z When the C{profile} module is not present, L{app.ProfilerRunner.run} should raise a C{SystemExit} exception. r$rN r0modulesrrr}r rrrr4clearupdaterQ savedModulesrrs r4test_withoutProfilez%AppProfilingTests.test_withoutProfiles {{'') %%'&z??6*!% I -   j(,, = KK    KK  | , KK    KK  | , !!C?C?cGddtj}|jtd|tj}|j |d<d|d<t j|}t}tj}|jt|j||jtj|y)z When an error happens during the print of the stats, C{sys.stdout} should be restored to its initial value. ceZdZdZy)GAppProfilingTests.test_profilePrintStatsError..ErroneousProfilectd)NBoomr%rcs r4r1zSAppProfilingTests.test_profilePrintStatsError..ErroneousProfile.print_statss "6**r6N)rSrTrUr1rXr6r4ErroneousProfilerHs +r6rLProfiler$rN)r$rMrDrr}rr rrwr0rrr%r4r)rQrLrrr oldStdouts r4test_profilePrintStatsErrorz-AppProfilingTests.test_profilePrintStatsErrors +w + 7I'78%%' KKMy&z??6*.JJ  , g> cjj),r6zcProfile module not availablectj}|j|d<d|d<tj|}t }|j ||j|jt|d5}|j}ddd|jd|jd|y#1swY.xYw)z L{app.CProfileRunner.run} should call the C{run} method of the reactor and save profile data in the specified file. r$r&rNr4r)r*r+s r4 test_cProfilezAppProfilingTests.test_cProfiles %%' KKMy'z??6*. W ' &# $ 668D  eT" &-  r.cBtj}|j|d<d|d<d|d<tj|}t }|j ||j|j|jtj|dy)z With the C{savestats} option specified, L{app.CProfileRunner.run} should save the raw stats object instead of a summary output. r$r&rTr8Nr9r;s r4test_cProfileSaveStatsz(AppProfilingTests.test_cProfileSaveStatss~%%' KKMy'z"{??6*. W '  fY&78r6ctjj}dtjd<tj}d|d<t j |} |jt|jdtjjtjj|y#tjjtjj|wxYw)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&rr>rBs r4test_withoutCProfilez&AppProfilingTests.test_withoutCProfiles {{'') "& J%%''z??6* -   j(,, = KK    KK  | , KK    KK  | ,rEctj}|j|d<d|d<|jtt j |}|jt|dy)zq Check that L{app.AppProfiler} raises L{SystemExit} when given an unknown profiler name. r$foobarrz!Unsupported profiler name: foobarN) rr}rrrr rrzr)rQrerrors r4test_unknownProfilerz&AppProfilingTests.test_unknownProfilersY %%' KKMy%z!!*coovF U%HIr6cftji}|j|jdy)zU L{app.Profiler} defaults to the cprofile profiler if not specified. cprofileNr rrzrrQrs r4test_defaultProfilerz&AppProfilingTests.test_defaultProfiler s(??2& **J7r6cjtjddi}|j|jdy)ze The case of the profiler name passed to L{app.AppProfiler} is not relevant. rCprOfiler[Nr\r]s r4test_profilerNameCaseInsentivez0AppProfilingTests.test_profilerNameCaseInsentives- ??J #;< **J7r6N)rSrTrUrVrr$r-r6r<rDrOr&rQrSrUrYr^rarXr6r4r'r'as K78.9.&%" K78999"-$ K78-9-, L9:.;.& L9:9;9$-$ J88r6r'cVgtjfd}|td|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|Sr)r?)logFilerkwargslogFilesoldFileLogObservers r4observerz+_patchTextFileLogObserver..observer(s$ !';D;F;;r6textFileLogObserver)rri)rDrhrfrgs @@r4_patchTextFileLogObserverrjs/H33< &'2 Or6cRgGfdd}|jtd|S)zu Make fake syslog, and return list to which prefix and then log messages will be appended if it is used. c"eZdZfdZfdZy)(_setupSyslog..fakesyslogobserverc(j|yr)r?)rQprefix logMessagess r4rrz1_setupSyslog..fakesyslogobserver.__init__8s   v &r6c(j|yr)r?)rQ eventDictrps r4emitz-_setupSyslog..fakesyslogobserver.emit;s   y )r6N)rSrTrUrrrs)rpsr4fakesyslogobserverrm7s  ' *r6rtSyslogObserver)rDsyslog)testCasertrps @r4 _setupSyslogrx0s. K** NN6+-?@ r6ceZdZdZdZdZdZdZdZdZ ie jfdZ d Z d Zd Zd Zee d ee ddZdZdZdZdZdZdZy)AppLoggerTestsz Tests for L{app.AppLogger}. @ivar observers: list of observers installed during the tests. @type observers: C{list} cLg_fd}jtd|y)z Override L{globaLogBeginner.beginLoggingTo} so that we can trace the observers installed in C{self.observers}. ct|D]2}jj|tj|4yr)) observersrr addObserver)r}rhrQs r4beginLoggingToz,AppLoggerTests.setUp..beginLoggingToQs2% 9%%h/"..x8 9r6rN)r}rDr)rQrs` r4rzAppLoggerTests.setUpJs%  9 $&6Gr6cP|jD]}tj|y)z1 Remove all installed observers. N)r}rremoveObserverrQrhs r4tearDownzAppLoggerTests.tearDownXs% 8H  - -h 7 8r6cHttGdd}|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}. ceZdZgZdZy)2AppLoggerTests._makeObserver..TestObserverc:|jj|yr))_logsr)rQevents r4__call__z;AppLoggerTests._makeObserver..TestObserver.__call__ks !!%(r6N)rSrTrUrrrXr6r4 TestObserverrgs E )r6r)rr)rQrs r4 _makeObserverzAppLoggerTests._makeObserver_s* \ " ) ) # ) ~r6c|j|j|g|jd|jdd|jd|jddy)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 classrN)rzr}rrrs r4_checkObserverzAppLoggerTests._checkObserverpsR (4 mX^^A%6|%DE ox~~a'8'FGr6ctji}|jfd|_|jt |j y)z L{app.AppLogger.start} calls L{globalLogBeginner.addObserver}, and then writes some messages about twistd and the reactor. cSr)rXrhsr4rz+AppLoggerTests.test_start..sr6N)r AppLoggerr_getLogObserverr^rr)rQrrhs @r4 test_startzAppLoggerTests.test_startzsG r"%%'!1 ]_% H%r6ct}|j}|jt|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)rr setComponentrr rr^r)rQr]rhrs r4$test_startUsesApplicationLogObserverz3AppLoggerTests.test_startUsesApplicationLogObserversS $o %%'  x8r" [! H%r6c|jdfdi}|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. rcSr)rXrsr4rz7AppLoggerTests._setupConfiguredLogger..sXr6)rrAr^)rQr] extraLogArgs appLoggerlogArgsrrhs @r4_setupConfiguredLoggerz%AppLoggerTests._setupConfiguredLoggersG"%%'-.|$7# [!r6cXt}|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)rrrr\s r4#test_startUsesConfiguredLogObserverz2AppLoggerTests.test_startUsesConfiguredLogObservers$$o  D77 DEr6c|j}t}|jt||j |j ||j |jgy)zk C{--logger} takes precedence over a L{ILogObserver} component set on Application. N)rrrrrrrzr)rQrhr]s r4(test_configuredLogObserverBeatsComponentz7AppLoggerTests.test_configuredLogObserverBeatsComponentsV %%'#o   x8 D77 DE ,r6cg}t}|jt|j|j |j ||j |gy)zq C{--logger} takes precedence over a L{LegacyILogObserver} component set on Application. N)rrLegacyILogObserverrrrrz)rQnonlogsr]s r4.test_configuredLogObserverBeatsLegacyComponentz=AppLoggerTests.test_configuredLogObserverBeatsLegacyComponentsN #o   !3W^^D D77 DE "%r6c<g}|j}t}|jt||jt|j t ji}|j||j||j|gy)zw A L{ILogObserver} takes precedence over a L{LegacyILogObserver} component set on Application. N) rrrrrrr rr^rrz)rQrrhr]rs r4.test_loggerComponentBeatsLegacyLoggerComponentz=AppLoggerTests.test_loggerComponentBeatsLegacyLoggerComponents} %%'#o   x8  !3W^^Dr" [! H% "%r6rzsyslog not availablect|}t}|j|j|ddit|j |gy)z` C{--logger} takes precedence over a C{--syslog} command line argument. rvTN)rxrrrr"rz)rQlogsr]s r4%test_configuredLogObserverBeatsSyslogz4AppLoggerTests.test_configuredLogObserverBeatsSyslogsLD!#o    ' ' h5E} U  r"r6ct}|j}|j|j|ddi|j t j j|y)za C{--logger} takes precedence over a C{--logfile} command line argument. logfilerN)rrrrrr:rr)rQr]rs r4&test_configuredLogObserverBeatsLogfilez5AppLoggerTests.test_configuredLogObserverBeatsLogfilesV $o {{}   ' ' i5H I  -.r6ctjddi}t|j}|j|j t |d|j|dtjtjddi}|j|j t |d|j|dtjy)z When logfile is empty or set to C{-}, L{app.AppLogger._getLogObserver} returns a log observer pointing at C{sys.stdout}. r-rrrN) r rrjrDrrzrrr0r)rQrrfs r4test_getLogObserverStdoutz(AppLoggerTests.test_getLogObserverStdouts  3/0,TZZ8  X* hqk3::. 2/  X* hqk3::.r6ct|j}|j}tjd|i}|j }|j |jj|jt|d|j|djtjj|y)z When passing the C{logfile} option, L{app.AppLogger._getLogObserver} returns a log observer pointing at the specified path. rrrN)rjrDrr rr addCleanup_outFiler rzrrr:abspath)rQrffilenamesutrhs r4test_getLogObserverFilez&AppLoggerTests.test_getLogObserverFiles -TZZ8;;=mmY12&&( ))//0 X* !))277??8+DEr6cTgt}fd}|jtd|tji}||_|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|yr)r?)rhremoveds r4removez(AppLoggerTests.test_stop..remove s NN8 $r6rN) r1rDrr r _observerr rzr)rQrhrrrs @r4 test_stopzAppLoggerTests.test_stops 8 % %'7@r"#  8*-  8*- &**+r6cfgtji}ttGfddfd|_|j t |jdtd|j|jg}|jt|d|y)zt L{app.AppLogger} using a legacy logger observer still works, wrapping it in a compat shim. ceZdZdZfdZy);AppLoggerTests.test_legacyObservers..LoggerObserverzX An observer which implements the legacy L{LegacyILogObserver}. c(j|y)z< Add C{x} to the logs list. Nr?)rQxrs r4rzDAppLoggerTests.test_legacyObservers..LoggerObserver.__call__:s Ar6N)rSrTrUrVrrsr4LoggerObserverr4s   r6rcSr)rX)rsr4rz5AppLoggerTests.test_legacyObservers..@s .*:r6rrN) r rrr_observerFactoryr^rrrrtest_legacyObserversrzr)rQrwarningsrrs @@r4rz#AppLoggerTests.test_legacyObservers,s r" ' (   ) #; ]_% m%6tAw%?@%%t'@'@&AB X84r6cXgtji}fd|_|jt |j dt d|j|jg}|j|ddd|jt|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}. cjSr)r?rsr4rzAAppLoggerTests.test_unmarkedObserversDeprecated..Os r6rrraZPassing 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.rN) r rrr^rrrr test_unmarkedObserversDeprecatedrzr)rQrrrs @r4rz/AppLoggerTests.test_unmarkedObserversDeprecatedGs r"!4 ]_% m%6tAw%?@%%t'L'L&MN  QK "0  X84r6N)rSrTrUrVrrrrrrr rrrrrrrrrvrrrrrrrrXr6r4rzrzBs H8"H & &)+cmm0F - &&" 9: J./ #0; # //& F,*565r6rzcTeZdZdZdZdZdZdZdZdZ e e dd Z y ) UnixAppLoggerTestszw Tests for L{UnixAppLogger}. @ivar signals: list of signal handlers installed. @type signals: C{list} cLg_fd}jtd|y)zs Fake C{signal.signal} for not installing the handlers but saving them in C{self.signals}. c@jj||fyr))signalsr)rrrQs r4 fakeSignalz,UnixAppLoggerTests.setUp..fakeSignalus LL  a )r6signalN)rrDr)rQrs` r4rzUnixAppLoggerTests.setUpns#   * 68Z0r6ct|j}tddd}|j|j t |d|j |dtjtddd}|j|j t |d|j |dtjy) 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}. rTrrBrrrrN) rjrDr"rrzrrr0r)rQrfrs r4rz,UnixAppLoggerTests.test_getLogObserverStdoutzs -TZZ83DAB  X* hqk3::.24@A  X* hqk3::.r6ctddd}|jt|j}|j t |dy)z When daemonized and C{logfile} is set to C{-}, L{UnixAppLogger._getLogObserver} raises C{SystemExit}. rFrz&Daemons cannot log to stdout, exiting!N)r"rrrrzr)rQrrXs r4test_getLogObserverStdoutDaemonz2UnixAppLoggerTests.test_getLogObserverStdoutDaemons@ 3EBC!!*f.D.DE U%MNr6ct|j}|j}td|i}|j }|j |j j|jt|d|j|djtjj||jt|jd|j|jddtjt!fd}||d_|jdd}|ddS)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. rrrc(jdyr))callback)dsr4rotatez:UnixAppLoggerTests.test_getLogObserverFile..rotates JJt r6N)rjrDrr"rrrr rzrrr:rrrSIGUSR1rr)rQrfrrrhr rotateLogrs @r4rz*UnixAppLoggerTests.test_getLogObserverFiles -TZZ8;;=Y12&&( ))//0 X* !))277??8+DE T\\*A. a+V^^< J $ LLOA& $r6cfd}jtd|j}td|i}|j }j |j jjjgy)zy If a signal handler is already installed, L{UnixAppLogger._getLogObserver} doesn't override it. cXj|tjtSr))rzrrr1)rrQs r4 fakeGetSignalzVUnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandler..fakeGetSignals   S&.. 18Or6 getsignalrN) rDrrr"rrrr rzr)rQrrrrhs` r4,test_getLogObserverDontOverrideSignalHandlerz?UnixAppLoggerTests.test_getLogObserverDontOverrideSignalHandlersn   6; 6;;=Y12&&( ))//0 r*r6cdt|j}tddd}|j}|j |j j |jt|d|j|djtjjdy)z When daemonized and C{logfile} is empty, the observer returned by L{UnixAppLogger._getLogObserver} points at C{twistd.log} in the current directory. rFrrrz twistd.logN) rjrDr"rrrr rzrrr:r)rQrfrrhs r4test_getLogObserverDefaultFilez1UnixAppLoggerTests.test_getLogObserverDefaultFiles -TZZ825AB)6))+ ))//0 X* !))277??<+HIr6rct|}tddd}|j}|j|dg|ddi|j|dddigy)z If C{syslog} is set to C{True}, L{UnixAppLogger._getLogObserver} starts a L{syslog.SyslogObserver} with given C{prefix}. Tz test-prefix)rvrorbN)rxr"rrz)rQrrrhs r4test_getLogObserverSyslogz,UnixAppLoggerTests.test_getLogObserverSyslogsd D!$-HI)6))+  /#s  Sz:;r6N) rSrTrUrVrrrrrrrrrrXr6r4rresF 1/$O<+& J 9: <; .rr6)rmockosrr}rrDrr!rr rr]r0rrJstderrrKrLrcs r4rzDaemonizeTests.setUpsh **,  <t{{3"88E ")"5"5e"<  #   #  #5  r6c(tt5|jjddd|j |j j gd|j |j jddgy#1swYZxYw)zw When double fork succeeded in C{daemonize}, the child process writes B{0} to the status pipe. N)rrrrforkTsetsidr)r0unlinkz twistd.pidr)rrrrfrzractionsclosedrcs r4 test_successzDaemonizeTests.test_successsu 46 7 * KK ' ' ) *  KK     ++b"X6 * *s BBcd|j_d|j_tt 5|j t |jjddd|j|jjgd|j|jjdgy#1swYYxYw)z The parent process initiating the C{daemonize} call reads data from the status pipe and then exit the process. FrN)rrrrdexitrrr) rchildreadDatarrr SystemErrorrrfrzrrrcs r4test_successInParentz#DaemonizeTests.test_successInParents " #  46 7 H   k4;;+F+F G H  KK     ++bT2 H Hs +B99Ccgfd}||j_tt5|jj ddd|j |jjgd|j |jjddg|j ddgy#1swYnxYw)z If the C{os.write} call to the status pipe raises an B{EINTR} error, the process child retries to write. czj||ftdk(rttjyrrrrrEINTR)fdr,writtens r4 raisingWritez6DaemonizeTests.test_successEINTR..raisingWrite$s3 NNB: &7|q ekk**!r6N)rrrrrrrr)rr) rrrrrrfrzrr)rQrrs @r4test_successEINTRz DaemonizeTests.test_successEINTRs  + )  46 7 * KK ' ' ) *  KK     ++b"X6 *j17; * *s B55B>cgfd}||j_d|j_tt 5|j t |jjddd|j|jjgd|j|jjdg|jddgy#1swYmxYw)z If the C{os.read} call on the status pipe raises an B{EINTR} error, the parent child retries to read. czj||ftdk(rttjy)Nrrr )r sizers r4 raisingReadz=DaemonizeTests.test_successInParentEINTR..raisingReadAs0 KKT #4yA~ekk**r6FN)rrrrrr)rr) rrrrrrrrrfrzrr)rQrrs @r4test_successInParentEINTRz(DaemonizeTests.test_successInParentEINTR:s   ' !  46 7 H   k4;;+F+F G H  KK     ++bT2 )Y/6 H Hs +CCc Gfddtj}|}|j|jjt t 5|jt|jjddd|j|jjddddddd |fd g|j|jjd d gy#1swYbxYw) z Assert L{UnixApplicationRunner.postApplication} writes C{reported} to its status pipe if the service raises an exception whose message is C{raised}. ceZdZfdZy)6DaemonizeTests.assertErrorWritten..FakeServicectr)rK)rQraiseds r4r_zCDaemonizeTests.assertErrorWritten..FakeService.startService`s"6**r6N)rSrTrUr_)rsr4rdr_s +r6rdNrrrrrrrr)r rOrXrr]rrrr%rfrzrrr)rQrreportedrd errorServices ` r4assertErrorWrittenz!DaemonizeTests.assertErrorWrittenXs +'// +#} %%dkk&=&=> 46 7 I   lDKK,G,G H I  KK   "h'(   ++b"X6 I Is +C((C1c*|jddy)z If an error happens during daemonization, the child process writes the exception error to the status pipe. zSomething is wrongs"1 RuntimeError: Something is wrongrrNrrcs r4 test_errorzDaemonizeTests.test_errorvs '2W  r6c*|jddy)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•s1 RuntimeError: \u2022rNr rcs r4test_unicodeErrorz DaemonizeTests.test_unicodeErrors x:TUr6cd|j_||j_t}|j t d|t t5|jt|jjddd|j|j||j|jj||j|jjdgy#1swYwxYw)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)rrrrrDr0rrrrrrfrzrrr)rQr errorMessage mockOSActionserrorIOs r4assertErrorInParentBehaviorz*DaemonizeTests.assertErrorInParentBehaviors" ' * 3 g. 46 7 H   k4;;+F+F G H ))+\: ,,m< ++bT2  H Hs +C88Dc0|jddgdy)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. rrrr)rrrrr&r'Nr)rcs r4test_errorInParentz!DaemonizeTests.test_errorInParents% ((8B ) r6c0|jddgdy)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. s1 Exception: zXAn error has occurred: b'Exception: \xff' Please look at log file for more information. r+r,Nr-rcs r4test_nonASCIIErrorInParentz)DaemonizeTests.test_nonASCIIErrorInParents% (()B ) r6ctd}djd}|j|dj|gdy)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. d1 RuntimeError: \u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022zb'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)rr))rQtruncatedMessagereportedMessages r4&test_errorInParentWithTruncatedUnicodez5DaemonizeTests.test_errorInParentWithTruncatedUnicodesLA066G ((%BBH&#C ) r6c*|jddy)z{ If an error occurs during daemonization and its message is too long, it's truncated by the child. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsd1 RuntimeError: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrNr rcs r4test_errorMessageTruncatedz)DaemonizeTests.test_errorMessageTruncateds 'F  r6c*|jddy)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••••••••••••••••••••••••••••••r2rNr rcs r4!test_unicodeErrorMessageTruncatedz0DaemonizeTests.test_unicodeErrorMessageTruncateds  :  r6ct}|jj||j|j|j|j y)z C{daemonize} indeed calls L{IReactorDaemonize.beforeDaemonize} and L{IReactorDaemonize.afterDaemonize} if the reactor implements L{IReactorDaemonize}. N)rrrrrrrs r4test_hooksCalledzDaemonizeTests.test_hooksCalledsB )* g& 667 556r6ct}|jj||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)rrrrrrrs r4test_hooksNotCalledz"DaemonizeTests.test_hooksNotCalledsF ,- g& 778 667r6N)rSrTrUrVrrrrrrr!r#r)r.r0r5r8r:r<r>rXr6r4rrsX67*3,<:7<7< V3" , , :    7 8r6rcDeZdZdZedZej dZy)SignalCapturingMemoryReactorz MemoryReactor that implements the _ISupportsExitSignalCapturing interface, all other operations identical to MemoryReactor. c|jSr)_valrcs r4rz(SignalCapturingMemoryReactor._exitSignals yyr6c||_yr)rB)rQvals r4rz(SignalCapturingMemoryReactor._exitSignals  r6N)rSrTrUrVpropertyrsetterrXr6r4r@r@ s5 r6r@c2eZdZdZeZfdZdZdZxZ 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. c2t||d|_yr))superrr _signalValue)rQr __class__s r4rrz(StubApplicationRunnerWithSignal.__init__'s   r6cy)z Does nothing. NrXrcs r4rdz.StubApplicationRunnerWithSignal.preApplication+rr6ct}|j|_|j|tj tj y)z` Instantiate a SignalCapturingMemoryReactor and start it in the runner. N)r@rLrrLr0rrrs r4rfz/StubApplicationRunnerWithSignal.postApplication0s4 /0"// '3::szz:r6) rSrTrUrVrZrgrrrdrf __classcell__)rMs@r4rIrIs&M! ;r6rIcfd}|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 )rIrL)rrsignums r4stubApplicationRunnerFactoryzIstubApplicationRunnerFactoryCreator..stubApplicationRunnerFactoryGs18$ r6rX)rSrTs` r4#stubApplicationRunnerFactoryCreatorrU:s ('r6c(eZdZdZdZdZdZdZy)ExitWithSignalTestsz? Tests for L{twisted.application.app._exitWithSignal}. c tj_dtij_t j_dj_ddg_fd}jtd|y)zM Set up the server options and a fake for use by test cases. r.NcB|jd<|jd<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. rrN) fakeKillArgs)rrrQs r4fakeKillz+ExitWithSignalTests.setUp..fakeKilljs%$'D  a #&D  a r6r) rr}rrKr0r1r2rrZrDr:)rQr[s` r4rzExitWithSignalTests.setUp`sg**, %35E5G$H !!' !/ !4L ' 2vx(r6cddgfd}|jtd|tjtj|j dtj|j dtj |j |jdtj|j |jdtjy)z exitWithSignal replaces the existing signal handler with the default handler and sends the replaced signal to the current process. Nc|d<|d<y)NrrrX)rhandlerfakeSignalArgss r4 fake_signalz.fake_signals #N1  'N1 r6rrr) rDrr _exitWithSignalSIGINTrSIG_DFLrZr:r)rQr`r_s @r4test_exitWithSignalz'ExitWithSignalTests.test_exitWithSignalws  ( 68[1 FMM* .+V]]; .+V^^< $++A. < $++A. >r6c|jtdtdtj|j|j |j d|j |j dy)zb _exitWithSignal is not called if the runner does not exit with a signal. reNrr)rDrrUrunApprrrZrcs r4test_normalExitz#ExitWithSignalTests.test_normalExitsc ,.QRV.W   dkk" $++A./ $++A./r6cZ|jtdttjtj |j |j|jdtj|j|jdtjy)zP _exitWithSignal is called when the runner exits with a signal. rerrN) rDrrUrrbrfrrrZr:rrcs r4test_runnerExitsWithSignalz.ExitWithSignalTests.test_runnerExitsWithSignalst  $ / >  dkk" $++A. < $++A. >r6N)rSrTrUrVrrdrgrirXr6r4rWrWZs).?( 0 ?r6rW)hrVrrr:rrr0r<_grpr9_pwd ImportErroriorunittestrzope.interfacerzope.interface.verifyrrrrr twisted.applicationr r r twisted.application.servicer twisted.internet.basertwisted.internet.deferrtwisted.internet.interfacesrr#twisted.internet.test.modulehelpersrtwisted.internet.testingrtwisted.loggerrrrtwisted.pythonrtwisted.python.componentsrtwisted.python.fakepwdrtwisted.python.logrrtwisted.python.reflectrtwisted.python.runtimertwisted.python.usagertwisted.scriptsrtwisted.test.test_processrtwisted.trial.unittestr rtwisted.scripts._twistd_unixr!r"r#rvr$r%r&rIrKrrZrerarirr rr$r"r,rrr rrrwr'rjrxrzrrr@rIrUrWrXr6r4rs    C C&.,,665-+X@2NN3/T0/+",+;<  . /  " x   $*.Z"      = =  UJUJpL56CKHCK7CKLD8D0  *JC11J(p4Xp4fL56F+F+7F+RL56O?O?7O?dL56>(>7><  8 6 (w8w8t*$`5X`5F L56y<y<7yf8Xf8?f8R  *+ = , ;f&C&C;<(@H?(H?OB C CsI== J  J