
    VhRF                        d Z ddlmZ ddlmZ 	 ddlZeZddlm	Z	 ddl
mZ ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZmZmZm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z'm(Z(  G d de jR                        Z* G d dejV                        Z+ G d de,      Z- G d de      Z. G d d      Z/ G d de      Z0y# e$ r dZY w xY w)z#
Tests for L{twisted.web.distrib}.
    )abspath)parseStringN)skipIf)verifyObject)deferreactor)globalLogPublisher)failurefilepath)pb
SIZE_LIMIT)proto_helpers)TestCase)clientdistribresourceserverstatic)Headers)_render)DummyChannelDummyRequestc                       e Zd Zy)MySiteN)__name__
__module____qualname__     M/home/dcms/DCMS/lib/python3.12/site-packages/twisted/web/test/test_distrib.pyr   r   #   s    r    r   c                       e Zd ZdZdZd Zy)PBServerFactoryz
    A PB server factory which keeps track of the most recent protocol it
    created.

    @ivar proto: L{None} or the L{Broker} instance most recently returned
        from C{buildProtocol}.
    Nc                 d    t         j                  j                  | |      | _        | j                  S N)r   r#   buildProtocolproto)selfaddrs     r!   r&   zPBServerFactory.buildProtocol2   s&    ''55dDA
zzr    )r   r   r   __doc__r'   r&   r   r    r!   r#   r#   '   s     Er    r#   c                       e Zd ZdZy)ArbitraryErrorz%
    An exception for this test.
    N)r   r   r   r*   r   r    r!   r,   r,   7   s    r    r,   c                   j    e Zd ZdZdZdZdZd Zd Zd Z	d Z
d Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zy)DistribTestsNc                 R   t        j                         t        j                         g| j                  ?| j                  j                  )| j                  j                  j	                  fd       nd   j                  d       | j                  | j                  j                  k| j                  j                  j                  j	                  fd       | j                  j                  j                  j                  j                          nd   j                  d       | j                  )j                  | j                  j                                | j                  )j                  | j                  j                                t        j                        S )z
        Clean up all the event sources left behind by either directly by
        test methods or indirectly via some distrib API.
        Nc                  ,     d   j                  d       S Nr   callbackdls   r!   <lambda>z'DistribTests.tearDown.<locals>.<lambda>J   s    RU^^D5I r    r   c                  ,     d   j                  d       S )N   r2   r4   s   r!   r6   z'DistribTests.tearDown.<locals>.<lambda>N   s    APTAU r    r8   )r   Deferredf1r'   notifyOnDisconnectr3   sub	publisherbroker	transportloseConnectionport1appendstopListeningport2gatherResults)r(   r5   s    @r!   tearDownzDistribTests.tearDownC   s   
 nn 0177477==#<GGMM,,-IJqENN4 88DHH$6$6$BHH%%889UVHH%%//>>@qENN4 ::!IIdjj..01::!IIdjj..01""2&&r    c                    t        j                         }|j                  dt        j                  dd             t        j                  |      }t        t        j                  |            | _
        t        j                  d| j                        | _        t        j                  d| j                  j                         j                         | _        t        j                         }|j                  d| j"                         t%        |      }t        j                  d|      | _        t)        j*                  t              }d| j&                  j                         j                    d}|j-                  d	      }|j/                  d
|      }|j1                  t(        j2                         |j1                  | j4                  d       |S )Ns   theres   rootz
text/plainr   	127.0.0.1s   herezhttp://127.0.0.1:z/here/thereascii   GET)r   ResourceputChildr   Datar   Siter#   r   ResourcePublisherr:   r   	listenTCPrA   ResourceSubscriptiongetHostportr<   r   rD   r   AgentencoderequestaddCallbackreadBodyassertEqual)r(   r1site1r2f2agenturlds           r!   testDistribzDistribTests.testDistribX   s@    
Hfkk'<@AB!'";";E"BC&&q$''2
//TZZ=O=O=Q=V=VW 
GTXX&BZ&&q"-
W%!$**"4"4"6";";!<KHjj!MM&#&	foo&	d&&0r    c                 b   t        j                         }|j                  d|       t        j                  |      }t        t        j                  |            x| _        }t        j                  d|d      }| j                  |j                         |j                         }t        j                  |j                  |j                         x| _        }t        j                  |      }t        j                  d|d      }	| j                  |	j                         |	j                         }
|	|
fS )z
        Set up a resource on a distrib site using L{ResourcePublisher}.

        @param child: The resource to publish using distrib.

        @return: A tuple consisting of the host and port on which to contact
            the created site.
        s   childr   rH   )	interface)r   rK   rL   r   rN   r#   r   rO   r:   r   rP   
