
    Vh5                    @   d Z ddlmZ ddlmZmZ ddlmZ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 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!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z(m)Z)m*Z* ddl+m,Z,  e	dd      Z-dZ. G d de&      Z/ G d de&      Z0	  e1d       ddl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 e G d de6             Z: G d  d!e8e:         Z; G d" d#e5e:         Z<e G d% d&ee-                Z> ee.d'       G d( d)e             Z?y*# e=$ r d$Z.Y 4w xY w)+z%
Tests for L{twisted.web.websocket}.
    )annotations)	dataclassfield)AnyGenericTypeVar)skipIf)implementer)Deferred)ConnectionDone)IPushProducer)AccumulatingProtocolMemoryReactorClock)Failure)ConnectionCompleterIOPump)SynchronousTestCase)BAD_REQUEST)AgentreadBody)IRequest)Resource)NOT_DONE_YETRequestSite)DataWSPWebSocketProtocol)boundFc                      e Zd ZddZy)WeirdResourcec                &    |j                  d       y)a  
        Per U{the wsproto documentation
        <https://python-hyper.org/projects/wsproto/en/latest/api.html#wsproto.events.RejectConnection.has_body>}:

            - The only scenario in which the caller receives a RejectConnection
              with C{has_body == False} is if the peer violates sends an
              informational status code (1xx) other than 101

        This is a weird edge case so we provoke it.
        f       )setResponseCodeselfrequests     O/home/dcms/DCMS/lib/python3.12/site-packages/twisted/web/test/test_websocket.py
render_GETzWeirdResource.render_GET#   s     	$r$   N)r(   r   returnbytes)__name__
__module____qualname__r*    r$   r)   r!   r!   "   s    r$   r!   c                      e Zd ZdZddZy)DelayedResponsez
    A resource that will not respond to a C{GET} request right away.  You will
    need to use the C{request.write(b'RESPONSE BODY')} and C{request.finish()}
    to trigger a response.
    c                    || _         t        S N)r(   r   r&   s     r)   r*   zDelayedResponse.render_GET9   s    r$   N)r(   r   r+   int)r-   r.   r/   __doc__r*   r0   r$   r)   r2   r2   2   s    r$   r2   wsproto)ConnectionRejectedWebSocketClientEndpointWebSocketClientFactoryr   WebSocketResourceWebSocketServerFactoryWebSocketTransportc                  |    e Zd ZU dZ ee      Zded<   dZded<   ddZ	dd	Z
dd
ZddZddZddZddZddZy)MyWSPz
        Used to implement both client-side and server-side WebSocket
        application that will help with testing.
        default_factoryzlist[bytes]pongsNzFailure | NonewasLostc                    || _         y r4   )	transport)r'   rE   s     r)   negotiationStartedzMyWSP.negotiationStartedW   s	    &DNr$   c                     y r4   r0   r'   s    r)   negotiationFinishedzMyWSP.negotiationFinishedZ   s    r$   c                    || _         y r4   )rC   )r'   reasons     r)   connectionLostzMyWSP.connectionLost]   s	    !DLr$   c                |    |dk(  r| j                   j                  d       y | j                  j                  |       y )N   request    response)rE   sendBytesMessage	bDeferredcallbackr'   datas     r)   bytesMessageReceivedzMyWSP.bytesMessageReceived`   s/    z!//0GH''-r$   c                |    |dk(  r| j                   j                  d       y | j                  j                  |       y )Nr(   response)rE   sendTextMessagedeferredrR   rS   s     r)   textMessageReceivedzMyWSP.textMessageReceivedf   s.    y ..z:&&t,r$   c                :    | j                   j                  |       y r4   )rB   append)r'   payloads     r)   pongReceivedzMyWSP.pongReceivedl   s    JJg&r$   c                n    t               | _        | j                  j                  d       | j                  S )zR
            Send a text message to the server and expect a response.
            r(   )r   rY   rE   rX   rH   s    r)   sendRequestzMyWSP.sendRequesto   s)     ,4:DMNN**95== r$   c                n    t               | _        | j                  j                  d       | j                  S )zS
            Send a bytes message to the server and expect a response.
            rN   )r   rQ   rE   rP   rH   s    r)   bytesRequestzMyWSP.bytesRequestw   s)     /7jDNNN++J7>>!r$   )rE   r=   r+   Noner+   rc   )rK   r   r+   rc   )rT   r,   r+   rc   )rT   strr+   rc   )r]   r,   r+   rc   )r+   zDeferred[str])r+   zDeferred[bytes])r-   r.   r/   r6   r   listrB   __annotations__rC   rF   rI   rL   rU   rZ   r^   r`   rb   r0   r$   r)   r?   r?   M   sJ    	
 #48{8"&&	'		"	.	-	'	!	"r$   r?   c                       e Zd ZU ded<   ddZy)	MyFactoryzWebSocketFixture[Any]fixturec                d    t               }| j                  j                  j                  |       |S r4   )r?   rj   serversr\   )r'   r(   news      r)   buildProtocolzMyFactory.buildProtocol   s&    'CLL  '',Jr$   N)r(   r   r+   r?   )r-   r.   r/   rg   rn   r0   r$   r)   ri   ri      s    &&	r$   ri   c                      e Zd ZddZy)MyClientFactoryc                    t               S r4   )r?   )r'   uris     r)   rn   zMyClientFactory.buildProtocol   s	    7Nr$   N)rr   re   r+   r?   )r-   r.   r/   rn   r0   r$   r)   rp   rp      s    	r$   rp   Tc                      e Zd ZU  e       Zded<    ee      Zded<    ee      Z	ded<   dZ
