Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / tests / websocket_new_test.py
1 import errno
2 import struct
3
4 from nose.tools import eq_
5
6 import eventlet
7 from eventlet import event
8 from eventlet import websocket
9 from eventlet.green import httplib
10 from eventlet.green import socket
11 from eventlet import websocket
12 from eventlet.support import six
13
14 from tests.wsgi_test import _TestBase
15
16
17 # demo app
18 def handle(ws):
19     if ws.path == '/echo':
20         while True:
21             m = ws.wait()
22             if m is None:
23                 break
24             ws.send(m)
25     elif ws.path == '/range':
26         for i in range(10):
27             ws.send("msg %d" % i)
28             eventlet.sleep(0.01)
29     elif ws.path == '/error':
30         # some random socket error that we shouldn't normally get
31         raise socket.error(errno.ENOTSOCK)
32     else:
33         ws.close()
34
35 wsapp = websocket.WebSocketWSGI(handle)
36
37
38 class TestWebSocket(_TestBase):
39     TEST_TIMEOUT = 5
40
41     def set_site(self):
42         self.site = wsapp
43
44     def test_incomplete_headers_13(self):
45         headers = dict(kv.split(': ') for kv in [
46             "Upgrade: websocket",
47             # NOTE: intentionally no connection header
48             "Host: localhost:%s" % self.port,
49             "Origin: http://localhost:%s" % self.port,
50             "Sec-WebSocket-Version: 13",
51         ])
52         http = httplib.HTTPConnection('localhost', self.port)
53         http.request("GET", "/echo", headers=headers)
54         resp = http.getresponse()
55
56         self.assertEqual(resp.status, 400)
57         self.assertEqual(resp.getheader('connection'), 'close')
58         self.assertEqual(resp.read(), b'')
59
60         # Now, miss off key
61         headers = dict(kv.split(': ') for kv in [
62             "Upgrade: websocket",
63             "Connection: Upgrade",
64             "Host: localhost:%s" % self.port,
65             "Origin: http://localhost:%s" % self.port,
66             "Sec-WebSocket-Version: 13",
67         ])
68         http = httplib.HTTPConnection('localhost', self.port)
69         http.request("GET", "/echo", headers=headers)
70         resp = http.getresponse()
71
72         self.assertEqual(resp.status, 400)
73         self.assertEqual(resp.getheader('connection'), 'close')
74         self.assertEqual(resp.read(), b'')
75
76         # No Upgrade now
77         headers = dict(kv.split(': ') for kv in [
78             "Connection: Upgrade",
79             "Host: localhost:%s" % self.port,
80             "Origin: http://localhost:%s" % self.port,
81             "Sec-WebSocket-Version: 13",
82         ])
83         http = httplib.HTTPConnection('localhost', self.port)
84         http.request("GET", "/echo", headers=headers)
85         resp = http.getresponse()
86
87         self.assertEqual(resp.status, 400)
88         self.assertEqual(resp.getheader('connection'), 'close')
89         self.assertEqual(resp.read(), b'')
90
91     def test_correct_upgrade_request_13(self):
92         for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
93             connect = [
94                 "GET /echo HTTP/1.1",
95                 "Upgrade: websocket",
96                 "Connection: %s" % http_connection,
97                 "Host: localhost:%s" % self.port,
98                 "Origin: http://localhost:%s" % self.port,
99                 "Sec-WebSocket-Version: 13",
100                 "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
101             ]
102             sock = eventlet.connect(('localhost', self.port))
103
104             sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
105             result = sock.recv(1024)
106             # The server responds the correct Websocket handshake
107             print('Connection string: %r' % http_connection)
108             self.assertEqual(result, six.b('\r\n'.join([
109                 'HTTP/1.1 101 Switching Protocols',
110                 'Upgrade: websocket',
111                 'Connection: Upgrade',
112                 'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
113             ])))
114
115     def test_send_recv_13(self):
116         connect = [
117             "GET /echo HTTP/1.1",
118             "Upgrade: websocket",
119             "Connection: Upgrade",
120             "Host: localhost:%s" % self.port,
121             "Origin: http://localhost:%s" % self.port,
122             "Sec-WebSocket-Version: 13",
123             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
124         ]
125         sock = eventlet.connect(
126             ('localhost', self.port))
127
128         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
129         sock.recv(1024)
130         ws = websocket.RFC6455WebSocket(sock, {}, client=True)
131         ws.send(b'hello')
132         eq_(ws.wait(), b'hello')
133         ws.send(b'hello world!\x01')
134         ws.send(u'hello world again!')
135         eq_(ws.wait(), b'hello world!\x01')
136         eq_(ws.wait(), u'hello world again!')
137         ws.close()
138         eventlet.sleep(0.01)
139
140     def test_breaking_the_connection_13(self):
141         error_detected = [False]
142         done_with_request = event.Event()
143         site = self.site
144
145         def error_detector(environ, start_response):
146             try:
147                 try:
148                     return site(environ, start_response)
149                 except:
150                     error_detected[0] = True
151                     raise
152             finally:
153                 done_with_request.send(True)
154         self.site = error_detector
155         self.spawn_server()
156         connect = [
157             "GET /echo HTTP/1.1",
158             "Upgrade: websocket",
159             "Connection: Upgrade",
160             "Host: localhost:%s" % self.port,
161             "Origin: http://localhost:%s" % self.port,
162             "Sec-WebSocket-Version: 13",
163             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
164         ]
165         sock = eventlet.connect(
166             ('localhost', self.port))
167         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
168         sock.recv(1024)  # get the headers
169         sock.close()  # close while the app is running
170         done_with_request.wait()
171         assert not error_detected[0]
172
173     def test_client_closing_connection_13(self):
174         error_detected = [False]
175         done_with_request = event.Event()
176         site = self.site
177
178         def error_detector(environ, start_response):
179             try:
180                 try:
181                     return site(environ, start_response)
182                 except:
183                     error_detected[0] = True
184                     raise
185             finally:
186                 done_with_request.send(True)
187         self.site = error_detector
188         self.spawn_server()
189         connect = [
190             "GET /echo HTTP/1.1",
191             "Upgrade: websocket",
192             "Connection: Upgrade",
193             "Host: localhost:%s" % self.port,
194             "Origin: http://localhost:%s" % self.port,
195             "Sec-WebSocket-Version: 13",
196             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
197         ]
198         sock = eventlet.connect(
199             ('localhost', self.port))
200         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
201         sock.recv(1024)  # get the headers
202         closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
203         sock.sendall(closeframe)  # "Close the connection" packet.
204         done_with_request.wait()
205         assert not error_detected[0]
206
207     def test_client_invalid_packet_13(self):
208         error_detected = [False]
209         done_with_request = event.Event()
210         site = self.site
211
212         def error_detector(environ, start_response):
213             try:
214                 try:
215                     return site(environ, start_response)
216                 except:
217                     error_detected[0] = True
218                     raise
219             finally:
220                 done_with_request.send(True)
221         self.site = error_detector
222         self.spawn_server()
223         connect = [
224             "GET /echo HTTP/1.1",
225             "Upgrade: websocket",
226             "Connection: Upgrade",
227             "Host: localhost:%s" % self.port,
228             "Origin: http://localhost:%s" % self.port,
229             "Sec-WebSocket-Version: 13",
230             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
231         ]
232         sock = eventlet.connect(
233             ('localhost', self.port))
234         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
235         sock.recv(1024)  # get the headers
236         sock.sendall(b'\x07\xff')  # Weird packet.
237         done_with_request.wait()
238         assert not error_detected[0]