88 :copyright: (c) 2013-present by Abhinav Singh and contributors.
99 :license: BSD, see LICENSE for more details.
1010"""
11+ import selectors
12+
1113import unittest
1214from unittest import mock
1315
1416from proxy .common .utils import (
1517 build_websocket_handshake_request , build_websocket_handshake_response ,
1618)
1719from proxy .http .websocket import WebsocketFrame , WebsocketClient
18- from proxy .common .constants import DEFAULT_PORT
20+ from proxy .common .constants import DEFAULT_PORT , DEFAULT_BUFFER_SIZE
1921
2022
2123class TestWebsocketClient (unittest .TestCase ):
2224
23- @mock .patch ('proxy.http.websocket.client.socket.gethostbyname' )
2425 @mock .patch ('base64.b64encode' )
26+ @mock .patch ('proxy.http.websocket.client.socket.gethostbyname' )
2527 @mock .patch ('proxy.http.websocket.client.new_socket_connection' )
26- def test_handshake (
27- self , mock_connect : mock .Mock ,
28- mock_b64encode : mock .Mock ,
29- mock_gethostbyname : mock .Mock ,
28+ def test_handshake_success (
29+ self ,
30+ mock_connect : mock .Mock ,
31+ mock_gethostbyname : mock .Mock ,
32+ mock_b64encode : mock .Mock ,
3033 ) -> None :
3134 key = b'MySecretKey'
3235 mock_b64encode .return_value = key
@@ -35,9 +38,71 @@ def test_handshake(
3538 build_websocket_handshake_response (
3639 WebsocketFrame .key_to_accept (key ),
3740 )
41+ mock_connect .assert_not_called ()
3842 client = WebsocketClient (b'localhost' , DEFAULT_PORT )
43+ mock_connect .assert_called_once ()
3944 mock_connect .return_value .send .assert_not_called ()
4045 client .handshake ()
4146 mock_connect .return_value .send .assert_called_with (
4247 build_websocket_handshake_request (key ),
4348 )
49+ mock_connect .return_value .recv .assert_called_once_with (
50+ DEFAULT_BUFFER_SIZE ,
51+ )
52+
53+ @mock .patch ('base64.b64encode' )
54+ @mock .patch ('selectors.DefaultSelector' )
55+ @mock .patch ('proxy.http.websocket.client.new_socket_connection' )
56+ def test_send_recv_frames_success (
57+ self ,
58+ mock_connect : mock .Mock ,
59+ mock_selector : mock .Mock ,
60+ mock_b64encode : mock .Mock ,
61+ ) -> None :
62+ key = b'MySecretKey'
63+ mock_b64encode .return_value = key
64+ mock_connect .return_value .recv .side_effect = [
65+ build_websocket_handshake_response (
66+ WebsocketFrame .key_to_accept (key ),
67+ ),
68+ WebsocketFrame .text (b'world' ),
69+ ]
70+
71+ def on_message (frame : WebsocketFrame ) -> None :
72+ assert frame .build () == WebsocketFrame .text (b'world' )
73+
74+ client = WebsocketClient (
75+ b'localhost' , DEFAULT_PORT , on_message = on_message ,
76+ )
77+ mock_selector .assert_called_once ()
78+ client .handshake ()
79+ client .queue (memoryview (WebsocketFrame .text (b'hello' )))
80+ mock_connect .return_value .send .assert_called_once ()
81+ mock_selector .return_value .select .side_effect = [
82+ [
83+ (mock .Mock (), selectors .EVENT_WRITE ),
84+ ],
85+ ]
86+ client .run_once ()
87+ self .assertEqual (mock_connect .return_value .send .call_count , 2 )
88+ mock_selector .return_value .select .side_effect = [
89+ [
90+ (mock .Mock (), selectors .EVENT_READ ),
91+ ],
92+ ]
93+ client .run_once ()
94+
95+ @mock .patch ('selectors.DefaultSelector' )
96+ @mock .patch ('proxy.http.websocket.client.new_socket_connection' )
97+ def test_run (
98+ self ,
99+ mock_connect : mock .Mock ,
100+ mock_selector : mock .Mock ,
101+ ) -> None :
102+ mock_selector .return_value .select .side_effect = KeyboardInterrupt
103+ client = WebsocketClient (b'localhost' , DEFAULT_PORT )
104+ client .run ()
105+ mock_connect .return_value .shutdown .assert_called_once ()
106+ mock_connect .return_value .close .assert_called_once ()
107+ mock_selector .return_value .unregister .assert_called_once_with (mock_connect .return_value )
108+ mock_selector .return_value .close .assert_called_once ()
0 commit comments