Ϫf*Y8 dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z  ddl Z ddlmZddlmZmZmZeZddlmZddlmZddlmZmZmZmZmZdd lm Z m!Z!dd l"m#Z#dd l$m%Z%dd l&m'Z'dd l(m Z e%ejRjTZ+dZ,e-ej\Z/ej`jcejTe/d<GddejdZ3Gdde jhZ5GddejdZ6GddejdZ7GddejdZ8GddejdZ9Gdde7Z:GddejdZ;Gd d!e;Z<Gd"d#e;Z=e ej|ed d$Gd%d&e jhZ?Gd'd(ejdZ@Gd)d*ZAe e!jjd+k7d,e ej|ed d$Gd-d.eAe jhZDe e!jjd/k7d0e ej|ed d$Gd1d2eAe jhZEGd3d4ejdZFe e!jjd/k7d0e ej|ed d$Gd5d6e jhZGGd7d8ejdZHGd9d:ZIGd;d<ZJGd=d>ZKGd?d@eZLGdAdBeZMGdCdDeZNGdEdFZOGdGdHe jhZPe e!jjd/k7d0e ej|ed d$GdIdJe jheIZQe e!jjd/k7d0e ej|ed d$GdKdLe jheIZRGdMdNe9ZSe e!jjd+k7d,e ej|ed d$GdOdPe jhZTe e!jjd+k7d,e ej|ed d$GdQdRe jhZUe e!jjd+k7d,e ej|ed d$GdSdTe jhZVe e!jjd+k7d,e ej|ed d$GdUdVe jhZWGdWdXe jhZXGdYdZejdZYe ej|ed d$Gd[d\e jhZZy#e $rdZ YwxYw#e $r dZeZeZeZYwxYw)]a Test running processes. @var CONCURRENT_PROCESS_TEST_COUNT: The number of concurrent processes to use to stress-test the spawnProcess API. This value is tuned to a number of processes which has been determined to stay below various experimentally-determined limitations of our supported platforms. Particularly, Windows XP seems to have some undocumented limitations which cause spurious failures if this value is pushed too high. U{Please see this ticket for a discussion of how we arrived at its current value. } @var properEnv: A copy of L{os.environ} which has L{bytes} keys/values on POSIX platforms and native L{str} keys/values on Windows. N)SkipTestskipIf)process) ProcessReader ProcessWriter PTYProcess)BytesIO) verifyObject)defererror interfacesprotocolreactor) procutilsruntime) networkString)FilePathmsg)unittest PYTHONPATHc.eZdZdZdZdZdZdZdZy)StubProcessProtocolz ProcessProtocol counter-implementation: all methods on this class raise an exception, so instances of this may be used to verify that only certain methods are called. ctNNotImplementedErrorselfdatas ;/usr/lib/python3/dist-packages/twisted/test/test_process.py outReceivedzStubProcessProtocol.outReceivedH !##ctrrrs r" errReceivedzStubProcessProtocol.errReceivedKr$r%ctrrr s r"inConnectionLostz$StubProcessProtocol.inConnectionLostNr$r%ctrrr)s r"outConnectionLostz%StubProcessProtocol.outConnectionLostQr$r%ctrrr)s r"errConnectionLostz%StubProcessProtocol.errConnectionLostTr$r%N) __name__ __module__ __qualname____doc__r#r'r*r,r.r%r"rrAs  $$$$$r%rc4eZdZdZdZdZdZdZdZdZ y) ProcessProtocolTestszj Tests for behavior provided by the process protocol base class, L{protocol.ProcessProtocol}. c\ttjtjy)zD L{ProcessProtocol} implements L{IProcessProtocol}. N)r r IProcessProtocolrProcessProtocolr)s r"test_interfacez#ProcessProtocolTests.test_interface^s Z00(2J2J2LMr%cgGfddt}d}|}|jd||j|gy)z Verify that when stdout is delivered to L{ProcessProtocol.childDataReceived}, it is forwarded to L{ProcessProtocol.outReceived}. ceZdZfdZy):ProcessProtocolTests.test_outReceived..OutProtocolc(j|yrappendr r!receiveds r"r#zFProcessProtocolTests.test_outReceived..OutProtocol.outReceivedm%r%N)r/r0r1r#rAsr" OutProtocolr<l &r%rDbytesNrchildDataReceived assertEqual)r rD bytesToSendprAs @r"test_outReceivedz%ProcessProtocolTests.test_outReceiveddsG  &- & M A{+ K=1r%cgGfddt}d}|}|jd||j|gy)zA Similar to L{test_outReceived}, but for stderr. ceZdZfdZy):ProcessProtocolTests.test_errReceived..ErrProtocolc(j|yrr>r@s r"r'zFProcessProtocolTests.test_errReceived..ErrProtocol.errReceived|rBr%N)r/r0r1r'rCsr" ErrProtocolrP{rEr%rRrFNrH)r rRrKrLrAs @r"test_errReceivedz%ProcessProtocolTests.test_errReceivedusG &- & M A{+ K=1r%cgGfddt}|}|jd|jdgy)z Verify that when stdin close notification is delivered to L{ProcessProtocol.childConnectionLost}, it is forwarded to L{ProcessProtocol.inConnectionLost}. ceZdZfdZy)BProcessProtocolTests.test_inConnectionLost..InLostProtocolc(jdyrr>r losts r"r*zSProcessProtocolTests.test_inConnectionLost..InLostProtocol.inConnectionLost D!r%N)r/r0r1r*rZsr"InLostProtocolrW "r%r]rNrchildConnectionLostrJ)r r]rLrZs @r"test_inConnectionLostz*ProcessProtocolTests.test_inConnectionLostsA  "0 "   a  v&r%cgGfddt}|}|jd|jdgy)zF Similar to L{test_inConnectionLost}, but for stdout. ceZdZfdZy)DProcessProtocolTests.test_outConnectionLost..OutLostProtocolc(jdyrr>rYs r"r,zVProcessProtocolTests.test_outConnectionLost..OutLostProtocol.outConnectionLostr[r%N)r/r0r1r,r\sr"OutLostProtocolrdr^r%rfrGNr_)r rfrLrZs @r"test_outConnectionLostz+ProcessProtocolTests.test_outConnectionLostA "1 "   a  v&r%cgGfddt}|}|jd|jdgy)zF Similar to L{test_inConnectionLost}, but for stderr. ceZdZfdZy)DProcessProtocolTests.test_errConnectionLost..ErrLostProtocolc(jdyrr>rYs r"r.zVProcessProtocolTests.test_errConnectionLost..ErrLostProtocol.errConnectionLostr[r%N)r/r0r1r.r\sr"ErrLostProtocolrkr^r%rmrSNr_)r rmrLrZs @r"test_errConnectionLostz+ProcessProtocolTests.test_errConnectionLostrhr%N) r/r0r1r2r9rMrTrargrnr3r%r"r5r5Xs& N 2" 2' ' 'r%r5c(eZdZdZdZdZdZdZy)TrivialProcessProtocolz Simple process protocol for tests purpose. @ivar outData: data received from stdin @ivar errData: data received from stderr c.||_g|_g|_y)zl Create the deferred that will be fired at the end, and initialize data structures. N)deferredoutDataerrDatar ds r"__init__zTrivialProcessProtocol.__init__s    r%cH||_|jjdyrreasonrrcallbackr rzs r" processEndedz#TrivialProcessProtocol.processEnded  t$r%c:|jj|yr)rsr?rs r"r#z"TrivialProcessProtocol.outReceived D!r%c:|jj|yr)rtr?rs r"r'z"TrivialProcessProtocol.errReceivedrr%N)r/r0r1r2rwr}r#r'r3r%r"rprps%""r%rpc$eZdZdZdZdZdZy)TestProcessProtocolcfdg|_d|_d|_|jj dy)NrGr%abcd)stagesr!err transportwriter)s r"connectionMadez"TestProcessProtocol.connectionMades+c   W%r%cp|dk(r|xj|z c_y|dk(r|xj|z c_yy)z Override and disable the dispatch provided by the base class to ensure that it is really this method which is being called, and the transport is not going directly to L{outReceived} or L{errReceived}. rGrSN)r!rr childFDr!s r"rIz%TestProcessProtocol.childDataReceiveds3 a< II I \ HH Hr%c |dk(r_|jjd|jdk7rtd|jd|jj dy |dk(rz|jjd|j dk7rtd|j d |jj d|jjd y |d k(r|jjd y y )z Similarly to L{childDataReceived}, disable the automatic dispatch provided by the base implementation to verify that the transport is calling this method directly. rGrSrz Data was z instead of 'abcd's1234zErr was z instead of '1234'rN)rr?r! RuntimeErrorrrrr rs r"r`z'TestProcessProtocol.childConnectionLosts a< KK  q !yyG#"Ytyym;M#NOO NN  ) \ KK  q !xx7""Xdhh\9K#LMM NN  ) KK  q ! \ KK  q !r%cH||_|jjdyrryr|s r"r}z TestProcessProtocol.processEndedr~r%N)r/r0r1rrIr`r}r3r%r"rrs& "(%r%rc:eZdZddzZdZdZdZdZdZdZ d Z y) EchoProtocols1234567 rNc ||_d|_yNr)onEndedcount)r rs r"rwzEchoProtocol.__init__s  r%cH|jdkDsJt|jdz D]'}|jj|j)|jj |j|jg|j|jz|_y)NrS)nrangerrs writeSequencebuffer)r is r"rzEchoProtocol.connectionMadesxvvzztvvz" )A NN  ( ) $$dffdff%56fftvvo r%c||j|j|jt|z|k7r/d||jf|_|jj y|xjt|z c_|jt|jk(r|jj yy)Nzwrong bytes received)rrlenfailurer closeStdinrs r"r#zEchoProtocol.outReceived s ;;tzzDJJT$: ;t C2D$**EDL NN % % ' JJ#d) #JzzS--))+.r%cd|_|jtjsdt |z|_|j j|y)NrGz#process didn't terminate normally: )finishedcheckr ProcessDonestrrrr{r|s r"r}zEchoProtocol.processEndeds= ||E--.@3v;NDL d#r%) r/r0r1rrrrrwrr#r}r3r%r"rrs/TA AHG&,$r%rc(eZdZdZdZdZdZdZy)SignalProtocola A process protocol that sends a signal when data is first received. @ivar deferred: deferred firing on C{processEnded}. @type deferred: L{defer.Deferred} @ivar signal: the signal to send to the process. @type signal: C{str} @ivar signaled: A flag tracking whether the signal has been sent to the child or not yet. C{False} until it is sent, then C{True}. @type signaled: C{bool} c.||_||_d|_yNF)rrsignalsignaled)r rrsigs r"rwzSignalProtocol.__init__*s    r%ctd|d|js-d|_|jj|jyy)z Handle the first output from the child process (which indicates it is set up and ready to receive the signal) by sending the signal to it. Also log all output to help with debugging. Received z from child stdoutTN)rrr signalProcessrrs r"r#zSignalProtocol.outReceived/s? ix1 23}} DM NN ( ( 5r%c"td|dy)z_ Log all data received from the child's stderr to help with debugging. rz from child stderrNrrs r"r'zSignalProtocol.errReceived:s ix1 23r%c td|j|jtjs'|j j td|S|j}t|jtrttd|jz}n |j}|j?|j j td|jd|jdS|j|k7rA|j j td|jd|jd|Stj|j |k7rQ|j j td|jd tj|j S|j j#dy) aL Callback C{self.deferred} with L{None} if C{reason} is a L{error.ProcessTerminated} failure with C{exitCode} set to L{None}, C{signal} set to C{self.signal}, and C{status} holding the status code of the exited process. Otherwise, errback with a C{ValueError} describing the problem. zChild exited: wrong termination: SIGNz: exitCode is z , not Nonez: .signal was z , wanted z: )r getTracebackrr ProcessTerminatedrrerrback ValueErrorvalue isinstancerrgetattrexitCodeosWTERMSIGstatusr{)r rzv signalValues r"r}zSignalProtocol.processEndedAsp nV0025 67||E334==((6I&4R)ST T LL dkk3 '!&%$++*=>K++K :: !==((S ^AJJE3  r%c g|_g|_yr)bytesrequestsr)s r"rwzUtilityProcessProtocol.__init__s  r%ct)zR Called with all bytes received on stdout when the process exits. rr rs r" parseChunksz"UtilityProcessProtocol.parseChunkss "##r%cdtj}|jj||S)z{ Return a Deferred which will fire with the result of L{parseChunks} when the child process exits. )r rrr?rus r" getResultz UtilityProcessProtocol.getResults' NN  Qr%cZ|j}d|_|D]}|j|y)zt Callback all Deferreds returned up until now by L{getResult} with the given result object. N)rr{)r resultrrvs r"_fireResultDeferredsz+UtilityProcessProtocol._fireResultDeferredss/ ==  A JJv  r%c:|jj|y)zE Accumulate output from the child process in a list. N)rr?rs r"r#z"UtilityProcessProtocol.outReceiveds % r%cX|j|j|jy)zu Handle process termination by parsing all received output and firing any waiting Deferreds. N)rrrr|s r"r}z#UtilityProcessProtocol.processEndeds! !!$"2"24::">?r%N)r/r0r1r2rr__annotations__ classmethodrrwrrrr#r}r3r%r"rrosD K  $ ! @r%rceZdZdZdZdZy)GetArgumentVectorzl Protocol which will read a serialized argv from a process and expose it to interested parties. stwisted.test.process_getargvcBdj|jdS)z Parse the output from the process to which this protocol was connected, which is a single unterminated line of \0-separated strings giving the argv of that process. Return this as a list of str objects. r%)joinsplit)r chunkss r"rzGetArgumentVector.parseChunkssxx%%e,,r%Nr/r0r1r2rrr3r%r"rrs 2K-r%rceZdZdZdZdZy)GetEnvironmentDictionaryzx Protocol which will read a serialized environment dict from a process and expose it to interested parties. stwisted.test.process_getenvcdj|}|siSt|jd}i} t|}t|}|||<#t$rY|SwxYw)a Parse the output from the process to which this protocol was connected, which is a single unterminated line of \0-separated strings giving key value pairs of the environment from that process. Return this as a dictionary. r%r)riterrnext StopIteration)r r environBytesenvironbrvkrs r"rz$GetEnvironmentDictionary.parseChunkssyxx' I **512  NN!!   s A AANrr3r%r"rrs 1Kr%rz'reactor doesn't support IReactorProcessceZdZdZdZdZdZdZdZdZ e e jjdd jd k(xrej j#d k(d d Ze e jjdd jd k(xrej j#d k(d dZdZdZy) ProcessTestsz! Test running a process. Fcd}ttjx}_t j t t dd|gtdjjjdjjdjjdjjfd }|j|S) z1 L{twisted.internet.stdio} test. ztwisted.test.process_twistedrrNrpathusePTY hello, worldsabcs123c jjjddjjdjjdy)Nshello, worldabc123zOutput follows: z- Error message from process_twisted follows:  )rJoutFgetvalueerrFignrLr s r"r}z-ProcessTests.test_stdio..processEndedsE   !%&&//+QVV__->@ r%) Accumulatorr r endedDeferredrrr properEnvrrrr addCallbackr scriptPathrvr}rLs` @r" test_stdiozProcessTests.test_stdios4 M#nn..AO  D$ +;;   /* &! &!   }}\**r%cPddl}|j|dd|jS)z In some scenarious, such as Python running as part of a Windows Windows GUI Application with no console, L{sys.stdout} is L{None}. rNstdout)syspatchr)r rs r"test_patchSysStdoutWithNonez(ProcessTests.test_patchSysStdoutWithNones$  3$'  r%cjddl}ddlm}|}|j|d||j S)z Some projects which use the Twisted reactor such as Buildbot patch L{sys.stdout} with L{io.StringIO} before running their tests. rNStringIOrriorrr)r rrstdoutStringIOs r"test_patchSysStdoutWithStringIOz,ProcessTests.test_patchSysStdoutWithStringIOs. ! 3.1  r%cddl}ddlm}|j|d||j|d||j S)z If L{sys.stdout} and L{sys.__stdout__} are patched with L{io.StringIO}, we should get a L{ValueError}. rNrr __stdout__r)r rrs r"$test_patch_sys__stdout__WithStringIOz1ProcessTests.test_patch_sys__stdout__WithStringIO&s;  3(*- 3 hj1  r%c2tj}t|}d}tj|t t dd|gt jjfd}|jj|j|S)z Test if pid is None/non-None before/after process termination. This reuses process_echoer.py to get a process that blocks on stdin. twisted.test.process_echoer-u-mrc<jjyr assertIsNonepid)ignored procTransr s r"afterProcessEndz3ProcessTests.test_unsetPid..afterProcessEnd?s   imm ,r%) r rrprrrr  assertTruer'rrr )r rrLrr*r)s` @r" test_unsetPidzProcessTests.test_unsetPid2s| >># "8 ,3 (( uueUJ7Y   & -  ##O44r%CItruewin32z/See https://twistedmatrix.com/trac/ticket/10014cd}tj}t|_t j t t dd|gtfd}|j||S)zp Test running a process: check its output, it exitCode, some property of signalProcess. twisted.test.process_testerr"r#rcjjgdj}|jtj j|j jdjtjjjd ddl }ddl }|j|jD]}tj |y#t"$rYywxYw)NrGrSrrrINTr)rJrrztrapr rrr assertRaisesProcessExitedAlreadyrrglobprocess_testertest_file_matchrremove BaseException)r(fr:r;rLr s r"rz(ProcessTests.test_process..checkUs   QXX 7A FF5** +   QWW--r 2   **AKK,E,Eu  %>#A#AB!AIIaL!   s'=C%% C10C1) r rrrrrrrr r )r rrvrrLs` @r" test_processzProcessTests.test_processEsZ4 NN   ! QueZ'HiX ( er%cZfd}d}tdd|g}g}g}ttD]Y}t}|j |t j |t|t|j |j[tj|d}|j|||S)Nc J|D]}j|jgddt|jt |jfz|j }|j tjj|jjdy)Nr4z[%d] stages = %sr5) rJridrrrzr7r rrr)results protocolsrLr?r s r"_checkz/ProcessTests.test_manyProcesses.._checkrs~ 7  HH#&"Q[[/3qxx=)II HHu../  !1!126 7r%r2r"r#rT) consumeErrors) rrCONCURRENT_PROCESS_TEST_COUNTrr?rrr rrr DeferredListr ) r rFrargsrE deferredsrrL deferredLists ` r"test_manyProcesseszProcessTests.test_manyProcessesls 74 ueZ0  45 )A')A   Q   E4Y ?   QZZ (  ) )))4H   3r%ctj}t|d}tjt t dd|gt fd}fd}|j|j|S)z A spawning a subprocess which echoes its stdin to its stdout via L{IReactorProcess.spawnProcess} will result in that echoed output being delivered to outReceived. r!r"r#rcjjjjtdj t j t jjzy)Nr) assertFalserr+hasattrrJrrrrr(rLr s r"assertsz'ProcessTests.test_echo..assertssV   QYY 2 OOGAx0 1   S]Cacc N ;r%c<jj|Sr)rr)rrLs r"takedownProcessz/ProcessTests.test_echo..takedownProcesss KK " " $Jr%) r rrrrrr r  addErrback)r rrrSrUrLs` @r" test_echozProcessTests.test_echose >>#  "3 QueZ'HiX <  ##G,77HHr%cgdd}ttjx}_t j t t dd|gztdfd}|j|S)N) sa\"b sa\b s a\\"bs a\\bs "foo bar" "s abs"\sa"bsa'bstwisted.test.process_cmdliner"r#rrcjjjdjjj }j|yNr%)rJrrr splitlines)r  recvdArgsrJrLr s r"r}z3ProcessTests.test_commandLine..processEndedsG   QVV__. 4)446I   Y -r% r r rr rrrr r )r rrvr}rJrLs` @@r"test_commandLinezProcessTests.test_commandLinesi  5 M#nn..AO uueUJ7$>ITX  . }}\**r%N)r/r0r1r2rrrrrr,rrenvirongetlowerrplatformgetTyper@rMrWr_r3r%r"rrs F+@! ! !5&  tR &&(F2 2    $ $ &' 19   D  tR &&(F2 2    $ $ &' 19   8I.+r%rc&eZdZdZdZdZdZdZy)TwoProcessProtocolrc6tj|_yrrr)s r"rwzTwoProcessProtocol.__init__rr%cyrr3rs r"r#zTwoProcessProtocol.outReceived r%cHd|_|jjdyNrG)rrrr{r|s r"r}zTwoProcessProtocol.processEndeds  t$r%N)r/r0r1numrrwr#r}r3r%r"rfrfs CH) %r%rfc,eZdZdZddZdZdZdZy)TestTwoProcessesBasecDddg|_ddg|_d|_d|_yr) processesppdoneverboser)s r"setUpzTestTwoProcessesBase.setUps&,  r%c d}dD]s}t|j|<||j|_tj|j|t t dd|gt |}||j|<uy)Nstwisted.test.process_reader)rrGr"r#rr)rfrrrmrrrr rq)r rrrmrLs r"createProcessesz$TestTwoProcessesBase.createProcessessv3  $C-/DGGCL"DGGCL $$ uj1 A#$DNN3  $r%cZ|jrtd|z|j|}|j|}|j |j d|j |jr;t|jdj |jdj yy)Nzclosing stdin [%d]Process finished too earlyrrG)rtprintrqrrrPrloseConnectionr rmrLrrs r"closezTestTwoProcessesBase.closes << &, - NN3  WWS\ &BC  << $''!*%%twwqz':': ; r%cztj|jDcgc]}|jc}Scc}wr)r gatherResultsrrrr)r rLs r"_onClosezTestTwoProcessesBase._onCloses)""#@1AJJ#@AA#@s8c|jr td|jtjd|j dtjd|j d|j S)Nstarting processesrGrrSrtr{rxr callLaterr~rr)s r" test_closezTestTwoProcessesBase.test_closesV << & ' !TZZ+!TZZ+}}r%N)r)r/r0r1rurxr~rrr3r%r"roros $<Br%ror0zOnly runs on Windowsc eZdZy)TwoProcessesNonPosixTestsN)r/r0r1r3r%r"rrs  r%rposixzOnly runs on POSIX platformc*eZdZdZdZdZdZdZy)TwoProcessesPosixTestsct|j|jD]A\}}|jr t j |j tjC|jS#t$rY_wxYwr) ziprrrqrrkillr'rSIGTERMOSErrorr)r rrprs r"tearDownzTwoProcessesPosixTests.tearDownsj$''4>>2 FB;;GGBFFFNN3 }} s.A55 BBc|jrtd|z|j|}|j|}|j |j dt j|jtj|jr;t|jdj |jdj yy)Nzkill [%d] with SIGTERMrzrrG) rtr{rqrrrPrrrr'rrr}s r"rzTwoProcessesPosixTests.kills << *S0 1 NN3  WWS\ &BC v~~& << $''!*%%twwqz':': ; r%c|jr td|jdtjd|j dtjd|j d|j S)NrrrrGrSrtr{rxrrrrr)s r" test_killz TwoProcessesPosixTests.test_kill[ << & ' A&!TYY*!TYY*}}r%c|jr td|jdtjd|j dtjd|j d|j SNrrGrrrSrr)s r" test_closePtyz$TwoProcessesPosixTests.test_closePty%s[ << & ' A&!TZZ+!TZZ+}}r%c|jr td|jdtjd|j dtjd|j d|j Srrr)s r" test_killPtyz#TwoProcessesPosixTests.test_killPty-rr%N)r/r0r1rrrrrr3r%r"rrs <r%rc<eZdZdZdZdZdZdZdZdZ dZ d Z y) FDCheckerrr%Nc||_yr)rrrus r"rwzFDChecker.__init__;s  r%cH||_|jjdyr)failedrrr{)r whys r"failzFDChecker.fail>s  t$r%cJ|jjddd|_y)NrrrG)r writeToChildstater)s r"rzFDChecker.connectionMadeBs ##Aw/ r%c&|jdk(r|dk7r|jd||fzy|xj|z c_t|jdk(rY|jdk7r|jd|jzyd|_d|_|jj dd y|jdk(r|jd |d |d y|jdk(r|dk7r|jd |d |d y|xj|z c_t|jdk(r5|jdk7r|jd|jzyd|_y|jdk(r|jd |d |dyy)NrGz)read '%s' on fd %d (not 1) during state 1srightoz"got '%s' on fd1, expected 'righto'r%rSrsefghzread 'z' on fd z during state 2z (not 1) during state 3sclosedz"got '%s' on fd1, expected 'closed'rz during state 4)rrr!rrrrs r"rIzFDChecker.childDataReceivedFsk ::?!| ERVWX II I499~"99 )IIBTYYNO  ++Aw7 ::? IIwixv_E F  ::?!| F7)8D69PQR II I499~"99 )IIBTYYNO  ::? IIwixv_E F  r%c|jdk(r|jd|zy|jdk(r=|dk7r|jd|zyd|_|jjdyy)NrGz%got connectionLost(%d) during state 1rSrz-got connectionLost(%d) (not 4) during state 2rr)rrr closeChildFDrs r"r`zFDChecker.childConnectionLosthsj ::? II=G H  ::?!| IGSTDJ NN ' ' *  r%cf|jj}|jdk7r|jd|zy|jjdk7r)|jd|jjzy|dk7r|jd|zy|j j dy)NrzprocessEnded early, rc %dzprocessEnded with signal %srzprocessEnded with rc %d)rrrrrrrr{)r rrcs r"r}zFDChecker.processEndedts \\ " " ::? II1B6 7  <<  $ & II3fll6I6II J  7 II/"4 5  t$r%) r/r0r1rr!rrwrrrIr`r}r3r%r"rr6s0 E D F% D  %r%rceZdZdZdZy)FDTestsc d}tj}t|tjt t dd|gt ddddddd|jfd |S) Nstwisted.test.process_fdsr"r#wrrS)rrGrSrrrrchildFDscPjjjSr)rPr)xrLr s r"z!FDTests.test_FD..s 0 0188 Dr%)r rrrrrr r )r rrvrLs` @r"test_FDzFDTests.test_FDsd0 NN  aL  E5* -sssC   DEr%c d}ttjx}_t j t t dd|gtdddfd}|j|S) Nstwisted.test.process_lingerr"r#rrS)rGrSrcZjjjdy)Nshere is some text goodbye )rJrrrs r"r}z)FDTests.test_linger..processEndeds   QVV__.0O Pr%r^rs` @r" test_lingerzFDTests.test_lingerse4 M#nn..AO  E5* -^   Q}}\**r%N)r/r0r1rrr3r%r"rrs +r%rc<eZdZdZdZdZdZdZdZdZ dZ d Z y) r zAccumulate data from a process.rNc@t|_t|_yr)r rrr)s r"rzAccumulator.connectionMadesI I r%c:|jj|yr)rrrus r"r#zAccumulator.outReceived r%c:|jj|yr)rrrus r"r'zAccumulator.errReceivedrr%cyrr3r)s r"r,zAccumulator.outConnectionLostrjr%cyrr3r)s r"r.zAccumulator.errConnectionLostrjr%cvd|_|j&|jdc}|_|jdyyrl)closedr r{)r rzrvs r"r}zAccumulator.processEndeds;    )$($6$6 !At! JJt  *r%) r/r0r1r2rr rr#r'r,r.r}r3r%r"r r s-) FM  r%r cVeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd Zy)PosixProcessBasez! Test running processes. Fctj|D]&}t|jjcStdj |}tdj |}|j r|jjS|j r|jjSt|dtjdd)zq Return the path of the shell command named C{commandName}, looking at common locations. z/binz/usr/binz1 found in neither standard location nor on PATH (PATH)) rwhichr asBytesModerchildexistsrrr`)r commandNamelocbinLoc usrbinLocs r" getCommandzPosixProcessBase.getCommands ??;/ 4CC=,,.33 3 4&!'' 4Z(..{; ==?%%',, ,    ((*// /-PQSQ[Q[\bQcPddef r%cjd}tj}t|t j |dgdj fd}|j||S)Nr/struerwcjjtjj jj j djjj jyr) rzr7r rrJrrr&rrRs r"rz6PosixProcessBase.test_normalTermination..checksS HHMM%++ ,   QXX^^44a 8   ahhnn33 4r%)rr rrprrrr )r cmdrvrrLs` @r"test_normalTerminationz'PosixProcessBase.test_normalTerminations[oof% NN  "1 %QgYDM 5 er%ctj}t|tjt t ddgdj fd}|j||S)z When a process terminates with a system exit code set to 1, C{processEnded} is called with a L{error.ProcessTerminated} error, the C{exitCode} attribute reflecting the system exit code. -csimport sys; sys.exit(1)Nrwcjjtjj jj j djjj jyrl) rzr7r rrJrrr&rrRs r"rz8PosixProcessBase.test_abnormalTermination..checksS HHMM%11 2   QXX^^44a 8   ahhnn33 4r%)r rrprrrrr )r rvrrLs` @r"test_abnormalTerminationz)PosixProcessBase.test_abnormalTerminations\ NN  "1 %  E5 6;;   5 er%cd}tj}t||}tj|t t dd|gt |j|S)Ntwisted.test.process_signalr"rrw)r rrrrrr rr rrrvrLs r" _testSignalzPosixProcessBase._testSignal sP3 NN  1c "  E4 ,;;  r%c$|jdS)ai Sending the SIGHUP signal to a running process interrupts it, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} set to L{None} and the C{signal} attribute set to C{signal.SIGHUP}. C{os.WTERMSIG} can also be used on the C{status} attribute to extract the signal value. HUPrr)s r"test_signalHUPzPosixProcessBase.test_signalHUP&&r%c$|jdS)ai Sending the SIGINT signal to a running process interrupts it, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} set to L{None} and the C{signal} attribute set to C{signal.SIGINT}. C{os.WTERMSIG} can also be used on the C{status} attribute to extract the signal value. r6rr)s r"test_signalINTzPosixProcessBase.test_signalINT!rr%c$|jdS)ak Sending the SIGKILL signal to a running process interrupts it, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} set to L{None} and the C{signal} attribute set to C{signal.SIGKILL}. C{os.WTERMSIG} can also be used on the C{status} attribute to extract the signal value. KILLrr)s r"test_signalKILLz PosixProcessBase.test_signalKILL+''r%c$|jdS)ak Sending the SIGTERM signal to a running process interrupts it, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} set to L{None} and the C{signal} attribute set to C{signal.SIGTERM}. C{os.WTERMSIG} can also be used on the C{status} attribute to extract the signal value. TERMrr)s r"test_signalTERMz PosixProcessBase.test_signalTERM5rr%ctj}tj|tj}|jtjtj||j tjS)z The disposition of signals which are ignored in the parent process is reset to the default behavior for the child process. )rSIGUSR1SIG_IGN addCleanupr)r rhandlers r"test_childSignalHandlingz)PosixProcessBase.test_childSignalHandling?sR --v~~6  v~~w?//r%ctjjrjr t dj d}t j}t|d}tj}|t_ dt_ tj|dgdjfd}|j||t_ |S#|t_ wxYw) zJ Raise an error during execvpe to check error management. z+Test is flaky from a Darwin bug. See #8840.falsectd)NOuch)r)commandrJ environments r" buggyexecvpez:PosixProcessBase.test_executionError..buggyexecvpees v& &r%TsfalseNrwcdjjjz}jd|jd|y)Nr%s Upon execvpesOuch)rrtrsassertIn)r(rtrLr s r"rz3PosixProcessBase.test_executionError..checkps:((199qyy#89 ow7 gw/r%)rrcisMacOSXrrrr rrprexecvper_neverUseSpawnrr )r rrvr oldexecvperrLs` @r"test_executionErrorz$PosixProcessBase.test_executionErrorYs    $ $ &4;;HI Ioog& NN  "1 % 'ZZ ! "& $  C(dkk R 0 MM% #BJ$BJs .ErrorInProcessEndedzM A protocol that raises an error in C{processEnded}. c(j|yrr{r r connecteds r"makeConnectionzUPosixProcessBase.test_errorInProcessEnded..ErrorInProcessEnded.makeConnection""9-r%c\tjdjdtd)NrzDeliberate error)rrr{rr rzendeds r"r}zSPosixProcessBase.test_errorInProcessEnded..ErrorInProcessEnded.processEndeds%!!!U^^T:"#566r%Nr/r0r1r2rr}rr sr"ErrorInProcessEndedrs  . 7r%rr"r#NrYcj|jj|jtj|j yr)r?r'rrreapProcessHandlersr|)rr'r s r" cbConnectedz>PosixProcessBase.test_errorInProcessEnded..cbConnecteds9 JJy}} % MM)--)D)D E  $ $ &r%cjt}jt|dj dt j y)NrGr)flushLoggedErrorsrrJr assertNotInrr)r(excsr'r s r"checkTerminatedzBPosixProcessBase.test_errorInProcessEnded..checkTerminatedsA)),7D   SY *   SVW%@%@ Ar%) r rrr8rrrr r )r rrrrrr r's` @@@r"test_errorInProcessEndedz)PosixProcessBase.test_errorInProcessEndedzs NN$  4  7(":": 7   !  E5* -   ' k* B /* r%N)r/r0r1r2rrrrrrrrrrrrr3r%r"rrsFF( 0 ''((04B6r%rceZdZdZdZdZy) MockSignalzF Neuter L{signal.signal}, but pass other attributes unscathed c,tj|Sr)r getsignal)r ractions r"rzMockSignal.signals$$r%c"tt|Sr)rr)r attrs r" __getattr__zMockSignal.__getattr__svt$$r%N)r/r0r1r2rr r3r%r"rrs%%r%rcHeZdZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZdZdZdZd Zd Zd Zd Zd ZdZdZdZdZdZdddddddddZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&d Z'd!Z(d"Z)d#Z*d$Z+d%Z,d&Z-d'Z.d(Z/d)Z0d*Z1d+Z2d,Z3d-Z4d.Z5d/Z6d0Z7d1Z8y)2MockOSaF The mock OS: overwrite L{os}, L{fcntl} and {sys} functions with fake ones. @ivar exited: set to True when C{_exit} is called. @type exited: C{bool} @ivar O_RDWR: dumb value faking C{os.O_RDWR}. @type O_RDWR: C{int} @ivar O_NOCTTY: dumb value faking C{os.O_NOCTTY}. @type O_NOCTTY: C{int} @ivar WNOHANG: dumb value faking C{os.WNOHANG}. @type WNOHANG: C{int} @ivar raiseFork: if not L{None}, subsequent calls to fork will raise this object. @type raiseFork: L{None} or C{Exception} @ivar raiseExec: if set, subsequent calls to execvpe will raise an error. @type raiseExec: C{bool} @ivar fdio: fake file object returned by calls to fdopen. @type fdio: C{BytesIO} or C{BytesIO} @ivar actions: hold names of some actions executed by the object, in order of execution. @type actions: C{list} of C{str} @ivar closed: keep track of the file descriptor closed. @type closed: C{list} of C{int} @ivar child: whether fork return for the child or the parent. @type child: C{bool} @ivar pipeCount: count the number of time that C{os.pipe} has been called. @type pipeCount: C{int} @ivar raiseWaitPid: if set, subsequent calls to waitpid will raise the error specified. @type raiseWaitPid: L{None} or a class @ivar waitChild: if set, subsequent calls to waitpid will return it. @type waitChild: L{None} or a tuple @ivar euid: the uid returned by the fake C{os.geteuid} @type euid: C{int} @ivar egid: the gid returned by the fake C{os.getegid} @type egid: C{int} @ivar seteuidCalls: stored results of C{os.seteuid} calls. @type seteuidCalls: C{list} @ivar setegidCalls: stored results of C{os.setegid} calls. @type setegidCalls: C{list} @ivar path: the path returned by C{os.path.expanduser}. @type path: C{str} @ivar raiseKill: if set, subsequent call to kill will raise the error specified. @type raiseKill: L{None} or an exception instance. @ivar readData: data returned by C{os.read}. @type readData: C{str} FNTrr%cg|_g|_d|_d|_d|_d|_d|_d|_d|_d|_ g|_ g|_ y ) z- Initialize data structures. rrgricyrr3rs r"rz!MockOS.__init__..r%cyrlr3r's r"rz!MockOS.__init__..r(r%N) actionsr pipeCountO_RDWRO_NOCTTYWNOHANGF_GETFD FD_CLOEXEC WEXITSTATUS WIFEXITED seteuidCalls setegidCallsr)s r"rwzMockOS.__init__s[      &$r%cy)zK Fake fcntl.fcntl for CLOEXEC file descriptor enumeration. rr3)r opflargs r"fcntlz MockOS.fcntl#sr%cy)ze Fake C{os.open}. Return a non fd number to be sure it's not used elsewhere. r3)r devflagss r"openz MockOS.open)s r%c,tjdS)zT Fake C{os.fstat}. Return a C{os.stat_result} filled with garbage. ) rrrrrrrrrr)r stat_resultr fds r"fstatz MockOS.fstat0s~~i((r%cF|dk(rt|_|jSJ)zz Fake C{os.fdopen}. Return a file-like object whose content can be tested later via C{self.fdio}. wb)r fdio)r rBflags r"fdopenz MockOS.fdopen6s' 4< DIyy 5r%c:|jjdy)z1 Fake C{os.setsid}. Save action. setsidNr*r?r)s r"rJz MockOS.setsidAs H%r%c|jjdtjf|j |j|j ryy)z Fake C{os.fork}. Save the action in C{self.actions}, and return 0 if C{self.child} is set, or a dumb number. forkr)r*r?gc isenabled raiseForkrr)s r"rMz MockOS.forkGsB VR\\^45 >> %.. ZZr%c:|jj|y)zK Fake C{os.close}, saving the closed fd in C{self.closed}. N)rr?rAs r"r~z MockOS.closeUs 2r%cy)z. Fake C{os.dup2}. Do nothing. Nr3)r fd1fd2s r"dup2z MockOS.dup2[r(r%c@|jjd||fy)z0 Fake C{os.write}. Save action. rNrK)r rBr!s r"rz MockOS.write`s Wb$/0r%cV|jjd||f|jS)z Fake C{os.read}: save action, and return C{readData} content. @param fd: The file descriptor to read. @param size: The maximum number of bytes to read. @return: A fixed C{bytes} buffer. read)r*r?readData)r rBsizes r"rYz MockOS.readfs' VR./}}r%ch|jjd|jr tdy)zn Fake C{os.execvpe}. Save the action, and raise an error if C{self.raiseExec} is set. execBarN)r*r? raiseExecr)r rrJrs r"rzMockOS.execvpess- F# >>u% % r%r3) file_actions setpgroupresetidsrJ setsigmask setsigdef schedulerc:|jjdy)z; Fake C{os.posix_spawnp}. Save the action. posix_spawnpNrK) r rrrr`rarbrJrcrdres r"rgzMockOS.posix_spawnp|s" N+r%cn|xjdz c_d|jzdzd|jzfS)z Fake C{os.pipe}. Return non fd numbers to be sure it's not used elsewhere, and increment C{self.pipeCount}. This is used to uniquify the result. rGr$)r+r)s r"pipez MockOS.pipes4 !DNN"Q&T^^(;;;r%cy)z; Fake C{os.ttyname}. Return a dumb string. foor3rAs r"ttynamezMockOS.ttynamesr%c^|jjd|fd|_t)zs Fake C{os._exit}. Save the action, set the C{self.exited} flag, and raise C{SystemError}. exitT)r*r?exited SystemError)r codes r"_exitz MockOS._exits+ VTN+ mr%cy)z6 Override C{fcntl.ioctl}. Do nothing. Nr3)r rBr=r8s r"ioctlz MockOS.ioctlr(r%cy)z? Override C{fdesc.setNonBlocking}. Do nothing. Nr3rAs r"setNonBlockingzMockOS.setNonBlockingr(r%c|jjd|j |j|j |jSy)z Override C{os.waitpid}. Return values meaning that the child process has exited, save executed action. waitpid)rGr)r*r? raiseWaitPid waitChild)r r'optionss r"rxzMockOS.waitpidsE I&    (## # >> %>> !r%cy)zD Override C{sys.settrace} to keep coverage working. Nr3)r r8s r"settracezMockOS.settracer(r%cy)z> Override C{os.getgid}. Return a dumb number. ir3r)s r"getgidz MockOS.getgidr%cy)z> Override C{os.getuid}. Return a dumb number. ir3r)s r"getuidz MockOS.getuidrr%c>|jjd|fy)z4 Override C{os.setuid}. Do nothing. setuidNrKr vals r"rz MockOS.setuid XsO,r%c>|jjd|fy)z4 Override C{os.setgid}. Do nothing. setgidNrKrs r"rz MockOS.setgidrr%c@|jjd||fy)z6 Override C{os.setregid}. Do nothing. setregidNrKr val1val2s r"rzMockOS.setregid Zt45r%c@|jjd||fy)z< Override C{os.setreuid}. Save the action. setreuidNrKrs r"rzMockOS.setreuidrr%c@|jjd||fy)z> Override L{util.switchUID}. Save the action. switchuidNrK)r uidgids r" switchUIDzMockOS.switchUIDs [#s34r%cy)zK Override C{pty.openpty}, returning fake file descriptors. )r3r)s r"openptyzMockOS.openptysr%c>|jjd|fy)z{ Override C{os.chdir}. Save the action. @param path: The path to change the current directory to. chdirNrKr rs r"rz MockOS.chdir WdO,r%c|jS)zE Mock C{os.geteuid}, returning C{self.euid} instead. )euidr)s r"geteuidzMockOS.geteuidyyr%c|jS)zE Mock C{os.getegid}, returning C{self.egid} instead. )egidr)s r"getegidzMockOS.getegidrr%c:|jj|y)z3 Mock C{os.seteuid}, store result. N)r3r?r rs r"seteuidzMockOS.seteuid   &r%c:|jj|y)z3 Mock C{os.setegid}, store result. N)r4r?rs r"setegidzMockOS.setegidrr%c|jS)z- Mock C{os.path.expanduser}. )rrs r" expanduserzMockOS.expanduserrr%cy)z' Mock C{pwd.getpwnam}. )rrrGrSr3)r users r"getpwnamzMockOS.getpwnamr%cy)zN Override C{os.listdir}, returning fake contents of '/dev/fd' )z-1z-2r3rs r"listdirzMockOS.listdir rr%cp|jjd||f|j |jy)zh Override C{os.kill}: save the action and raise C{self.raiseKill} if specified. rN)r*r? raiseKill)r r'signalIDs r"rz MockOS.kill&s6 VS(34 >> %..  &r%c>|jjd|fy)zl Override C{os.unlink}. Save the action. @param filename: The file name to remove. unlinkNrK)r filenames r"rz MockOS.unlink/s Xx01r%c>|jjd|fy)zo Override C{os.umask}. Save the action. @param mask: The new file mode creation mask. umaskNrK)r masks r"rz MockOS.umask7rr%cy)zL Return a fixed PID value. @return: A fixed value. ir3r)s r"getpidz MockOS.getpid?s r%cy)z` Return a fixed filesystem encoding. @return: A fixed value of "utf8". utf8r3r)s r"getfilesystemencodingzMockOS.getfilesystemencodingGs r%)9r/r0r1r2ror_rFrryrQrzrrrrrZrwr9r>rCrHrJrMr~rVrrYrrgrirlrrrtrvrxr}rrrrrrrrrrrrrrrrrrrrrr3r%r"r"r"s+CJFI D ELII D D DIH" ) &   1 &,&<      - - 6 6 5  -  ' '    !2-r%r"ceZdZdZdZy)DumbProcessWriterz1 A fake L{ProcessWriter} used for tests. cyz< Here's the faking: don't do anything here. Nr3r)s r" startReadingzDumbProcessWriter.startReadingUr(r%Nr/r0r1r2rr3r%r"rrP  r%rceZdZdZdZy)DumbProcessReaderz1 A fake L{ProcessReader} used for tests. cyrr3r)s r"rzDumbProcessReader.startReading`r(r%Nrr3r%r"rr[rr%rceZdZdZdZy)DumbPTYProcessz. A fake L{PTYProcess} used for tests. cyrr3r)s r"rzDumbPTYProcess.startReadingkr(r%Nrr3r%r"rrfrr%rceZdZdZy) ForkOrSpawnc|dk(ry|dk(ryy)NrMFTrgFr3)r others r"__eq__zForkOrSpawn.__eq__rs O # N "r%N)r/r0r1rr3r%r"rrqsr%rceZdZdZedZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ y)MockProcessTestsz? Mock a process runner to test forked child code path. Nz1twisted.internet.process is never used on Windowsctjr |jtjn|jtjt |_d|j _d|j _|jtd|j |jtd|j |jtd|j |jtd|j j|jtd|j |jtjdt|jtjd t|jtjd d |jtd |j t|_|jtd |j y)z| Replace L{process} os, fcntl, sys, switchUID, fdesc and pty modules with the mock class L{MockOS}. irr9rrfdescprocessReaderFactoryprocessWriterFactory_trySpawnInsteadOfForkcyrr3)ars r"rz(MockProcessTests.setUp..r(r%ptyrN)rOrPrenabledisabler"mockosrrrrrProcessrrrmocksigr)s r"ruzMockProcessTests.setUps+ <<> OOBII & OOBJJ 'h    7D$++. 7GT[[1 7E4;;/ 7K)>)>? 7GT[[1 7??$:ST 7E4;;/!|  7Hdll3r%cit_y)z6 Reset processes registered for reap. N)rrr)s r"rzMockProcessTests.tearDowns ')#r%cd|j|jjtdgy)z} A process should have been launched, but I don't care whether it was with fork() or posix_spawnp(). rxN)rJrr*rr)s r"assertProcessLaunchedz&MockProcessTests.assertProcessLauncheds% ,,{}i.HIr%ctjd}tj}t |} t j ||dgdd|jd|jtjy#t$rP|j|jj|j|jjgdY|wxYw)zk Test a classic spawnProcess. Check the path of the client code: fork, exec, exit. /mock/ouchouchNFrwShould not be hererr]rnrG)rOrr rrprrrrpr+rrorJr*rPrPr rrvrLs r" test_mockForkzMockProcessTests.test_mockForks  NN  "1 % ,  C'U K II* + (  OODKK.. /    ##%K  sBAC C c d|j_d}tj}t |}t j ||dgdd|jt|jjhd|jy)z Assert that in the main process, spawnProcess disables the garbage collector, calls fork, closes the pipe file descriptors it created for the child process, and calls waitpid. FrrNrw>r%rg) rrr rrprrrJsetrrrs r"_mockForkInParentTestz&MockProcessTests._mockForkInParentTestsn "  NN  "1 %QgYDG T[[//0,? ""$r%ctj|j|jtjy)z The garbage collector should be enabled when L{reactor.spawnProcess} returns if it was initially enabled. @see L{_mockForkInParentTest} N)rOrrr+rPr)s r",test_mockForkInParentGarbageCollectorEnabledz=MockProcessTests.test_mockForkInParentGarbageCollectorEnableds+  ""$  'r%ctj|j|jtjy)z The garbage collector should be disabled when L{reactor.spawnProcess} returns if it was initially disabled. @see L{_mockForkInParentTest} N)rOrrrPrPr)s r"-test_mockForkInParentGarbageCollectorDisabledz>MockProcessTests.test_mockForkInParentGarbageCollectorDisableds-  ""$ (r%c 6d}tj}t|}|jtt j ||dgdd|j|jj|j|jjgdy)zg Test a TTY spawnProcess: check the path of the client code: fork, exec, exit. rrNTrw)rrJr]r) r rrpr8rprrr+rrorJr*rs r"test_mockForkTTYz!MockProcessTests.test_mockForkTTYs  NN  "1 %  --q#ydSW    **+  KK  !Q r%cttjd|j_t d}|j ttj|d|j|jjdgy)z Assert that if the fork call fails, no other process setup calls are made and that spawnProcess raises the exception fork raised. Nr) rerrnoEAGAINrrQrpr8rrrJr*r rs r"_mockWithForkErrorz#MockProcessTests._mockWithForkErrors\ !( d ; )$/ '7#7#74H ,,.?@r%ctj|j|jtjy)z The garbage collector should be enabled when L{reactor.spawnProcess} raises because L{os.fork} raised, if it was initially enabled. N)rOrrr+rPr)s r"-test_mockWithForkErrorGarbageCollectorEnabledz>MockProcessTests.test_mockWithForkErrorGarbageCollectorEnableds+  !  'r%ctj|j|jtjy)z The garbage collector should be disabled when L{reactor.spawnProcess} raises because L{os.fork} raised, if it was initially disabled. N)rOrrrPrPr)s r".test_mockWithForkErrorGarbageCollectorDisabledz?MockProcessTests.test_mockWithForkErrorGarbageCollectorDisabled s-  ! (r%c|j|jt|jjhdy)z} When C{os.fork} raises an exception, the file descriptors created before are closed and don't leak. >rr%r;r$rgN)rrJrrrr)s r"test_mockForkErrorCloseFDsz+MockProcessTests.test_mockForkErrorCloseFDss0 ! T[[//02JKr%c ttjd|j_t d}|j ttj|ddddd|j|jjdg|j|jjg|j ttj|ddddd|jt|jjd d hy) z When C{os.forks} raises an exception and that file descriptors have been specified with the C{childFDs} arguments of L{reactor.spawnProcess}, they are not closed. Niir)rrGrSrrrrgr$) rrrrrQrpr8rrrJr*rrrs r"test_mockForkErrorGivenFDsz+MockProcessTests.test_mockForkErrorGivenFDss !( d ; )$/     -   ,,.?@ ++R0     -   T[[//02r(;r%clttjd|j_t d}|j ttj|dd|j|jjdg|jt|jjddhy)z When C{os.fork} raises an exception, the file descriptors created by C{pty.openpty} are closed and don't leak, when C{usePTY} is set to C{True}. NTrrrr) rrrrrQrpr8rrrJr*rrrs r"test_mockForkErrorClosePTYz+MockProcessTests.test_mockForkErrorClosePTY8s !( d ; )$/ '7#7#74PTU ,,.?@ T[[//03*=r%cVttjd|j_t d}|j ttj|dd|j|jjdg|j|jjgy)z If a tuple is passed to C{usePTY} to specify slave and master file descriptors and that C{os.fork} raises an exception, these file descriptors aren't closed. N)iirkrr) rrrrrQrpr8rrrJr*rrs r"test_mockForkErrorPTYGivenFDsz.MockProcessTests.test_mockForkErrorPTYGivenFDsDs !( d ; )$/  W))8TBS   ,,.?@ ++R0r%cd}tj}t|}d|j_ t j ||dgdd|jdy#t$r|j|jj|j|jjgd|jd |jj|jd |jj|jd |jj|jd |jjj!YywxYw) z Spawn a process but simulate an error during execution in the client path: C{os.execvpe} raises an error. It should close all the standard fds, try to print the error encountered, and exit cleanly. rTrNFrwrrrrGrSsRuntimeError: Bar)r rrprr_rrrrpr+rorJr*rrrFrrs r"test_mockWithExecErrorz'MockProcessTests.test_mockWithExecErrorRs   NN  "1 % $  ,  C'U K II* + M OODKK.. /    ##%K  MM!T[[// 0 MM!T[[// 0 MM!T[[// 0 MM. 0@0@0I0I0K L MsA!!C.pipes9 yy|UYYq\11 i s!%9N>r%r;r$rg) rrirpr8rrrrJr*rr)r rirr,s @r"test_mockErrorInPipez%MockProcessTests.test_mockErrorInPipes{ !   )$/ '7#7#74H ,,b1 T[[//02BCr%c.d|j_d|j_d}td}t j ||dgdd}|j d|j|jjdd d d tjfgy) z{ L{process.Process.signalProcess} calls C{os.kill} translating the given signal string to the PID. Fr rNrrwrrrxrrN) rrrzrprrrrJr*rSIGKILLr rrLr"s r"rzMockProcessTests.test_kills "  &  "4 (##AsWI4N 6"  KK   i&"fnn)E F r%cd|j_d}td}tj||dgdd}|j t j|jdy)zz L{process.Process.signalProcess} raises L{error.ProcessExitedAlready} if the process has exited. FrNrrwr) rrrprrr8r r9rr0s r"test_killExitedz MockProcessTests.test_killExited sY "  "4 (##AsWI4N %44d6H6H&Qr%c@d|j_d|j_d}td}t j ||dgdd}t tjd|j_ |jtj|jdy) a* L{process.Process.signalProcess} raises L{error.ProcessExitedAlready} if the process has exited but that twisted hasn't seen it (for example, if the process has been waited outside of twisted): C{os.kill} then raise C{OSError} with C{errno.ESRCH} as errno. Fr rNrrwz Not foundr)rrrzrprrrrESRCHrr8r r9rr0s r"test_killExitedButNotDetectedz.MockProcessTests.test_killExitedButNotDetectedsz"  &  "4 (##AsWI4N ' [ A  %44d6H6H&Qr%cd|j_d|j_d}td}t j ||dgdd}t tjd|j_ |jt |jd}|j|jtjy) z L{process.Process.signalProcess} doesn't mask C{OSError} exceptions if the errno is different from C{errno.ESRCH}. Fr rNrrwzInvalid signalr) rrrzrprrrrEINVALrr8rrJ)r rrLr"rs r"test_killErrorInKillz%MockProcessTests.test_killErrorInKill(s "  &  "4 (##AsWI4N ' 6F G ););VD ELL1r%)!r/r0r1r2rskiprurrrrrrrrrrrrr r rrrrrr$r'r-rr2r5r8r3r%r"rrzsB42) J)0% ( ) "A()L<8 > 1,6,6 %,:%& $$D& R R 2r%rceZdZdZdZy)PosixProcessTestsc d}ttjx}_t j t t dtdj|gddjfd}|j|S)z Bytes written to stderr by the spawned process are passed to the C{errReceived} callback on the C{ProcessProtocol} passed to C{spawnProcess}. 42rz"import sys; sys.stderr.write('{}')N/tmprcZjdjjy)Ns42)rJrrrs r"r}z3PosixProcessTests.test_stderr..processEndedVs   UAFFOO$5 6r%) r r rr rrrrformatrr )r rrvr}rLs` @r" test_stderrzPosixProcessTests.test_stderr?s|  M#nn..AO ELLUST  ;;  7}}\**r%c`jd}dttjx}_t j ||dgddjjjjjfd}|j|S)NgzipsTthere's no place like home! there's no place like home! there's no place like home! rr>rcj}|jddtj|5}j |j dddy#1swYyxYw)Nr)fileobj)rseekrCGzipFilerJrY)r r?gfrLrr s r"r}z4PosixProcessTests.test_process..processEndedfsRA FF1aLq) /R  A. / / /s !A  A)) rr r rr rrrrrrr )r rrvr}rLrs` @@r"r@zPosixProcessTests.test_process[soof% 0 M#nn..AO sS%Ld   !   / }}\**r%N)r/r0r1rAr@r3r%r"r;r;7s +8+r%r;c eZdZdZdZdZdZy)PosixProcessPTYTestszE Just like PosixProcessTests, but use ptys instead of pipes. Tc d}ttjx}_t j t t dd|gtjjjdfd}|j|S)Nstwisted.test.process_ttyr"r#rws hello world! cjtjjjdj j jddj jdy)Nrshello world! hello world! z)Error message from process_tty follows: z )r8r r9rrrJrrrs r"r}z:PosixProcessPTYTests.test_openingTTY..processEndeds_   **AKK,E,Eu    !3-.FFOO,=@  r%) r r rr rrrr rrrr rs` @r"test_openingTTYz$PosixProcessPTYTests.test_openingTTYsw0 M#nn..AO  E5* -;;   +, }}\**r%c tdddg}t}|jttj |t|dddiy)Nr"rprint('hello')rGr)rrrr r8rrrr pyArgsrLs r" test_badArgsz!PosixProcessPTYTests.test_badArgssJ'89 M     Y  r%N)r/r0r1r2rrMrTr3r%r"rJrJos F+8  r%rJceZdZdZdZy)Win32SignalProtocolz A win32-specific process protocol that handles C{processEnded} differently: processes should exit with exit code 1. c^|jtjs'|jj t d|S|j }|jdk7r1|jj t d|jS|jjdy)z Callback C{self.deferred} with L{None} if C{reason} is a L{error.ProcessTerminated} failure with C{exitCode} set to 1. Otherwise, errback with a C{ValueError} describing the problem. rrGzWrong exit code: N) rr rrrrrrrr{)r rzrs r"r}z Win32SignalProtocol.processEndeds ||E334==((6I&4R)ST T LL ::?==((6G |4T)UV V t$r%N)r/r0r1r2r}r3r%r"rVrVs  %r%rVcFeZdZdZdZdZdZdZdZdZ dZ d Z d Z y ) Win32ProcessTestsz? Test process programs that are packaged with twisted. cttjx}_t j ||||j jdj jfd}|j|S)zH Spawn a process, write to stdin, and check the output. rcjjjdjjjdy)Nserr err sout hello, world out )rJrrrrs r"r}z9Win32ProcessTests._test_stdinReader..processEndeds:   QVV__. >   QVV__.0K Lr%) r r rr rrrrrr )r rrJrrrvr}rLs` @r"_test_stdinReaderz#Win32ProcessTests._test_stdinReadersn M#nn..AOQtS$7 /*   M}}\**r%cddl}ttjj }|dddg}t t j}t jjtjjtj|d<|j}|jtj}|j||||}|S)z= Pass L{bytes} args to L{_test_stdinReader}. rNr"r#s twisted.test.process_stdinreaders PYTHONPATH)win32apirr executable _asBytesPathdictrr`pathseprrencoder GetTempPathr\)r r^rrJrrrvs r"test_stdinReader_bytesArgsz,Win32ProcessTests.test_stdinReader_bytesArgss (557ue%HI2::ZZ__SXX6==  % % ' M##%{{34467  " "5$T :r%cddl}ttjj}|dddg}t }t jjtj}||d<|j}|j||||}|S)z? Pass L{unicode} args to L{_test_stdinReader}. rNrrz twisted.test.process_stdinreaderr) r^rrr_rr rrbrrdr\)r r^rrJr pythonPathrrvs r"test_stdinReader_unicodeArgsz.Win32ProcessTests.test_stdinReader_unicodeArgssx (--tT#EFZZ__SXX. &L##%  " "5$T :r%c tdddg}t}|jttj |t|d|jttj |t|d|jttj |t|d|jttj |t|ddi y) Nr"rrOrG)r)rrrrrQrRs r"rTzWin32ProcessTests.test_badArgss'89 M *g&:&:AufRST *g&:&:AufRST *g&:&:AufUVW  ,,a!S  r%cd}tj}t||}tj|t t dd|gt |S)Nrr"r#r)r rrVrrrr rs r"rzWin32ProcessTests._testSignal sA3 NN  3 'QueZ'HiXr%c$|jdS)z Sending the SIGTERM signal terminates a created process, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} attribute set to 1. rrr)s r"rz!Win32ProcessTests.test_signalTERM  ''r%c$|jdS)z Sending the SIGINT signal terminates a created process, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} attribute set to 1. r6rr)s r"rz Win32ProcessTests.test_signalINT s &&r%c$|jdS)z Sending the SIGKILL signal terminates a created process, and C{processEnded} is called with a L{error.ProcessTerminated} instance with the C{exitCode} attribute set to 1. rrr)s r"rz!Win32ProcessTests.test_signalKILL rlr%c ddl tjtjGfddtj}|}t dddg}t j|t | fd}j| fd }j|tjgS) zU The win32 handles should be properly closed when the process exits. rNc&eZdZdZfdZfdZy);Win32ProcessTests.test_closeHandles..SimpleProtocolzZ A protocol that fires deferreds when connected and disconnected. c(j|yrrrs r"rzJWin32ProcessTests.test_closeHandles..SimpleProtocol.makeConnection0 r r%c(jdyrrr s r"r}zHWin32ProcessTests.test_closeHandles..SimpleProtocol.processEnded3 st$r%Nr rsr"SimpleProtocolrq+ s  . %r%rtr"rrOcj|jjjjj_j_yr)assertIsGetHandleInformationhProcesshThread)rr"r r^s r"rz8Win32ProcessTests.test_closeHandles..cbConnected: sK MM)T *  ) )$-- 8  ) )$,, 7 MMDM<.checkTerminatedE s   dhh '   dmm ,   dll +    = =t}}     = =t|| r%) r^r rrr8rrrr r) r rtrLrSrrrr r"r^s ` @@@@r"test_closeHandlesz#Win32ProcessTests.test_closeHandles" s NN$   %X55 %  '89##Auf5 ( k*  /*""Iu#566r%N) r/r0r1r2r\rerhrTrrrrr{r3r%r"rYrYs4 + "  ('(27r%rYceZdZdZdZeejjejk7djejjejdZ y)Win32UnicodeEnvironmentTestsz2 Tests for Unicode environment on Windows c"dtjd<jtjtjdt j tgtj}fd}|jj|S)z C{os.environ} (inherited by every subprocess on Windows) contains Unicode keys and Unicode values which can be ASCII-encodable. VALUE_ASCII KEY_ASCIIc0j|ddy)Ns KEY_ASCIIs VALUE_ASCIIrJ)rr s r"gotEnvironmentz[Win32UnicodeEnvironmentTests.test_AsciiEncodeableUnicodeEnvironment..gotEnvironmentk s   Xl3^ Dr% rr`roperatordelitemrrrrr )r rLrs` r"&test_AsciiEncodeableUnicodeEnvironmentzCWin32UnicodeEnvironmentTests.test_AsciiEncodeableUnicodeEnvironmenta sd #0 ; (("**kB $ ( ("bjj A E{{}((88r%zsys.stdout.encoding: {} does not match sys.getfilesystemencoding(): {} . May need to set PYTHONUTF8 and PYTHONIOENCODING environment variables.c2d}dd}|tj|<jtjtj|t j tgtj}fd}|jj|S)zt L{os.environ} (inherited by every subprocess on Windows) can contain a UTF-8 string value. !TWISTED_BUILD_SOURCEVERSIONAUTHORs!TWISTED_BUILD_SOURCEVERSIONAUTHORSpeciał Committórcj|j|djtjj y)Nr)rrJrcrrencoding)r envKeyBytesr s r"rzQWin32UnicodeEnvironmentTests.test_UTF8StringInEnvironment..gotEnvironment s? MM+x 0   %'<'C'CCJJDWDW'X r%r)r envKeyenvValrLrrs` @r"test_UTF8StringInEnvironmentz9Win32UnicodeEnvironmentTests.test_UTF8StringInEnvironmentp sr5: &# 6 (("**f= $ ( ("bjj A  {{}((88r%N) r/r0r1r2rrrrrrr@rr3r%r"r}r}W so  9  8s88:: AAG JJ  !:!:!:!<B 99r%r}ceZdZdZdZdZy)DumbWin32ProcTestsz3 L{twisted.internet._dumbwin32proc} tests. c ddlm}ddlm}j |d|t t jdj}t tjj}tj}t|}d}|d||g}|jt|d|id j!d j"j!d t%  fd } |j'| S) z Simple test for the pid attribute of Process on win32. Launch process with mock win32process. The only mock aspect of this module is that the pid of the process created will always be 42. r_dumbwin32proc)mock_win32process win32processprocess_cmdline.pyzcmd.exe/cN*zc<jjyrr%)rrLr s r" pidCompleteCbz2DumbWin32ProcTests.test_pid..pidCompleteCb s   aee $r%)twisted.internetr twisted.testrrr__file__siblingrrr_r rrprrrJr'reprr ) r rrrrrv processProtocomspecrrrLs ` @r"test_pidzDumbWin32ProcTests.test_pid s 42 >>3DEh'//0DEJJ (-- NN -a0 eZ0  " "7L$R N QUU# +T!W5 %}}]++r%cddlm}td}|jd||j}|j |dy)zP Look for the string after the shebang C{#!} in a file. r) _findShebangs example.cgis#!/usr/bin/pythonz/usr/bin/pythonN)twisted.internet._dumbwin32procrr setContentrrJ)r r cgiScriptprograms r"test_findShebangz#DumbWin32ProcTests.test_findShebang s@ A^, 12y~~. "34r%N)r/r0r1r2rrr3r%r"rr s ,6 5r%rc4eZdZdZej dZy)Win32CreateProcessFlagsTestsz2 Check the flags passed to CreateProcess. c# Kddlm}g |jj fd}|j |jd|t j }ttjd}tj}t|}ttjd}|d||j g}|j#t$|d|id||j' |jj(gyw) a Verify that the flags passed to win32process.CreateProcess() prevent a new console window from being created. Use the following script to test this interactively:: # Add the following lines to a script named # should_not_open_console.pyw from twisted.internet import reactor, utils def write_result(result): open("output.log", "w").write(repr(result)) reactor.stop() PING_EXE = r"c:\windows\system32\ping.exe" d = utils.getProcessOutput(PING_EXE, ["slashdot.org"]) d.addCallbacks(write_result) reactor.run() To test this, run:: pythonw.exe should_not_open_console.pyw rrc F j| ||||||||| S)a See the Windows API documentation for I{CreateProcess} for further details. @param appName: The name of the module to be executed @param commandLine: The command line to be executed. @param processAttributes: Pointer to SECURITY_ATTRIBUTES structure or None. @param threadAttributes: Pointer to SECURITY_ATTRIBUTES structure or None @param bInheritHandles: boolean to determine if inheritable handles from this process are inherited in the new process @param creationFlags: flags that control priority flags and creation of process. @param newEnvironment: pointer to new environment block for new process, or None. @param currentDirectory: full path to current directory of new process. @param startupinfo: Pointer to STARTUPINFO or STARTUPINFOEX structure @return: True on success, False on failure @rtype: L{bool} r>) appName commandLineprocessAttributesthreadAttributesbInheritHandles creationFlagsnewEnvironmentcurrentDirectory startupinfor=realCreateProcesss r"fakeCreateprocesszBWin32CreateProcessFlagsTests.test_flags..fakeCreateprocess s96 LL '$!    r% CreateProcessrCOMSPECrN)rrrrrrr_rrrr rrprrr`rrrrJCREATE_NO_WINDOW) r rrexerrvrrrr=rs @@r" test_flagsz'Win32CreateProcessFlagsTests.test_flags s0 4*77EE& P >..ARSnnh'//0DE NN -a0 bjj+,c:??3w dCTJ !r~chmodr`raoldPathrb)r jbaservnamemodes r"ruzUtilTests.setUp" s GGLL{{}T5>T5>%( %( %( %( dkk4;; C A KKN t{{L )5 1 txx & . t{{L )5 1 t{{, -u 5 t{{L )1 -   !JD$ t  " " $ HHT4  !zz~~fd3 ZZ__ [[$++t{{DKK @  6r%c2tjtjj|jdt j |j tjd=y|jtjd<y#t$rYywxYw)z Restore the saved PATH setting, and set all created files readable again so that they can be deleted easily. r_Nr) rrrrrstatS_IWUSRrr`KeyErrorr)s r"rzUtilTests.tearDownD sl dkk<8$,,G <<  JJv&"&BJJv   sB BBcptjd=|jtjdgy)z} Test that if C{os.environ} does not have a C{'PATH'} key, L{procutils.which} returns an empty list. rr_N)rr`rJrrr)s r"test_whichWithoutPATHzUtilTests.test_whichWithoutPATHR s) JJv  6;r%cRtjj}tjd}||j d||j dg}tjjr"|j||jd|j||y)Nr_) rrrrrrrrrc isWindowsr?rrJ)r rpaths expectedPathss r" test_whichzUtilTests.test_whichZ sx GGLL -4;; 5ql7ST    % % '  4;; != >  .r%ctjj}tjj dd}tj jdtjd< t jd}|tjd=n|tjd< ||jd||jd||jdg}tjjr"|j||jd|j||y#|tjd=w|tjd<wxYw)NPATHEXT)z.binz.exez.shr_r)rrrr`rarbrrrrrrcrr?rrJ)r roldrrs r"test_whichPathExtzUtilTests.test_whichPathExtb s GGLLjjnnY- " 0G H 9 ,OOL1E{JJy)(+ 9% dkk< ( dkk< ( dkk+ ,    % % '  4;; != >  .{JJy)(+ 9%s ,D44)EN) r/r0r1r2rurrrrr3r%r"rr s!  D .<//r%rc,eZdZdZdZdZdZdZdZy)ClosingPipesProcessProtocolr%cDtj|_||_yr)r rrroutOrErr)r rs r"rwz$ClosingPipesProcessProtocol.__init__{ s(   r%c:|jj|yr)rrr{r|s r"r}z(ClosingPipesProcessProtocol.processEnded s v&r%c.|xj|z c_yr)outputrs r"r#z'ClosingPipesProcessProtocol.outReceived  t r%c.|xj|z c_yr)errputrs r"r'z'ClosingPipesProcessProtocol.errReceived rr%N) r/r0r1rrrwr}r#r'r3r%r"rrw s F F!'r%rc$eZdZdZdZdZdZy)ClosingPipesTestsc *td}|j|jtj|jj |j |tj|ttddtd|fzgd|dk(r|jjn&|dk(r|jjnt|jjd |jj!|jS) a  Create a child process and close one of its output descriptors using L{IProcessTransport.closeStdout} or L{IProcessTransport.closeStderr}. Return a L{Deferred} which fires after verifying that the descriptor was really closed. Tr"rzpinput() import sys, os, time for i in range(1000): os.write(%d, b"foo\n") time.sleep(0.01) sys.exit(42) NrrGrSsgo )r assertFailurerrr rr  _endProcessrrrrr closeStdout closeStderrrrr)r rBrLs r"doitzClosingPipesTests.doit s ( - 1::u'>'>? t//3  %)+u -   ") . 7 KK # # % 1W KK # # %  '"  zzr%c|j|jdd|z|j|jd|jS)zo Check that a failed write prevented the process from getting to its custom exit code. rzprocess reason was %rr%)assertNotEqualrrJrr)r rzrLs r"rzClosingPipesTests._endProcess s= FOOR1H61QR 3'xxr%cVjd}fd}|j||S)zQ ProcessProtocol.transport.closeStdout actually closes the pipe. rGctjjr%jd|jd|njd|tjj dk7rjd|yy)NsOSErrors22sBrokenPipeErrorr0s Broken pipe)rrcrrrdrr s r"rFz-ClosingPipesTests.test_stdout.._check sj))+ j&1 eV, 0&9'')W4 nf55r%rr r rvrFs` r" test_stdoutzClosingPipesTests.test_stdout s* IIaL 6 fr%cVjd}fd}|j||S)zQ ProcessProtocol.transport.closeStderr actually closes the pipe. rSc*j|dyr[rrs r"rFz-ClosingPipesTests.test_stderr.._check s   VS )r%rrs` r"rAzClosingPipesTests.test_stderr s* IIaL * fr%N)r/r0r1rrrrAr3r%r"rr s -^$ r%r)[r2rrOrCrrrrrrrrr9 ImportErrorrr_processtwisted.internet.processrrrobjectrr zope.interface.verifyr r r r rrtwisted.pythonrrtwisted.python.compatrtwisted.python.filepathrtwisted.python.logr twisted.trialr_rrrHrar`r rbrr8rTestCaser5rprrrrrrrIReactorProcessrrfrorcrdrrrrr rrr"rrrrrr;rJrVrYr}rrrrrr3r%r"r s"  % 4QQG.HH-/,""  %% "   **//#((3 ,$(22$.V'8,,V'r"X55"8(%(22(%V $8++ $FE%X--E%P *1 *A@X55A@H-.-$5>" ""7D11-T+8$$T+ T+n %11 %((V  "g-/EF" ""7D11- 4h6G6G G    "g-/LM" ""7D11-,183D3D, N ,^I%((I%X  "g-/LM" ""7D11-!+h!+ N !+H(**:hhV % %NNb      Z z2x((z2z   "g-/LM" ""7D11-0+))+;0+ N 0+f  "g-/LM" ""7D11-4 8,,.>4 N 4 n%.%(  "g-/EF" ""7D11-P7))P7 G P7f  "g-/EF" ""7D11-/98#4#4/9 G /9d  "g-/EF" ""7D11-*5***5 G *5Z  "g-/EF" ""7D11-TP8#4#4TP G TPnX/!!X/v(":":$" ""7D11-X))X XYS E GMMJ s"W:X:XX XX