ϪfNdZddlZddlmZddlmZddlmZddlm Z ddl m Z m Z ddl mZmZdd lmZmZmZdd lmZdd lmZmZdd lmZdd lmZmZmZddlm Z ddl!m"Z"ddl#m$Z$dejJejLfdZ'GddeZ(GddZ)GddeZ*dZ+dZ,GddeZ-GddZ.Gdd eZ/Gd!d"e(Z0Gd#d$Z1Gd%d&Z2Gd'd(Z3Gd)d*Z4y)+z? Various helpers for tests for connection-oriented transports. N)collect)Optional)ref) verifyObject)Deferred gatherResults) IConnector IReactorFDSet) ClientFactoryProtocol ServerFactory)needsRunningReactor)contextlog)Failure) ILogContexterrmsg)platform)ClosingProtocol)SkipTestz 127.0.0.1ctj|ddd}tj||} |j||tjk(r_|j }tj |tj tjzd}||df|jS|j |jS#|jwxYw)a Ask the platform to allocate a free port on the specified interface, then release the socket and return the address which was allocated. @param interface: The local address to try to bind the port on. @type interface: C{str} @param type: The socket type which will use the resulting port. @return: A two-tuple of address and port, like that returned by L{socket.getsockname}. r) socket getaddrinfobindAF_INET6 getsockname getnameinfoNI_NUMERICHOSTNI_NUMERICSERVclose) interfacefamilytypeaddrprobesocknamehostnames H/usr/lib/python3/dist-packages/twisted/internet/test/connectionmixins.py findFreePortr,s   i +A .q 1D MM&$ 'E  4 V__ $((*H))&//&2G2GGHhqk*  $$&  sA2C7CC)c eZdZdZdZdZdZy)ConnectableProtocolab A protocol to be used with L{runProtocolsWithReactor}. The protocol and its pair should eventually disconnect from each other. @ivar reactor: The reactor used in this test. @ivar disconnectReason: The L{Failure} passed to C{connectionLost}. @ivar _done: A L{Deferred} which will be fired when the connection is lost. Nc ||_||_y)aN Set attributes on the protocol that are known only externally; this will be called by L{runProtocolsWithReactor} when this protocol is instantiated. @param reactor: The reactor used in this test. @param done: A L{Deferred} which will be fired when the connection is lost. N)reactor_done)selfr0dones r+_setAttributesz"ConnectableProtocol._setAttributesJs  cL||_|jjd|`yN)disconnectReasonr1callbackr2reasons r+connectionLostz"ConnectableProtocol.connectionLostXs! & D! Jr5)__name__ __module__ __qualname____doc__r8r4r<r5r+r.r.:s  r5r.ceZdZdZdZdZy)EndpointCreatorzT Create client and server endpoints that know how to connect to each other. ct)z Return an object providing C{IStreamServerEndpoint} for use in creating a server to use to establish the connection type to be tested. NotImplementedErrorr2r0s r+serverzEndpointCreator.serverc "##r5ct)z Return an object providing C{IStreamClientEndpoint} for use in creating a client to use to establish the connection type to be tested. rE)r2r0 serverAddresss r+clientzEndpointCreator.clientjrIr5N)r=r>r?r@rHrLrAr5r+rCrC^s$$r5rCceZdZdZdZdZy)_SingleProtocolFactoryz Factory to be used by L{runProtocolsWithReactor}. It always returns the same protocol (i.e. is intended for only a single connection). c||_yr7 _protocol)r2protocols r+__init__z_SingleProtocolFactory.__init__zs !r5c|jSr7rP)r2r's r+ buildProtocolz$_SingleProtocolFactory.buildProtocol}s ~~r5Nr=r>r?r@rSrUrAr5r+rNrNrs"r5rNc |j |j t|j tt|}t| j }|j |}  fd}|j |d}t|j|jg |j fd|j||j fd|j  S)a Connect two protocols using endpoints and a new reactor instance. A new reactor will be created and run, with the client and server protocol instances connected to each other using the given endpoint creator. The protocols should run through some set of tests, then disconnect; when both have disconnected the reactor will be stopped and the function will return. @param reactorBuilder: A L{ReactorBuilder} instance. @param serverProtocol: A L{ConnectableProtocol} that will be the server. @param clientProtocol: A L{ConnectableProtocol} that will be the client. @param endpointCreator: An instance of L{EndpointCreator}. @return: The reactor run by this test. cfj|j}|jSr7)rLgetHostconnect)pclientEndpoint clientFactoryendpointCreatorr0s r+gotPortz(runProtocolsWithReactor..gotPorts,(//E%%m44r5c0tj|dy)NzConnection setup failed.)rr)results r+failedz'runProtocolsWithReactor..faileds 23r5cSr7rA)_ disconnecteds r+z)runProtocolsWithReactor..sLr5c0tjSr7)rstop)rdr0s r+rfz)runProtocolsWithReactor..s/Fr5) buildReactorr4rrNrHlisten addCallbackrr1 addErrback runReactor) reactorBuilderserverProtocolclientProtocolr^ serverFactoryserverEndpointdr_rbr]rer0s ` @@@r+runProtocolsWithReactorrts,))+G!!'8:6!!'8:6*>:M*>:M%++G4Nm,A5MM'4!."6"68L8L!MNLMM()LLMMFGg& Nr5ctj|r|jSd|jjvr |j St d|)zZ Like L{IReactorFDSet.getWriters}, but with support for IOCP reactor as well. IOCPzCannot find writers on )r providedBy getWriters __class__r=handles Exceptionr0s r+ _getWritersr}sT (!!## 7$$-- -1'=>>r5ceZdZdZdZdZy)_AcceptOneClientaN This factory fires a L{Deferred} with a protocol instance shortly after it is constructed (hopefully long enough afterwards so that it has been connected to a transport). @ivar reactor: The reactor used to schedule the I{shortly}. @ivar result: A L{Deferred} which will be fired with the protocol instance. c ||_||_yr7)r0ra)r2r0ras r+rSz_AcceptOneClient.__init__s  r5ctj||}|jjd|jj ||S)Nr)r rUr0 callLaterrar9)r2r'rRs r+rUz_AcceptOneClient.buildProtocols9 ..tT: q$++"6"6Ar5NrVrAr5r+rrsr5rc"eZdZdZdZdZdZy)_SimplePullProducerz A pull producer which writes one byte whenever it is resumed. For use by C{test_unregisterProducerAfterDisconnect}. c||_yr7)consumer)r2rs r+rSz_SimplePullProducer.__init__s   r5cyr7rAr2s r+ stopProducingz!_SimplePullProducer.stopProducings r5cdtjd|jjdy)NProducer.resumeProducingx)rrrwriters r+resumeProducingz#_SimplePullProducer.resumeProducings! *+ D!r5N)r=r>r?r@rSrrrAr5r+rrs ! "r5rc eZdZdZdZdZdZy)StopzQ A client factory which stops a reactor when a connection attempt fails. Nc||_yr7r|rGs r+rSz Stop.__init__s  r5c~||_td|j|jj y)NzStop(CF) cCFailed: ) failReasonrgetErrorMessager0rh)r2 connectorr;s r+clientConnectionFailedzStop.clientConnectionFaileds3  !&"8"8":!; <= r5)r=r>r?r@rrSrrAr5r+rrsJr5rc(eZdZdZdZdZdZdZy)ClosingLaterProtocolz ClosingLaterProtocol exchanges one byte with its peer and then disconnects itself. This is mostly a work-around for the fact that connectionMade is called before the SSL handshake has completed. c d|_||_yr7)lostConnectionReasononConnectionLost)r2rs r+rSzClosingLaterProtocol.__init__s$(! 0r5ctdy)Nz#ClosingLaterProtocol.connectionMade)rrs r+connectionMadez#ClosingLaterProtocol.connectionMades  12r5cTtd||jjy)Nz"ClosingLaterProtocol.dataReceived r transportloseConnectionr2bytess r+ dataReceivedz!ClosingLaterProtocol.dataReceiveds" 0 :; %%'r5c^td||_|jj|y)Nz#ClosingLaterProtocol.connectionLost)rrrr9r:s r+r<z#ClosingLaterProtocol.connectionLost s' 12$*! &&t,r5N)r=r>r?r@rSrrr<rAr5r+rrs 13(-r5rc8eZdZUdZdZeeed<dZdZ dZ y)ConnectionTestsMixinzg This mixin defines test methods which should apply to most L{ITransport} implementations. N endpointscGddt}|d}|d}t||||j|jd|j|jd|jy)z Client and server transports implement L{ILoggingContext.logPrefix} to return a message reflecting the protocol they are running. c$eZdZdZdZdZdZy)DConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocolc ||_d|_yr7)_prefixsystem)r2prefixs r+rSzMConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.__init__ s% " r5c:|jjdy)Na)rrrs r+rzSConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.connectionMade$s$$T*r5c|jSr7)rrs r+ logPrefixzNConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.logPrefix's ||#r5ctjtd|_|jj dd|vr|jj yy)Nrb)rgetrrrrrrs r+rzQConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.dataReceived*sG%kk+6x@ $$T*5=NN113!r5N)r=r>r?rSrrrrAr5r+CustomLogPrefixProtocolrs # + $ 4r5rz Custom Clientz Custom ServerN)r.rtrassertInr)r2rrLrHs r+test_logPrefixz#ConnectionTestsMixin.test_logPrefixs[  4&9 4&)9(9ffdnnE ov}}5 ov}}5r5cLjgtfd}jjj t j |fdfd}t|jjddgy)z} After a connection is disconnected, L{ITransport.write} and L{ITransport.writeSequence} are no-ops. ctSr7r)serverConnectionLostDeferredsr+rfz@ConnectionTestsMixin.test_writeAfterDisconnect..Bs/0LMr5ctd|j jj|j}t fd}|j t j|}d}|j|jfd}j| j|t gS)N Listening on ctSr7r)lostConnectionDeferredsr+rfzSConnectionTestsMixin.test_writeAfterDisconnect..listening..Ls34JKr5cVtd||jjdy)NzAbout to write to r)rrrprotos r+rzPConnectionTestsMixin.test_writeAfterDisconnect..listening..writeOs$( 23%%d+r5ct|d|jjd|jjddgj dy)Nz disconnectedssome bytes to get lostssomesmoreT)rrr writeSequenceappend)rfinisheds r+rezWConnectionTestsMixin.test_writeAfterDisconnect..listening..disconnectedUsHui}-.%%&?@--w.@A%r5) rrYrrLrrZr forProtocol addCallbackserrbackrkr) portendpointrRrLrrerrr0r2rs @r+ listeningzAConnectionTestsMixin.test_writeAfterDisconnect..listeningGs - 12 3~~,,WdllnEH%-Z "KH%%m&?&?&IJF ,   '='E'E F & # . .| < ( 4 4\ B "8:V!WX Xr5czjjtjfdy)Nc$jSr7rhignoredr0s r+rfzRConnectionTestsMixin.test_writeAfterDisconnect..onListen..bs W\\^r5)rkrlrr portDeferredr0sr+onListenz@ConnectionTestsMixin.test_writeAfterDisconnect..onListen_s.  $ $Y /  # #C (  $ $%C Dr5TN) rirrrHrjr rrrm assertEqual)r2rRrrrrr0rs` @@@@@r+test_writeAfterDisconnectz.ConnectionTestsMixin.test_writeAfterDisconnect8s ##%'/z$M~~,,W5<<  % %h /  Y0 E GX.   D$<0r5cttt}jjj j tjtfdfd}t|jdtj|y)z After the connection a protocol is being used for is closed, the reactor discards all of its references to the protocol. c@td|jjj|j}|j t j fd}d}|j||jjS)NrcSr7rA)rpsr+rfzaConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listening..{sr5cTtd||jjy)NzAbout to disconnect rrs r+ disconnectzcConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listening..disconnect}s"*5)45..0r5) rrYrrLrZr rrkrlr)rrrLrrprr0r2s r+rzOConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listeningws - 12 3~~,,WdllnEH%%m&?&?@V&WXF 1   z *   4<< =) )r5czjjtjfdy)Nc$jSr7rrs r+rfzcConnectionTestsMixin.test_protocolGarbageAfterLostConnection..onListening..s r5)rkrlraddBothrsr+ onListeningzQConnectionTestsMixin.test_protocolGarbageAfterLostConnection..onListenings.  $ $Y /  # #C (  !? @r5N)rrrrirrHrjr rr rrmr assertIsNone)r2 clientRefrrprrrr0s` @@@@@r+'test_protocolGarbageAfterLostConnectionzr?r@rrrC__annotations__rrrrAr5r+rrs( ,0Ix(/6>/1b)'r5rceZdZdZdZy)LogObserverMixinzL Mixin for L{TestCase} subclasses which want to observe log events. cg}tj|j|jtj|j|Sr7)r addObserverr addCleanupremoveObserver)r2loggedMessagess r+observezLogObserverMixin.observes9 --. **N,A,ABr5N)r=r>r?r@rrAr5r+rrs r5rceZdZdZdZdZy)BrokenContextFactoryzv A context factory with a broken C{getContext} method, for exercising the error handling for such a case. zSome path was wrong maybec,t|jr7) ValueErrormessagers r+ getContextzBrokenContextFactory.getContexts&&r5N)r=r>r?r@rrrAr5r+rrs *G'r5rc.eZdZdZdZdZdZdZdZy)StreamClientTestsMixinau This mixin defines tests applicable to SOCK_STREAM client implementations. This must be mixed in to a L{ReactorBuilder } subclass, as it depends on several of its methods. Then the methods C{connect} and C{listen} must defined, defining a client and a server communicating with each other. c|j}|j|t}|jt t |y)zR The C{connect} method returns an object providing L{IConnector}. N)rirZr assertTruerr )r2r0rs r+test_interfacez%StreamClientTestsMixin.test_interfaces7##%LL-/:   Z;.sT\\'4=-Qr5N)rirrmrGs`@r+'test_clientConnectionFailedStopsReactorz>StreamClientTestsMixin.test_clientConnectionFailedStopsReactors* ##%G%QR  r5c.jjtjtgGfddt}t |_tfdjjy)z This test checks that we correctly get notifications event for a client. This ought to prevent a regression under Windows using the GTK2 reactor. See #3925. ceZdZfdZy)AStreamClientTestsMixin.test_connectEvent..CheckConnectioncHj|jyr7)rrh)r2 connectedr0s r+rzPStreamClientTestsMixin.test_connectEvent..CheckConnection.connectionMades  & r5N)r=r>r?r)rr0sr+CheckConnectionrs r5rc(jSr7)rZ)r]r0r2sr+rfz:StreamClientTestsMixin.test_connectEvent..sT\\'=-Qr5N) rirjr rr rrRrrunr)r2rr]rr0s` @@@r+test_connectEventz(StreamClientTestsMixin.test_connectEventsp ##% G]66x@A  h  W !0 G%QR   "r5c|j|jtjtt j tjjfdgGfddt}t}||_ |j||j|jddy)a3 If a producer is unregistered from a transport after the transport has been disconnected (by the peer) and after C{loseConnection} has been called, the transport is not re-added to the reactor as a writer as would be necessary if the transport were still connected. c$jSr7rignr0s r+rfzOStreamClientTestsMixin.test_unregisterProducerAfterDisconnect.. r5c,eZdZdZdZfdZdZy)UStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocolz Protocol to connect, register a producer, try to lose the connection, wait for the server to disconnect from us, and then unregister the producer. ctjd|jjt |jd|jj y)NClientProtocol.connectionMadeF)rrrregisterProducerrrrs r+rzdStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.connectionMadesA78//'7--/r5ctjd|jj|jt vj dyNzClientProtocol.connectionLost)rr unregisterrrr}r9)r2r;rr0writings r+r<zdStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.connectionLostsB78!t~~W1EEF!!$'r5cbtjd|jjy)NClientProtocol unregister)rrrunregisterProducerrs r+rz`StreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.unregisters34113r5N)r=r>r?r@rr<r)rr0rsr+ClientProtocolr s   0 (  4r5rrz/Transport was writing after unregisterProducer.N)rirjr rrrrlrrrkr r rRrZrm assertFalse)r2rr]rr0rs @@@r+&test_unregisterProducerAfterDisconnectz=StreamClientTestsMixin.test_unregisterProducerAfterDisconnects##% G]66GH:CGG$78 4 4X 40& !/  Wm,   %VWr5c|jddg}jj}||vrtjr t dGdd|j tjttjtjjfdGfddt}t}||_|j#||j%y ) z If C{loseConnection} is called while a producer is registered with the transport, the connection is closed after the producer is unregistered. Glib2Reactor Gtk2Reactorz=A pygobject/pygtk bug disables this functionality on Windows.ceZdZdZy)FStreamClientTestsMixin.test_disconnectWhileProducing..Producerc.tjdy)Nr)rrrs r+rzVStreamClientTestsMixin.test_disconnectWhileProducing..Producer.resumeProducing%s23r5N)r=r>r?rrAr5r+Producerr$s 4r5rc$jSr7rrs r+rfzFStreamClientTestsMixin.test_disconnectWhileProducing..,r r5c4eZdZdZfdZfdZfdZy)LStreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocolz Protocol to connect, register a producer, try to lose the connection, unregister the producer, and wait for the connection to actually be lost. ctjd|jjd|jj j dj d|j y)Nr Fr)rrrrrrr)r2rr0s r+rz[StreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.connectionMade5sV78// EB--/ !!!W%6%64??Kr5c tjd|jjj dj t tdy)Nrg?zConnection was not lost)rrrrrrrr{)r2rr0s r+rzWStreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.unregister?sH34113!!))79=V3W+Xr5cRtjdjdyr)rrr9)r2r;rs r+r<z[StreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.connectionLostIs78!!$'r5N)r=r>r?r@rrr<)rrr0sr+rr".s   L  (r5rN)riryr=r isWindowsrrjr rr rrlrrrkr rRrZrm)r2skippedReactorsreactorClassNamerr]rrr0s @@@r+test_disconnectWhileProducingz4StreamClientTestsMixin.test_disconnectWhileProducings ##%*=9",,55  .83E3E3GR  4 4 G]66x@A:CGG$78 ( (X (>& !/  Wm,  r5N) r=r>r?r@rrrrr)rAr5r+rrs" =!#2,X\?!r5r)5r@rgcrtypingrweakrefrzope.interface.verifyrtwisted.internet.deferrrtwisted.internet.interfacesr r twisted.internet.protocolr r r #twisted.internet.test.reactormixinsrtwisted.pythonrrtwisted.python.failurertwisted.python.logrrrtwisted.python.runtimertwisted.test.test_tcprtwisted.trial.unittestrAF_INET SOCK_STREAMr,r.rCrNrtr}rrrrrrrrrAr5r+r:s  .:ALLC'*44+1+'v~~FDVDV:!(!H$$( ] 1h ?}*""" =  -.-0A'A'H   ' 'c!c!r5