d	ed
<    ee      Zded<    ee      Zded<   edd       ZdddZdddZy)WebSocketFixtureWebSocketClientFactory[WSP]clientFactoryr@   r   reactorr   resourceP   r5   
portNumberz	list[WSP]rl   r2   slowResourcec                    | |      }t               }||_        |j                  j                  dt	        |             |j                  j                  dt        dd             |j                  j                  dt                      |j                  j                  d|j                         |j                  j                  |j                  t        |j                  |j                               |S )Ns   connects   resources	   some-datazapplication/octet-streams
   processings   slow)rw   )ri   rj   rx   putChildr;   r   r!   r{   rw   	listenTCPrz   r   )clsrv   r'   serverFactorys       r)   rm   zWebSocketFixture.new   s    =!! $z+<]+KLl,FG	
 	}mo>w(9(9:OOT$--F	
 r$   c                   K   t        j                  | j                  |      }|j                  | j                         d {   S 7 wr4   )r9   rm   rw   connectrv   )r'   rr   clients      r)   r   zWebSocketFixture.connect   s7     (,,T\\3?^^D$6$67777s   ?AAAc                f    t        | j                        }|j                  |      }|J d       |S )aP  
        There should be a single websocket connection in progress; complete it.

        @param greet: Should we immediately issue a greeting, i.e. deliver any
            pending buffered TCP data, upon connection?  If C{False}, the
            caller must call C{flush} on the result to deliver any pending
            data.
        greetzConnection not in progress.)r   rw   succeedOnce)r'   r   	completer	succeededs       r)   completezWebSocketFixture.complete   s=     (5	)))6	$C&CC$r$   N)rv   ru   r+   zWebSocketFixture[WSP])zhttp://localhost:80/connect)rr   re   r+   r   )T)r   boolr+   r   )r-   r.   r/   r   rv   rg   r   rw   r   rx   rz   rf   rl   r2   r{   classmethodrm   r   r   r0   r$   r)   rt   rt      ss    16M.8"'8J"KGKx8Hh8Jt4GY4$)/$JL/J 8r$   rt   z'wsproto library required for websocketsc                  T    e Zd ZddZddZddZddZddZddZddZ	ddZ
dd	Zy
)WebSocketTestsc                H   t         j                  t                     }t        j                  |j                               }| j                  |       | j                  t        |j                  j                        d       | j                  t        |j                  j                        d       |j                         }| j                  |      }|j                         }| j                  |       |j                          | j                  | j                  |      d       y)z
        Connecting to a websocket server (installed with L{WebSocketResource})
        from a websocket client (connected with L{WebSocketClientEndpoint})
        results in a websocket connection.
           rW   N)rt   rm   rp   r   fromCoroutiner   assertNoResultassertEquallenrw   