addCleanuprC   rR   rQ   hostrS   r<   )r(   childdistribRootdistribSitedistribFactorydistribPortr)   mainRootmainSitemainPortmainAddrs              r!   _setupDistribServerz DistribTests._setupDistribServerl   s     '')Xu-kk+.#2%%k2$
 	
. ''>[Q112""$%::499diiPP8;;x($$QKH../##%!!r    c                 "   | j                  |      \  }}t        j                  t              }d|j                   d|j
                   d}|j                  d      } |j                  d|fi |}|j                  t        j                         |S )a  
        Set up a resource on a distrib site using L{ResourcePublisher} and
        then retrieve it from a L{ResourceSubscription} via an HTTP client.

        @param child: The resource to publish using distrib.
        @param **kwargs: Extra keyword arguments to pass to L{Agent.request} when
            requesting the resource.

        @return: A L{Deferred} which fires with the result of the request.
        http://:/childrI   rJ   )
ro   r   rT   r   re   rS   rU   rV   rW   rX   )r(   rf   kwargsrm   rn   r^   r_   r`   s           r!   _requestTestzDistribTests._requestTest   s}     "55e<(W%af=jj!EMM&#00	foo&r    c                    | j                  |      \  }}d|j                   d|j                   d}|j                  d      } t	        j
                  t              j                  d|fi |}d }|j                  |       |S )a;  
        Set up a resource on a distrib site using L{ResourcePublisher} and
        then retrieve it from a L{ResourceSubscription} via an HTTP client.

        @param child: The resource to publish using distrib.
        @param **kwargs: Extra keyword arguments to pass to L{Agent.request} when
            requesting the resource.

        @return: A L{Deferred} which fires with a tuple consisting of a
            L{twisted.test.proto_helpers.AccumulatingProtocol} containing the
            body of the response and an L{IResponse} with the response itself.
        rq   rr   rs   rI   rJ   c                      t        j                          j                         t        j                         x}_        |j                   fd       |S )Nc                     fS r%   r   )_protocolresponses    r!   r6   zGDistribTests._requestAgentTest.<locals>.cbCollectBody.<locals>.<lambda>   s    Xx$8 r    )r   AccumulatingProtocoldeliverBodyr   r9   closedDeferredrW   )r{   r`   rz   s   ` @r!   cbCollectBodyz5DistribTests._requestAgentTest.<locals>.cbCollectBody   sE    $99;H  **/..*::A'MM89Hr    )	ro   re   rS   rU   r   rT   r   rV   rW   )r(   rf   rt   rm   rn   r_   r`   r   s           r!   _requestAgentTestzDistribTests._requestAgentTest   s}     "55e<(af=jj!)FLL!))&#@@	 	
m$r    c                 *    i t        j                         t        j                         dg G fddt        j
                        } fd j                   |       t        ddgi            } fd}|j                  |       |S )	z
        The request headers are available on the request object passed to a
        distributed resource's C{render} method.
        Nc                       e Zd Z fdZy)>DistribTests.test_requestHeaders.<locals>.ReportRequestHeadersc                 t    |d<   j                  t        |j                  j                                      y)Nr   r    )updatedictrequestHeadersgetAllRawHeaders)r(   rV   reqr   s     r!   renderzEDistribTests.test_requestHeaders.<locals>.ReportRequestHeaders.render   s1     A%%d7+A+A+R+R+T&UVr    Nr   r   r   r   )r   r   s   r!   ReportRequestHeadersr      s    r    r   c                      D  cg c]  } | d   	 }} j                  d|       j                  d|       j                  d   |       t        j                         y c c} w )N
