ϪfhdZddlZddlZddlZddlZddlZddlZddlmZddl Z ddl m Z ddl m Z mZmZddlmZmZddlmZmZddlmZdd lmZdd lmZdd lmZmZdd lm Z m!Z!dd l"m#Z#ddl$m%Z%ddl&m'Z'm(Z(eejRjUZ+dZ,dZ-e.ej^Z0ejbjeejfe0d< ddl m4Z5ejldk7rdZ,dZ-e5Z4ddl7m8Z8de:fdZ;dZ<GddeZ=GddeZ>Gdd e>Z?e@je?jGd!d"e>ZCe@jeCjGd#d$e(ZDGd%d&e(ZEGd'd(e(ZFd)ZGd*ZHe<Gd+d,e'ZIy#e9$r dZ4dZ,dZ-YwxYw)-z Tests for implementations of L{IReactorProcess}. @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)skipIf)utils)DeferredinlineCallbackssucceed) ProcessDoneProcessTerminated)IProcessTransportIReactorProcess)ProcessProtocol)ReactorBuilder) networkString)FilePath_asFilesystemBytes)errmsg)platform) Accumulator)SynchronousTestCaseTestCaseF PYTHONPATHprocessTz$Cannot change UID/GID except as root)_getFileActionsz Cannot change UID/GID on Windowsreturncddlm}m}||dtjdg}t j r|jdt|S)Nr) RLIMIT_NOFILE getrlimit SC_OPEN_MAXi() resourcerrossysconfrisMacOSXappendmin)rrpotentialLimitss D/usr/lib/python3/dist-packages/twisted/internet/test/test_process.py_getRealMaxOpenFilesr)9sI1 /2BJJ}4MNO v&  c:tjdk7rd|_|S)z Only run this test on POSIX platforms. @param testMethod: A test function, being decorated. @return: the C{testMethod} argument. posix%Test only applies to POSIX platforms.)r"nameskip) testMethods r( onlyOnPOSIXr1Js ww'A  r*c"eZdZdZdZdZdZy) _ShutdownCallbackProcessProtocolz An L{IProcessProtocol} which fires a Deferred when the process it is associated with ends. @ivar received: A C{dict} mapping file descriptors to lists of bytes received from the child process on those file descriptors. c ||_i|_yN) whenFinishedreceived)selfr6s r(__init__z)_ShutdownCallbackProcessProtocol.__init__`s( r*cZ|jj|gj|yr5)r7 setdefaultr%)r8fdbytess r(childDataReceivedz2_ShutdownCallbackProcessProtocol.childDataReceivedds!   R(//6r*c:|jjdyr5)r6callbackr8reasons r( processEndedz-_ShutdownCallbackProcessProtocol.processEndedgs ""4(r*N)__name__ __module__ __qualname____doc__r9r>rCr*r(r3r3Ws7)r*r3ceZdZUdZegZeed<dZdZ dZ dZ dZ dZ eeed d d ud d Zd ZdZeej*ddZedZdZdZeeedZeeedZdZy )ProcessTestsBuilderBasez Base class for L{IReactorProcess} tests which defines some tests which can be applied to PTY or non-PTY uses of C{spawnProcess}. Subclasses are expected to set the C{usePTY} attribute to C{True} or C{False}. usePTYc6t}t|}|jj|ttddg|j }|j tj||jfd|jy)z L{IReactorProcess.spawnProcess} connects the protocol passed to it to a transport which provides L{IProcessTransport}. -cr*rKc$jSr5stopignoredreactors r(zHProcessTestsBuilderBase.test_processTransportInterface.. ',,.r*N) rr3 buildReactor spawnProcesspyExerK assertTruer providedBy addCallback runReactor)r8endedprotocol transportrTs @r(test_processTransportInterfacez6ProcessTestsBuilderBase.test_processTransportInterfacews  3E:##%(( eeUC0)  )44Y?@ 89  r*cn|jt}t|dttj zdfd}j ||jfd|j|jdjjdy)a Helper for testing L{IProcessTransport} write functionality. This method spawns a child process and gives C{write} a chance to write some bytes to it. It then verifies that the bytes were actually written to it (by relying on the child process to echo them back). @param write: A two-argument callable. This is invoked with a process transport and some bytes to write to it. s hello, worlds2import sys sys.stdout.write(sys.stdin.readline()) cjttdg} |y#t$r tdd|j dYywxYw)NrMz!Unhandled exception while writingKILL)rXrY BaseExceptionr signalProcess)r` bytesToSendprogramr_rTwrites r(startupz3ProcessTestsBuilderBase._writeTest..startupsU,,XuueW>UVI 0i-  0D=>''/ 0s +&AAc$jSr5rPrRs r(rUz4ProcessTestsBuilderBase._writeTest..rVr*r*N) rWrr3rr"linesepcallWhenRunningr\r] assertEqualjoinr7)r8rir^rjrgrhr_rTs ` @@@@r( _writeTestz"ProcessTestsBuilderBase._writeTests##% 3E:% bjj(AA M 0 0 ( 89   chhx/@/@/C&DEr*c,d}|j|y)z~ L{IProcessTransport.write} writes the specified C{bytes} to the standard input of the child process. c&|j|yr5rir`rgs r(riz1ProcessTestsBuilderBase.test_write..writes OOK (r*Nrqr8ris r( test_writez"ProcessTestsBuilderBase.test_writes  ) r*c,d}|j|y)z L{IProcessTransport.writeSequence} writes the specified C{list} of C{bytes} to the standard input of the child process. c(|j|gyr5) writeSequencerus r(riz9ProcessTestsBuilderBase.test_writeSequence..writes  # #[M 2r*Nrvrws r(test_writeSequencez*ProcessTestsBuilderBase.test_writeSequence  3 r*c,d}|j|y)z L{IProcessTransport.writeToChild} writes the specified C{bytes} to the specified file descriptor of the child process. c(|jd|y)Nr) writeToChildrus r(riz8ProcessTestsBuilderBase.test_writeToChild..writes  " "1k 2r*Nrvrws r(test_writeToChildz)ProcessTestsBuilderBase.test_writeToChildr}r*c2fd}j|y)z L{IProcessTransport.writeToChild} raises L{KeyError} if passed a file descriptor which is was not set up by L{IReactorProcess.spawnProcess}. c jt|jd||j|y#|j|wxYw)N ) assertRaisesKeyErrorrri)r`rgr8s r(rizIProcessTestsBuilderBase.test_writeToChildBadFileDescriptor..writes= -!!(I,B,BB T ,  ,s "7A Nrvrws` r("test_writeToChildBadFileDescriptorz:ProcessTestsBuilderBase.test_writeToChildBadFileDescriptors  - r*SIGCHLDNz;Platform lacks SIGCHLD, early-spawnProcess test can't work.cP|j|jrd}ni}tjfd}t jtj |t }jt|ttddg|j|jdjs|jdg}|j|j|ry|jfd|j|j!|y) z If, before the reactor is started with L{IReactorCore.run}, a process is started with L{IReactorProcess.spawnProcess} and terminates, the process is reaped once the reactor is started. Nc&jyr5)set)argssignaleds r(handlerzGProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped..handlers LLNr*rMr*)rKchildFDsxz,Timed out waiting for child process to exit.c$jSr5rPrRs r(rUzHProcessTestsBuilderBase.test_spawnProcessEarlyIsReaped..rVr*)rWrK threadingEventsignalrrrXr3rYwaitisSetfailr\r%r]rZ)r8rrr^resultrTrs @@r(test_spawnProcessEarlyIsReapedz6ProcessTestsBuilderBase.test_spawnProcessEarlyIsReapeds##% ;;HH??$   fnng.  ,U 3  E3 ;;    c~~ IID E &--(   89   r*cdttdztd}Gfddt}j j j |ttd|gjfd}j|jtjfd jy ) z The C{reason} argument passed to L{IProcessProtocol.processExited} is a L{ProcessTerminated} instance if the child process exits with a signal. TERMSIGsEimport sys sys.stdout.write('x') sys.stdout.flush() sys.stdin.read() c.eZdZfdZdZfdZdZy)DProcessTestsBuilderBase.test_processExitedWithSignal..Exiterc\td||fz|jjyNzchildDataReceived(%d, %r))rr`rf)r8r<datasigNames r(r>zVProcessTestsBuilderBase.test_processExitedWithSignal..Exiter.childDataReceived7s'/2t*<=,,W5r*c"td|fzyNchildConnectionLost(%d)r)r8r<s r(childConnectionLostzXProcessTestsBuilderBase.test_processExitedWithSignal..Exiter.childConnectionLost;s-56r*cHtd|dj|gyNzprocessExited()rr@r8rBexiteds r( processExitedzRProcessTestsBuilderBase.test_processExitedWithSignal..Exiter.processExited>s$nVJa01 )r*c"td|dyNz processEnded(rrrAs r(rCzQProcessTestsBuilderBase.test_processExitedWithSignal..Exiter.processEndedGsmF:Q/0r*NrDrErFr>rrrC)rrsr(Exiterr6s 6 7 * 1r*rrMrNcV|\}|jt|j}tjr8j |j j|jdyj|j j |jy)Nrl) trapr valuer isWindows assertIsNonerroexitCode)rfailurerr8sigNums r(cbExitedzFProcessTestsBuilderBase.test_processExitedWithSignal..cbExitedSs|JW LL* +--C!!#!!#**-  q1  V4!!#,,/r*c$jSr5rPignrTs r(rUzFProcessTestsBuilderBase.test_processExitedWithSignal..h w||~r*N) getattrrrr rWrnrXrYrKr\ addErrbackrr])r8sourcerrrrTrrs` @@@@r(test_processExitedWithSignalz4ProcessTestsBuilderBase.test_processExitedWithSignal"s 1 "  1_ 1(##%  H  E6 ";;   0& 8$#56  r*c|jgfd}j||j|jdtj j dzgy)a If a child process exits while a system call is in progress, the system call should not be interfered with. In particular, it should not fail with EINTR. Older versions of Twisted installed a SIGCHLD handler on POSIX without using the feature exposed by the SA_RESTART flag to sigaction(2). The most noticeable problem this caused was for blocking reads and writes to sometimes fail with EINTR. c tjtj}t j |ddgt j |ddgtj }|j5j|jjdddjy#1swYxYw#jwxYw)N-czimport time; time.sleep(0.1)z)import time; time.sleep(0.5);print('Foo'))stdout) rYdecodesysgetfilesystemencoding subprocessPopenPIPErr%readrQ)exef2rTrs r(fzJProcessTestsBuilderBase.test_systemCallUninterruptedByChildExit..fzs ll3#<#<#>?  #t-K!LM%%$!OQ%??YY4MM")).."234 44 s$A3C6*B9 C9C>CCsFooasciiN)rWrnr]ror"rmencode)r8rrTrs @@r('test_systemCallUninterruptedByChildExitz?ProcessTestsBuilderBase.test_systemCallUninterruptedByChildExitls`##% " "   &2::+<+.GatheringProtocolc&jyr5rPr8rBrTs r(rCzXProcessTestsBuilderBase.test_openFileDescriptors..GatheringProtocol.processEndeds  r*N)rDrErFri outReceivedrC)outputrTsr(GatheringProtocolrs ,,K r*rs-WignorerMenvrKrrlN)rr"pipe addCleanupcloser)dup2ioBytesIOr rWrnrXrY properEnvrKr]revalgetvaluero intersection) r8rrw fudgeFactorhardResourceLimit unlikelyFDrreportedChildFDsstdFDsrrTs @@r(test_openFileDescriptorsz0ProcessTestsBuilderBase.test_openFileDescriptorss?  wwy1 !$ !$* 02&4  : *-   ##%     K /;;    tFOO$567   ) )#f |.C*D Es6{ r*cd}jtd|jtddjd_t j jrdndjfd}jd jd jjy ) z When L{os.execvpe} raises an exception, it will format that exception on stderr as UTF-8, regardless of system encoding information. czd}t|ts|jd}td|d}t |y)Nu<☃>utf-8z1/0single) isinstancestrrcompiler)rkwfilenamecodeobjs r(execvpez=ProcessTestsBuilderBase.test_errorDuringExec..execvpes6'Hh,#??73eXx8G Mr*rrcy)NrrHrHr*r(rUz>ProcessTestsBuilderBase.test_errorDuringExec..sr*TrlrcGfddt}j|ttddgjy)Nc$eZdZfdZfdZy)[ProcessTestsBuilderBase.test_errorDuringExec..whenRunning..TracebackCatcherc4|k(rj|yyr5rt)r8childr expectedFDrs r(r>zmProcessTestsBuilderBase.test_errorDuringExec..whenRunning..TracebackCatcher.childDataReceiveds * T*+r*c&jyr5rPrs r(rCzhProcessTestsBuilderBase.test_errorDuringExec..whenRunning..TracebackCatcher.processEndeds LLNr*N)rDrErFr>rC)rrrTsr(TracebackCatcherrs +#r*rrMr*rN)r rXrYrK)rrrrTr8s r( whenRunningzAProcessTestsBuilderBase.test_errorDuringExec..whenRunnings@ # #? #   "EE5#+>t{{ ! r*timeoutu☃N) patchr"rrW_neverUseSpawnrrrKrnr]assertInrr)r8rrrrrTs` @@@r(test_errorDuringExecz,ProcessTestsBuilderBase.test_errorDuringExecs  2y'* 3/A##%"&++Q1    !  , m**,foo.?@r*c jGfddt}|}jj|ttddgj j dj|jy) zi If a spawned process exits, C{processExited} will be called in a timely manner. ceZdZdZfdZy)IProcessTestsBuilderBase.test_timelyProcessExited..ExitingProtocolFcd|_jj|jjdy)NTr)rrQrorr) protoSelfrBrTr8s r(rzWProcessTestsBuilderBase.test_timelyProcessExited..ExitingProtocol.processExiteds.#'     !6!6:r*N)rDrErFrr)rTr8sr(ExitingProtocolrs F ;r*rrMsraise SystemExit(0)rNr r N) rWr rnrXrYrKr]rZr)r8rr_rTs` @r(test_timelyProcessExitedz0ProcessTestsBuilderBase.test_timelyProcessExited s ##% ;o ;#$    E1 2;;   , (r*c Zdd|dg}gGfddt}|j|}jj|ttddj |gfi|di|j |jd d jjy ) aT Launch a child process, using either the C{uid} or C{gid} argument to L{IReactorProcess.spawnProcess} to change either its UID or GID to a different value. If the child process reports this hasn't happened, raise an exception to fail the test. @param which: Either C{b"uid"} or C{b"gid"}. z import oszraise SystemExit(os.getz() != 1)ceZdZfdZy)@ProcessTestsBuilderBase._changeIDTest..CaptureExitStatuscHj|jyr5)r%rQ)r8rB containerrTs r(rCzMProcessTestsBuilderBase._changeIDTest..CaptureExitStatus.processEnded7s  ( r*N)rDrErFrC)rrTsr(CaptureExitStatusr6s r*rr rlrN) r rWrnrXrYrpr]rorr)r8whichrhrr_rrTs @@r( _changeIDTestz%ProcessTestsBuilderBase._changeIDTest)s"9% IJ    ##%$&    D$))G, -  aj     IaL..778r*c&|jdy)z If a value is passed for L{IReactorProcess.spawnProcess}'s C{uid}, the child process is run with that UID. uidNrr8s r(test_changeUIDz&ProcessTestsBuilderBase.test_changeUIDI 5!r*c&|jdy)z If a value is passed for L{IReactorProcess.spawnProcess}'s C{gid}, the child process is run with that GID. gidNr"r#s r(test_changeGIDz&ProcessTestsBuilderBase.test_changeGIDQr%r*c|jGddtGfddt}|}j|ttddg|j }|j t[ttjjD]1\}}||ur tj|||jd 3|jd t|jy) zY If L{IProcessProtocol.processExited} raises an exception, it is logged. c eZdZy)GProcessTestsBuilderBase.test_processExitedRaises..TestExceptionN)rDrErFrHr*r( TestExceptionr+as r*r,ceZdZfdZy)BProcessTestsBuilderBase.test_processExitedRaises..Protocolc4jd)NzprocessedExited raisedrP)r8rBr,rTs r(rzPProcessTestsBuilderBase.test_processExitedRaises..Protocol.processExitedes #$<==r*N)rDrErFr)r,rTsr(Protocolr.ds >r*r0rMr*rNNzEAfter processExited raised, transport was left in reapProcessHandlersrl)rW Exceptionr rXrYrKr]rlistreapProcessHandlersitemsunregisterReapProcessHandlerrrolenflushLoggedErrors)r8r0r_r`pidrr,rTs @@r(test_processExitedRaisesz0ProcessTestsBuilderBase.test_processExitedRaisesYs ##% I  > > :(( eeUC0)     $W%@%@%F%F%H I  W)+44S'B +   C 6 6} EFGr*) rDrErFrGr requiredInterfacesbool__annotations__rarqrxr|rrrrrrrrrrrr1rrr _uidgidSkip_uidgidSkipReasonr$r(r9rHr*r(rJrJks** L!4FB      4(D0E: : xH!T!HF H   "IJM KM ^+A+AZ)89@ K*+"," K*+","#Hr*rJceZdZdZdZdZejrdZndZdZ dZ dZ d Z d Z d Zd Zed ZdZdZdZedZedZedZedZedZedZy)ProcessTestsBuilderzp Builder defining tests relating to L{IReactorProcess} for child processes which do not have a PTY. Fs$twisted.internet.test.process_helperswindowsr*c ttttdGfddt}d}|j j j|t t d|gt |jfd}j|fd}j|d }j|jt fd }j||j y ) z L{IProcessProtocol.childConnectionLost} is called each time a file descriptor associated with a child process is closed. rc"eZdZfdZfdZy).Closerc(j|yr5r@)r8r` connecteds r(makeConnectionzKProcessTestsBuilder.test_childConnectionLost..Closer.makeConnections""9-r*c.|jdyr5rEr8childFDlosts r(rzPProcessTestsBuilder.test_childConnectionLost..Closer.childConnectionLostsW &&t,r*N)rDrErFrGr)rFrKsr(CloserrCs  . -r*rLs,twisted.internet.test.process_loseconnection-mrcVjddjfdS)Ns2 rcSr5rHrr`s r(rUzSProcessTestsBuilder.test_childConnectionLost..cbConnected..9r*rir\r`rKs`r( cbConnectedzAProcessTestsBuilder.test_childConnectionLost..cbConnected% OOF #7&&'<= =r*cVjddjfdS)Ns1 rlcSr5rHrPs r(rUzRProcessTestsBuilder.test_childConnectionLost..lostSecond..rQr*rRrSs`r( lostSecondz@ProcessTestsBuilder.test_childConnectionLost..lostSecondrUr*c&|jdy)N rt)r`s r( lostFirstz?ProcessTestsBuilder.test_childConnectionLost..lostFirsts OOE "r*c&jyr5rPrRs r(cbEndedz=ProcessTestsBuilder.test_childConnectionLost..cbEnded LLNr*N) rr rWrnrXrYrrKr\rrr]) r8rLtargetrTrXr[r]rFrKrTs @@@r(test_childConnectionLostz,ProcessTestsBuilder.test_childConnectionLosts J :(*< -_ -A##%  H  E6 ";;   > k* > j) # i(S!  g&  r*c tgGfddt}jjj|t t dj djgtjfd}j|jtjfdjy) z L{IProcessProtocol.processEnded} is called after the child process exits and L{IProcessProtocol.childConnectionLost} is called for each of its file descriptors. c.eZdZdZfdZdZfdZy)4ProcessTestsBuilder.test_processEnded..EndercXtd||fz|jjyr)rr`loseConnectionr8r<rs r(r>zFProcessTestsBuilder.test_processEnded..Ender.childDataReceiveds$/2t*<=--/r*cFtd|fzj|yr)rr%rIs r(rzHProcessTestsBuilder.test_processEnded..Ender.childConnectionLosts- :; G$r*c"td|dyrrrAs r(rzBProcessTestsBuilder.test_processEnded..Ender.processExitedsnVJa01r*cHtd|dj|gyrr)r8rBr^s r(rCzAProcessTestsBuilder.test_processEnded..Ender.processEndeds"mF:Q/0x(r*Nr)r^rKsr(Enderrcs 0 % 2 )r*rjrMchildrcr|\}|jtjthdyN>rrlr)rrror)rrrKr8s r(r]z6ProcessTestsBuilder.test_processEnded..cbEndeds*JW LL %   SY 2r*c$jSr5rPrs r(rUz7ProcessTestsBuilder.test_processEnded..s gllnr*Nrr rWrnrXrYkeepStdioOpenProgramkeepStdioOpenArgrrKr\rrr])r8rjr]r^rKrTs` @@@r(test_processEndedz%ProcessTestsBuilder.test_processEndeds   )O ) ##%  G  E444h@U@U V;;   3 '"  45  r*c ttgGfddt}jjj|t t ddj djgtjfd}j|fd}j|jtjfd jy ) z L{IProcessProtocol.processExited} is called when the child process exits, even if file descriptors associated with the child are still open. c*eZdZdZfdZfdZy)6ProcessTestsBuilder.test_processExited..Waiterc$td||fzyrrrfs r(r>zHProcessTestsBuilder.test_processExited..Waiter.childDataReceiveds/2t*<=r*ctd|fzj|tdk(rjdyy)Nr)rr%r6r@)r8rJallLostrKs r(rzJProcessTestsBuilder.test_processExited..Waiter.childConnectionLosts=- :; G$t9>$$T*"r*c|td|dj|g|jjyr)rr@r`rers r(rzDProcessTestsBuilder.test_processExited..Waiter.processExited s2nVJa01)--/r*N)rDrErFr>rr)ryrrKsr(Waiterrus > +  0r*r{s-urMrkrcz|\}|jttdjgS)NzcbExited; lost = )rrrro)rrryrKr8s r(rz8ProcessTestsBuilder.test_processExited..cbExited"s;JW LL % #D6* +   T2 &Nr*c@jthdyrm)ror)rSrKr8s r( cbAllLostz9ProcessTestsBuilder.test_processExited..cbAllLost+s   SY 2r*c$jSr5rPrs r(rUz8ProcessTestsBuilder.test_processExited..1rr*Nro)r8r{rr~ryrrKrTs` @@@@r(test_processExitedz&ProcessTestsBuilder.test_processExiteds * 0 0_ 0 ##%  H ))%%  ;;    8$ 3 9%#56  r*c2t|j}t|d5}|jtj j |tj zdddtjj|S#1swY(xYw)zj Write the given list of lines to a text file and return the absolute path to it. wtN) rmktempopenrir"rmrppathabspath)r8 sourceLinesscript scriptFiles r(makeSourceFilez"ProcessTestsBuilder.makeSourceFile5sp $DKKM2 &$  H:   RZZ__[9BJJF G Hwwv&& H Hs AB  Bc tdjdjtjdddjjddgt j dj fdfd fd }j|jy ) z Spawning a process with an executable which is a script starting with an interpreter definition line (#!) uses that interpreter to evaluate the script. sthis is the shebang outputz#!{}rz import syszsys.stdout.write('{}')zsys.stdout.flush()ic|\}}}td|||fzj|j|dj|dy)NzcbProcessExited((%r, %r, %d))r*r)rro)routrcoder8 shebangOutputs r(cbProcessExitedz9ProcessTestsBuilder.test_shebang..cbProcessExitedSsS!NCd /3T2BB C   S- 0   S# &   T1 %r*c(j|Sr5rP) passthroughrTs r(shutdownz2ProcessTestsBuilder.test_shebang..shutdownZs LLN r*ctj}|j|j|j t y)N)rT)rgetProcessOutputAndValueaddBothr\rr)drrTrrs r(startz/ProcessTestsBuilder.test_shebang..start^s9..z7KA IIh  MM/ * LL r*N) rformatrYrr"chmodrWrnr])r8rrrTrrrs` @@@@@r( test_shebangz ProcessTestsBuilder.test_shebang?s 6 (( ell734(// 0D0DW0MN$    U###% &   &  r*cvfd}j}|j||j|y)z< Pause producing and then resume producing. c t}|j|ttddgj}|j |j |j y#|j wxYw)NrMr*rN)r rXrYrKpauseProducingresumeProducingrQ)rTr_r`r8s r(pauseAndResumezHProcessTestsBuilder.test_pauseAndResumeProducing..pauseAndResumelsf *,#00eeUC%81 ((*))+  s AA((A:N)rWrnr])r8rrTs` r(test_pauseAndResumeProducingz0ProcessTestsBuilder.test_pauseAndResumeProducinggs4 ##%8  r*c <dgddjtttdd}t |t r|j djfdfdfd }j|jy ) zq Arguments given to spawnProcess are passed to the child process as originally intended. s!twisted.internet.test.process_cli)shello"s |<>^&s "\\"hello\\"s"foo\ bar baz\""rrlrcx|\}}}|jd}|jj|y)N)splitpopro) finishedArgsrrrrr8s r(processFinishedzMProcessTestsBuilder.test_processCommandLineArguments..processFinisheds6 , FC\\%(F JJL   T6 *r*c(j|Sr5rP)rrTs r(rzFProcessTestsBuilder.test_processCommandLineArguments..shutdowns LLNMr*ctd}|jfd|j|jy)NcPtjtdgztS)NrM)rrT)rrrYr)dummyrrTuss r(rUzZProcessTestsBuilder.test_processCommandLineArguments..spawnChild..s$e<<E2;-9gr*)rr\r)rrrrTrrs r( spawnChildzHProcessTestsBuilder.test_processCommandLineArguments..spawnChilds7 A MM  MM/ * IIh r*N) rpmapchrrangerrrrWrnr])r8allCharsrrrrTrrs` @@@@@r( test_processCommandLineArgumentsz4ProcessTestsBuilder.test_processCommandLineArguments{s~ 2T773sE!SM23 h $ OOG $##% +     +  r*cgGfddttfd}|j}|j|||j |t j t jdgy)z Process is removed from reapProcessHandler dict before running ProcessProtocol.processEnded() callback. c"eZdZdZdZfdZy)iProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback..TestProcessProtocola7 Process protocol captures own presence in process.reapProcessHandlers at time of .processEnded() callback. @ivar deferred: A deferred fired when the .processEnded() callback has completed. @type deferred: L{Deferred} c"t|_yr5)rdeferredr#s r(r9zrProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback..TestProcessProtocol.__init__s (  r*cddlm}|j}|j}|j|vrj dnj d|j jdy)z Capture whether the process has already been removed from process.reapProcessHandlers. @param status: unused rrz!process present but should not be"process already removed as desiredN)twisted.internetrr3valuesr`r%rr@)r8statusrhandlers processesresultss r(rCzvProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback..TestProcessProtocol.processEndedsW5"66$OO- >>Y.NN#FGNN#GH &&t,r*N)rDrErFrGr9rC)rsr(TestProcessProtocolrs  + -r*rc3 K }|j|ttdg|j|j y#t$r}j |Yd}~0d}~wwxYw#|j wxYww)a Launch and wait for a subprocess and allow the TestProcessProtocol to capture the order of the .processEnded() callback vs. removal from process.reapProcessHandlers. @param reactor: Reactor used to spawn the test process and to be stopped when checks are complete. @type reactor: object providing L{twisted.internet.interfaces.IReactorProcess} and L{twisted.internet.interfaces.IReactorCore}. z --versionN)rXrYrr1r%rQ)rTtestProcessProtocolerrs r(launchProcessAndWaitzjProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callback..launchProcessAndWaitsv &9&;#$$'K( *222  "q!! " s9B2AB A,A'"A/'A,,A//BBrN)r rrWrnr]hamcrest assert_thatequal_to)r8rrTrrs @@r(8test_process_unregistered_before_protocol_ended_callbackzLProcessTestsBuilder.test_process_unregistered_before_protocol_ended_callbacks{  -/ -@    2##% 4g>      CD E r*c t}tx}|_|j| _j j |ttdtdgfd|ji|fd}|j||j|jdd|jdd|jttt!|j#d|jr|j$j'y|j(j'y) a  Shared code for testing the environment variables present in the spawned process. The spawned process serializes its environ to stderr or stdout (depending on usePTY) which is checked against os.environ of the calling process. rMzimport os, sys; env = dict(os.environ); env.pop("LC_CTYPE", None); env.pop("__CF_USER_TEXT_ENCODING", None); sys.stderr.write(str(sorted(env.items())))rKc&jyr5rPrs r(rzBProcessTestsBuilder.checkSpawnProcessEnvironment..shutdownr^r*LC_CTYPEN__CF_USER_TEXT_ENCODINGr)rr endedDeferredrWr rnrXrYrrKrr]rror=rsortedr4outFrerrF)r8 spawnKwargs expectedEnvusePosixSpawnpprrrTs @r(checkSpawnProcessEnvironmentz0ProcessTestsBuilder.checkSpawnProcessEnvironments M&j(AO##%%3!3  A   ;;! "# (  (   D)148  #f[..012G Aq\E1: & r*cV|jtdgddittgy)z If a file descriptor is not close-on-exec and it's left in the same place, then there should be no actions taken. rrNrr#s r( test_stayPutz GetFileActionsTests.test_stayPut s% *1vudKRPr*c|jtdgdditttddftddftdfgy)a If a file descriptor is close-on-exec and it's left in the same place, then we need to DUP2 it elsewhere, close the original, then DUP2 it back so it doesn't get closed by the implicit exec at the end of posix_spawn's file actions. r!rrlNrr#s r(test_cloexecStayPutz'GetFileActionsTests.test_cloexecStayPuts@  YK!Q =Aq\D!Q<% 4 r*c|jtddgdddtttddftddftddftdfgy)z If our file descriptor mapping requests that file descriptors change places, we must DUP2 them to a new location before DUP2ing them back. r)rlFrlr)rrlrNrr#s r(test_inheritableConflictz,GetFileActionsTests.test_inheritableConflicts^  Z( q! q! q!    r*)rN) rDrErFrGrrr"r$r&r(r*r,rHr*r(rrs3 CWL  Q   r*r)JrGrr"rrrrunittestrrrrtwisted.internet.deferrrrtwisted.internet.errorrr twisted.internet.interfacesr r twisted.internet.protocolr #twisted.internet.test.reactormixinsr twisted.python.compatrtwisted.python.filepathrrtwisted.python.logrrtwisted.python.runtimertwisted.test.test_processrtwisted.trial.unittestrr executable _asBytesPathrYr=r>dictrrpathseprprr_processgetuidrrrintr)r1r3rJr@globalsupdatemakeTestCaseClassesrrrrrrrrHr*r(rCs  "EEAJ5>/@'+1@  --/    **//#((3 , 94ryy{a B G8 c " ))(QHnQHhj 1j Z $88:; 4 $ ';;=>+(+4%h%"( (( V   V -V  V _%;GK:;sF33 GG