tcpServers
tcpClientsr   successResultOfr`   flush)r'   rj   	connectedpumpwsClient	requesteds         r)   test_websocketzWebSocketTests.test_websocket   s     #&&'89**7??+<=	I&W__778!<W__778!<!''	2((*	I&

--i8*Er$   c                j   t         j                  t                     }t        j                  |j                               }|j                         }| j                  |      }|j                         }| j                  |       |j                          | j                  | j                  |      d       y)z
        Connecting to a websocket server and sending it a bytes message results
        in C{bytesMessageReceived} being called.
        rO   N)rt   rm   rp   r   r   r   r   r   rb   r   r   r   )r'   rj   r   r   r   
bRequesteds         r)   test_bytesMessagez WebSocketTests.test_bytesMessage   s    
 #&&'89**7??+<=	!''	2**,
J'

--j9;RSr$   c                   t         j                  t                     }t        j                  |j                                |j                         }g t        t               G fdd             } |       }|j                  d   j                  j                  |       | j                  g        |j                  j                  j                          | j                  dg       |j                  j                  j!                          | j                  ddg       |j                  j                  j#                          | j                  g d       | j%                  |j                  j                  |       |j                  d   j                  j'                          | j%                  |j                  j                  d       y)zo
        Websocket transports can notify a producer of backpressure events via
        attachProducer.
        c                  2    e Zd Zd fdZd fdZd fdZy)6WebSocketTests.test_backpressure.<locals>.TestProducerc                (    j                  d       y )Npausedr\   r'   eventss    r)   pauseProducingzEWebSocketTests.test_backpressure.<locals>.TestProducer.pauseProducing   s    h'r$   c                (    j                  d       y )Nresumedr   r   s    r)   resumeProducingzFWebSocketTests.test_backpressure.<locals>.TestProducer.resumeProducing       i(r$   c                (    j                  d       y )Nstoppedr   r   s    r)   stopProducingzDWebSocketTests.test_backpressure.<locals>.TestProducer.stopProducing   r   r$   Nrd   )r-   r.   r/   r   r   r   )r   s   r)   TestProducerr      s    ())r$   r   r   r   r   )r   r   r   N)rt   rm   rp   r   r   r   r   r
   r   rl   rE   attachProducerr   serverIOproducerr   r   r   assertIsdetachProducer)r'   rj   r   r   testProducerr   s        @r)   test_backpressurez WebSocketTests.test_backpressure   sW   
 #&&'89w01!	]	#	) 	) 
$	) $~$$33LA$--/(,..0(I!67,,.!ABdmm,,l;$$335dmm,,d3r$   c                   t         j                  t                     }t        j                  |j                               }|j                         }| j                  |      }|j                  j                  d       | j                  |j                  g        |j                          | j                  |j                  dg       y)a6  
        Internally, Twisted's websocket resource responds to all ping requests
        with a pong as required by the spec, so peers can issue a C{ping} and
        receive a C{pong} message with the same payload; our websocket
        transport also implements a C{ping} method to send that message.
        s   123N)rt   rm   rp   r   r   r   r   r   rE   pingr   rB   r   r'   rj   r   r   r   s        r)   test_pingPongzWebSocketTests.test_pingPong   s     #&&'89**7??+<=	!''	2',

&2r$   c                   t         j                  t                     }t        j                  |j                               }|j                         }| j                  |      }| j                  |j                  d   j                  d       | j                  |j                  d       |j                  j                          | j                  |j                  d   j                  d       | j                  |j                  d       |j                          | j                  |j                  d   j                  d       | j                  |j                  d       y)zu
        When the underlying TCP connection is lost,
        L{WebSocketProtocol.connectionLost} is invoked.
        r   N)rt   rm   rp   r   r   r   r   r   r   rl   rC   rE   loseConnectionr   assertIsNotr   s        r)   test_serverConnectionLostz(WebSocketTests.test_serverConnectionLost  s    
 #&&'89**7??+<=	!''	2gooa(00$7h&&-))+gooa(00$7h&&-

+33T:))40r$   c                   t         j                  t                     }t        |j                        }|j                  dd      }| j                  |       |j                          | j                  |      }| j                  |j                  t               t        |      }| j                  | j                  |      d       y)z
        Attempting to issue an C{HTTP GET} against a websocket server
        (installed with L{WebSocketResource}) results in a C{BAD_REQUEST}
        response.
        s   GETs   http://localhost/connects$   websocket protocol negotiation errorN)rt   rm   rp   r   rw   r(   r   r   r   r   coder   r   )r'   rj   agentrW   rbodys         r)   test_badzWebSocketTests.test_bad  s     #&&'89goo&==)DEH%  *-{  &(O	
r$   c                   t         j                  t                     }t        j                  |j                  d            }|j                  d      }| j                  |       |j                          | j                  |t               y)
        Attempting to connect to a regular HTTP resource that does not support
        websockets will result in the Deferred returned from
        L{WebSocketClientEndpoint} failing.
        zhttp://localhost/emptyFr   Nrt   rm   rp   r   r   r   r   r   r   failureResultOfr8   r'   rj   r   r   s       r)   test_connectionRefusedz%WebSocketTests.test_connectionRefused0  sl     #&&'89**7??;S+TU	e,I&

Y(:;r$   c                   t         j                  t                     }t        j                  |j                  d            }|j                  d      }| j                  |       |j                          | j                  |t               y)r   zhttp://localhost/processingFr   Nr   r   s       r)   test_connectionRefusedWeirdz*WebSocketTests.test_connectionRefusedWeird=  sq     #&&'89**OO9:
	 e,I&

Y(:;r$   c                   t         j                  t                     }t        j                  |j                  d            }|j                  d      }| j                  |       |j                  j                  j                  d       |j                          | j                  |t              }|j                  j                  }|j!                  t#               x}       | j%                  |j&                  d       |j                  j                  }|j                  d       |j                          | j%                  |j&                  d       |j                  d       |j                          | j%                  |j&                  d       |j)                          | j+                  |j,                  d       |j                          |j,                  J d	       | j%                  |j,                  j.                  t0               y)
z
        When the client connection is refused by an asynchronous HTTP response,
        the websocket client will not be notified until the response arrives.
        zhttp://localhost/slowTr   r$   s   hellos   worlds
   helloworldNzshould be closed now)rt   rm   rp   r   r   r   r   r   r{   r(   writer   r   r8   valuerW   deliverBodyr   r   rT   finishr   closedReasontyper   )r'   rj   r   r   rejectedresppreqs           r)   test_connectionRefusedSlowz)WebSocketTests.test_connectionRefusedSlowL  sy   
 #&&'89**7??;R+ST	d+I&$$**3/

''	3EF~~&&2445%""**		(

*		(

/

annd+

~~)A+AA),,n=r$   Nrd   )r-   r.   r/   r   r   r   r   r   r   r   r   r   r0   r$   r)   r   r      s2    F$T 4D3 1$
$<<>r$   r   N)@r6   
__future__r   dataclassesr   r   typingr   r   r   unittestr	   zope.interfacer
   twisted.internet.deferr   twisted.internet.errorr   twisted.internet.interfacesr   twisted.internet.testingr   r   twisted.python.failurer   twisted.test.iosimr   r   twisted.trial.unittestr   twisted.web._responsesr   twisted.web.clientr   r   twisted.web.iwebr   twisted.web.resourcer   twisted.web.serverr   r   r   twisted.web.staticr   r   
shouldSkipr!   r2   
__import__twisted.web.websocketr8   r9   r:   r   r;   r<   r=   r?   ri   rp   ImportErrorrt   r   r0   r$   r)   <module>r      s.   # ( ( (  & + 1 5 M * : 6 . . % ) : : #e./
H  	h 	Ky   /"! /" /"b*51 07 
 (ws| ( (V 
=>o>( o> ?o>s  Js   "D DD