log_formatzconnected to publisherz3could not connect to distributed web service: {msg}r   )assertInr	   removeObserver)emsgslogObserverr   r(   s     r!   
check_logsz4DistribTests.test_requestHeaders.<locals>.check_logs   s^    -89AlO9D9MM2D9MMOQUVMM#a&$'--k:	 :s   A#foobar)headersc                 |    j                   j                  j                         j                  d   dg       y )Ns   Foos   bar)r:   r'   r;   rY   )resultr   r   r(   s    r!   cbRequestedz5DistribTests.test_requestHeaders.<locals>.cbRequested   s0    GGMM,,Z8^F3fX>r    )	r   EventLoggingObserverr	   addObserverr   rK   ru   r   rW   )r(   r   rV   r   r   r   r   r   s   `   @@@@r!   test_requestHeadersz DistribTests.test_requestHeaders   s    
 #88:&&{3f	8#4#4 		; ## "GUUG4D,E $ 
	? 	K(r    c                       G d dt         j                        } j                   |             } fd}|j                  |       |S )z
        The response code can be set by the request object passed to a
        distributed resource's C{render} method.
        c                       e Zd Zd Zy)>DistribTests.test_requestResponseCode.<locals>.SetResponseCodec                 &    |j                  d       y)N    setResponseCoder(   rV   s     r!   r   zEDistribTests.test_requestResponseCode.<locals>.SetResponseCode.render   s    '',r    Nr   r   r    r!   SetResponseCoder          r    r   c                     j                  | d   j                  d       j                  | d   j                  d       j                  | d   j                  d       y )Nr   r    r8   r   s   OKrY   datacodephraser   r(   s    r!   r   z:DistribTests.test_requestResponseCode.<locals>.cbRequested   sM    VAY^^S1VAY^^S1VAY--u5r    r   rK   r   rW   r(   r   rV   r   s   `   r!   test_requestResponseCodez%DistribTests.test_requestResponseCode   sD    	h// 	
 (():;	6
 	K(r    c                       G d dt         j                        } j                   |             } fd}|j                  |       |S )z
        The response code and message can be set by the request object passed to
        a distributed resource's C{render} method.
        c                       e Zd Zd Zy)EDistribTests.test_requestResponseCodeMessage.<locals>.SetResponseCodec                 (    |j                  dd       y)Nr      some-messager   r   r   s     r!   r   zLDistribTests.test_requestResponseCodeMessage.<locals>.SetResponseCode.render   s    ''_=r    Nr   r   r    r!   r   r      r   r    r   c                     j                  | d   j                  d       j                  | d   j                  d       j                  | d   j                  d       y )Nr   r    r8   r   r   r   r   s    r!   r   zADistribTests.test_requestResponseCodeMessage.<locals>.cbRequested   sM    VAY^^S1VAY^^S1VAY--?r    r   r   s   `   r!   test_requestResponseCodeMessagez,DistribTests.test_requestResponseCodeMessage   sE    	h// 	
 (():;	@
 	K(r    c                      G d dt         j                        }| j                   |             }|j                  | j                  dt
        z  dz          |S )z
        If a string longer than the Banana size limit is passed to the
        L{distrib.Request} passed to the remote resource, it is broken into
        smaller strings to be transported over the PB connection.
        c                       e Zd Zd Zy)0DistribTests.test_largeWrite.<locals>.LargeWritec                 x    |j                  dt        z  dz          |j                          t        j                  S N   x   y)writer   finishr   NOT_DONE_YETr   s     r!   r   z7DistribTests.test_largeWrite.<locals>.LargeWrite.render  s.    dZ/$67 ***r    Nr   r   r    r!   
LargeWriter   
  s    +r    r   r   r   r   rK   ru   rW   rY   r   )r(   r   rV   s      r!   test_largeWritezDistribTests.test_largeWrite  sM    	+** 	+ ##JL1D,,dZ.?$.FGr    c                      G d dt         j                        }| j                   |             }|j                  | j                  dt
        z  dz          |S )z
        Like L{test_largeWrite}, but for the case where C{render} returns a
        long string rather than explicitly passing it to L{Request.write}.
        c                       e Zd Zd Zy)2DistribTests.test_largeReturn.<locals>.LargeReturnc                     dt         z  dz   S r   r   r   s     r!   r   z9DistribTests.test_largeReturn.<locals>.LargeReturn.render  s    j(4//r    Nr   r   r    r!   LargeReturnr     s    0r    r   r   r   r   )r(   r   rV   s      r!   test_largeReturnzDistribTests.test_largeReturn  sM    	0(++ 	0 ##KM2D,,dZ.?$.FGr    c                 T    t        t        j                               x _        }t	        j
                  d|      x _        }t        j                  d|j                         j                        x _        }t        dg      t        |      } fd}|j                  |       |S )zz
        If there is an error issuing the request to the remote publisher, an
        error response is returned.
        r   rH   r    c                    j                  j                  d       j                  t        j                        }j                  t        |      d       g d}j                  dj                  |      gj                         y )Ni  r8   )
