ϪfM'dZddlZddlZddlZddlmZddlmZddl m Z ddl m Z ddl mZmZddlmZmZdd lmZdd lmZdd lmZmZdd lmZdd lmZddlmZddl m!Z!ddl"m#Z#ddl$m%Z%m&Z&ddl'm(Z(m)Z)m*Z*ddl+m,Z,ddl-m.Z.GddZ/GddZ0Gdde!Z1GddZ2Gdde2e!Z3Gdd e2Z4Gd!d"e4e!Z5Gd#d$e4e!Z6Gd%d&e2e!Z7Gd'd(e2e!Z8y))z Tests for L{twisted.web.wsgi}. N)exc_info)quote) verifyObject)reactor) IPv4Address IPv6Address)Deferred gatherResults)ConnectionLost)EventLoggingObserver)LoggerglobalLogPublisher)Failure) getThreadID) ThreadPool)TestCase)http) IResourceResource)RequestSiteversion) DummyChannel) WSGIResourcec$eZdZdZeZdZy)SynchronousThreadPoola A single-threaded implementation of part of the L{ThreadPool} interface. This implementation calls functions synchronously rather than running them in a thread pool. It is used to make the tests which are not directly for thread-related behavior deterministic. cj ||i|y#t$r|jjdYywxYw)zp Call C{f(*a, **kw)} in this thread rather than scheduling it to be called in a thread. zz)WSGIResourceTests.setUp..Wr-N)rr/rresourcer"s r&setUpzWSGIResourceTests.setUpNs % % ' ! # /  r-ctt|j|j|jjy)zW L{WSGIResource} implements L{IResource} and stops resource traversal. N)rrr= assertTrueisLeafr>s r&test_interfacesz!WSGIResourceTests.test_interfacesZs( Y .  ,,-r-c |jt|jjdt t d|jt|jj dty)z A L{WSGIResource} cannot have L{IResource} children. Its C{getChildWithDefault} and C{putChild} methods raise L{RuntimeError}. fooFN) assertRaises RuntimeErrorr=getChildWithDefaultrrputChildrr>s r&test_unsupportedz"WSGIResourceTests.test_unsupportedasS   MM - -  LNE *  , (>(> Sr-ctj|t}GddtGddt}fd}Gfdd}t |t ||_|jj|td|jd t||d d }|j|j|jy ) z If an exception is thrown by the application, and then in the exception handling code, verify it should be propagated to the provided L{ThreadPool}. ceZdZdZy)IWSGIResourceTests.test_applicationAndRequestThrow..ArbitraryErrorz; An arbitrary error for this class N)r(r)r*r+r,r-r&ArbitraryErrorrMvs r-rNc"eZdZdZdZdZdZy)PWSGIResourceTests.test_applicationAndRequestThrow..FinishThrowingRequestzL An L{IRequest} request whose finish method throws. c`tj|g|i|d|_d|_d|_y)Nswww.example.com/stuff)r__init__prepathpostpathuri)r"argskwargss r&rSzYWSGIResourceTests.test_applicationAndRequestThrow..FinishThrowingRequest.__init__s/  777! " 3r-cy)zi Return loopback address. @return: loopback ip address. 127.0.0.1r,r>s r& getClientIPz\WSGIResourceTests.test_applicationAndRequestThrow..FinishThrowingRequest.getClientIPs #r-ctdddS)z` Return a fake Address @return: A fake address TCPrZi0u)rr>s r&getHostzXWSGIResourceTests.test_applicationAndRequestThrow..FinishThrowingRequest.getHosts #5+u==r-N)r(r)r*r+rSr[r^r,r-r&FinishThrowingRequestrP{s  4  # >r-r_c)z An application object that throws an exception. @param environ: unused @param startResponse: unused r,)r9r:rNs r& applicationzFWSGIResourceTests.test_applicationAndRequestThrow..applications!" "r-ceZdZdZfdZy)QWSGIResourceTests.test_applicationAndRequestThrow..ThrowingReactorThreadszt An L{IReactorThreads} implementation whose callFromThread raises an exception. c)z Raise an exception to the caller. @param f: unused @param a: unused @param kw: unused r,)r"r#r$r%rNs r&r1z`WSGIResourceTests.test_applicationAndRequestThrow..ThrowingReactorThreads.callFromThreads%&&r-Nr2)rNsr&ThrowingReactorThreadsrcs   'r-reFr log_failureN)r createWithCleanupr Exceptionrrrr=renderr assertEqualslenassertIsInstancevalueflushLoggedErrors)r" logObserverr_rarer#rNs @r&test_applicationAndRequestThrowz1WSGIResourceTests.test_applicationAndRequestThrowns +<G >6 # ' '$% " $&;&={   2<>5IJ !S-. N= ) agg~6 ~.r-N)r(r)r*r?rCrJrqr,r-r&r4r4Ms  . TL/r-r4cHeZdZdZeZdZdgddfdZdZe fdZ dZ d d Z y) WSGITestsMixinz @ivar channelFactory: A no-argument callable which will be invoked to create a new HTTP channel to associate with request objects. c@t|_t|_yr7)r threadpoolr/rr>s r&r?zWSGITestsMixin.setUps/102 r-NrRc dd} t|j|j|} |j|D]&}t }|j | || |} (|}t | |_||d}| D]-\}}|jj| || |/|jd| r6|jj| |jjdddj|Dcgc]}t|| c}z}|O|ddj|Dcgc],\}}djt|| t|| g.c}}zz }|j!| || |d| |z|Scc}wcc}}w) a @param method: A C{str} giving the request method to use. @param version: A C{str} like C{'1.1'} giving the request version. @param resourceSegments: A C{list} of unencoded path segments which specifies the location in the resource hierarchy at which the L{WSGIResource} will be placed, eg C{['']} for I{/}, C{['foo', 'bar', '']} for I{/foo/bar/}, etc. @param requestSegments: A C{list} of unencoded path segments giving the request URI. @param query: A C{list} of two-tuples of C{str} giving unencoded query argument keys and values. @param headers: A C{list} of two-tuples of C{str} giving request header names and corresponding values. @param safe: A C{str} giving the bytes which are to be considered I{safe} for inclusion in the request URI and not quoted. @return: A L{Deferred} which will be called back with a two-tuple of the arguments passed which would be passed to the WSGI application object for this configuration and request (ie, the environment and start_response callable). cHt|tr|S|jdS)Nz iso-8859-1) isinstancebytesencode)strings r& _toByteStringz4WSGITestsMixin.lowLevelRender.._toByteStrings"&%( }}\22r-Fr/?&=sHTTP/)rrrureverserrIrsiterequestHeaders addRawHeader gotLengthcontentwriteseekjoinurlquoterequestReceived)r"requestFactoryapplicationFactorychannelFactorymethodrresourceSegmentsrequestSegmentsqueryheadersbodysafer|rootsegtmpchannelrequestkvrVs r&lowLevelRenderzWSGITestsMixin.lowLevelRendersT 3DLL$//;M;OP  "# C*C LLs+T 2D  !"Dz  %0 TDAq  " " / / a0@-PQBR S T!  OO ! !$ ' OO  #CHH_MchsD1MNN   3PUVfq!8At,hq$.?@AV C  & !=#5x-PWBX7X NWs F' 1F,ctfd}|jd|j}|jt||g|i|S)Ncfd}|S)NcX|\}}j||dgtdSN200 OKr,callbackiter)rWr9r:results r&razFWSGITestsMixin.render..applicationFactory..applications,)-&%h+Bxr-r,rars r&rz1WSGITestsMixin.render..applicationFactorys  r-r)r poprrr)r"r$r%rrrs @r&rjzWSGITestsMixin.rendersL  0$2E2EFG%7R!RrR r-c.tfd}|fS)NcV|i|}|jj|Sr7) notifyFinish chainDeferred)r$r%rd requestClasss r&rz.requestFactory)s0"A,,G  " 0 0 3Nr-r )r"rrrs ` @r&requestFactoryFactoryz$WSGITestsMixin.requestFactoryFactory&s J .  r-c,|jdddS)N rf)split)r"responses r&getContentFromResponsez%WSGITestsMixin.getContentFromResponse4s~~k1-a00r-c<tfd}t|j|j|}t }|j d||j }t||_Gddt}||d}|jd|fS)aj Prepare a L{Request} which, when a request is received, captures the C{environ} and C{start_response} callable passed to a WSGI app. @param application: An optional WSGI application callable that accepts the familiar C{environ} and C{start_response} args and returns an iterable of body content. If not supplied, C{start_response} will be called with a "200 OK" status and no headers, and no content will be yielded. @return: A two-tuple of (C{request}, C{deferred}). The former is a Twisted L{Request}. The latter is a L{Deferred} which will be called back with a two-tuple of the arguments passed to a WSGI application (i.e. the C{environ} and C{start_response} callable), or will errback with any error arising within the WSGI app. c |dgtd}n ||}j||f|S#t$r'j|dgtdcYSwxYw)Nrr,z 500 Error)rrrerrback)r9r:rrars r&outerApplicationz7WSGITestsMixin.prepareRequest..outerApplicationJss &!(B/"2hG)'=AG - 89 !  k2.Bx s 8-A('A(sresceZdZdZddZy)4WSGITestsMixin.prepareRequest..CannedRequestz Convenient L{Request} derivative which has canned values for all of C{requestReceived}'s arguments. c4tj||||S)N)commandpathr)rr)r"rrrs r&rzDWSGITestsMixin.prepareRequest..CannedRequest.requestReceivedgs..'gr-N)GET/res1.1)r(r)r*r+rr,r-r& CannedRequestras    r-rF)queuedr) r rrrurrIrrrrr) r"rarr=rrrrrs ` @r&prepareRequestzWSGITestsMixin.prepareRequest7s"   doo?OPz fh'%%'Dz  G  6!r-r7) r(r)r*r+rrr?rrjrrrrr,r-r&rsrssA "N3  KZ 29 !18r-rsceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!y )! EnvironTestsz Tests for the values in the C{environ} C{dict} passed to the application object by L{twisted.web.wsgi.WSGIResource}. cfd}|S)Nc<|\}}j|Sr7 assertEqual)rr9r:keyr"rns r&assertEnvironKeyEqualz;EnvironTests.environKeyEqual..assertEnvironKeyEqualys&%+ "G]   WS\5 1Lr-r,)r"rrnrs``` r&environKeyEqualzEnvironTests.environKeyEqualxs  %$r-c^jddgdg}fd}|j||S)z L{WSGIResource} calls the application object with an C{environ} parameter which is exactly of type C{dict}. GET1.1rRc|\}}jt|t|D]}j|tyr7)assertIdenticaltypedictrmstr)rr9r:namer"s r& cbRenderedz3EnvironTests.test_environIsDict..cbRendereds@%+ "G]  g 5 1%%dC0 1r-)rj addCallback)r"rrs` r&test_environIsDictzEnvironTests.test_environIsDicts3 KKub2$ / 1 j!r-c|jddgdg}|j|jdd|jddgdg}|j|jddt||gS)z The C{'REQUEST_METHOD'} key of the C{environ} C{dict} passed to the application contains the HTTP method in the request (RFC 3875, section 4.1.12). rrrRREQUEST_METHODPOSTrjrrr )r"getposts r&test_requestMethodzEnvironTests.test_requestMethodsw kk%RD1 ,,-=uEF{{65"rd3 --.>GHc4[))r-cdD]l}|j\}}|j||j|jdd|j |j |t ny)z The C{'REQUEST_METHOD'} key of the C{environ} C{dict} passed to the application is always a native string. )rrrrNrrrrrmsuccessResultOfr)r"rrrs r& test_requestMethodIsNativeStringz-EnvironTests.test_requestMethodIsNativeStringsl $ EF"113OGV  # #F +   t334DeL M  ! !$"6"6v"> D  Er-c|jddgdg}|j|jdd|jdddgdg}|j|jdd|jdddgdg}|j|jdd|jddddgddg}|j|jdd|jdddgdd g}|j|jdd|jddgd gd }|j|jdd t||||||gS) z The C{'SCRIPT_NAME'} key of the C{environ} C{dict} passed to the application contains the I{abs_path} (RFC 2396, section 3) to this resource (RFC 3875, section 4.1.13). rrrR SCRIPT_NAMEr}fooz/fooz/foo/barrr}sbar /foo///barÿr)r"r emptyChildleaf containerinternal unencodeds r&test_scriptNamezEnvironTests.test_scriptNamesV {{5%bT2 --mR@A[[tbT: t33M3GH{{5%%5': --mVDEKKuubkE2;G d22='JK;;ueeWuenET11-HIKK 524L d22=BRSTdJi9UVVr-cD|j\}}|jd|j|jdd|j |j |t |j\}}|jt|jdy)z The C{'SCRIPT_NAME'} key of the C{environ} C{dict} passed to the application is always a native string. rrrz/resN rrrrrmrrrF TypeErrorr"rrs r&test_scriptNameIsNativeStringz*EnvironTests.test_scriptNameIsNativeStrings --/W-4// vFG d226:C@--/ )W%<%<6Jr-c|jdd}|jddgdg}|j|jdd|jdddgdg}|j||jdddgdg}|j||jddddgddg}|j||jdddgddg}|j|jdd|jdddgddg}|j|jdd|jddggd }|j|jdd t||||||gS) z The C{'PATH_INFO'} key of the C{environ} C{dict} passed to the application contains the suffix of the request URI path which is not included in the value for the C{'SCRIPT_NAME'} key (RFC 3875, section 4.1.5). PATH_INFOrRrrr}rrz/barrr)rrjrr ) r"assertKeyEmptyrrrr internalLeafinternalContainerrs r& test_pathInfozEnvironTests.test_pathInfosw--k2>{{5%bT2 --k3?@[[tbT: ~.{{5%%5': (KKuubkE2;G n-{{5%%5%.I   !5!5k6!JK KKuugr{K%%d&:&:;&LMKKub2JK d22;@PQR 4L2CY O  r-cD|j\}}|jd|j|jdd|j |j |t |j\}}|jt|jdy)z The C{'PATH_INFO'} key of the C{environ} C{dict} passed to the application is always a native string. s /res/foo/barrrz/foo/barz /res/foo/barNrrs r&test_pathInfoIsNativeStringz(EnvironTests.test_pathInfoIsNativeStrings --/_54// ZHI d226:C@--/ )W%<%<>Rr-cR|jddgdgd}|j|jdd|jddgdgg}|j|jdd|jddgdgdg}|j|jdd|jddgdgdg}|j|jdd |jddgdgd gd }|j|jdd t|||||gS)z The C{'QUERY_STRING'} key of the C{environ} C{dict} passed to the application contains the portion of the request URI after the first I{?} (RFC 3875, section 4.1.7). rrrRN QUERY_STRINGrrfoo=bar)r}r}z%2F=%2F)rz?barr~)rzfoo=?barr)r"missingemptypresentrdoubleQuestions r&test_queryStringzEnvironTests.test_queryString s/ ++eUBd;D00DE E5"rdB7 $..~rBC++eUB~6FGD00KLKKub2$ E d22>9MN  5"rd_$5C%  ""4#7#7 #STgugy.QRRr-cD|j\}}|jd|j|jdd|j |j |t |j\}}|jt|jdy)z The C{'QUERY_STRING'} key of the C{environ} C{dict} passed to the application is always a native string. s /res?foo=barrrrz /res?foo=barNrrs r&test_queryStringIsNativeStringz+EnvironTests.test_queryStringIsNativeString&s --/_54// JK d226:C@--/ )W%<%<>Rr-c|jddgdg}|j|jdd|jddgdgddg}|j|jddt||gS)z The C{'CONTENT_TYPE'} key of the C{environ} C{dict} passed to the application contains the value of the I{Content-Type} request header (RFC 3875, section 4.1.3). rrrR CONTENT_TYPEN) content-type x-foo/barr rr"rrs r&test_contentTypezEnvironTests.test_contentType5s ++eUB5D00DE++ 5"rdD+H*I  D00MNgw/00r-cdD]}|j\}}|jjd||j|j |j dd|j |j|ty)z The C{'CONTENT_TYPE'} key of the C{environ} C{dict} passed to the application is always a native string. )s x-foo/barr s Content-Typer r N rrrrrrrmrr)r" contentTyperrs r&test_contentTypeIsNativeStringz+EnvironTests.test_contentTypeIsNativeStringEs 5 EK"113OGV  " " / / M  # # %   t33NKP Q  ! !$"6"6v"> D  Er-c|jddgdg}|j|jdd|jddgdgddg}|j|jddt||gS)z The C{'CONTENT_LENGTH'} key of the C{environ} C{dict} passed to the application contains the value of the I{Content-Length} request header (RFC 3875, section 4.1.2). rrrRCONTENT_LENGTHN)content-length1234rrrs r&test_contentLengthzEnvironTests.test_contentLengthQs ++eUB5D001A2FG++ 5"rdD+E*F  D001A6JKgw/00r-cdD]}|j\}}|jjd||j|j |j dd|j |j|ty)z The C{'CONTENT_LENGTH'} key of the C{environ} C{dict} passed to the application is always a native string. )s1234rsContent-LengthrrNr)r" contentLengthrrs r& test_contentLengthIsNativeStringz-EnvironTests.test_contentLengthIsNativeStringas - EM"113OGV  " " / /0A= Q  # # %   t334DfM N  ! !$"6"6v"> D  Er-c|jddgdg}|j|jdd|jddgdgddg}|j|jddt||gS) a_ The C{'SERVER_NAME'} key of the C{environ} C{dict} passed to the application contains the best determination of the server hostname possible, using either the value of the I{Host} header in the request or the address the server is listening on if that header is not present (RFC 3875, section 4.1.14). rrrR SERVER_NAMEz10.0.0.1N)host example.orgrrrs r&test_serverNamezEnvironTests.test_serverNamems++eUB5 D00 KL++eUBd=T.sr-rr"N)rgetRequestHostnamerrrrmrr)r"rrr$s @r&test_serverNameIsNativeStringz*EnvironTests.test_serverNameIsNativeStringsv B EJ"113OGV* D Er-cdfd}||_|jddgdg}|j|jdt |S)z The C{'SERVER_PORT'} key of the C{environ} C{dict} passed to the application contains the port number of the server which received the request (RFC 3875, section 4.1.15). iB0cpt}tj|_|j_|Sr7)rr] transportport)r portNumbers r& makeChannelz1EnvironTests.test_serverPort..makeChannels."nG , 0 0 2G %/G   "Nr-rrrR SERVER_PORT)rrjrrr)r"r,rr+s @r&test_serverPortzEnvironTests.test_serverPortsQ    * KKub2$ / d**=#j/JKr-c|j\}}|j|j|jdd|j |j |t y)z The C{'SERVER_PORT'} key of the C{environ} C{dict} passed to the application is always a native string. r-80Nrrs r&test_serverPortIsNativeStringz*EnvironTests.test_serverPortIsNativeStringsX --/!4// tDE d226:C@r-c|jddgdg}|j|jdd|jddgdg}|j|jddt||gS)z The C{'SERVER_PROTOCOL'} key of the C{environ} C{dict} passed to the application contains the HTTP version number received in the request (RFC 3875, section 4.1.16). rz1.0rRSERVER_PROTOCOLzHTTP/1.0rzHTTP/1.1r)r"oldnews r&test_serverProtocolz EnvironTests.test_serverProtocolss kk%RD1 ,,-> KLkk%RD1 ,,-> KLc3Z((r-cdD]u}|j\}}d|_|jd|j|j dd|j |j |twy)z The C{'SERVER_PROTOCOL'} key of the C{environ} C{dict} passed to the application is always a native string. )rrcyr7r,)datas r&r;z@EnvironTests.test_serverProtocolIsNativeString..r<r-r)rr3rN)rrrrrrmrr)r"serverProtocolrrs r&!test_serverProtocolIsNativeStringz.EnvironTests.test_serverProtocolIsNativeStringsx , EN"113OGV.GM  # #F # 3   t334EuM N  ! !$"6"6v"> D Er-cr|jddgdg}|j|jdd|S)z The C{'REMOTE_ADDR'} key of the C{environ} C{dict} passed to the application contains the address of the client making the request. rrrR REMOTE_ADDRz 192.168.1.1rjrr)r"rs r&test_remoteAddrzEnvironTests.test_remoteAddrs8 KKub2$ / d**=-HIr-c|d}|jddgdg|}|j|jdd|S)z The C{'REMOTE_ADDR'} key of the C{environ} C{dict} passed to the application contains the address of the client making the request when connecting over IPv6. c0ttdddS)Nr]::1i)peer)rrr,r-r&rz8EnvironTests.test_remoteAddrIPv6..channelFactorys[t%DE Er-rrrR)rr=rBr>)r"rrs r&test_remoteAddrIPv6z EnvironTests.test_remoteAddrIPv6sB F KKub2$~K N d**=%@Ar-c jddgdgdddg}fd}|j|jddgdgdddg}|jjd d jddgdgdd g}|jjd d jddgdgddg}|jjd dt||||gS)z HTTP request headers are copied into the C{environ} C{dict} passed to the application with a C{HTTP_} prefix added to their names. rrrRNrbazquuxcd|\}}j|ddj|ddy)NHTTP_FOOrHTTP_BAZrHr)rr9r:r"s r&rz-EnvironTests.test_headers..cbRendereds7%+ "G]   WZ0% 8   WZ0& 9r-)rrGrJzbar,baz)zfoo-barrG HTTP_FOO_BARrG)rzbar bazzbar bazr)r" singleValuer multiValue withHyphen multiLines` r& test_headerszEnvironTests.test_headerss kk 5"rdD>?*K  :  +[[ 5"rdD>>*J  t33J JK[[rB4@R?ST t33NEJKKKub2$?T>UV d22:{KLk:z9MNNr-cr|jddgdg}|j|jdd|S)z The C{'wsgi.version'} key of the C{environ} C{dict} passed to the application has the value C{(1, 0)} indicating that this is a WSGI 1.0 container. rrrRz wsgi.version)rfrr>)r"versionDeferreds r&test_wsgiVersionzEnvironTests.test_wsgiVersions; ++eUB=##D$8$8$PQr-cr|jddgdg}|j|jdd|S)z| The C{'wsgi.run_once'} key of the C{environ} C{dict} passed to the application is set to C{False}. rrrRz wsgi.run_onceFr>)r"onces r&test_wsgiRunOncezEnvironTests.test_wsgiRunOnce s: {{5%bT2 --ouEF r-cr|jddgdg}|j|jdd|S)z~ The C{'wsgi.multithread'} key of the C{environ} C{dict} passed to the application is set to C{True}. rrrRzwsgi.multithreadTr>)r"threads r&test_wsgiMultithreadz!EnvironTests.test_wsgiMultithreads; UE2t44//0BDIJ r-cr|jddgdg}|j|jdd|S)z The C{'wsgi.multiprocess'} key of the C{environ} C{dict} passed to the application is set to C{False}. rrrRzwsgi.multiprocessFr>)r"processs r&test_wsgiMultiprocessz"EnvironTests.test_wsgiMultiprocesss; ++eUB5D001DeLMr-cd}t|_|jddgdg}|j|j dd||_|jddgdg}|j|j ddt ||gS)z The C{'wsgi.url_scheme'} key of the C{environ} C{dict} passed to the application has the request URL scheme. cLt}tj|_|Sr7)rSSLr)rs r&rz7EnvironTests.test_wsgiURLScheme..channelFactory,s"nG , 0 0 2G Nr-rrrRzwsgi.url_schemerhttps)rrrjrrr )r"r httpDeferred httpsDeferreds r&test_wsgiURLSchemezEnvironTests.test_wsgiURLScheme$s  +{{5%bT:   !5!56G!PQ, E5"rd; !!$"6"67H'"RSlM:;;r-ctjtjddgdg}fd}|j ||S)a` The C{'wsgi.errors'} key of the C{environ} C{dict} passed to the application is a file-like object (as defined in the U{Input and Errors Streams} section of PEP 333) which converts bytes written to it into events for the logging system. rrrRc|\}}|d}|jd|jdg|jjdddjdddj dd jd dd jd ddj d d jt d y) N wsgi.errors some message another message rmessage)risystemwsgiisErrorrf)rj)r writelinesflushrrArl)rr9startApplicationerrorseventsr"s r&cbErrorsz.EnvironTests.test_wsgiErrors..cbErrorsGs(. %G%]+F LL) *   34 5 LLN   VAYy13F G   VAYx0& 9 OOF1Ii0 1   VAYy13J K   VAYx0& 9 OOF1Ii0 1   S[! ,r-)r rhrrjr)r"rsrurts` @r&test_wsgiErrorszEnvironTests.test_wsgiErrors;sH&77>PQUE2t4 - 8$ r-c|j\}}|j|j|\}}|d}|jt|j d}|j dt|y)z The C{'wsgi.errors'} file-like object from the C{environ} C{dict} permits writes of only native strings in Python 3, and raises C{TypeError} for writes of non-native strings. rhsfredz1write() argument must be str, not b'fred' (bytes)N)rrrrFrrrr)r"rrr9_rserrors r&0test_wsgiErrorsAcceptsOnlyNativeStringsInPython3z=EnvironTests.test_wsgiErrorsAcceptsOnlyNativeStringsInPython3Xso --/!))&1 '!!)V\\7C  ?U r-N)"r(r)r*r+rrrrrrrrrr rrrrr r&r.r1r6r;r?rDrQrTrWrZr]rervrzr,r-r&rrrs %"* EW< K  D SS8 S1 E1 E1$ E(A ) E O:<.: r-rceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZy)InputStreamTestMixinz A mixin for L{TestCase} subclasses which defines a number of tests against L{_InputStream}. The subclass is expected to create a file-like object to be wrapped by an L{_InputStream} under test. cFt|jjd)Nz.getFile must be implemented)NotImplementedError __class__r(r>s r& getFileTypez InputStreamTestMixin.getFileTypeps%!~~&&''C D  r-c |jGfddt}d}||\}}|j||tddgdgdg| |S)NceZdZfdZy)LInputStreamTestMixin._renderAndReturnReaderResult..CustomizedRequestc|_yr7)r)r"lengthrs r&rzVInputStreamTestMixin._renderAndReturnReaderResult..CustomizedRequest.gotLengthys +} r-N)r(r)r*r)rsr&CustomizedRequestrxs -r-rc.tfd}|fS)Ncfd}|S)Ncj|\}}j|d|dgtdS)Nz wsgi.inputrr,r)rWr9r:readerrs r&raz}InputStreamTestMixin._renderAndReturnReaderResult..appFactoryFactory..applicationFactory..applications6-1*G]OOF7<+@$AB!(B/8Or-r,)rarrs r&rzhInputStreamTestMixin._renderAndReturnReaderResult..appFactoryFactory..applicationFactorys$ #"r-r)rrrs` @r&appFactoryFactoryzLInputStreamTestMixin._renderAndReturnReaderResult..appFactoryFactorysZF #-- -r-PUTrrR)rrrr)r"rrrrr appFactoryrs @r&_renderAndReturnReaderResultz1InputStreamTestMixin._renderAndReturnReaderResultusg&&(  - - .*&1 :        D    r-chd}|jd|}|j|j||S)zi Calling L{_InputStream.read} with no arguments returns the entire input stream. some bytes are herec"|jSr7readinputs r&r;z3InputStreamTestMixin.test_readAll..s EJJLr-rrrr"ryrs r& test_readAllz!InputStreamTestMixin.test_readAlls5 '  - -.H% P d&&.r-chd}|jd|}|j|jd|S)z Calling L{_InputStream.read} with an integer returns that many bytes from the input stream, as long as it is less than or equal to the total number of bytes available. s hello, world.c$|jdSNrrs r&r;z4InputStreamTestMixin.test_readSome..sEJJqMr-shelrrs r& test_readSomez"InputStreamTestMixin.test_readSomes5 !  - -.I5 Q d&&/r-cnd|jfd}|j|j|S)z Calling L{_InputStream.read} with an integer that is greater than the total number of bytes in the input stream returns all bytes in the input stream. rc>|jtdzSr)rrl)rrys r&r;z8InputStreamTestMixin.test_readMoreThan..s%**SZ!^4r-r)r"rrys @r&test_readMoreThanz&InputStreamTestMixin.test_readMoreThans: '  - - 4e  d&&.r-crd}d}|j||}|j|j|dd|S)z Calling L{_InputStream.read} a second time returns bytes starting from the position after the last byte returned by the previous read. ssome bytes, hellocD|jd|jSrrrs r&rz1InputStreamTestMixin.test_readTwice..reads JJqM::< r-rNr)r"ryrrs r&test_readTwicez#InputStreamTestMixin.test_readTwicesA %   - -dE : d&&ab 2r-chd}|jd|}|j|j||S)zy Calling L{_InputStream.read} with L{None} as an argument returns all bytes in the input stream. sthe entire streamc$|jdSr7rrs r&r;z4InputStreamTestMixin.test_readNone..sEJJt.sEJJrNr-rrs r&test_readNegativez&InputStreamTestMixin.test_readNegatives5 $  - -.JE R d&&.r-chd}|jd|}|j|jd|S)zs Calling L{_InputStream.readline} with no argument returns one line from the input stream. s hello worldc"|jSr7readliners r&r;z4InputStreamTestMixin.test_readline..s ENN.sENN1.ENN2.readline s NN >># #r-s second line r)r"ryrrs r&test_readlineTwicez'InputStreamTestMixin.test_readlineTwices< 6 $  - -h > d&&(89r-chd}|jd|}|j|jd|S)z~ Calling L{_InputStream.readline} with L{None} as an argument returns one line from the input stream. s%this is one line this is another linec$|jdSr7rrs r&r;z8InputStreamTestMixin.test_readlineNone..sENN4r-chd}|jd|}|j|jd|S)z Calling L{_InputStream.readline} with a negative integer as an argument returns one line from the input stream. sinput stream line one line twoc$|jdSrrrs r&r;z.$rr-sinput stream line one rrs r&test_readlineNegativez*InputStreamTestMixin.test_readlineNegatives7 3  - -.NPU V d&&(BCr-cld}|jd|}|j|jgd|S)z Calling L{_InputStream.readlines} with no arguments returns a list of all lines from the input stream. salice bob carolc"|jSr7 readlinesrs r&r;z5InputStreamTestMixin.test_readlines...s EOO.9sEOOA.cbLines;s    U2AY8(< =r-)rr)r"ryrrs` r&test_readlinesSomez'InputStreamTestMixin.test_readlinesSome2s6 $  - -.NPU V > gr-cld}|jd|}|j|jgd|S)z Calling L{_InputStream.readlines} with an integer which is greater than the total number of bytes in the input stream returns a list of all lines from the input. s"one potato two potato three potatoc$|jdS)Ndrrs r&r;z=InputStreamTestMixin.test_readlinesMoreThan..JsEOOC.readlinesXs JJqM??$ $r-sorld rEr)r"ryrrs r&test_readlinesAfterReadz,InputStreamTestMixin.test_readlinesAfterReadPs@ % %  - -i ? d&&F(;<r-cld}|jd|}|j|jddg|S)zy Calling L{_InputStream.readlines} with L{None} as an argument returns all lines from the input. sone fish two fish c$|jdSr7rrs r&r;z9InputStreamTestMixin.test_readlinesNone..gs%//$/r-s one fish s two fish rrs r&test_readlinesNonez'InputStreamTestMixin.test_readlinesNone`s> (  - - /  d&& (FGr-cld}|jd|}|j|jddg|S)z Calling L{_InputStream.readlines} with a negative integer as an argument returns a list of all lines from the input. sred fish blue fish c$|jdSrrrs r&r;z=InputStreamTestMixin.test_readlinesNegative..rsEOOB.{s DKr-s green eggs and ham rrs r& test_iterablez"InputStreamTestMixin.test_iterablevs:)  - -.G O d&&,(GHr-cpd}d}|j||}|j|jddg|S)z Iterating over L{_InputStream} after calling L{_InputStream.read} produces lines from the input stream starting from the first byte after the last byte returned by the C{read} call. rc:|jdt|Sr)rrrs r&iteratez.iterates JJqM; r-sen eggs rr)r"ryrrs r&test_iterableAfterReadz+InputStreamTestMixin.test_iterableAfterReads@ )   - -gu = d&&|(DEr-N)r(r)r*r+rrrrrrrrrrrrrrrrrrrrrrr,r-r&r|r|isv  %N     "  r-r|ceZdZdZdZy)InputStreamBytesIOTestszO Tests for L{_InputStream} when it is wrapped around an L{io.BytesIO}. cddlm}|S)Nr)BytesIO)ior)r"rs r&rz#InputStreamBytesIOTests.getFileTypes r-Nr(r)r*r+rr,r-r&rrs r-rceZdZdZdZy)InputStreamTemporaryFileTestszZ Tests for L{_InputStream} when it is wrapped around a L{tempfile.TemporaryFile}. c"tjSr7)tempfile TemporaryFiler>s r&rz)InputStreamTemporaryFileTests.getFileTypes%%%r-Nrr,r-r&rrs &r-rceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZy)StartResponseTestszl Tests for the I{start_response} parameter passed to the application object by L{WSGIResource}. c td}j\}}fd}|j|j||fdddgdgdg |S)z The response status passed to the I{start_response} callable is written as the status of the response to the request. c d}|S)Nc*|dgtdS)Nz107 Strange messager,rr8s r&razOStartResponseTests.test_status..applicationFactory..applications3R8Bxr-r,ras r&rz:StartResponseTests.test_status..applicationFactory  r-cjjjjj dy)NsHTTP/1.1 107 Strange messagerAr)writtengetvalue startswithignoredrr"s r&rz2StartResponseTests.test_status..cbRendereds5 OO!!))224??3 r-cSr7r,rasr&r;z0StartResponseTests.test_status..Gr-rrrRNrrrrr"rrrrrs` @r& test_statuszStartResponseTests.test_statussk . !668>  j!        D   r-cdfd}j|\}}|jfd}j|tj |S)z The response status passed to the I{start_response} callable MUST be a native string in Python 2 and Python 3. s200 OKc,|gtdS)Nr,r)r9r:statuss r&razEStartResponseTests.test_statusMustBeNativeString..applications &" %8Or-c<jdt|y)Nz)status must be str, not b'200 OK' (bytes)rrryr"s r& checkMessagezFStartResponseTests.test_statusMustBeNativeString..checkMessages   H#e* Ur-rr assertFailurerr)r"rarrr rs` @r&test_statusMustBeNativeStringz0StartResponseTests.test_statusMustBeNativeStringsW  --k:! V!!&)4@@NNr-c jtddtfd}j\}}fd}|j |j ||fdddgdgd g |S) a Verify that if the response headers given by C{appHeaders} are passed to the I{start_response} callable, then the response header lines given by C{expectedHeaders} plus I{Server} and I{Date} header lines are included in the response. datetimeToStringcy)NTuesdayr,r,r-r&r;z1StartResponseTests._headersTest..r<r-cfd}|S)Nc,|dtdSrr)r9r: appHeaderss r&razPStartResponseTests._headersTest..applicationFactory..applicationsh 3Bxr-r,)rars r&rz;StartResponseTests._headersTest..applicationFactorys  r-c"jjj}|jdd\}}|jddd}|j ddt zdgz}|j j ||y)Nrrfs s Date: TuesdaysServer: sTransfer-Encoding: chunked)r)rrrsortrr) rrrrest headerLinesallExpectedHeadersrexpectedHeadersr"s r&rz3StartResponseTests._headersTest..cbRendereds((0099;H$NN;:MGT!--04K    !0 g%-4"   # # %   [*< =r-cSr7r,rasr&r;z1StartResponseTests._headersTest.. rr-rrrRN)patchrrrrr)r"rrrrrrrs``` @r& _headersTestzStartResponseTests._headersTests} 4+->?. !668> > j!        D   r-c.|jddgddgS)z The headers passed to the I{start_response} callable are included in the response as are the required I{Date} and I{Server} headers and the necessary connection (hop to hop) header I{Transfer-Encoding}. rrFs Baz: quuxsFoo: barrr>s r&rQzStartResponseTests.test_headerss&   _ - k/J  r-cdgfd}j|\}}|jfd}j|tj |S)zb The headers passed to the I{start_response} callable MUST be a sequence. rrnc>|dttdSrr)r9r:rs r&razBStartResponseTests.test_headersMustBeSequence..application&s (DM 28Or-c<jt|dy)NzKheaders must be a list, not <(list_?|sequence)iterator .+> [(]\1iterator[)] assertRegexrr s r&r zCStartResponseTests.test_headersMustBeSequence..checkMessage-s   E C r-r )r"rarrr rs` @r&test_headersMustBeSequencez-StartResponseTests.test_headersMustBeSequencesY $$ --k:! !!&)4@@NNr-cd}|j|\}}tjd5}|j|j |}ddd|j dt |j t|dj|j dt|djy#1swYpxYw)a According to PEP-3333, the headers passed to the I{start_response} callable MUST be a plain list: The response_headers argument ... must be a Python list; i.e. type(response_headers) is ListType However, for bug-compatibility, any sequence is accepted. In both Python 2 and Python 3, only a warning is issued when a sequence other than a list is encountered. c*|ddtdS)Nr))notrr,rr8s r&razEStartResponseTests.test_headersShouldBePlainList..applicationCs ($6 78Or-TrecordNrfrz8headers should be a list, not (('not', 'list'),) (tuple) rwarningscatch_warningsrrrrlRuntimeWarningcategoryrrkr"rarrcaughts r&test_headersShouldBePlainListz0StartResponseTests.test_headersShouldBePlainList6s --k:  $ $D 1 2V  # # %))&1F 2 CK( ););<  F q !! "  2 2 "B??Ccdfd}j|\}}|jfd}j|tj |S)zb Each header passed to the I{start_response} callable MUST be a sequence. r"c@|dtgtdSrr)r9r:headers r&razFStartResponseTests.test_headersMustEachBeSequence..applicationZs (T&\N 38Or-c<jt|dy)Nz[header must be a [(]str, str[)] tuple, not <(tuple_?|sequence)iterator .+> [(]\1iterator[)]r%r s r&r zGStartResponseTests.test_headersMustEachBeSequence..checkMessageas   E D r-r )r"rarrr r8s` @r&test_headersMustEachBeSequencez1StartResponseTests.test_headersMustEachBeSequenceSsV " --k:! !!&)4@@NNr-cd}|j|\}}tjd5}|j|j |}ddd|j dt |j t|dj|j dt|djy#1swYpxYw)a According to PEP-3333, each header passed to the I{start_response} callable should be a tuple: The response_headers argument is a list of (header_name, header_value) tuples However, for bug-compatibility, any 2 element sequence is also accepted. In both Python 2 and Python 3, only a warning is issued when a sequence other than a tuple is encountered. c0|dddggtdS)Nrr*tupler,rr8s r&razEStartResponseTests.test_headersShouldEachBeTuple..applicationws (eW%5$6 78Or-Tr+Nrfrz@header should be a (str, str) tuple, not ['not', 'tuple'] (list)r-r2s r&test_headersShouldEachBeTuplez0StartResponseTests.test_headersShouldEachBeTuplejs --k:  $ $D 1 2V  # # %))&1F 2 CK( ););<  N q !! "  2 2r5cd}j|\}}|jfd}j|tj |S)z Each header passed to the I{start_response} callable MUST hold a key and a value, and ONLY a key and a value. c,|ddgtdS)Nr)toomanycooksr,rr8s r&razMStartResponseTests.test_headersShouldEachHaveKeyAndValue..applications (%=$> ?8Or-c<jdt|y)Nz?header must be a (str, str) tuple, not ('too', 'many', 'cooks')r r s r&r zNStartResponseTests.test_headersShouldEachHaveKeyAndValue..checkMessages   TE  r-r r"rarrr s` r&%test_headersShouldEachHaveKeyAndValuez8StartResponseTests.test_headersShouldEachHaveKeyAndValuesO  --k:!  !!&)4@@NNr-cdfd}j|\}}|jfd}j|tj |S)z Each header key passed to the I{start_response} callable MUST be at native string in Python 2 and Python 3. skeyc2|ddfgtdS)Nrrnr,r)r9r:rs r&razHStartResponseTests.test_headerKeyMustBeNativeString..applications (c7^$4 58Or-cDjddt|y)Nz&header must be (str, str) tuple, not (z , 'value')r )ryrr"s r&r zIStartResponseTests.test_headerKeyMustBeNativeString..checkMessages$   8zJE  r-r )r"rarrr rs` @r& test_headerKeyMustBeNativeStringz3StartResponseTests.test_headerKeyMustBeNativeStringsV  --k:!  !!&)4@@NNr-cdfd}j|\}}|jfd}j|tj |S)z Each header value passed to the I{start_response} callable MUST be at native string in Python 2 and Python 3. svaluec2|ddfgtdS)Nrrr,r)r9r:rns r&razJStartResponseTests.test_headerValueMustBeNativeString..applications (eU^$4 58Or-cDjddt|y)Nz-header must be (str, str) tuple, not ('key', )r )ryr"rns r&r zKStartResponseTests.test_headerValueMustBeNativeString..checkMessages$   ?yJE  r-r )r"rarrr rns` @r&"test_headerValueMustBeNativeStringz5StartResponseTests.test_headerValueMustBeNativeStringsV  --k:!  !!&)4@@NNr-c*|jdgdgS)z If I{Content-Type} is included in the headers passed to the I{start_response} callable, one I{Content-Type} header is included in the response. )r zmonkeys are greatsContent-Type: monkeys are greatr r>s r&#test_applicationProvidedContentTypez6StartResponseTests.test_applicationProvidedContentTypes#   2 3 / 0  r-c*|jgdgS)z If either I{Server} or I{Date} is included in the headers passed to the I{start_response} callable, they are disregarded. ))serverr)Serverr)dater)dATErr r>s r&%test_applicationProvidedServerAndDatez8StartResponseTests.test_applicationProvidedServerAndDates   TVX  r-c tgfdfd}j\}}fd}|j|j||fdddgdgdg |S) a Nothing is written in response to a request when the I{start_response} callable is invoked. If the iterator returned by the application object produces only empty strings, the response is written after the last element is produced. cljjjjyr7appendr)rrrintermediateValuessr&r,z:StartResponseTests.test_delayedUntilReturn..record&  % %g&7&7&?&?&H&H&J Kr-cfd}|S)Nc3:K|dddgdyw)NrrrFr-r,r9r:r,s r&raz[StartResponseTests.test_delayedUntilReturn..applicationFactory..applications h(IJ sr,rar,s r&rzFStartResponseTests.test_delayedUntilReturn..applicationFactorys   r-c,jdgy)Nr-rrr]r"s r&rz>StartResponseTests.test_delayedUntilReturn..cbRendereds   /# 7r-cSr7r,rasr&r;z.rr-rrrRNrr"rrrrrr]r,s` @@@r&test_delayedUntilReturnz*StartResponseTests.test_delayedUntilReturnsw. L !668> 8 j!        D   r-c tgfdfd}j\}}fd}|j|j||fdddgdgdg |S) a Nothing is written in response to a request when the I{start_response} callable is invoked. Once a non-empty string has been produced by the iterator returned by the application object, the response status and headers are written. cljjjjyr7rZr\sr&r,z;StartResponseTests.test_delayedUntilContent..recordr^r-cfd}|S)Nc3NK|ddgddyw)Nrrr-rEr,ras r&raz\StartResponseTests.test_delayedUntilContent..applicationFactory..applications(h(89  "%r,rbs r&rzGStartResponseTests.test_delayedUntilContent..applicationFactory  r-cVjdjdy)Nrrf) assertFalserArds r&rz?StartResponseTests.test_delayedUntilContent..cbRendered!s)   /2 3 OO.q1 2r-cSr7r,rasr&r;z=StartResponseTests.test_delayedUntilContent..*rr-rrrRNrrfs` @@@r&test_delayedUntilContentz+StartResponseTests.test_delayedUntilContentsw. L !668> 3 j!        D   r-c tgfdfd}j\}}fd}|j|j||fdddgdgdg |S) z Content produced by the iterator returned by the application object is written to the request as it is produced. cljjjjyr7rZr\sr&r,z/StartResponseTests.test_content..record>r^r-cfd}|S)Nc3NK|ddgddyw)Nrr6rEbarr,ras r&razPStartResponseTests.test_content..applicationFactory..applicationBs)h)@(AB  rlr,rbs r&rz;StartResponseTests.test_content..applicationFactoryArmr-cjjddjjddyNrrErfsfoobarrrrds r&rz3StartResponseTests.test_content..cbRenderedMI   T889KA9NOQW X   ++,>q,ABI r-cSr7r,rasr&r;z1StartResponseTests.test_content..Xrr-rrrRNrrfs` @@@r& test_contentzStartResponseTests.test_content5sw . L !668>  j!        D   r-c td}j\}}fd}|j|j||fdddgdgdg |S)z If the I{start_response} callable is invoked multiple times before a data for the response body is produced, the values from the last call are used. c d}|S)Nc<|dg|dgtdS)N100 Fooz200 Barr,rr8s r&raz^StartResponseTests.test_multipleStartResponse..applicationFactory..applicationlsi,i,Bxr-r,rs r&rzIStartResponseTests.test_multipleStartResponse..applicationFactoryk  r-cjjjjj dy)NsHTTP/1.1 200 Bar rrs r&rzAStartResponseTests.test_multipleStartResponse..cbRenderedu3 OO!!))224??@WX r-cSr7r,rasr&r;z?StartResponseTests.test_multipleStartResponse..rr-rrrRNrrs` @r&test_multipleStartResponsez-StartResponseTests.test_multipleStartResponsecsk . !668>  j!        D   r-c td}j\}}fd}|j|j||fdddgdgdg |S)z If the I{start_response} callable is invoked with a third positional argument before the status and headers have been written to the response, the status and headers become the newly supplied values. c d}|S)NcL|dgttddftdS)Nrrr,)rirr8s r&razcStartResponseTests.test_startResponseWithException..applicationFactory..applications#ii59I4-PQBxr-r,rs r&rzNStartResponseTests.test_startResponseWithException..applicationFactoryrr-cjjjjj dy)NsHTTP/1.1 100 Foo rrs r&rzFStartResponseTests.test_startResponseWithException..cbRenderedrr-cSr7r,rasr&r;zDStartResponseTests.test_startResponseWithException..rr-rrrRNrrs` @r&test_startResponseWithExceptionz2StartResponseTests.test_startResponseWithExceptionsk . !668>  j!        D   r-c $tGddt} |#t$r tYnwxYwgfd}j \}}fd}|j |j ||fdddgdgd g |S) z If the I{start_response} callable is invoked with a third positional argument after the status and headers have been written to the response, the supplied I{exc_info} values are re-raised to the application. c eZdZy)PStartResponseTests.test_startResponseWithExceptionTooLate..SomeExceptionN)r(r)r*r,r-r& SomeExceptionrs r-rcfd}|S)Nc3K|dgd |dgy#t$rjtYywxYww)NrrEz500 ERR)rr[r)r9r:excInforeraiseds r&razjStartResponseTests.test_startResponseWithExceptionTooLate..applicationFactory..applicationsCh+ 0!)R9$0OOHJ/0s$A A"AAAAr,)rarrs r&rzUStartResponseTests.test_startResponseWithExceptionTooLate..applicationFactorys 0 r-cjjjjj dj dddj dddddj }d}j tj|dtj|dy)NsHTTP/1.1 200 OK rrfro) rAr)rrrrtb_next traceback extract_tb)rtb1tb2rrrr"s r&rzMStartResponseTests.test_startResponseWithExceptionTooLate..cbRendereds OO!!))224??@VW    Xa[^WQZ 8   Xa[^WQZ 81+a.((C!*C   Y11#6q99;O;OPS;TUV;W Xr-cSr7r,rasr&r;zKStartResponseTests.test_startResponseWithExceptionTooLate..rr-rrrRN)rrirrrrr) r"rrrrrrrrs ` @@@r&&test_startResponseWithExceptionTooLatez9StartResponseTests.test_startResponseWithExceptionTooLates. I  !/ ! !jG ! !668> Y j!        D   s &<<c tgfdfd}j\}}fd}|j|j||fdddgdgdg |S) z I{start_response} returns the I{write} callable which can be used to write bytes to the response body without buffering. cljjjjyr7rZr\sr&r,z-StartResponseTests.test_write..recordr^r-cfd}|S)Ncj|ddg}|d|dtdS)NrrvrErxr,r)r9r:rr,s r&razNStartResponseTests.test_write..applicationFactory..applications4%i2I1JKf f Bxr-r,rbs r&rz9StartResponseTests.test_write..applicationFactorys  r-cjjddjjddyrzr{rds r&rz1StartResponseTests.test_write..cbRenderedr|r-cSr7r,rasr&r;z/StartResponseTests.test_write..rr-rrrRNrrfs` @@@r& test_writezStartResponseTests.test_writesw . L !668>  j!        D   r-cd}j|\}}|jfd}j|tj |S)zj The C{write} callable returned from C{start_response} only accepts byte strings. c:|dg}|dtdS)Nrbogusr,rr9r:rs r&razHStartResponseTests.test_writeAcceptsOnlyByteStrings..application!s!(B/E 'N8Or-c<jdt|y)Nz0Can only write bytes to a transport, not 'bogus'r r s r&r zIStartResponseTests.test_writeAcceptsOnlyByteStrings..checkMessage)s   BCJ r-r rEs` r& test_writeAcceptsOnlyByteStringsz3StartResponseTests.test_writeAcceptsOnlyByteStringssO   --k:!  !!&)4@@NNr-N)r(r)r*r+rrrrQr'r4r:r>rFrJrOrQrWrgrqr~rrrrrr,r-r&rrs %NO&/b O. :O. :O*O,O,   )V,\,\%N$L:x-^Or-rc^eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZy)ApplicationTestszd Tests for things which are done to the application object and the iterator it returns. ct|_t|_|jj|j |jj yr7)rrrustart addCleanupstopr>s r& enableThreadszApplicationTests.enableThreads7s8 $,  ,,-r-c tGdd}|fd}j\}}fd}|j|j||fdddgdg|S) z If the application object returns an iterator which also has a I{close} method, that method is called after iteration is complete. ceZdZdZdZdZy)+ApplicationTests.test_close..Resultcd|_y)NTopenr>s r&rSz4ApplicationTests.test_close..Result.__init__Es   r-c3VKtdD]}|jsd|fzywNrs%d)ranger)r"is r&__iter__z4ApplicationTests.test_close..Result.__iter__Hs,q+Ayy#qdl*+s) )cd|_y)NFrr>s r&closez1ApplicationTests.test_close..Result.closeMs ! r-Nr(r)r*rSrrr,r-r&ResultrDs ! +  "r-rcfd}|S)Nc|ddgS)Nrr3r,)r9r:rs r&razLApplicationTests.test_close..applicationFactory..applicationSsh)@(AB r-r,rs r&rz7ApplicationTests.test_close..applicationFactoryRs  r-cjjjjj dj j y)Ns012)rrr)rrror)rrrr"s r&rz/ApplicationTests.test_close..cbRendered[sK   ++G,=,=,E,E,N,N,PQ    V[[ )r-cSr7r,rasr&r;z-ApplicationTests.test_close..esr-rrrRr)r"rrrrrrrs` @@r& test_closezApplicationTests.test_close=su . " " !668> * j!  .rTVSW r-c jgfd}j\}}fd}|j|j||tddgdg|S)zu The application object is invoked and iterated in a thread which is not the reactor thread. cfd}|S)Ncbfd}jt|ddg|S)Nc3pKtdD]#}jtd|fz%ywr)rr[r)rinvokeds r&rzpApplicationTests.test_applicationCalledInThread..applicationFactory..application..resultts4"1X+{}5#qdl*+s36rr)r[r)r9r:rrs r&raz`ApplicationTests.test_applicationCalledInThread..applicationFactory..applicationss-+ {}-h)@(ABxr-r,)rars r&rzKApplicationTests.test_applicationCalledInThread..applicationFactoryrs  r-cjtjtt dy)Nrf) assertNotInrrrlsetrrr"s r&rzCApplicationTests.test_applicationCalledInThread..cbRendereds.   []G 4   SW. 2r-rrrR)rrrrr)r"rrrrrs` @r&test_applicationCalledInThreadz/ApplicationTests.test_applicationCalledInThreadjsl  !668> 3 j!  . eUBQSPT r-c jgGfddt}d}j|\}}fd}|j|j ||t ddgdg|S)z The I{write} callable returned by I{start_response} calls the request's C{write} method in the reactor thread. ceZdZfdZy)CApplicationTests.test_writeCalledFromThread..ThreadVerifiercbjttj||Sr7r[rrrr"ryrs r&rzIApplicationTests.test_writeCalledFromThread..ThreadVerifier.write"{}-}}T511r-Nr(r)r*rrsr&ThreadVerifierr 2r-rc d}|S)Nc:|dg}|dtdS)NrrEr,rrs r&raz\ApplicationTests.test_writeCalledFromThread..applicationFactory..applications%h3f Bxr-r,rs r&rzGApplicationTests.test_writeCalledFromThread..applicationFactoryrr-cNjtthyr7rrrrs r&rz?ApplicationTests.test_writeCalledFromThread..cbRendered   S\KM? ;r-rrrRrrrrrrr"rrrrrrs` @r&test_writeCalledFromThreadz+ApplicationTests.test_writeCalledFromThreadsz  2W 2  !66~F> < j!  . eUBQSPT r-c jgGfddt}d}j|\}}fd}|j|j ||t ddgdg|S)z Strings produced by the iterator returned by the application object are written to the request in the reactor thread. ceZdZfdZy)MApplicationTests.test_iteratedValuesWrittenFromThread..ThreadVerifiercbjttj||Sr7rrs r&rzSApplicationTests.test_iteratedValuesWrittenFromThread..ThreadVerifier.writerr-Nrrsr&rrrr-rc d}|S)Nc3&K|dgdyw)NrrEr,r8s r&razfApplicationTests.test_iteratedValuesWrittenFromThread..applicationFactory..applicationsh+ sr,rs r&rzQApplicationTests.test_iteratedValuesWrittenFromThread..applicationFactorys  r-cNjtthyr7rrs r&rzIApplicationTests.test_iteratedValuesWrittenFromThread..cbRenderedrr-rrrRrrs` @r&$test_iteratedValuesWrittenFromThreadz5ApplicationTests.test_iteratedValuesWrittenFromThreadsz  2W 2  !66~F> < j!  . eUBQSPT r-c jgGfddt}d}j|\}}fd}|j|j ||t ddgdg|S)zY The response status is set on the request object in the reactor thread. ceZdZfdZy)EApplicationTests.test_statusWrittenFromThread..ThreadVerifiercdjttj|||Sr7)r[rrsetResponseCode)r"coderkrs r&rzUApplicationTests.test_statusWrittenFromThread..ThreadVerifier.setResponseCodes&{}-..tT7CCr-N)r(r)r*rrsr&rrs  Dr-rc d}|S)Nc*|dgtdSrrr8s r&raz^ApplicationTests.test_statusWrittenFromThread..applicationFactory..applicationsh+Bxr-r,rs r&rzIApplicationTests.test_statusWrittenFromThread..applicationFactoryrr-cNjtthyr7rrs r&rzAApplicationTests.test_statusWrittenFromThread..cbRenderedrr-rrrRrrs` @r&test_statusWrittenFromThreadz-ApplicationTests.test_statusWrittenFromThreads|  DW D  !66~F> < j!  . eUBQSPT r-c Gddt}d_fdfd}j|\}}fd}|j|j ||t ddgd gj |tS) z If the request connection is lost while the application object is being iterated, iteration is stopped. ceZdZdZdZy)SApplicationTests.test_connectionClosedDuringIteration..UnreliableConnectionz This is a request which pretends its connection is lost immediately after the first write is done to it. cJ|jttdy)NzNo more connection)connectionLostrr )r"rys r&rzYApplicationTests.test_connectionClosedDuringIteration..UnreliableConnection.writes##GN;O,P$QRr-N)r(r)r*r+rr,r-r&UnreliableConnectionrs    Sr-rFc38Kdd_tdw)NrETzShould not have gotten here)badIterrir>sr&appIterzFApplicationTests.test_connectionClosedDuringIteration..appItersLDL9: :scfd}|S)Nc$|dgSNrr,)r9r:rs r&razfApplicationTests.test_connectionClosedDuringIteration..applicationFactory..applicationsh+y r-r,)rars r&rzQApplicationTests.test_connectionClosedDuringIteration..applicationFactorys ! r-c>jjdy)Nz!Should not have resumed iteration)ror)rr"s r&rzIApplicationTests.test_connectionClosedDuringIteration..cbRendereds   T\\+N Or-rrrR)rrrrrrr r )r"rrrrrrs` @r&$test_connectionClosedDuringIterationz5ApplicationTests.test_connectionClosedDuringIterations  S7 S  ;  !667KL> P j!  . eUBQSPT !!!^44r-c tfd}j\}}fd}|j|j||fdddgdgdg |S)NcSr7r,rsr&rzEApplicationTests._internalServerErrorTest..applicationFactory  r-cjt}jt|dj j j jjdy)Nrfs"HTTP/1.1 500 Internal Server Error) rorGrrlrAr)rrr)rrsrr"s r&rz=ApplicationTests._internalServerErrorTest..cbRendered"sY++L9F   S[! , OO!!))224??9 r-cSr7r,rasr&r;z;ApplicationTests._internalServerErrorTest..1rr-rrrRr)r"rarrrrrs`` @r&_internalServerErrorTestz)ApplicationTests._internalServerErrorTestsi. !668>  j!        D   r-c*d}|j|S)z If the application raises an exception before calling I{start_response} then the response status is I{500} and the exception is logged. ctdN This application had some error.rGr8s r&razRApplicationTests.test_applicationExceptionBeforeStartResponse..applicationBsAB Br-r r"ras r&,test_applicationExceptionBeforeStartResponsez=ApplicationTests.test_applicationExceptionBeforeStartResponse<s  C,,[99r-c*d}|j|S)z If the application calls I{start_response} but then raises an exception before any data is written to the response then the response status is I{500} and the exception is logged. c*|dgtdNrrrr8s r&razQApplicationTests.test_applicationExceptionAfterStartResponse..applicationNs (B 'AB Br-rrs r&+test_applicationExceptionAfterStartResponsez.applicationFactoryYrr-c<j|i|dSr)r[)r$r%rrequestss r&requestFactoryWrapperzEApplicationTests._connectionClosedTest..requestFactoryWrapperas# OONA44 5B< r-cfjdtd}|d}j|jtj tj jj}j|jdj|y)NrfrrgsHTTP/1.1 200 OK) rkrlrmrnrGror)rrrArassertIn)reventr#rrrpresponseContentr"s r& ebRenderedz:ApplicationTests._connectionClosedTest..ebRenderedes   a[!1 2NEm$A  ! !!''< 8  " "< 0((0099;H OOH//0BC D MM/8 4r-cSr7r,rasr&r;z8ApplicationTests._connectionClosedTest..vrr-rrrRrzAll gone) rr rhrr addErrbackrrAr) disconnectedrrr ) r"rarrrrr rrprrs ``` @@@@r&_connectionClosedTestz&ApplicationTests._connectionClosedTestTs.*<  5 Z   !      D    ))667 ""7>*+E#FGr-c6dfd}|j|S)z If the application raises an exception after the response status has already been sent then the connection is closed and the exception is logged. s?Some bytes, triggering the server to start sending the responsec3<K|dgtdwrr)r9r:rs r&razIApplicationTests.test_applicationExceptionAfterWrite..applications# (B '! !AB Bsr$)r"rars @r&#test_applicationExceptionAfterWritez4ApplicationTests.test_applicationExceptionAfterWrites) O  C ))+GGr-cDdGfdd}|j|S)z If the application returns a closeable iterator and the C{close} method raises an exception when called then the connection is still closed and the exception is logged. rEc$eZdZdZfdZdZy)DApplicationTests.test_applicationCloseException..Applicationc|dgyrr,)r"r9r:s r&rSzMApplicationTests.test_applicationCloseException..Application.__init__s h+r-c3Kywr7r,)r"rs r&rzMApplicationTests.test_applicationCloseException..Application.__iter__s %%s ctdr rr>s r&rzJApplicationTests.test_applicationCloseException..Application.closes"#EFFr-Nr)rsr& Applicationr+s , & Gr-r/r')r"r/rs @r&test_applicationCloseExceptionz/ApplicationTests.test_applicationCloseExceptions+ ! G G))+GGr-N)r(r)r*r+rrrrrrrr rrr$r(r0r,r-r&rr1sR . +Z!F DB@(5T D : :0dH"Hr-r)9r+rrr.sysr urllib.parserrzope.interface.verifyrtwisted.internetrtwisted.internet.addressrrtwisted.internet.deferr r twisted.internet.errorr twisted.internet.testingr twisted.loggerr rtwisted.python.failurertwisted.python.threadablertwisted.python.threadpoolrtwisted.trial.unittestr twisted.webrtwisted.web.resourcerrtwisted.web.serverrrrtwisted.web.test.test_webrtwisted.web.wsgirrr/r4rsrr|rrrrr,r-r&rCs*.$=:195*10+4552)4$m/m/`rrjt >8t nd>dN 2H&$8(&J OJ OZxH~xxHr-