o bN@sdZddlZddlmZddlmZddlmZddlm Z ddl m Z m Z ddl mZmZdd lmZmZmZdd lmZdd lmZmZdd lmZdd lmZmZmZddlm Z ddl!m"Z"ddl#m$Z$dej%ej&fddZ'GdddeZ(GdddZ)GdddeZ*ddZ+ddZ,GdddeZ-Gd d!d!Z.Gd"d#d#eZ/Gd$d%d%e(Z0Gd&d'd'Z1Gd(d)d)Z2Gd*d+d+Z3Gd,d-d-Z4dS).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.1cCst|ddd}t||}z.|||tjkr6|}t|tjtjBd}||dfW|S|W|S|w)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) interfacefamilytypeaddrprobesocknamehostnamer)H/usr/lib/python3/dist-packages/twisted/internet/test/connectionmixins.py findFreePorts      r+c@$eZdZdZdZddZddZdS)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. NcCs||_||_dS)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)selfr.doner)r)r*_setAttributesJs z"ConnectableProtocol._setAttributescCs||_|jd|`dSN)disconnectReasonr/callbackr0reasonr)r)r*connectionLostXs z"ConnectableProtocol.connectionLost)__name__ __module__ __qualname____doc__r4r2r8r)r)r)r*r-:s   r-c@ eZdZdZddZddZdS)EndpointCreatorzT Create client and server endpoints that know how to connect to each other. cCt)z Return an object providing C{IStreamServerEndpoint} for use in creating a server to use to establish the connection type to be tested. NotImplementedErrorr0r.r)r)r*serverczEndpointCreator.servercCr?)z Return an object providing C{IStreamClientEndpoint} for use in creating a client to use to establish the connection type to be tested. r@)r0r. serverAddressr)r)r*clientjrDzEndpointCreator.clientN)r9r:r;r<rCrFr)r)r)r*r>^s r>c@r=)_SingleProtocolFactoryz Factory to be used by L{runProtocolsWithReactor}. It always returns the same protocol (i.e. is intended for only a single connection). cC ||_dSr3 _protocol)r0protocolr)r)r*__init__z z_SingleProtocolFactory.__init__cC|jSr3rI)r0r%r)r)r* buildProtocol}z$_SingleProtocolFactory.buildProtocolNr9r:r;r<rLrOr)r)r)r*rGrs rGc s||t|tt|}t|}||}fdd}||dd}t|j|jg|fdd| ||fdd| 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. cs|}|Sr3)rFgetHostconnect)pclientEndpoint) clientFactoryendpointCreatorr.r)r*gotPorts z(runProtocolsWithReactor..gotPortcSst|ddS)NzConnection setup failed.)rr)resultr)r)r*failedz'runProtocolsWithReactor..failedcSr3r)_) disconnectedr)r*z)runProtocolsWithReactor..cs tjSr3)r stopr]r.r)r*r` ) buildReactorr2rrGrClisten addCallbackrr/ addErrback runReactor) reactorBuilderserverProtocolclientProtocolrW serverFactoryserverEndpointdrXrZr))rVr_rWr.r*runProtocolsWithReactors      rpcCs2t|r |Sd|jjvr|jStd|)zZ Like L{IReactorFDSet.getWriters}, but with support for IOCP reactor as well. IOCPzCannot find writers on )r providedBy getWriters __class__r9handles Exceptionrcr)r)r* _getWriterss  rwc@r=)_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. cCs||_||_dSr3)r.rY)r0r.rYr)r)r*rL z_AcceptOneClient.__init__cCs$t||}|jd|jj||S)Nr)r rOr. callLaterrYr5)r0r%rKr)r)r*rOs z_AcceptOneClient.buildProtocolNrQr)r)r)r*rxs rxc@s(eZdZdZddZddZddZdS) _SimplePullProducerz A pull producer which writes one byte whenever it is resumed. For use by C{test_unregisterProducerAfterDisconnect}. cCrHr3)consumer)r0r|r)r)r*rLrMz_SimplePullProducer.__init__cCsdSr3r)r0r)r)r* stopProducingsz!_SimplePullProducer.stopProducingcCstd|jddS)NProducer.resumeProducingx)rrr|writer}r)r)r*resumeProducings z#_SimplePullProducer.resumeProducingN)r9r:r;r<rLr~rr)r)r)r*r{s  r{c@r,)StopzQ A client factory which stops a reactor when a connection attempt fails. NcCrHr3rcrBr)r)r*rLrMz Stop.__init__cCs&||_td||jdS)NzStop(CF) cCFailed: ) failReasonrgetErrorMessager.rb)r0 connectorr7r)r)r*clientConnectionFailedszStop.clientConnectionFailed)r9r:r;r<rrLrr)r)r)r*rs  rc@s0eZdZdZddZddZddZdd Zd S) 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. cCsd|_||_dSr3)lostConnectionReasononConnectionLost)r0rr)r)r*rLryzClosingLaterProtocol.__init__cCs tddS)N#ClosingLaterProtocol.connectionMade)rr}r)r)r*connectionMades rcCstd||jdS)Nz"ClosingLaterProtocol.dataReceived r transportloseConnectionr0bytesr)r)r* dataReceivedz!ClosingLaterProtocol.dataReceivedcCstd||_|j|dS)N#ClosingLaterProtocol.connectionLost)rrrr5r6r)r)r*r8 srN)r9r:r;r<rLrrr8r)r)r)r*rs  rc@s:eZdZUdZdZeeed<ddZddZ dd Z dS) ConnectionTestsMixinzg This mixin defines test methods which should apply to most L{ITransport} implementations. N endpointscCsPGdddt}|d}|d}t||||j|d|j|d|jdS)z Client and server transports implement L{ILoggingContext.logPrefix} to return a message reflecting the protocol they are running. c@s,eZdZddZddZddZddZd S) zDConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocolcSs||_d|_dSr3)_prefixsystem)r0prefixr)r)r*rL ryzMConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.__init__cSs|jddS)Na)rrr}r)r)r*r$r[zSConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.connectionMadecSrNr3)rr}r)r)r* logPrefix'rPzNConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.logPrefixcSs6ttd|_|jdd|vr|jdSdS)Nrb)rgetrrrrrrr)r)r*r*s  zQConnectionTestsMixin.test_logPrefix..CustomLogPrefixProtocol.dataReceivedN)r9r:r;rLrrrr)r)r)r*CustomLogPrefixProtocols  rz Custom Clientz Custom ServerN)r-rprassertInr)r0rrFrCr)r)r*test_logPrefixs z#ConnectionTestsMixin.test_logPrefixcsgtfdd}jt|fddfdd}t| ddgdS) z} After a connection is disconnected, L{ITransport.write} and L{ITransport.writeSequence} are no-ops. ctSr3rr))serverConnectionLostDeferredr)r*r`Bz@ConnectionTestsMixin.test_writeAfterDisconnect..cstd|j|}tfdd}|t|}dd}||j fdd} | |t gS)N Listening on crr3rr)lostConnectionDeferredr)r*r`LrzSConnectionTestsMixin.test_writeAfterDisconnect..listening..cSstd||jddS)NzAbout to write to r)rrrprotor)r)r*rOszPConnectionTestsMixin.test_writeAfterDisconnect..listening..writecs8t|d|jd|jddgddS)Nz disconnectedssome bytes to get lostssomesmoreT)rrr writeSequenceappendrfinishedr)r*r_Us zWConnectionTestsMixin.test_writeAfterDisconnect..listening..disconnected) rrRrrFrrSr forProtocol addCallbackserrbackrgr)portendpointrKrFrr_)rr.r0rrr* listeningGs     zAConnectionTestsMixin.test_writeAfterDisconnect..listeningcs*tfdddS)NcSr3rbignoredrcr)r*r`brzRConnectionTestsMixin.test_writeAfterDisconnect..onListen..)rgrhrr)r portDeferredr.r)r*onListen_  z@ConnectionTestsMixin.test_writeAfterDisconnect..onListenTN) rerrrCrfr rr ri assertEqual)r0rKrr))rrrr.r0rr*test_writeAfterDisconnect8s    z.ConnectionTestsMixin.test_writeAfterDisconnectcsttt}jtt fddfdd}t | dt  |dS)z After the connection a protocol is being used for is closed, the reactor discards all of its references to the protocol. cs^td|j|}|tfdd}dd}|||j S)Nrcr\r3r)r))rlr)r*r`{razaConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listening..cSstd||jdS)NzAbout to disconnect rrr)r)r* disconnect}rzcConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listening..disconnect) rrRrrFrSr rrgrhr)rrrFr)rlrr.r0r)r*rws  zOConnectionTestsMixin.test_protocolGarbageAfterLostConnection..listeningcs*tfdddS)Ncrr3rrrcr)r*r`rzcConnectionTestsMixin.test_protocolGarbageAfterLostConnection..onListening..)rgrhraddBothr)rr)r* onListeningrzQConnectionTestsMixin.test_protocolGarbageAfterLostConnection..onListeningN)rrrrerrCrfr rr r rir assertIsNone)r0 clientRefrr))rlrrrr.r0r*'test_protocolGarbageAfterLostConnectionis   z__annotations__rrrr)r)r)r*rs  1rc@seZdZdZddZdS)LogObserverMixinzL Mixin for L{TestCase} subclasses which want to observe log events. cCs$g}t|j|tj|j|Sr3)r addObserverr addCleanupremoveObserver)r0loggedMessagesr)r)r*observes zLogObserverMixin.observeN)r9r:r;r<rr)r)r)r*rs rc@seZdZdZdZddZdS)BrokenContextFactoryzv A context factory with a broken C{getContext} method, for exercising the error handling for such a case. zSome path was wrong maybecCs t|jr3) ValueErrormessager}r)r)r* getContextrMzBrokenContextFactory.getContextN)r9r:r;r<rrr)r)r)r*rs rc@s8eZdZdZddZddZddZdd Zd d Zd S) 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. cCs*|}||t}|tt|dS)zR The C{connect} method returns an object providing L{IConnector}. N)rerSr assertTruerr)r0r.rr)r)r*test_interfacesz%StreamClientTestsMixin.test_interfacecs*tfdddS)zl The reactor can be stopped by a client factory's C{clientConnectionFailed} method. cstSr3)rSrr)r.r0r)r*r`szPStreamClientTestsMixin.test_clientConnectionFailedStopsReactor..N)rer rir}r)rr*'test_clientConnectionFailedStopsReactorsz>StreamClientTestsMixin.test_clientConnectionFailedStopsReactorcsnttgGfdddt}t|_tfdd dS)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. cseZdZfddZdS)zAStreamClientTestsMixin.test_connectEvent..CheckConnectioncs|dSr3)rrbr} connectedr.r)r*rs  zPStreamClientTestsMixin.test_connectEvent..CheckConnection.connectionMadeN)r9r:r;rr)rr)r*CheckConnectionsrcs Sr3)rSr))rVr.r0r)r*r`rdz:StreamClientTestsMixin.test_connectEvent..N) rerfr rr rrKr runr)r0rr))rVrr.r0r*test_connectEventsz(StreamClientTestsMixin.test_connectEventcs||ttttj fddgGfdddt }t }||_ | |||dddS)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. crr3rignrcr)r*r`rzOStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..cs0eZdZdZddZfddZddZdS) zUStreamClientTestsMixin.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. cSs,td|jt|jd|jdS)NClientProtocol.connectionMadeF)rrrregisterProducerr{rr}r)r)r*rs  zdStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.connectionMadecs4td||jtvddSNzClientProtocol.connectionLost)rr unregisterrrrwr5r6rr.writingr)r*r8s zdStreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.connectionLostcSstd|jdS)NClientProtocol unregister)rrrunregisterProducerr}r)r)r*r z`StreamClientTestsMixin.test_unregisterProducerAfterDisconnect..ClientProtocol.unregisterN)r9r:r;r<rr8rr)rr)r*ClientProtocols  rrz/Transport was writing after unregisterProducer.N)rerfr rrrrhrrrgr r rKrSri assertFalse)r0rrVr)rr*&test_unregisterProducerAfterDisconnects   z=StreamClientTestsMixin.test_unregisterProducerAfterDisconnectcs|ddg}jj}||vrtrtdGddd|tt t  t j fddGfdd d t }t}||_|||d S) 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.c@seZdZddZdS)zFStreamClientTestsMixin.test_disconnectWhileProducing..ProducercSstddS)Nr)rrr}r)r)r*r%szVStreamClientTestsMixin.test_disconnectWhileProducing..Producer.resumeProducingN)r9r:r;rr)r)r)r*Producer$s rcrr3rrrcr)r*r`,rzFStreamClientTestsMixin.test_disconnectWhileProducing..cs8eZdZdZfddZfddZfddZdS) zLStreamClientTestsMixin.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. cs<td|jd|jdjd|jdS)NrFr)rrrrrrzrr})rr.r)r*r5s  z[StreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.connectionMadecs0td|jdjttddS)Nrg?zConnection was not lost)rrrrrzrrrvr})rr.r)r*r?s  zWStreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.unregistercstdddSr)rrr5r6rr)r*r8Irz[StreamClientTestsMixin.test_disconnectWhileProducing..ClientProtocol.connectionLostN)r9r:r;r<rrr8r)rrr.r)r*r.s   rN)rertr9r isWindowsrrfr rr rrhrrrgr rKrSri)r0skippedReactorsreactorClassNamerrVr)rr*test_disconnectWhileProducings"  z4StreamClientTestsMixin.test_disconnectWhileProducingN) r9r:r;r<rrrrrr)r)r)r*rs   .r)5r<rgcrtypingrweakrefrzope.interface.verifyrtwisted.internet.deferrrtwisted.internet.interfacesrr twisted.internet.protocolr r r #twisted.internet.test.reactormixinsr twisted.pythonrrtwisted.python.failurertwisted.python.logrrrtwisted.python.runtimertwisted.test.test_tcprtwisted.trial.unittestrAF_INET SOCK_STREAMr+r-r>rGrprwrxr{rrrrrrr)r)r)r*s>         $4