r    s   <html>s:     <head><title>500 - Server Connection Lost</title></head>s     <body>s#       <h1>Server Connection Lost</h1>s       <p>Connection to distributed server lost:<pre>[Failure instance: Traceback from remote host -- twisted.spread.flavors.NoSuchMethod: No such method: remote_requests   ]</pre></p>s	     </body>s   </html>r       
)rY   responseCodeflushLoggedErrorsr   NoSuchMethodlenjoinwritten)ignorederrorsexpectedrV   r(   s      r!   
cbRenderedz4DistribTests.test_connectionLost.<locals>.cbRendered2  sl    W1137 ++BOO<FS[!,H  ejj23W__Er    )r#   r   Rootr:   r   rP   rA   r   rQ   rR   rS   r<   r   r   rW   )r(   serverFactory
serverPortsubscriptionr`   r   rV   s   `     @r!   test_connectionLostz DistribTests.test_connectionLost"  s     #2"'')"<<-")"3"3A}"EE
Z")">">++-22#
 	
< u%L'*	F2 	
j!r    c                 P   t         j                  j                  | t              }t	        j
                  t                     }t        dg      }t        j                  |      }|j                  |       | j                  dt        |             | j                  d|d   d          y)zQ
        When a request fails, the string form of the failure is logged.
        r    r8   zFailure instancer   r   N)r   r   createWithCleanupr	   r
   Failurer,   r   r   IssuefailedassertEqualsr   r   )r(   r   frV   issues        r!   test_logFailedzDistribTests.test_logFailedN  s     $88JJ$
 OON,-u%g&Q!S-.(+a.*FGr    c                 v   t         j                  j                  | t              }t	               }t        j                  |      }t        j                  t                     }|j                  |       | j                  t               | j                  dt        |             | j                  |d   d   |       y)zf
        When L{twisted.web.distrib.Request}'s fail is called, the failure
        is logged.
        r8   r   log_failureN)r   r   r   r	   r,   r
   r   r   Requestr   failr   r   r   assertIs)r(   r   errr   r   s        r!   test_requestFailzDistribTests.test_requestFail]  s    
 $88JJ$
 OOC ooln-~.!S-.k!n]3Q7r    )r   r   r   rA   rD   r<   r:   rF   ra   ro   ru   r   r   r   r   r   r   r   r   r   r   r    r!   r.   r.   =   sZ    EE
C	B'*("6&: D**"*XH8r    r.   c                       e Zd Zd Zd Zd Zy)_PasswordDatabasec                     || _         y r%   )_users)r(   userss     r!   __init__z_PasswordDatabase.__init__o  s	    r    c                 ,    t        | j                        S r%   )iterr   r(   s    r!   getpwallz_PasswordDatabase.getpwallr  s    DKK  r    c                 P    | j                   D ]  }|d   |k(  s|c S  t               r1   )r   KeyError)r(   usernameusers      r!   getpwnamz_PasswordDatabase.getpwnamu  s0    KK 	DAw("	 jr    N)r   r   r   r   r   r   r   r    r!   r   r   n  s    !r    r   c                   p    e Zd ZdZd Zd ZdeddfdZd Zd	 Z	d
 Z
d Zd Zd Z ee d      d        Zy)UserDirectoryTestszj
    Tests for L{UserDirectory}, a resource for listing all user resources
    available on a system.
    c                    ddddd| j                         df| _        dddd	d
| j                         df| _        t        | j                  | j                  g      | _        t        j                  | j                        | _        y )Nalicex{   i  zAlice,,,z/bin/shbob   i7  zBob,,,)mktempr   r  r   databaser   UserDirectory	directoryr   s    r!   setUpzUserDirectoryTests.setUp  si    sCj$++-S
3S(DKKM9M)4::txx*@A ..t}}=r    c                 j    | j                  t        t        j                  | j                               y)zK
        L{UserDirectory} instances provide L{resource.IResource}.
        N)
