Ϫf@dZddlZddlmZmZddlmZmZmZm Z ddl m Z ddl m Z mZddlmZddlmZdd lmZdd lmZdd lmZdd lmZmZmZmZmZmZm Z dZ! ddl"Z"ddl#Z"ddl$Z"ddl%Z%ddl&Z&dd l'm(Z(m)Z)ddl*m+Z+GddZ-GddZ.d-dZ/d-dZ0dZ1GddejdZ3e e3Z4GddejdZ5e e5Z6Gdde5Z7e e7Z8GddejdZ9e e9Z:Gdd Z;e e;Z<Gd!d"Z=Gd#d$ej|e=Z?Gd%d&ej|e=Z@Gd'd(ej|e=ZAGd)d*ej|e=ZBGd+d,ej|e=ZCy#e,$rdZ!YwxYw).z Test HTTP/2 support. N)directlyProvides providedBy)defererrorreactortask) IPv4Address)MemoryReactorClockStringTransport)failure) iterbytes) DummyProducer)unittest)http)DelayedHTTPHandlerDelayedHTTPHandlerProxyDummyHTTPHandlerDummyHTTPHandlerProxyDummyPullProducerHandlerProxy._IDeprecatedHTTPChannelToRequestInterfaceProxy_makeRequestProxyFactory)DecoderEncoder) H2ConnectionzHTTP/2 support not enabledcfeZdZdZdZdZdZgdfdZddZdd Z d Z dd Z dd Z dd Z gfdZy) FrameFactoryz A class containing lots of helper methods and state to build frames. This allows test cases to easily build correct HTTP/2 frames to feed to hyper-h2. c"t|_yNrencoderselfs =/usr/lib/python3/dist-packages/twisted/web/test/test_http2.py__init__zFrameFactory.__init__8 y c"t|_yrrr!s r#refreshEncoderzFrameFactory.refreshEncoder;r%r&cy)NsPRI * HTTP/2.0 SM r!s r#clientConnectionPrefacez$FrameFactory.clientConnectionPreface>s2r&c Htjj|}|jj ||_|j jd|D]}|j j||jD]\}}t||||S)zS Builds a single valid headers frame out of the contained headers. END_HEADERS) hyperframeframe HeadersFramer encodedataflagsadditemssetattr) r"headersr4streamIDpriorityKwargsfflagkvs r#buildHeadersFramezFrameFactory.buildHeadersFrameAs    ) )( 3$$W-  M" D GGKK  #((* DAq Aq!  r&Nc| t|n t}tjj|}||_||_|S)zD Builds a single data frame out of a chunk of data. )setr/r0 DataFramer3r4)r"r3r4r9r;s r#buildDataFramezFrameFactory.buildDataFramePs?$/E SU    & &x 0r&ctjjd}|r|jj d||_|S)z1 Builds a single settings frame. rACK)r/r0 SettingsFramer4r5settings)r"rGackr;s r#buildSettingsFramezFrameFactory.buildSettingsFrameZs9    * *1 -  GGKK  r&cRtjj|}||_|S)z5 Builds a single WindowUpdate frame. )r/r0WindowUpdateFramewindow_increment)r"r9 incrementr;s r#buildWindowUpdateFramez#FrameFactory.buildWindowUpdateFramees'    . .x 8&r&cntjjd}||_||_||_|S)z/ Builds a single GOAWAY frame. r)r/r0 GoAwayFrame error_codelast_stream_idadditional_data)r" lastStreamID errorCodeadditionalDatar;s r#buildGoAwayFramezFrameFactory.buildGoAwayFramems6    ( ( +  '*r&cRtjj|}||_|S)z3 Builds a single RST_STREAM frame. )r/r0RstStreamFramerQ)r"r9rUr;s r#buildRstStreamFramez FrameFactory.buildRstStreamFramews&    + +H 5  r&cntjj|}||_||_||_|S)z1 Builds a single priority frame. )r/r0 PriorityFrame depends_on stream_weight exclusive)r"r9weight dependsOnr_r;s r#buildPriorityFramezFrameFactory.buildPriorityFrames4    * *8 4    r&ctjj|}||_|jj ||_t||_|jjd|S)z5 Builds a single Push Promise frame. r.) r/r0PushPromiseFramepromised_stream_idr r2r3rAr4r5)r"r9promisedStreamIDr8r4r;s r#buildPushPromiseFramez"FrameFactory.buildPushPromiseFramesX    - -h 7/$$W-e*  M"r&Nr,)F)rr&)r)rF)__name__ __module__ __qualname____doc__r$r(r+r?rCrIrNrWrZrbrgr*r&r#rr1sL !!302A  PR r&rc,eZdZdZdZdZdZdZeZy) FrameBuffera A test object that converts data received from Twisted's HTTP/2 stack and turns it into a sequence of hyperframe frame objects. This is primarily used to make it easier to write and debug tests: rather than have to serialize the expected frames and then do byte-level comparison (which can be unclear in debugging output), this object makes it possible to work with the frames directly. It also ensures that headers are properly decompressed. c0t|_d|_y)Nr&)rdecoder_datar!s r#r$zFrameBuffer.__init__sy  r&c.|xj|z c_yr)rq)r"r3s r# receiveDatazFrameBuffer.receiveDatas d r&c|Srr*r!s r#__iter__zFrameBuffer.__iter__s r&c(t|jdkr ttjj j |jdd\}}t|j|dzkr t|jt|jdd|z|jd|zd|_t|tjjr,|jj|jd|_ |S)N T)raw)lenrq StopIterationr/r0Frameparse_frame_header parse_body memoryview isinstancer1rpdecoder3)r"r0lengths r#nextzFrameBuffer.nexts tzz?Q / !"((..AA$**Ra.Q v tzz?VaZ '/ ! DJJq1v:$>?@ZZF - eZ--:: ;,,UZZT,BEJ r&N) rirjrkrlr$rsrur__next__r*r&r#rnrns"  Hr&rnc tg}|jj||jfd|D|djj d|S)a Provides a sequence of HTTP/2 frames that encode a single HTTP request. This should be used when you want to control the serialization yourself, e.g. because you want to interleave other frames with these. If that's not necessary, prefer L{buildRequestBytes}. @param headers: The HTTP/2 headers to send. @type headers: L{list} of L{tuple} of L{bytes} @param data: The HTTP data to send. Each list entry will be sent in its own frame. @type data: L{list} of L{bytes} @param frameFactory: The L{FrameFactory} that will be used to construct the frames. @type frameFactory: L{FrameFactory} @param streamID: The ID of the stream on which to send the request. @type streamID: L{int} r8r9c3DK|]}j|yw)r9N)rC).0chunk frameFactoryr9s r# z%buildRequestFrames..s&BG ##EH#=s  END_STREAM)rappendr?extendr4r5r8r3rr9framess `` r#buildRequestFramesrsk*#~ F MM,0080TU MMKO 2J& Mr&cNt||||}djd|DS)a: Provides the byte sequence for a collection of HTTP/2 frames representing the provided request. @param headers: The HTTP/2 headers to send. @type headers: L{list} of L{tuple} of L{bytes} @param data: The HTTP data to send. Each list entry will be sent in its own frame. @type data: L{list} of L{bytes} @param frameFactory: The L{FrameFactory} that will be used to construct the frames. @type frameFactory: L{FrameFactory} @param streamID: The ID of the stream on which to send the request. @type streamID: L{int} r&c3<K|]}|jywr serializerr;s r#rz$buildRequestBytes..s2aAKKM2)rjoinrs r#buildRequestBytesrs)& |X FF 88262 22r&cNt}|j|t|S)a Given a sequence of bytes, decodes them into frames. Note that this method should almost always be called only once, before making some assertions. This is because decoding HTTP/2 frames is extremely stateful, and this function doesn't preserve any of that state between calls. @param data: The serialized HTTP/2 frames. @type data: L{bytes} @returns: A list of HTTP/2 frames. @rtype: L{list} of L{hyperframe.frame.Frame} subclasses. )rnrslist)r3buffers r#framesFromBytesrs#]F t <r&ceZdZdZdZdZy)ChunkedHTTPHandlerz A HTTP request object that writes chunks of data back to the network based on the URL. Must be called with a path /chunked/ s hello world!ct|jjdd}|jdt |D]}|j |j |jy)N/r)inturisplitsetResponseCoderangewrite chunkDatafinish)r"chunks_s r#processzChunkedHTTPHandler.processsZTXX^^D)"-. S!v 'A JJt~~ & ' r&N)rirjrkrlrrr*r&r#rr s Ir&rc(eZdZdZdZdZdZdZy)ConsumerDummyHandlera This is a HTTP request handler that works with the C{IPushProducer} implementation in the L{H2Stream} object. No current IRequest object does that, but in principle future implementations could: that codepath should therefore be tested. ctjj|g|i||jj d|_d|_y)NF)rRequestr$channelpauseProducing_requestReceivedrqr"argskwargss r#r$zConsumerDummyHandler.__init__*s? d4T4V4 ##% % r&c8|jjy)z& Start the data pipe. N)rresumeProducingr!s r# acceptDatazConsumerDummyHandler.acceptData2s $$&r&cVd|_tjj|g|i|S)NT)rrrrequestReceivedrs r#rz$ConsumerDummyHandler.requestReceived8s) $||++DB4B6BBr&c|jd|jj|_d}|j ||j y)Nrs0this is a response from a consumer dummy handler)rcontentreadrqrr)r" returnDatas r#rzConsumerDummyHandler.process<s> S!\\&&( H  : r&N)rirjrkrlr$rrrr*r&r#rr"s' Cr&rceZdZdZdZy)AbortingConsumerDummyHandlerz This is a HTTP request handler that works with the C{IPushProducer} implementation in the L{H2Stream} object. The difference between this and the ConsumerDummyHandler is that after resuming production it immediately aborts it again. cl|jj|jjy)z@ Start and then immediately stop the data pipe. N)rr stopProducingr!s r#rz'AbortingConsumerDummyHandler.acceptDataOs$ $$& ""$r&N)rirjrkrlrr*r&r#rrGs %r&rceZdZdZdZy)DummyProducerHandlerz An HTTP request handler that registers a dummy producer to serve the body. The owner must call C{finish} to complete the response. cZ|jd|jtdy)NrT)rregisterProducerrr!s r#rzDummyProducerHandler.processcs" S! mot4r&N)rirjrkrlrr*r&r#rr\s  5r&rceZdZdZdZdZy)NotifyingRequestFactorya( A L{http.Request} factory that calls L{http.Request.notifyFinish} on all L{http.Request} objects before it returns them, and squirrels the resulting L{defer.Deferred} away on the class for later use. This is done as early as possible to ensure that we always see the result. clg|_||_t|jD]}t||yr)results_wrappedFactoryrr)r"wrappedFactory interfaces r#r$z NotifyingRequestFactory.__init__ss7 - $D$8$89 .I T9 - .r&c|j|i|}|jj|jt |Sr)rrr notifyFinishr)r"rrreqs r#__call__z NotifyingRequestFactory.__call__}s?"d""D3F3 C,,./=cBBr&N)rirjrkrlr$rr*r&r#rrks.Cr&rceZdZdZereZdZy)HTTP2TestHelpersz] A superclass that contains no tests but provides test helpers for HTTP/2 tests. cb|jtjt|jy)z Confirm that all streams are blocked: that is, the priority tree believes that none of the streams have data ready to send. N) assertRaisespriority DeadlockErrorr)r" connections r#assertAllStreamsBlockedz(HTTP2TestHelpers.assertAllStreamsBlockeds" (00$ 8K8KLr&N)rirjrkrlskipH2skiprr*r&r#rrs Mr&rceZdZgdZgdZgdZgdZdZgdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'd&Z(d'Z)d(Z*y))*HTTP2ServerTests:methodGETs :authoritys localhost:pathrs:schemeshttpss user-agentstwisted-test-code) custom-header1)r2)rPOSTr)r/post_endpointrr)content-lengths25shello sworld, sit's shttp/2!):statuss200)requestr)commandrsversionsHTTP/2)rs13 ''' None ''' )rrrrrr)rs36$''' 25 hello world, it's http/2!''' ct}t}|j}|t|||z }|j |t |D]}|j |||fS)a! Takes a single L{H2Connection} object and connects it to a L{StringTransport} using a brand new L{FrameFactory}. @param connection: The L{H2Connection} object to connect. @type connection: L{H2Connection} @param headers: The headers to send on the first request. @type headers: L{Iterable} of L{tuple} of C{(bytes, bytes)} @param body: Chunks of body to send, if any. @type body: L{Iterable} of L{bytes} @return: A tuple of L{FrameFactory}, L{StringTransport} )rr r+rmakeConnectionr dataReceived)r"rr8bodyr transport requestBytesbytes r#connectAndReceivez"HTTP2ServerTests.connectAndReceivesr $~ #% #;;= )'4FF !!),l+ *D  # #D ) *Y&&r&ct}t|_j|jg\}fd}|j dj |S)z Send request over a TCP connection and confirm that we get back the expected data in the order and style we expect. c@tj}jt|dj t d|ddDj t |dtjjj t |dtjjj t |dtjjjt|djtjj|djjj|djdj d|djvy)Nc3:K|]}|jdk(ywr,N stream_idrs r#rzGHTTP2ServerTests.test_basicRequest..validate..EQ q 0Er,r&r)rvalue assertEqualry assertTrueallrr/r0r1rBdictr3getResponseHeadersgetResponseDatar4r9rr"rs r#validatez4HTTP2ServerTests.test_basicRequest..validates%$Y__%67F   S[! , OOCE&*EE F OOJvay*2B2B2O2OP Q OOJvay*2B2B2L2LM N OOJvay*2B2B2L2LM N   T&)..148O8O3P Q   VAY^^T-A-A B   VAY^^S 1 OOLF1IOO; .validate.. FQ q 0Fr rr&r)rrrryrrrr/r0r1rBrr3postResponseHeaderspostResponseDatar4rs r#rz3HTTP2ServerTests.test_postRequest..validates)$Y__%67F   S[! , OOCF&+FF G OOJvbz:3C3C3P3PQ R OOJvbz:3C3C3M3MN O OOJvbz:3C3C3M3MN O   T&*//2D9Q9Q4R S   VBZ__d.C.C D   VBZ__c 2 OOLF2J,<,<< =r&r,)rrrrpostRequestHeaderspostRequestDatarrrs` @r#test_postRequestz!HTTP2ServerTests.test_postRequests^"^ $9 !-- //1E1E 9 > 11!4@@JJr&c$ gddjDcgc]\}}|dk7s ||f}}}t}t|_j ||j \}  fd}|j dj|Scc}}w)zm Send a POST request without length and confirm that the data is safely transferred. )rrrr)rs38s&''' None hello world, it's http/2!''' rctj}jt|dj t d|ddDj t |dtjjj t |dtjjj t |dtjjjt|djtj|djj|djdj d|djvy)Nrc3:K|]}|jdk(ywrrrs r#rzNHTTP2ServerTests.test_postRequestNoLength..validate..4r r r!r"rr&r)rrrryrrrr/r0r1rBrr3r4)r9rr$r#r"rs r#rz;HTTP2ServerTests.test_postRequestNoLength..validate/s$Y__%67F   S[! , OOCF&+FF G OOJvbz:3C3C3P3PQ R OOJvbz:3C3C3M3MN O OOJvbz:3C3C3M3MN O   T&*//2D9L4M N   VBZ__.> ?   VBZ__c 2 OOLF2J,<,<< =r&r,)r%rrrrr&rr) r"xyr%rrrr$r#rs ` @@@r#test_postRequestNoLengthz)HTTP2ServerTests.test_postRequestNoLengths  H $66 q!!?P:PQF  "^ $9 !-- *D,@,@ 9 > 11!4@@JJ5 s B B c  d}t}t t}t|_t t d|dzd Dcgc]$}tjj||&}}|j}tjjt|}|djd|Dz }|j! t#|D]}|j%| fd}t'j(t |j*j-j/|Scc}w)zi Many interleaved POST requests all get received and responded to appropriately. (r,r r&c3<K|]}|jywrrrr0s r#rz.\ Gu!2 Grctj}jt|dD]}|Dcgc]7}|j|k(r&t |t jjs|9}}jt|djt|djtjj|djjj|djdjd|djvycc}w)Nyr rr,r r&r)rrrryr rr/r0rKrr3r#r$rr4)rrr9r; streamFramesbr" streamIDss r#rz;HTTP2ServerTests.test_interleavedRequests..validatebs$QWWY/F   S[, 7& G$ {{h.&q**:*:*L*LM     \!2A6  a--.T5M5M0N  a!5!5t7L7LM  a!5!5s; Q0E0E EF G s.r2rc tj}jt|d|Dcgc]3}t |t j js(|j5}}gd}j||ycc}w)N)r,r r,r,r r,r,r rBr rBr rBrBrB) rrrryrr/r0rBr )rrr;r7 expectedOrderr6r"s r#rz?HTTP2ServerTests.test_sendAccordingToPriority..validates{$QWWY/F   S[" -&, !z!Z=M=M=W=W/X IJM   Y 6 s )B $B )rr rChunkedHTTPHandlerProxyrrrr4r5r^rbinsertr8r9r:r+rrr rrr<rrr=r) r"r;r?rr9r priorityFramerrrr6s ` @r#test_sendAccordingToPriorityz-HTTP2ServerTests.test_sendAccordingToPrioritys" N   N2 226!&  0"a B   q ! z*%'q ! "q ! z*%'q ! ",, - q M*..v6002  G GGG  l+ !D NN4  ! 7!!$q'@'@'G'G'I"JKWW   W sF%ct}t}t}t|_|j }|t |jg|z }||jdd|jdgjz }|j|t|D]!}|j||js!nt|j}|j!t#|d|j%t'|dt(j*j,|j%|jy)zR A protocol error from the remote peer terminates the connection. r,r r.)r9rfr8r4r rN)rr rrrr+rrrgrrr r disconnectingrrrryrrr/r0rP)r"r;r6r?rrrs r#&test_protocolErrorTerminatesConnectionz7HTTP2ServerTests.test_protocolErrorTerminatesConnections N   N0002 )$*@*@"aHH //** / 0 )+    l+ D NN4   !+ Va(  6":z/?/?/K/KLM (r&ct}t|_j|jj \}|j djj}j|jtj}jt|d|jj!|jj!|j"dtj}jt|dfd}|j$dj'|S)z The H2Stream data implements IPushProducer, and can have its data production controlled by the Request if the Request chooses to. r,shello world, it's http/2!r ctj}jt|dj d|dj vyNrrrrrrryrr4rs r#rz;HTTP2ServerTests.test_streamProducingData..validatesE$Y__%67F   S[! , OOLF2J,<,<< =r&)rConsumerDummyHandlerProxyrrr%r&streams_requestoriginal assertFalserrrrryrrrqrr)r"rrrequestrrrs` @r#test_streamProducingDataz)HTTP2ServerTests.test_streamProducingDatas "^ $= !-- //1E1E 9 $$Q'0099 112 !!23 Va(  001  'CD !!23 Va( >11!4@@JJr&c` t}t t}t|_t j j|}t|d_ |j}|djd|Dz }|j t|D]}|j||jdj j"}j%|j&|j(d}|j+ fd}|j-|S)z The H2Stream data implements IPushProducer, and can have its data production controlled by the Request if the Request chooses to. When the production is stopped, that causes the stream connection to be lost. rr&c3<K|]}|jywrrrs r#rzAHTTP2ServerTests.test_abortStreamProducingData.., ?1 ?rr,ctj}jt|dj t |dt jjj|djdy)Nr rr,) rrrryrrr/r0rYr )r9rr6r"s r#rz@HTTP2ServerTests.test_abortStreamProducingData..validate?sf$QWWY/F   S[! , OOJvbz:3C3C3R3RS T   VBZ111 5r&)rr r!AbortingConsumerDummyHandlerProxyrrr%r&rAr4r+rrr rrWrXrYrZrrrr) r"r;r?rrrr[cleanupCallbackrr6s ` @r#test_abortStreamProducingDataz.HTTP2ServerTests.test_abortStreamProducingDatas  N   N<$D$;$;T=Q=QSTU5r 002  ? ???  l+ !D NN4  ! ))A,''00 11233A6  6**844r&c8t}t|_j|jg\}|j dj j}|jd|jd|jd}|j|jddjj|jj|jdu|jdfd}|j!|S)z When a RstStream frame is received, the L{H2Connection} and L{H2Stream} objects tear down the L{http.Request} and swallow all outstanding writes. r, first chunk second chunk)rUNs third chunkctj}jt|dj|djdj t |dtjjyNr r, rrrryr rrr/r0r1rs r#rz9HTTP2ServerTests.test_terminatedRequest..validateue$Y__%67F   S[! ,   VAY00! 4 OOJvay*2B2B2O2OP Qr&)rDummyProducerHandlerProxyrrrrWrXrYrrrrZrr _disconnectedrrr"rrr[rbrrs` @r#test_terminatedRequestz'HTTP2ServerTests.test_terminatedRequestJs"^ $= !"&"8"8 ..#  i $$Q'0099  n% o&%<.validaterjr&)rrkrrrrWrXrYrrrrWrrrlrrZ_stillProducingrrms` @r#test_terminatedConnectionz*HTTP2ServerTests.test_terminatedConnections"^ $= !"&"8"8 ..#  i $$Q'0099  n% o&%<.validate..r r r,)rs100rr) rrrryrrrr/r0r1r3r4rs r#rz>HTTP2ServerTests.test_respondWith100Continue..validates$Y__%67F   S[! , OOCE&*EE F OOJvay*2B2B2O2OP Q   VAY^^.B-C D OOLF2J,<,<< =r&r,)rrrrrrr)r"rr8rrrs` @r#test_respondWith100Continuez,HTTP2ServerTests.test_respondWith100Continuese "^ $9 !((,H+II--j'2F 9  >11!4@@JJr&ct}t|_j|jg\}|j d}|j j}|jd}|jj|jj|jdufd}|j|S)z Triggering the call to L{H2Stream._respondToBadRequestAndDisconnect} leads to a 400 error being sent automatically and the stream being torn down. r,NcZtj}jt|dj t |dt jjj|djdgj d|djvy)Nr r,)rs400rr) rrrryrrr/r0r1r3r4rs r#rz6HTTP2ServerTests.test_respondWith400..validates$Y__%67F   S[! , OOJvay*2B2B2O2OP Q   VAY^^.B-C D OOLF2J,<,<< =r&)rrkrrrrWrXrYr!_respondToBadRequestAndDisconnectrrlrr)r"rrstreamr[rbrrs` @r#test_respondWith400z$HTTP2ServerTests.test_respondWith400s"^ $= !--j$:P:PRTU 9##A&//**$<**844r&c^t}t|_j|jg\}|j d}|j j}gdD]}|j||jfd}|jdj|S)z Calling L{Request.loseConnection} causes all data that has previously been sent to be flushed, and then the stream cleanly closed. r,)helloworldherearesomewritesctj}jt|dj t d|ddDj t |dtjjj d|djv|Dcgc]3}t |tjjs(|j5}}j|dgzycc}w)Nrwc3:K|]}|jdk(ywrrrs r#rzQHTTP2ServerTests.test_loseH2StreamConnection..validate..r r r,rrr& rrrryrrrr/r0r1r4rBr3)r9rr;receivedDataChunks dataChunksr"rs r#rz>HTTP2ServerTests.test_loseH2StreamConnection..validates$Y__%67F   S[! , OOCE&*EE F OOJvay*2B2B2O2OP Q OOLF2J,<,<< =!'"*Q 8H8H8R8R*S" "   "cU" "s 4)DD) rrkrrrrWrXrYrloseConnectionrr) r"rrr{r[rrrrs ` @@r#test_loseH2StreamConnectionz,HTTP2ServerTests.test_loseH2StreamConnections"^ $= !--j$:P:PRTU 9##A&//**O  !E MM%  !   $11!4@@JJr&ct}t|_|j||jg|j d}|j j}|jt|j|dy)zK The L{H2Stream} object forbids registering two producers. r,TN) rrkrrrrWrXrYr ValueErrorr)r"rr{r[s r#test_cannotRegisterTwoProducersz0HTTP2ServerTests.test_cannotRegisterTwoProducers#sf"^ $= ! z4+A+A2F##A&//** *f&=&=wMr&cXt}t|_j|jg\}|j d}|j jjj}|jfdfd}|jdj|S)z L{Request} objects that have registered pull producers get blocked and unblocked according to HTTP/2 flow control. r,c$jSr)r)r+r[s r#z;HTTP2ServerTests.test_handlesPullProducer..?sw~~/?r&c&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|gdycc}w)Nrr) 0rr3456789r& rrrr4rr/r0rBr3rr9rr;rr"rs r#rz;HTTP2ServerTests.test_handlesPullProducer..validateBs$Y__%67F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Q  )B)B) rrrrrrWrXrY_actualProducerresultrr)r"rrr{producerCompleterr[rs` @@r#test_handlesPullProducerz)HTTP2ServerTests.test_handlesPullProducer1s "^ $A !--j$:P:PRTU 9##A&//**"2299$$%?@ 11!4@@JJr&c&t}t|_|j||jg|j dj j}|j|j|j djy)zJ L{Request} objects can correctly ask isSecure on HTTP/2. r,N) rrrrrrWrXrYrZisSecureabortConnection)r"rr[s r#test_isSecureWorksProperlyz+HTTP2ServerTests.test_isSecureWorksProperlySsu"^ $; ! z4+A+A2F$$Q'0099 ))+,1--/r&c>t}t|_j|jg\}|j dj j}tjd|jfd}|jdj|S)zL L{H2Connection} correctly unblocks when a stream is ended. r,{Gz?ctj}jt|dj d|dj vy)Nr rrrU)rrr"rs r#validateCompletezCHTTP2ServerTests.test_lateCompletionWorks..validateCompletelsE$Y__%67F   S[! , OOLF2J,<,<< =r&) rrrrrrWrXrYr callLaterrrr)r"rrr[rrs` @r#test_lateCompletionWorksz)HTTP2ServerTests.test_lateCompletionWorks_s"^ $; !--j$:P:PRTU 9$$Q'0099$/ >11!4@@AQRRr&cnt}t|_j|jg\}|j d}|j j}|jd|jgd|j|jd}fd}|j|S)zW L{H2Stream} objects can send a series of frames via C{writeSequence}. r,r)Hello,world!c&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|gdycc}w)Nrr)rrrr&rrs r#rz@HTTP2ServerTests.test_writeSequenceForChannels..validates~$Y__%67F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Z)I Jr) rrrrrrWrXrYr writeSequencerrr)r"rrr{r[completionDeferredrrs` @r#test_writeSequenceForChannelsz.HTTP2ServerTests.test_writeSequenceForChannelsus"^ $; !--j$:P:PRTU 9##A&//**$89'??B K"--h77r&c t ttt_ j }| j tjjjdijz }|tjg z }jt|D]}j!|j"d}|j$j& j)dgd fd}t+j,t.d|}|j1 fd fd}j2dj1|S) z Delaying writes from L{Request} causes the L{H2Connection} to block on sending until data is available. However, data is *not* sent if there's no room in the flow control window. rBr,fiver)rrrrcVD]}j|jyr)rr)rrr[s r# write_chunksz7HTTP2ServerTests.test_delayWrites..write_chunkss(# % e$ % NN r&rcdjjddjS)Nr,2r9rM)rrNr)rr?r;s r#rz3HTTP2ServerTests.test_delayWrites..s,!..((!r(BLLNr&ctj}jt|dj t d|ddDj t |dtjjj d|djv|Dcgc]3}t |tjjs(|j5}}j|dgzdgzycc}w)Nrwc3:K|]}|jdk(ywrrrs r#rzFHTTP2ServerTests.test_delayWrites..validate..r r r rrrr&r)r9rr;rr6rr"s r#rz3HTTP2ServerTests.test_delayWrites..validates$QWWY/F   S[! , OOCE&*EE F OOJvay*2B2B2O2OP Q OOLF2J,<,<< =!'"*Q 8H8H8R8R*S" "   " Z'3%/ "s 4)D D )rr rrrr+rIh2rG SettingCodesINITIAL_WINDOW_SIZErrrrr rrWrXrYrr deferLaterrrr) r"rrr{rdrr?r6rr;r[s ` @@@@@r#test_delayWritesz!HTTP2ServerTests.test_delayWritess/ N   N2002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  !1//**  h:   OOGT< 8    $((+77AAr&ct}t}t}t|_|j }|t |jg|z }||jdjz }|j||j|t|j}|jt|d|j!d|j"y)zu A client that immediately resets after sending the body causes Twisted to send no response. r8r3rr,rN)rr rrrr+rrrZrrrrrrry assertNotInr)r"rrr?rrs r#test_resetAfterBodyz$HTTP2ServerTests.test_resetAfterBodys $~ #% N0#;;= )**,    88!8DNNPP  # |$ !23 Va( A556r&ctjGfddt}tt j }t |_|_t_ jjgfd}j|jd}tj|gS)z A custom L{Request} subclass that requires the site and factory in the constructor is able to get them. ceZdZfdZy)THTTP2ServerTests.test_RequestRequiringFactorySiteInConstructor..SuperRequestctj|g|i|j|jj|jj fyr)rr$callbackrsitefactory)r"rrrs r#r$z]HTTP2ServerTests.test_RequestRequiringFactorySiteInConstructor..SuperRequest.__init__s@ ))$@@@ DLL--t||/C/CDEr&N)rirjrkr$)rsr# SuperRequestrs  Fr&rc|\}}j|jj|jyr)assertIsrr)rrrrr"s r#validateFactoryAndSitez^HTTP2ServerTests.test_RequestRequiringFactorySiteInConstructor..validateFactoryAndSites2 MD' MM$  0 MM':#5#5 6r&r,)rDeferredrrr HTTPFactoryrrrobjectrrrrr gatherResults)r"r httpFactoryrrbrrs` @@r#-test_RequestRequiringFactorySiteInConstructorz>HTTP2ServerTests.test_RequestRequiringFactorySiteInConstructors NN  F+ F "^ &&( $<\$J !)  (  z4+A+A2F 7 ,-%<.validates   f %r&r) rrrrrrrrryrrrr)r"rrr deferredsrrrbs` r#test_notifyOnCompleteRequestz-HTTP2ServerTests.test_notifyOnCompleteRequests "^ $;.callback6 II; .errback92  ! !&'// : MM&++u';'; <r&rr) rrrrrrrrry addCallbacksrZrr) r"rrrrrrr invalidDatas ` r#test_notifyOnResetStreamz)HTTP2ServerTests.test_notifyOnResetStream&s "^ $;.callbackarr&cj|tjj|jtj j yr)rr rrr exceptions ProtocolErrorrs r#rz.errbackds8  ! !&'// :  ! !&,, 0K0K Lr&yor3r9)rrrrrrrrrrryrrCrrr r"rrr secondRequestrrrrrs ` r#test_failWithProtocolErrorz+HTTP2ServerTests.test_failWithProtocolErrorGs"^ $;.callbackrr&cj|tjj|jt j yrrrs r#rz3HTTP2ServerTests.test_failOnGoaway..errbackrr&rp)rrrrrrrrrrryrrWrrrrs ` r#test_failOnGoawayz"HTTP2ServerTests.test_failOnGoawayss"^ $;.callbackrr&cj|tjj|jt j yrrrs r#rz:HTTP2ServerTests.test_failOnStopProducing..errbackrr&)rrrrrrrrrrryrrrr) r"rrrrrrrrs ` r#test_failOnStopProducingz)HTTP2ServerTests.test_failOnStopProducings"^ $;.callbackrr&cj|tjj|jt j yrrrs r#rz6HTTP2ServerTests.test_notifyOnFast400..errbackrr&r) rrrrrrrrryrrWrz) r"rrrrrrrr{s ` r#test_notifyOnFast400z%HTTP2ServerTests.test_notifyOnFast400s "^ $;  ../r&cHt}t|_t}t }|j }|j ||j||jtddD]0}|j|jij2t|j}|jt|d|j!t|j}|jt|dy)z If a the L{H2Connection} has been paused by the transport, it will not write automatic frame data triggered by writes. rdr,eN)rrrrr r+rrrrrIrrrrryr)r"rrrr+rrs r# test_bufferingAutomaticFrameDataz1HTTP2ServerTests.test_bufferingAutomaticFrameDatas "^ $9 !#~ #% "."F"F"H!!), 78 !!#q# UA  # #L$C$CB$G$Q$Q$S T U!!23 Va( ""$ !23 Vc*r&cdt}t|_t}t }|j }|j ||j||jd|_ |j|jtddD]0}|j|jij2|j|j|j|jij|j|j y)z If the L{H2Connection} has been paused by the transport, it will not write automatic frame data triggered by writes. If this buffer gets too large, the connection will be dropped. rr N)rrrrr r+rrrr rZrPrrIrrr )r"rrrr+rs r#2test_bufferingAutomaticFrameDataWithCircuitBreakerzCHTTP2ServerTests.test_bufferingAutomaticFrameDataWithCircuitBreaker6s"^ $9 !#~ #% "."F"F"H!!), 78 !!#47 0 001q" UA  # #L$C$CB$G$Q$Q$S T U 001  ? ? C M M OP  ../r&cGddt}t}t|_t }|}|j |d|j }|j||j||j|jt|j}|jt|d|j|jdt!ddD]0}|j|j#ij%2t|j}|jt|d|j|jd|j't|j}|jt|d|j|jd y ) z If the L{H2Connection} has buffered control frames, is unpaused, and then paused while unbuffering, it persists the buffer and stops trying to write. ceZdZdZy)eHTTP2ServerTests.test_bufferingContinuesIfProducerIsPausedOnWrite..AutoPausingStringTransportcjtj|g|i||jjyr)r rproducerrrs r#rzkHTTP2ServerTests.test_bufferingContinuesIfProducerIsPausedOnWrite..AutoPausingStringTransport.write_s*%%d>Bq" UA  # #L$C$CB$G$Q$Q$S T U!!23 Va( >>G ""$ !23 Va( >>Gr&ct}t|}|j|_t}t }|j }|j ||j||jd|_ |jddj}|j||j|jy)z A client that triggers a L{h2.exceptions.ProtocolError} over a paused connection that's reached its buffered control frame limit causes that connection to be aborted. rrrrN)r rrrr r+rrrr rCrrr )r"r rrrr+rs r#+test_circuitBreakerAbortsAfterProtocolErrorz @E N%)N+KZ,5\35j25hK8%5N+KZ N KD 0S,8>@BD7. 9D9.B*.X(.T'.R%N(0T+> 0D+HZ0r&rc~eZdZdZgdZdZgdZgdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZy)H2FlowControlTestszT Tests that ensure that we handle HTTP/2 flow control limits appropriately. )rrrrrrrrrc t}t t}t|_|j }||j tjjjdijz }|tjg|z }|j t|D]}|j!|t#j$dz }t'|D]4}|j)dd}|j!|j6 fd}|j*dj-|S)z When a L{Request} object is not using C{IProducer} to generate data and so is not having backpressure exerted on it, the L{H2Stream} object will buffer data until the flow control window is opened. rBr,rctj}jd|djvdj d|D}j j |y)Nrrr&c3~K|]5}t|tjjs(|j7ywrrr/r0rBr3rs r#rzMH2FlowControlTests.test_bufferExcessData..validate...**Q 8H8H8R8R*S*)==)rrrr4rrrr9ractualResponseDatar6r"s r#rz:H2FlowControlTests.test_bufferExcessData..validatesg$QWWY/F OOLF2J,<,<< ="%* &*"    T113E Fr&)rr rrrr+rIrrGrrrrrrr rryrrrNrr) r"r;r?rr bonusFramesrr0rr6s ` @r#test_bufferExcessDataz(H2FlowControlTests.test_bufferExcessDatas* N   N0002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  ! $../!3 {# .A,,a1,EE NN5??, - . G((+77AAr&ct}tt}t|_|j }||j tjjjdijz }|tjg|z }|jt|D]}|j!||j"d}|j$j&}j)|j*|j-dj/|j*j1|j2j4dg|j!|j7ddjj/|j*j1|j2j4dg|j!|j7ddjj/|j*j1|j2j4dg|j!|j7ddjj)|j*j1|j2j4ddg|j-dj/|j*j1|j2j4gd|j!|j7dd jj)|j*j1|j2j4gd |j9|j;fd }|j<dj?|S) z L{Request} objects that have registered producers get blocked and unblocked according to HTTP/2 flow control. rBr, helloworldpauserrresume)r1r2r1r)r1r2r1r2c&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|gdycc}w)Nrr)r0r0r&rr9rr;rr6r"s r#rzDH2FlowControlTests.test_producerBlockingUnblocking..validate3s}$QWWY/F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Z)L Mr) rr rrkrr+rIrrGrrrrrrr rrWrXrYr_producerProducingrrZrreventsrNunregisterProducerrrr r"r;r?rrr{r[rr6s ` @r#test_producerBlockingUnblockingz2H2FlowControlTests.test_producerBlockingUnblockings N   N4002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  !1//** 112  m$ 223 ))007)< q//a/HRRTU 223 ))007)< q//a/HRRTU 223 ))007)< q//a/HRRTU 112 ))007H2EF  m$ 223 ))002NO q//b/ISSUV 112     # #%K  ""$ N((+77AAr&c t ttt_ j }| j tjjjdijz }|tjg z }jt|D]}j!|j"d j$j& j) j* j-dj/ j*j1 j2j4dg j-d fd}t7j8t:d|}fd}j<dj?|}tAjB||gS) zQ Exactly filling the flow control window still blocks producers. rBr,r0r1hc,jjddjjjj j jddgjjy)Nr,rrr1r2) rrNrrr5rrr6r7r)r?r;r[r"r{sr# window_openz=H2FlowControlTests.test_flowControlExact..window_openhsv NN((!r(BLLN  OOF55 6   W--44w6I J  & & ( NN r&rc&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|gdycc}w)Nrr)r~rr;r&rr4s r#rz:H2FlowControlTests.test_flowControlExact..validatets}$QWWY/F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Z)H Ir)"rr rrkrr+rIrrGrrrrrrr rrWrXrYrr5rrZrrr6rrrrrrr<) r"rrr= windowDeferr validateDeferr?r6r;r[r{s ` @@@@@r#test_flowControlExactz(H2FlowControlTests.test_flowControlExactAs N   N4002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  !1//** 112  m$ 223 ))007)<  d  oogq+>  J11!4@@J !!; ">??r&c|t}tt}t|_|j }||j tjjjdijz }|tjg|z }|jt|D]}|j!||j"d}|j$j&}j)|j*|j-d|j/|j1j)|j2t5j6d|j |j9ddjfd}|j:dj=|S)z L{Request} objects that end a stream that is currently blocked behind flow control can still end the stream and get cleaned up. rBr,r0rrrc&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|gdycc}w)Nrr)r~rr&rr4s r#rz=H2FlowControlTests.test_endingBlockedStream..validates}$QWWY/F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Z)B Cr)rr rrkrr+rIrrGrrrrrrr rrWrXrYrr5rr7rfinishedrrrNrrr8s ` @r#test_endingBlockedStreamz+H2FlowControlTests.test_endingBlockedStreamsw N   N4002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  !1//** 112  m$""$ (()  NN $ $a2 $ > H H J  D((+77AAr&c t}t t}t|_|j }|t jg|z }|j t|D]}|j||jd}|jj}|jd}|j|j!j#|j$ fd}|j'|S)z< We safely handle responses without bodies. r,cZtj}jt|dj d|dj v|Dcgc]3}t |tjjs(|j5}}j|dgycc}wNr rrr& rrrryrr4rr/r0rBr3r4s r#rz=H2FlowControlTests.test_responseWithoutBody..validate$QWWY/F   S[! , OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ     )B(B()rr rrkrr+rrrr rrWrXrYrr7rrrDr r"r;r?rrr{r[rbrr6s ` @r#test_responseWithoutBodyz+H2FlowControlTests.test_responseWithoutBodys N   N5002 )$*@*@"aHH  l+ !D NN4  !1//**33A6 ""$ (() "**844r&c| t}t t}t|_|j }|t jg|z }|j t|D]}|j||jd}|jj}|jd}|j|j!j#|j$|j|j'ddj) fd}|j+|S)zk WindowUpdate frames received after we've completed the stream are safely handled. r,rrcZtj}jt|dj d|dj v|Dcgc]3}t |tjjs(|j5}}j|dgycc}wrHrIr4s r#rzGH2FlowControlTests.test_windowUpdateForCompleteStream..validaterJrK)rr rrkrr+rrrr rrWrXrYrr7rrrDrNrrrLs ` @r#"test_windowUpdateForCompleteStreamz5H2FlowControlTests.test_windowUpdateForCompleteStreams N   N5002 )$*@*@"aHH  l+ !D NN4  !1//**33A6 ""$ (() q//b/ISSUV "**844r&c*t}tt}t|_|j }||j tjjjdijz }|tjg|z }|jt|D]}|j!||j"d}|j$j&}j)|j*|j-dj)|j*j/|j0j2g|j!|j5ddjj)|j*j/|j0j2g|j7|j9fd}|j:dj=|S)z L{Request} objects that have registered producers that are not blocked behind flow control do not have their producer notified. rBr,wordrc&tj}jd|djv|Dcgc]3}t |t j js(|j5}}j|ddgycc}w)NrrrRr&rr4s r#rz;H2FlowControlTests.test_producerUnblocked..validateZs$QWWY/F OOLF2J,<,<< =!'*Q 8H8H8R8R*SJ   Z'3 8r)rr rrkrr+rIrrGrrrrrrr rrWrXrYrr5rrrr6rNr7rrrr8s ` @r#test_producerUnblockedz)H2FlowControlTests.test_producerUnblocked,s N   N4002 ,, [[ % % 9 91 = )+   )$*@*@"aHH  l+ !D NN4  !1//** 112  g 112 ))00"5 q//a/HRRTU 112 ))00"5 ""$ 9((+77AAr&ct}tt}t|_t j j|}|jd|jdd|j}|djd|Dz }|jt|D]}|j|fd}|jdj!|S)z When a WindowUpdate frame is received for the whole connection but no data is currently waiting, nothing exciting happens. r,rrBrr&c3<K|]}|jywrrrs r#rzBH2FlowControlTests.test_unnecessaryWindowUpdate..vr_rctj}jd|djvdj d|D}j j |y)Nrrr&c3~K|]5}t|tjjs(|j7ywrr(rs r#rzTH2FlowControlTests.test_unnecessaryWindowUpdate..validate..r)r*)rrrr4rrr$r+s r#rzAH2FlowControlTests.test_unnecessaryWindowUpdate..validate}sg$QWWY/F OOLF2J,<,<< ="%* &*"    T224F Gr&)rr rrrrr%r&rLrNr+rrr rrr)r"r;r?rrrrr6s` @r#test_unnecessaryWindowUpdatez/H2FlowControlTests.test_unnecessaryWindowUpdatehs N   N0$D$;$;T=Q=QSTU a1111JK002  ? ???  l+ !D NN4  ! H((+77AAr&ct}t}t}t|_g}|j |j |jd|j |jdd|j}|djd|Dz }|j||j||j|y)z When a WindowUpdate frame is received for a stream but no data is currently waiting, that stream is not marked as unblocked and the priority tree continues to assert that no stream can progress. r,rrBrr&c3<K|]}|jywrrrs r#rzKH2FlowControlTests.test_unnecessaryWindowUpdateForStream..s717rN)rr rrrrr?r%rNr+rrrr)r"r;rconnrr3s r#%test_unnecessaryWindowUpdateForStreamz8H2FlowControlTests.test_unnecessaryWindowUpdateForStreams N#% ~3  a))$2I2ITU)VW a..Q.GH((* 7777 I& $ $$T*r&ct}t}t}t|_t |j |j|}|j}|djd|Dz }|j|t|D]}|j||jdj|jdd}|j|j!t#|j%}|j't)|dt*j,j.y)zq When a WindowUpdate frame is received for a stream that has been aborted it is ignored. r&c3<K|]}|jywrrrs r#rzEH2FlowControlTests.test_windowUpdateAfterTerminate..r_rr,rBrrN)rr rrrrr%r&r+rrr rrWrrNrrrrrr/r0rY)r"r;r6r?rrrwindowUpdateFrames r#test_windowUpdateAfterTerminatez2H2FlowControlTests.test_windowUpdateAfterTerminates N   N0$D$;$;T=Q=QSTU002  ? ???  l+ !D NN4  ! ! $$&44a14M (2245!+  6":z/?/?/N/NOPr&c t ttt_t j j } j}|djd|Dz }jt|D]}j| fd}fd}jdj|}|j|S)zs When a WindowUpdate frame is received for a stream that has been completed it is ignored. r&c3<K|]}|jywrrrs r#rzDH2FlowControlTests.test_windowUpdateAfterComplete..r_rcjjdd}j|jy)Nr,rBr)rNrr)rr`r?r;s r# update_windowzHH2FlowControlTests.test_windowUpdateAfterComplete..update_windows/ ! 8 8!q 8 Q  NN,668 9r&cvtj}jd|djy)Nrr)rrassertInr4rrr6r"s r#rzCH2FlowControlTests.test_windowUpdateAfterComplete..validates-$QWWY/F MM,r (8(8 9r&r,)rr rrrrr%r&r+rrr rrr) r"rrrrerrr?r6r;s ` @@@r#test_windowUpdateAfterCompletez1H2FlowControlTests.test_windowUpdateAfterCompletes N   N0$D$;$;T=Q=QSTU002  ? ???  l+ !D NN4  ! :  :  % %a ( 4 4] C}}X&&r&ct}t}t}t|_ddzgdz}t d|D}|j ddd|fgz}t|||}|d=|j|jd tjjj |j}|d jd |Dz }|j!||j#|t%|j'}|D cgc]2} t)| t*j,j.r | j04} } |j3d g| |D cgc])} t)| t*j,j4s(| +} } |D cgc])} t)| t*j,j6s(| +} } |j9| |j9| ycc} wcc} wcc} w)z When a DATA frame is received at the same time as RST_STREAM, Twisted does not send WINDOW_UPDATE frames for the stream. i@rc32K|]}t|ywr)ry)rr3s r#rz;H2FlowControlTests.test_dataAndRstStream..s<$CI. r_rr)rr rrrsumr%rrrZrerrors ErrorCodesINTERNAL_ERRORr+rrrrrrr/r0rKr rr1rBrZ) r"rrr? frameData bodyLengthr8rrr;windowUpdateFrameIDs headersFrames dataFramess r#test_dataAndRstStreamz(H2FlowControlTests.test_dataAndRstStreams $~ #% N0 &'!+ <)<<= ))#2.3CZ2P1QQ#),  2J  , ,bii&:&:&I&I -  $;;=  ? ???  # |$!!23  !Z--??@ KK  !23  Az/?/?/L/L!MA  "(UA:a9I9I9S9S+TaU U ' $  Vs7G1*)G6G6)G;G;cRt}t|}|j|_t|_t }t }|j}|j||j|d}|j|j|j}|j||jd|_|j|j!||j#|j%|j'|j(y)z Aborting a request associated with a paused connection that's reached its buffered control frame limit causes that connection to be aborted. r,rrN)r rrrrrr r+rrr?r%rrr clear abortRequestrZrrr )r"r rrrr+r9headersFrameDatas r##test_abortRequestWithCircuitBreakerz6H2FlowControlTests.test_abortRequestWithCircuitBreaker s +, !-0 ,66 $9 !#~ #% #/"F"F"H!!), 78'99++h: )+   01 !!#34 0  ) *+  ../r&N)rirjrkrlrrr%r&r$r.r9rArErMrPrTrYr]rarirwr|r*r&r#r$r$s*ODOA+BZQBf@@D8Bt25h95v:Bx!BF+2Q@ 'D5%n)0r&r$c,eZdZgdZdZdZdZdZy)HTTP2TransportCheckingrct}t}t|_|j |d|j |j |uy)zU L{H2Connection} can be registered with the transport as a producer. TN)r rrrrrr)r"r6r?s r#"test_registerProducerWithTransportz9HTTP2TransportChecking.test_registerProducerWithTransportT s?   N0 1d#  a(r&c t}t tt_t j g|}|j}|djd|Dz }j  jdt|D]}j|jjd  fd} fd}tj t"d|}|j%||S)z| L{H2Connection} can be paused by its consumer. When paused it stops sending data to the transport. r&c3<K|]}|jywrrrs r#rzNHTTP2TransportChecking.test_pausingProducerPreventsDataSend..l r_rTr,c|tj}jt|dj t |dt jjjjjjjS)Nr r) rrrryrZrr/r0rBr)rrr?r6rbr"s r#validateNotSentzTHTTP2TransportChecking.test_pausingProducerPreventsDataSend..validateNotSent s$QWWY/F   S[! ,   Zr J4D4D4N4NO P                " "r&ctj}jt|dj d|dj vyrTrUrhs r#rzUHTTP2TransportChecking.test_pausingProducerPreventsDataSend..validateComplete sD$QWWY/F   S[! , OOLF2J,<,<< =r&r)rr rrrrrr+rrrr rrrrrrr) r"r;rrrrrrr?r6rbs ` @@@r#$test_pausingProducerPreventsDataSendz;HTTP2TransportChecking.test_pausingProducerPreventsDataSend_ s N   N0$D$:$:BB002  ? ???   1d#l+ !D NN4  ! 33A6 # > OOGT? ; &'r&ct}t}t}t|_t |j g|}|j}|djd|Dz }|j||j|dt|D]}|j||jt|j}|j!t#|d|j%t'|dt(j*j,|j%|j.y)zo L{H2Connection} can be stopped by its producer. That causes it to lose its transport. r&c3<K|]}|jywrrrs r#rz. r_rTr rN)rr rrrrrr+rrrr rrrrrryrZrr/r0rBrr)r"r;r6r?rrrs r#test_stopProducingz)HTTP2TransportChecking.test_stopProducing s N   N0$D$:$:BB002  ? ???   1d#l+ !D NN4  !  + Va( F2J 0@0@0J0JKL **+r&cl tddd tddd t}t }t}t|_|j |tjg|}|j}|djd|Dz }t|D]}|j||jd  j j j j! |j"d } fd }|j%|S) z{ A L{H2Stream} object correctly passes through host and peer information from its L{H2Connection}. TCPz 17.52.24.8iz 17.188.0.12i}) hostAddress peerAddressr&c3<K|]}|jywrrr1s r#rzEHTTP2TransportChecking.test_passthroughHostAndPeer.. r2rr,cjjjjyr)rgetHostgetPeer)rrrr"r{s r#rzDHTTP2TransportChecking.test_passthroughHostAndPeer..validate s1   V^^-{ ;   V^^-{ ;r&)r rr rrrrrrr+rr rrWrrrrr) r"rrrrrrrbrrrr{s ` @@@r#test_passthroughHostAndPeerz2HTTP2TransportChecking.test_passthroughHostAndPeer s "%s; !%> #~ # U !^ $9 !!!),#D$:$:B M#;;=  G GGG l+ *D  # #D ) *##A& );7 );7%<!5r&r~ceZdZdZdZy)HTTP2SchedulingTestsz The H2Connection object schedules certain events (mostly its data sending loop) using callbacks from the reactor. These tests validate that the calls are scheduled correctly. ctj}t|}|j}|j t |d|d}|j |j|j |jd|j |j|j|j |jd|j |jiy)z} When a H2Connection is established it schedules one call to be run as soon as the reactor has time. r,rr*N) rClockrgetDelayedCallsrryractivetimefunc_sendPrioritisedDatarkw)r"rr?callscalls r#"test_initiallySchedulesOneDataCallz7HTTP2SchedulingTests.test_initiallySchedulesOneDataCall s **,  !''') UQ'Qx  & A& A$:$:; B' "%r&N)rirjrkrlrr*r&r#rr s  &r&rc~eZdZdZgdZeZdZdZdZ efdZ dZ dZ d Z d Zd Zd Zd ZdZdZdZy)HTTP2TimeoutTestsz@ The L{H2Connection} object times out idle connections. rc&|j|_y)a Unfortunately, TimeoutMixin does not allow passing an explicit reactor to test timeouts. For that reason, we need to monkeypatch the method set up by the TimeoutMixin. @param connection: The HTTP/2 connection object to patch. @type connection: L{H2Connection} @param reactor: The reactor whose callLater method we want. @type reactor: An object implementing L{twisted.internet.interfaces.IReactorTime} N)r)r"rrs r#patch_TimeoutMixin_clockz*HTTP2TimeoutTests.patch_TimeoutMixin_clock s '00 r&ctj}t|}d|_|j ||t }t ||_|j|t|D]}|j||||fS)a Performs test setup by building a HTTP/2 connection object, a transport to back it, a reactor to run in, and sending in some initial data as needed. @param initialData: The initial HTTP/2 data to be fed into the connection after setup. @type initialData: L{bytes} @param requestFactory: The L{Request} factory to use with the connection. r) rrrtimeOutrr rrrr r)r" initialDatarrr\rrs r#initiateH2Connectionz&HTTP2TimeoutTests.initiateH2Connection s**,G$  %%dG4#% 6~F I&k* $D   d # $y))r&c8t|}|jt|||jt |dt j j|j|dj||j|dj|y)z Confirm that the data that was sent matches what we expect from a timeout: namely, that it ends with a GOAWAY frame carrying an appropriate error code and last stream ID. rN) rrryrrr/r0rPrQrR)r"r3 frameCountrUrTrs r#assertTimedOutz HTTP2TimeoutTests.assertTimedOut9 sy !& Vj1  6":z/?/?/K/KLM .. : 22LAr&c||jurtj}t}|j }|j |t \}}}||_|jd|j|jdtjjjd|j|j|j!|j"|||fS)a Does the common setup for tests that want to test the aborting functionality of the HTTP/2 stack. @param abortTimeout: The value to use for the abortTimeout. Defaults to whatever is set on L{H2Connection.abortTimeout}. @type abortTimeout: L{int} or L{None} @return: A tuple of the reactor being used for the connection, the connection itself, and the transport. rrr rrrUrT)_DEFAULTr abortTimeoutrr+rradvancerrrrorpNO_ERRORrrPrZr )r"rrrrr\rs r#prepareAbortTestz"HTTP2TimeoutTests.prepareAbortTestF s 4== ('44L#~ "::< #'#<#< +$=$  y)   OO ii**33   //0 //0i''r&c t}|j}|j|t\}}}|j }|j d|j ||j |j|j|j d|j|j dtjjjd|j|jy)z When a L{H2Connection} does not receive any data for more than the time out interval, it closes the connection cleanly. rrr rrN)rr+rrrrrrZrPrrrorprr)r"rrrr\rpreambles r#test_timeoutAfterInactivityz-HTTP2TimeoutTests.test_timeoutAfterInactivityl s $~ "::< #'#<#< +$=$  y ??$  9??#45 001   OO ii**33   //0r&ct}d}|j|t\}}}t|j D]@}|j ||j d|j|jB|j d|j|jdtjjjd|j|jy)zM When a L{H2Connection} receives data, the timeout is reset. r&rrr rrN)rrrr r+rrrZrPrrrrorprr)r"rrrr\rrs r#test_timeoutResetByRequestDataz0HTTP2TimeoutTests.test_timeoutResetByRequestData s $~  #'#<#< +$=$  y lBBDE 6D   d # GOOB    Y44 5 6   OO ii**33   //0r&c t}d}g t|jg|}|j}|dj d|Dz } fd}|j ||\}}}|j |j|jd|jt dtdD]C} djd |jd|j|jE|jd |j|jd t j"j$j&d y )zJ When a L{H2Connection} sends data, the timeout is reset. r&c3<K|]}|jywrrrs r#rzDHTTP2TimeoutTests.test_timeoutResetByResponseData.. >! >rcDt||}j||S)N)queued)rr)r{rrrequestss r# saveRequestzFHTTP2TimeoutTests.test_timeoutResetByResponseData..saveRequest s $VF;C OOC Jr&rrr, rs some bytesr  rN)rrrr+rrrr assertEqualsryrrrZrPrrrrorpPROTOCOL_ERROR) r"rrrrrr\rr+rs @r#test_timeoutResetByResponseDataz1HTTP2TimeoutTests.test_timeoutResetByResponseData sD $~  #D$:$:B M"::< sxx>v>>>   $(#<#< &$=$  y ,>>@A  #h-+r 6A QK  m , GOOB    Y44 5  6   OO ii**99  r&ct}t|jg|}|j}|dj d|Dz }|j |t \}}}|jd|j|jdtjjjd|j|jy) z When a L{H2Connection} times out with active streams, the error code returned is L{h2.errors.ErrorCodes.PROTOCOL_ERROR}. r&c3<K|]}|jywrrrs r#rzOHTTP2TimeoutTests.test_timeoutWithProtocolErrorIfStreamsOpen.. rrrrr r,rN)rrrr+rrrrrrrrorprrrP)r"rrrrr\rs r#*test_timeoutWithProtocolErrorIfStreamsOpenzv>>> #'#<#< /$=$  y   OO ii**99   //0r&c t}t|jg|}|j}|dj d|Dz }|j |t \}}}|j}t|j}|jdt|j} |j|dz | |jd|j|j|y)zU When a L{H2Connection} loses its connection it cancels its timeout. r&c3<K|]}|jywrrrs r#rzCHTTP2TimeoutTests.test_noTimeoutIfConnectionLost.. rrrrr,rN) rrrr+rrrrryrconnectionLostrr) r"rrrrr\rsentData oldCallCountcurrentCallCounts r#test_noTimeoutIfConnectionLostz0HTTP2TimeoutTests.test_noTimeoutIfConnectionLost s$~ #D$:$:B M"::< sxx>v>>> #'#<#< /$=$  y ??$272245  H%6w6689 )+;<  *H5r&cL|j\}}}|jd|j|j|j |j |jd|j|j|j|j y)z When a L{H2Connection} has timed the connection out, and the transport doesn't get torn down within 15 seconds, it gets forcibly closed. r,NrrrrPrZr r"rr\rs r#,test_timeoutEventuallyForcesConnectionClosedz>HTTP2TimeoutTests.test_timeoutEventuallyForcesConnectionClosed s $(#8#8#: y   //0 //0  //0  ../r&c|j\}}}|jd|jd|jd|j|j|j |j y)z When a L{H2Connection} has timed the connection out, getting C{connectionLost} called on it cancels the forcible connection close. rNr,)rrrrrPrZr rs r#$test_losingConnectionCancelsTheAbortz6HTTP2TimeoutTests.test_losingConnectionCancelsTheAbort! sm $(#8#8#: y  D!   //0 //0r&c|jd\}}}|jd|j|j|j |j y)z When a L{H2Connection} has timed the connection out but the C{abortTimeout} is set to L{None}, the connection is never aborted. N)rlrrs r#'test_losingConnectionWithNoAbortTimeOutz9HTTP2TimeoutTests.test_losingConnectionWithNoAbortTimeOut1 sT $(#8#8d#8#K y   //0 //0r&c|j\}}}|jd|j|j|j|j|j t jy)z} If a timed out transport doesn't close after 15 seconds, the L{HTTPChannel} will forcibly close it. N)rrrrPr rrConnectionDoners r#"test_connectionLostAfterForceClosez4HTTP2TimeoutTests.test_connectionLostAfterForceClose> sc $(#8#8#: y   //0  ../ E001r&ct}t|}|j|_d|_t }t }|j }|j||j|t|j|jzD]A}|j|jdj|jdC|j|jy)zR A client that sends only invalid frames is eventually timed out. <r,N)r rrrrr r+rrrrrZrrrr )r"r rrrr+rs r#,test_timeOutClientThatSendsOnlyInvalidFramesz>HTTP2TimeoutTests.test_timeOutClientThatSendsOnlyInvalidFramesO s+, !-0 ,66  #~ #% "."F"F"H!!), 78z))J,C,CCD %A  # #L$D$DQ$G$Q$Q$S T  ! !! $ %  ../r&N)rirjrkrlrrrrrrrrrrrrrrrrrr*r&r#rr shxH 1*8 B-5$(L 1D 1D* X1468 01 12"0r&rrh)Drlr8zope.interfacerrtwisted.internetrrrrtwisted.internet.addressr twisted.internet.testingr r twisted.pythonr twisted.python.compatr twisted.test.test_internetr twisted.trialr twisted.webrtwisted.web.test.test_httprrrrrrrrr h2.errors h2.exceptionsr/r hpack.hpackrrtwisted.web._http2r ImportErrorrrnrrrrrrKrrVrrarrkrNotifyingRequestFactoryProxyrTestCaserr$r~rrr*r&r#rs 7880H"+4"  *,/ aaH''TB3.((33EF4<<D55IJ %#7 % %= %! 54<< 555IJCC0 88OPMM"K0x((*:K0\(a 0**,<a 0HT5X..0@T5n&8,,.>&8l0))+;l0aN* )F*s"FFF