assertTruer   r   	IResourcer  r   s    r!   test_interfacez!UserDirectoryTests.test_interface  s!     	X%7%7HIr    namereturnNc                    K   t        |g      }| j                  j                  ||      }t        ||      }| d{    | j	                  |j
                  d       y7 !w)zr
        Verify that requesting the C{name} child of C{self.directory} results
        in a 404 response.
        Ni  )r   r  getChildr   rY   r   )r(   r  rV   r   r`   s        r!   _404TestzUserDirectoryTests._404Test  sX     
 v&((w7FG$--s3 	s   :A A"A c                 B   K   | j                  d       d{    y7 w)z
        L{UserDirectory.getChild} returns a resource which renders a 404
        response when passed a string which does not correspond to any known
        user.
        s   carolNr  r   s    r!   test_getInvalidUserz&UserDirectoryTests.test_getInvalidUser        mmH%%%   c                 B   K   | j                  d       d{    y7 w)z
        L{UserDirectory.getChild} returns a resource which renders a 404
        response when passed a string which corresponds to a known user who has
        neither a user directory nor a user distrib socket.
        s   aliceNr  r   s    r!   test_getUserWithoutResourcez.UserDirectoryTests.test_getUserWithoutResource  r  r  c                 f   t        j                  | j                  d         }|j                  d      }|j	                          t        dg      }| j                  j                  d|      }| j                  |t        j                         | j                  |j                  |j                         y)z
        L{UserDirectory.getChild} returns a L{static.File} instance when passed
        the name of a user with a home directory containing a I{public_html}
        directory.
        public_htmlr  s   bobN)r   FilePathr  rf   makedirsr   r  r  assertIsInstancer   FilerY   path)r(   homer  rV   r   s        r!   test_getPublicHTMLChildz*UserDirectoryTests.test_getPublicHTMLChild  s       ".jj/w'((9ffkk2k&6&67r    c                    t        j                  | j                  d         }|j                          |j	                  d      }t        dg      }| j                  j                  d|      }| j                  |t        j                         | j                  |j                  d       | j                  t        |j                        |j                         y)z
        L{UserDirectory.getChild} returns a L{ResourceSubscription} instance
        when passed the name of a user suffixed with C{".twistd"} who has a
        home directory containing a I{.twistd-web-pb} socket.
        r  .twistd-web-pbr  s
   bob.twistdunixN)r   r  r  r  rf   r   r  r  r  r   rQ   rY   re   r   rS   r!  )r(   r"  webrV   r   s        r!   test_getDistribChildz'UserDirectoryTests.test_getDistribChild  s       ".jj)*w'((@fg&B&BCf--sxx8r    c                     t        dg      }d|_        | j                  t        j                  | j
                  j                  |       y)zr
        L{UserDirectory.render} raises L{UnsupportedMethod} in response to a
        non-I{GET} request.
        r   POSTN)r   methodassertRaisesr   UnsupportedMethodr  r   r   s     r!   test_invalidMethodz%UserDirectoryTests.test_invalidMethod  s9    
 t$&22DNN4I4I7Sr    c                     t        j                   j                  d         j                  d      }|j	                          t        j                   j
                  d         }|j	                          |j                  d      j                  d       t        dg      t         j                        } fd}|j                  |       |S )z}
        L{UserDirectory} renders a list of links to available user content
        in response to a I{GET} request.
        r  r  r%  r    r   c                 z   t        dj                  j                              }|j                  d      \  }}j	                  |j
                  j                  d       j	                  |j
                  j                  d      d       j	                  |j
                  j
                  j                  d       j	                  |j
                  j                  d       j	                  |j
                  j                  d      d       j	                  |j
                  j
                  j                  d       y )	Nr    liahrefzalice/zAlice (file)zbob.twistd/zBob (twistd))	r   r   r   getElementsByTagNamerY   
firstChildtagNamegetAttributer   )r   documentr   r  rV   r(   s       r!   r   z2UserDirectoryTests.test_render.<locals>.cbRendered  s    "388GOO#<=H $88>LUCU--55s;U--::6BHMU--88==~NS^^33S9S^^88@-PS^^66;;^Lr    )r   r  r   rf   r  r  
setContentr   r   r  rW   )r(   r  r'  r   r   rV   s   `    @r!   test_renderzUserDirectoryTests.test_render  s    
 ''

27==mL- 			"#..s3t$1
	M 	:&r    zpwd module requiredc                 l    t        j                         }| j                  |j                  t               y)z
        If L{UserDirectory} is instantiated with no arguments, it uses the
        L{pwd} module as its password database.
        N)r   r  assertIdentical_pwdpwd)r(   r  s     r!   test_passwordDatabasez(UserDirectoryTests.test_passwordDatabase  s&     ))+	Y^^S1r    )r   r   r   r*   r	  r  bytesr  r  r  r#  r(  r.  r:  r   r>  r?  r   r    r!   r   r   |  sc    
>J	45 	4T 	4&&89T@ G*+2 ,2r    r   )1r*   os.pathr   xml.dom.minidomr   r>  r=  ImportErrorunittestr   zope.interface.verifyr   twisted.internetr   r   twisted.loggerr	   twisted.pythonr
   r   twisted.spreadr   twisted.spread.bananar   twisted.testr   twisted.trial.unittestr   twisted.webr   r   r   r   r   twisted.web.http_headersr   twisted.web.test._utilr   twisted.web.test.requesthelperr   r   rN   r   r#   	Exceptionr,   r.   r   r   r   r    r!   <module>rR     s     ' C  . + - ,  , & + A A , * E	V[[ 	b((  Y n88 n8b	 z2 z2_  
Cs   C CC