1*1130Szelenkov@nginx.comimport time
2*1130Szelenkov@nginx.comimport struct
3*1130Szelenkov@nginx.comimport unittest
4*1130Szelenkov@nginx.comfrom unit.applications.lang.node import TestApplicationNode
5*1130Szelenkov@nginx.comfrom unit.applications.websockets import TestApplicationWebsocket
6*1130Szelenkov@nginx.com
7*1130Szelenkov@nginx.comclass TestNodeWebsockets(TestApplicationNode):
8*1130Szelenkov@nginx.com    prerequisites = ['node']
9*1130Szelenkov@nginx.com
10*1130Szelenkov@nginx.com    ws = TestApplicationWebsocket()
11*1130Szelenkov@nginx.com
12*1130Szelenkov@nginx.com    @classmethod
13*1130Szelenkov@nginx.com    def setUpClass(cls):
14*1130Szelenkov@nginx.com        raise unittest.SkipTest('Websockets is not available')
15*1130Szelenkov@nginx.com
16*1130Szelenkov@nginx.com    def close_connection(self, sock):
17*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
18*1130Szelenkov@nginx.com
19*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
20*1130Szelenkov@nginx.com
21*1130Szelenkov@nginx.com        self.check_close(sock)
22*1130Szelenkov@nginx.com
23*1130Szelenkov@nginx.com    def check_close(self, sock, code = 1000, no_close = False):
24*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
25*1130Szelenkov@nginx.com
26*1130Szelenkov@nginx.com        self.assertEqual(frame['fin'], True, 'close fin')
27*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'close opcode')
28*1130Szelenkov@nginx.com        self.assertEqual(frame['code'], code, 'close code')
29*1130Szelenkov@nginx.com
30*1130Szelenkov@nginx.com        if not no_close:
31*1130Szelenkov@nginx.com            sock.close()
32*1130Szelenkov@nginx.com
33*1130Szelenkov@nginx.com    def check_frame(self, frame, fin, opcode, payload, decode=True):
34*1130Szelenkov@nginx.com        if opcode == self.ws.OP_BINARY or not decode:
35*1130Szelenkov@nginx.com            data = frame['data']
36*1130Szelenkov@nginx.com        else:
37*1130Szelenkov@nginx.com            data = frame['data'].decode('utf-8')
38*1130Szelenkov@nginx.com
39*1130Szelenkov@nginx.com        self.assertEqual(frame['fin'], fin, 'fin')
40*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], opcode, 'opcode')
41*1130Szelenkov@nginx.com        self.assertEqual(data, payload, 'payload')
42*1130Szelenkov@nginx.com
43*1130Szelenkov@nginx.com    def test_node_websockets_handshake(self):
44*1130Szelenkov@nginx.com        self.load('websockets/mirror')
45*1130Szelenkov@nginx.com
46*1130Szelenkov@nginx.com        resp, sock, key = self.ws.upgrade()
47*1130Szelenkov@nginx.com        sock.close()
48*1130Szelenkov@nginx.com
49*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
50*1130Szelenkov@nginx.com        self.assertEqual(
51*1130Szelenkov@nginx.com            resp['headers']['Upgrade'], 'websocket', 'upgrade'
52*1130Szelenkov@nginx.com        )
53*1130Szelenkov@nginx.com        self.assertEqual(
54*1130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
55*1130Szelenkov@nginx.com        )
56*1130Szelenkov@nginx.com        self.assertEqual(
57*1130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
58*1130Szelenkov@nginx.com        )
59*1130Szelenkov@nginx.com
60*1130Szelenkov@nginx.com    def test_node_websockets_mirror(self):
61*1130Szelenkov@nginx.com        self.load('websockets/mirror')
62*1130Szelenkov@nginx.com
63*1130Szelenkov@nginx.com        message = 'blah'
64*1130Szelenkov@nginx.com
65*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
66*1130Szelenkov@nginx.com
67*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
68*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
69*1130Szelenkov@nginx.com
70*1130Szelenkov@nginx.com        self.assertEqual(
71*1130Szelenkov@nginx.com            message, frame['data'].decode('utf-8'), 'mirror'
72*1130Szelenkov@nginx.com        )
73*1130Szelenkov@nginx.com
74*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
75*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
76*1130Szelenkov@nginx.com
77*1130Szelenkov@nginx.com        self.assertEqual(
78*1130Szelenkov@nginx.com            message, frame['data'].decode('utf-8'), 'mirror 2'
79*1130Szelenkov@nginx.com        )
80*1130Szelenkov@nginx.com
81*1130Szelenkov@nginx.com        sock.close()
82*1130Szelenkov@nginx.com
83*1130Szelenkov@nginx.com    def test_node_websockets_no_mask(self):
84*1130Szelenkov@nginx.com        self.load('websockets/mirror')
85*1130Szelenkov@nginx.com
86*1130Szelenkov@nginx.com        message = 'blah'
87*1130Szelenkov@nginx.com
88*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
89*1130Szelenkov@nginx.com
90*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
91*1130Szelenkov@nginx.com
92*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
93*1130Szelenkov@nginx.com
94*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'no mask opcode')
95*1130Szelenkov@nginx.com        self.assertEqual(frame['code'], 1002, 'no mask close code')
96*1130Szelenkov@nginx.com
97*1130Szelenkov@nginx.com        sock.close()
98*1130Szelenkov@nginx.com
99*1130Szelenkov@nginx.com    def test_node_websockets_fragmentation(self):
100*1130Szelenkov@nginx.com        self.load('websockets/mirror')
101*1130Szelenkov@nginx.com
102*1130Szelenkov@nginx.com        message = 'blah'
103*1130Szelenkov@nginx.com
104*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
105*1130Szelenkov@nginx.com
106*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
107*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
108*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
109*1130Szelenkov@nginx.com
110*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
111*1130Szelenkov@nginx.com
112*1130Szelenkov@nginx.com        self.assertEqual(
113*1130Szelenkov@nginx.com            message + ' ' + message,
114*1130Szelenkov@nginx.com            frame['data'].decode('utf-8'),
115*1130Szelenkov@nginx.com            'mirror framing',
116*1130Szelenkov@nginx.com        )
117*1130Szelenkov@nginx.com
118*1130Szelenkov@nginx.com        sock.close()
119*1130Szelenkov@nginx.com
120*1130Szelenkov@nginx.com    def test_node_websockets_frame_fragmentation_invalid(self):
121*1130Szelenkov@nginx.com        self.load('websockets/mirror')
122*1130Szelenkov@nginx.com
123*1130Szelenkov@nginx.com        message = 'blah'
124*1130Szelenkov@nginx.com
125*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
126*1130Szelenkov@nginx.com
127*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
128*1130Szelenkov@nginx.com
129*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
130*1130Szelenkov@nginx.com
131*1130Szelenkov@nginx.com        frame.pop('data')
132*1130Szelenkov@nginx.com        self.assertDictEqual(
133*1130Szelenkov@nginx.com            frame,
134*1130Szelenkov@nginx.com            {
135*1130Szelenkov@nginx.com                'fin': True,
136*1130Szelenkov@nginx.com                'rsv1': False,
137*1130Szelenkov@nginx.com                'rsv2': False,
138*1130Szelenkov@nginx.com                'rsv3': False,
139*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
140*1130Szelenkov@nginx.com                'mask': 0,
141*1130Szelenkov@nginx.com                'code': 1002,
142*1130Szelenkov@nginx.com                'reason': 'Fragmented control frame',
143*1130Szelenkov@nginx.com            },
144*1130Szelenkov@nginx.com            'close frame',
145*1130Szelenkov@nginx.com        )
146*1130Szelenkov@nginx.com
147*1130Szelenkov@nginx.com        sock.close()
148*1130Szelenkov@nginx.com
149*1130Szelenkov@nginx.com    def test_node_websockets_partial_send(self):
150*1130Szelenkov@nginx.com        self.load('websockets/mirror')
151*1130Szelenkov@nginx.com
152*1130Szelenkov@nginx.com        message = 'blah'
153*1130Szelenkov@nginx.com
154*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
155*1130Szelenkov@nginx.com
156*1130Szelenkov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, message)
157*1130Szelenkov@nginx.com        sock.sendall(frame[:1])
158*1130Szelenkov@nginx.com        sock.sendall(frame[1:2])
159*1130Szelenkov@nginx.com        sock.sendall(frame[2:3])
160*1130Szelenkov@nginx.com        sock.sendall(frame[3:])
161*1130Szelenkov@nginx.com
162*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
163*1130Szelenkov@nginx.com
164*1130Szelenkov@nginx.com        self.assertEqual(
165*1130Szelenkov@nginx.com            message,
166*1130Szelenkov@nginx.com            frame['data'].decode('utf-8'),
167*1130Szelenkov@nginx.com            'partial send',
168*1130Szelenkov@nginx.com        )
169*1130Szelenkov@nginx.com
170*1130Szelenkov@nginx.com        sock.close()
171*1130Szelenkov@nginx.com
172*1130Szelenkov@nginx.com    def test_node_websockets_large(self):
173*1130Szelenkov@nginx.com        self.load('websockets/mirror_fragmentation')
174*1130Szelenkov@nginx.com
175*1130Szelenkov@nginx.com        message = '0123456789' * 3000
176*1130Szelenkov@nginx.com
177*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
178*1130Szelenkov@nginx.com
179*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
180*1130Szelenkov@nginx.com
181*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
182*1130Szelenkov@nginx.com        data = frame['data'].decode('utf-8')
183*1130Szelenkov@nginx.com
184*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
185*1130Szelenkov@nginx.com        data += frame['data'].decode('utf-8')
186*1130Szelenkov@nginx.com
187*1130Szelenkov@nginx.com        self.assertEqual(message, data, 'large')
188*1130Szelenkov@nginx.com
189*1130Szelenkov@nginx.com        sock.close()
190*1130Szelenkov@nginx.com
191*1130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode(self):
192*1130Szelenkov@nginx.com        self.load('websockets/mirror')
193*1130Szelenkov@nginx.com
194*1130Szelenkov@nginx.com        message = 'blah'
195*1130Szelenkov@nginx.com
196*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
197*1130Szelenkov@nginx.com
198*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
199*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
200*1130Szelenkov@nginx.com
201*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
202*1130Szelenkov@nginx.com
203*1130Szelenkov@nginx.com        frame.pop('data')
204*1130Szelenkov@nginx.com        frame.pop('reason')
205*1130Szelenkov@nginx.com        self.assertDictEqual(
206*1130Szelenkov@nginx.com            frame,
207*1130Szelenkov@nginx.com            {
208*1130Szelenkov@nginx.com                'fin': True,
209*1130Szelenkov@nginx.com                'rsv1': False,
210*1130Szelenkov@nginx.com                'rsv2': False,
211*1130Szelenkov@nginx.com                'rsv3': False,
212*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
213*1130Szelenkov@nginx.com                'mask': 0,
214*1130Szelenkov@nginx.com                'code': 1002,
215*1130Szelenkov@nginx.com            },
216*1130Szelenkov@nginx.com            'close frame',
217*1130Szelenkov@nginx.com        )
218*1130Szelenkov@nginx.com
219*1130Szelenkov@nginx.com        sock.close()
220*1130Szelenkov@nginx.com
221*1130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode_2(self):
222*1130Szelenkov@nginx.com        self.load('websockets/mirror')
223*1130Szelenkov@nginx.com
224*1130Szelenkov@nginx.com        message = 'blah'
225*1130Szelenkov@nginx.com
226*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
227*1130Szelenkov@nginx.com
228*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
229*1130Szelenkov@nginx.com
230*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
231*1130Szelenkov@nginx.com
232*1130Szelenkov@nginx.com        frame.pop('data')
233*1130Szelenkov@nginx.com        self.assertDictEqual(
234*1130Szelenkov@nginx.com            frame,
235*1130Szelenkov@nginx.com            {
236*1130Szelenkov@nginx.com                'fin': True,
237*1130Szelenkov@nginx.com                'rsv1': False,
238*1130Szelenkov@nginx.com                'rsv2': False,
239*1130Szelenkov@nginx.com                'rsv3': False,
240*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
241*1130Szelenkov@nginx.com                'mask': 0,
242*1130Szelenkov@nginx.com                'code': 1002,
243*1130Szelenkov@nginx.com                'reason': 'Unrecognized opcode 0',
244*1130Szelenkov@nginx.com            },
245*1130Szelenkov@nginx.com            'close frame',
246*1130Szelenkov@nginx.com        )
247*1130Szelenkov@nginx.com
248*1130Szelenkov@nginx.com        sock.close()
249*1130Szelenkov@nginx.com
250*1130Szelenkov@nginx.com    def test_node_websockets_two_clients(self):
251*1130Szelenkov@nginx.com        self.load('websockets/mirror')
252*1130Szelenkov@nginx.com
253*1130Szelenkov@nginx.com        message1 = 'blah1'
254*1130Szelenkov@nginx.com        message2 = 'blah2'
255*1130Szelenkov@nginx.com
256*1130Szelenkov@nginx.com        _, sock1, _ = self.ws.upgrade()
257*1130Szelenkov@nginx.com        _, sock2, _ = self.ws.upgrade()
258*1130Szelenkov@nginx.com
259*1130Szelenkov@nginx.com        self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
260*1130Szelenkov@nginx.com        self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
261*1130Szelenkov@nginx.com
262*1130Szelenkov@nginx.com        frame1 = self.ws.frame_read(sock1)
263*1130Szelenkov@nginx.com        frame2 = self.ws.frame_read(sock2)
264*1130Szelenkov@nginx.com
265*1130Szelenkov@nginx.com        self.assertEqual(
266*1130Szelenkov@nginx.com            message1, frame1['data'].decode('utf-8'), 'client 1'
267*1130Szelenkov@nginx.com        )
268*1130Szelenkov@nginx.com        self.assertEqual(
269*1130Szelenkov@nginx.com            message2, frame2['data'].decode('utf-8'), 'client 2'
270*1130Szelenkov@nginx.com        )
271*1130Szelenkov@nginx.com
272*1130Szelenkov@nginx.com        sock1.close()
273*1130Szelenkov@nginx.com        sock2.close()
274*1130Szelenkov@nginx.com
275*1130Szelenkov@nginx.com    @unittest.skip('not yet')
276*1130Szelenkov@nginx.com    def test_node_websockets_handshake_upgrade_absent(self): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
277*1130Szelenkov@nginx.com        self.load('websockets/mirror')
278*1130Szelenkov@nginx.com
279*1130Szelenkov@nginx.com        key = self.ws.key()
280*1130Szelenkov@nginx.com        resp = self.get(headers={
281*1130Szelenkov@nginx.com            'Host': 'localhost',
282*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
283*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
284*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
285*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
286*1130Szelenkov@nginx.com        }, read_timeout=1)
287*1130Szelenkov@nginx.com
288*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'upgrade absent')
289*1130Szelenkov@nginx.com
290*1130Szelenkov@nginx.com    def test_node_websockets_handshake_case_insensitive(self):
291*1130Szelenkov@nginx.com        self.load('websockets/mirror')
292*1130Szelenkov@nginx.com
293*1130Szelenkov@nginx.com        key = self.ws.key()
294*1130Szelenkov@nginx.com        resp = self.get(headers={
295*1130Szelenkov@nginx.com            'Host': 'localhost',
296*1130Szelenkov@nginx.com            'Upgrade': 'WEBSOCKET',
297*1130Szelenkov@nginx.com            'Connection': 'UPGRADE',
298*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
299*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
300*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
301*1130Szelenkov@nginx.com        }, read_timeout=1)
302*1130Szelenkov@nginx.com
303*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
304*1130Szelenkov@nginx.com
305*1130Szelenkov@nginx.com    @unittest.skip('not yet')
306*1130Szelenkov@nginx.com    def test_node_websockets_handshake_connection_absent(self): # FAIL
307*1130Szelenkov@nginx.com        self.load('websockets/mirror')
308*1130Szelenkov@nginx.com
309*1130Szelenkov@nginx.com        key = self.ws.key()
310*1130Szelenkov@nginx.com        resp = self.get(headers={
311*1130Szelenkov@nginx.com            'Host': 'localhost',
312*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
313*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
314*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
315*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
316*1130Szelenkov@nginx.com        }, read_timeout=1)
317*1130Szelenkov@nginx.com
318*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
319*1130Szelenkov@nginx.com
320*1130Szelenkov@nginx.com    def test_node_websockets_handshake_version_absent(self):
321*1130Szelenkov@nginx.com        self.load('websockets/mirror')
322*1130Szelenkov@nginx.com
323*1130Szelenkov@nginx.com        key = self.ws.key()
324*1130Szelenkov@nginx.com        resp = self.get(headers={
325*1130Szelenkov@nginx.com            'Host': 'localhost',
326*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
327*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
328*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
329*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat'
330*1130Szelenkov@nginx.com        }, read_timeout=1)
331*1130Szelenkov@nginx.com
332*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 426, 'status')
333*1130Szelenkov@nginx.com
334*1130Szelenkov@nginx.com    @unittest.skip('not yet')
335*1130Szelenkov@nginx.com    def test_node_websockets_handshake_key_invalid(self):
336*1130Szelenkov@nginx.com        self.load('websockets/mirror')
337*1130Szelenkov@nginx.com
338*1130Szelenkov@nginx.com        resp = self.get(headers={
339*1130Szelenkov@nginx.com            'Host': 'localhost',
340*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
341*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
342*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': '!',
343*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
344*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
345*1130Szelenkov@nginx.com        }, read_timeout=1)
346*1130Szelenkov@nginx.com
347*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'key length')
348*1130Szelenkov@nginx.com
349*1130Szelenkov@nginx.com        key = self.ws.key()
350*1130Szelenkov@nginx.com        resp = self.get(headers={
351*1130Szelenkov@nginx.com            'Host': 'localhost',
352*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
353*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
354*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': [key, key],
355*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
356*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
357*1130Szelenkov@nginx.com        }, read_timeout=1)
358*1130Szelenkov@nginx.com
359*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'key double') # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
360*1130Szelenkov@nginx.com
361*1130Szelenkov@nginx.com    def test_node_websockets_handshake_method_invalid(self):
362*1130Szelenkov@nginx.com        self.load('websockets/mirror')
363*1130Szelenkov@nginx.com
364*1130Szelenkov@nginx.com        key = self.ws.key()
365*1130Szelenkov@nginx.com        resp = self.post(headers={
366*1130Szelenkov@nginx.com            'Host': 'localhost',
367*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
368*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
369*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
370*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
371*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
372*1130Szelenkov@nginx.com        }, read_timeout=1)
373*1130Szelenkov@nginx.com
374*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
375*1130Szelenkov@nginx.com
376*1130Szelenkov@nginx.com    def test_node_websockets_handshake_http_10(self):
377*1130Szelenkov@nginx.com        self.load('websockets/mirror')
378*1130Szelenkov@nginx.com
379*1130Szelenkov@nginx.com        key = self.ws.key()
380*1130Szelenkov@nginx.com        resp = self.get(headers={
381*1130Szelenkov@nginx.com            'Host': 'localhost',
382*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
383*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
384*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
385*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
386*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
387*1130Szelenkov@nginx.com        }, http_10=True, read_timeout=1)
388*1130Szelenkov@nginx.com
389*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
390*1130Szelenkov@nginx.com
391*1130Szelenkov@nginx.com    def test_node_websockets_handshake_uri_invalid(self):
392*1130Szelenkov@nginx.com        self.load('websockets/mirror')
393*1130Szelenkov@nginx.com
394*1130Szelenkov@nginx.com        key = self.ws.key()
395*1130Szelenkov@nginx.com        resp = self.get(headers={
396*1130Szelenkov@nginx.com            'Host': 'localhost',
397*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
398*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
399*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
400*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
401*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
402*1130Szelenkov@nginx.com        }, url='!', read_timeout=1)
403*1130Szelenkov@nginx.com
404*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
405*1130Szelenkov@nginx.com
406*1130Szelenkov@nginx.com    def test_node_websockets_protocol_absent(self):
407*1130Szelenkov@nginx.com        self.load('websockets/mirror')
408*1130Szelenkov@nginx.com
409*1130Szelenkov@nginx.com        key = self.ws.key()
410*1130Szelenkov@nginx.com        resp = self.get(headers={
411*1130Szelenkov@nginx.com            'Host': 'localhost',
412*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
413*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
414*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
415*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
416*1130Szelenkov@nginx.com        }, read_timeout=1)
417*1130Szelenkov@nginx.com
418*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
419*1130Szelenkov@nginx.com        self.assertEqual(
420*1130Szelenkov@nginx.com            resp['headers']['Upgrade'], 'websocket', 'upgrade'
421*1130Szelenkov@nginx.com        )
422*1130Szelenkov@nginx.com        self.assertEqual(
423*1130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
424*1130Szelenkov@nginx.com        )
425*1130Szelenkov@nginx.com        self.assertEqual(
426*1130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
427*1130Szelenkov@nginx.com        )
428*1130Szelenkov@nginx.com
429*1130Szelenkov@nginx.com    # autobahn-testsuite
430*1130Szelenkov@nginx.com
431*1130Szelenkov@nginx.com    # Some following tests fail because of Unit does not support UTF-8
432*1130Szelenkov@nginx.com    # validation for websocket frames.  It should be implemented
433*1130Szelenkov@nginx.com    # by application, if necessary.
434*1130Szelenkov@nginx.com
435*1130Szelenkov@nginx.com    def test_node_websockets_1_1_1__1_1_8(self):
436*1130Szelenkov@nginx.com        self.load('websockets/mirror')
437*1130Szelenkov@nginx.com
438*1130Szelenkov@nginx.com        opcode = self.ws.OP_TEXT
439*1130Szelenkov@nginx.com
440*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
441*1130Szelenkov@nginx.com
442*1130Szelenkov@nginx.com        def check_length(length, chopsize=None):
443*1130Szelenkov@nginx.com            payload = '*' * length
444*1130Szelenkov@nginx.com
445*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
446*1130Szelenkov@nginx.com
447*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
448*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
449*1130Szelenkov@nginx.com
450*1130Szelenkov@nginx.com        check_length(0)                      # 1_1_1
451*1130Szelenkov@nginx.com        check_length(125)                    # 1_1_2
452*1130Szelenkov@nginx.com        check_length(126)                    # 1_1_3
453*1130Szelenkov@nginx.com        check_length(127)                    # 1_1_4
454*1130Szelenkov@nginx.com        check_length(128)                    # 1_1_5
455*1130Szelenkov@nginx.com        check_length(65535)                  # 1_1_6
456*1130Szelenkov@nginx.com        check_length(65536)                  # 1_1_7
457*1130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_1_8
458*1130Szelenkov@nginx.com
459*1130Szelenkov@nginx.com        self.close_connection(sock)
460*1130Szelenkov@nginx.com
461*1130Szelenkov@nginx.com    def test_node_websockets_1_2_1__1_2_8(self):
462*1130Szelenkov@nginx.com        self.load('websockets/mirror')
463*1130Szelenkov@nginx.com
464*1130Szelenkov@nginx.com        opcode = self.ws.OP_BINARY
465*1130Szelenkov@nginx.com
466*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
467*1130Szelenkov@nginx.com
468*1130Szelenkov@nginx.com        def check_length(length, chopsize=None):
469*1130Szelenkov@nginx.com            payload = b'\xfe' * length
470*1130Szelenkov@nginx.com
471*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
472*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
473*1130Szelenkov@nginx.com
474*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
475*1130Szelenkov@nginx.com
476*1130Szelenkov@nginx.com        check_length(0)                      # 1_2_1
477*1130Szelenkov@nginx.com        check_length(125)                    # 1_2_2
478*1130Szelenkov@nginx.com        check_length(126)                    # 1_2_3
479*1130Szelenkov@nginx.com        check_length(127)                    # 1_2_4
480*1130Szelenkov@nginx.com        check_length(128)                    # 1_2_5
481*1130Szelenkov@nginx.com        check_length(65535)                  # 1_2_6
482*1130Szelenkov@nginx.com        check_length(65536)                  # 1_2_7
483*1130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_2_8
484*1130Szelenkov@nginx.com
485*1130Szelenkov@nginx.com        self.close_connection(sock)
486*1130Szelenkov@nginx.com
487*1130Szelenkov@nginx.com    def test_node_websockets_2_1__2_6(self):
488*1130Szelenkov@nginx.com        self.load('websockets/mirror')
489*1130Szelenkov@nginx.com
490*1130Szelenkov@nginx.com        op_ping = self.ws.OP_PING
491*1130Szelenkov@nginx.com        op_pong = self.ws.OP_PONG
492*1130Szelenkov@nginx.com
493*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
494*1130Szelenkov@nginx.com
495*1130Szelenkov@nginx.com        def check_ping(payload, chopsize=None, decode=True):
496*1130Szelenkov@nginx.com            self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
497*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
498*1130Szelenkov@nginx.com
499*1130Szelenkov@nginx.com            self.check_frame(frame, True, op_pong, payload, decode=decode)
500*1130Szelenkov@nginx.com
501*1130Szelenkov@nginx.com        check_ping('')                                                 # 2_1
502*1130Szelenkov@nginx.com        check_ping('Hello, world!')                                    # 2_2
503*1130Szelenkov@nginx.com        check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False)  # 2_3
504*1130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, decode=False)                        # 2_4
505*1130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, chopsize=1, decode=False)            # 2_6
506*1130Szelenkov@nginx.com
507*1130Szelenkov@nginx.com        self.close_connection(sock)
508*1130Szelenkov@nginx.com
509*1130Szelenkov@nginx.com        # 2_5
510*1130Szelenkov@nginx.com
511*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
512*1130Szelenkov@nginx.com
513*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
514*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
515*1130Szelenkov@nginx.com
516*1130Szelenkov@nginx.com    def test_node_websockets_2_7__2_9(self):
517*1130Szelenkov@nginx.com        self.load('websockets/mirror')
518*1130Szelenkov@nginx.com
519*1130Szelenkov@nginx.com        # 2_7
520*1130Szelenkov@nginx.com
521*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
522*1130Szelenkov@nginx.com
523*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, '')
524*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_7')
525*1130Szelenkov@nginx.com
526*1130Szelenkov@nginx.com        # 2_8
527*1130Szelenkov@nginx.com
528*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
529*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_8')
530*1130Szelenkov@nginx.com
531*1130Szelenkov@nginx.com        # 2_9
532*1130Szelenkov@nginx.com
533*1130Szelenkov@nginx.com        payload = 'ping payload'
534*1130Szelenkov@nginx.com
535*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
536*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, payload)
537*1130Szelenkov@nginx.com
538*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
539*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, payload)
540*1130Szelenkov@nginx.com
541*1130Szelenkov@nginx.com        self.close_connection(sock)
542*1130Szelenkov@nginx.com
543*1130Szelenkov@nginx.com    def test_node_websockets_2_10__2_11(self):
544*1130Szelenkov@nginx.com        self.load('websockets/mirror')
545*1130Szelenkov@nginx.com
546*1130Szelenkov@nginx.com        # 2_10
547*1130Szelenkov@nginx.com
548*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
549*1130Szelenkov@nginx.com
550*1130Szelenkov@nginx.com        for i in range(0, 10):
551*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
552*1130Szelenkov@nginx.com
553*1130Szelenkov@nginx.com        for i in range(0, 10):
554*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
555*1130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
556*1130Szelenkov@nginx.com
557*1130Szelenkov@nginx.com        # 2_11
558*1130Szelenkov@nginx.com
559*1130Szelenkov@nginx.com        for i in range(0, 10):
560*1130Szelenkov@nginx.com            opcode = self.ws.OP_PING
561*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
562*1130Szelenkov@nginx.com
563*1130Szelenkov@nginx.com        for i in range(0, 10):
564*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
565*1130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
566*1130Szelenkov@nginx.com
567*1130Szelenkov@nginx.com        self.close_connection(sock)
568*1130Szelenkov@nginx.com
569*1130Szelenkov@nginx.com    @unittest.skip('not yet')
570*1130Szelenkov@nginx.com    def test_node_websockets_3_1__3_7(self):
571*1130Szelenkov@nginx.com        self.load('websockets/mirror')
572*1130Szelenkov@nginx.com
573*1130Szelenkov@nginx.com        payload = 'Hello, world!'
574*1130Szelenkov@nginx.com
575*1130Szelenkov@nginx.com        # 3_1
576*1130Szelenkov@nginx.com
577*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
578*1130Szelenkov@nginx.com
579*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
580*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
581*1130Szelenkov@nginx.com
582*1130Szelenkov@nginx.com        # 3_2
583*1130Szelenkov@nginx.com
584*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
585*1130Szelenkov@nginx.com
586*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
587*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
588*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
589*1130Szelenkov@nginx.com
590*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
591*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
592*1130Szelenkov@nginx.com
593*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
594*1130Szelenkov@nginx.com
595*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_2')
596*1130Szelenkov@nginx.com        sock.close()
597*1130Szelenkov@nginx.com
598*1130Szelenkov@nginx.com        # 3_3
599*1130Szelenkov@nginx.com
600*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
601*1130Szelenkov@nginx.com
602*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
603*1130Szelenkov@nginx.com
604*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
605*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
606*1130Szelenkov@nginx.com
607*1130Szelenkov@nginx.com        self.ws.frame_write(
608*1130Szelenkov@nginx.com            sock,
609*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
610*1130Szelenkov@nginx.com            payload,
611*1130Szelenkov@nginx.com            rsv1=True,
612*1130Szelenkov@nginx.com            rsv2=True,
613*1130Szelenkov@nginx.com        )
614*1130Szelenkov@nginx.com
615*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
616*1130Szelenkov@nginx.com
617*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_3')
618*1130Szelenkov@nginx.com        sock.close()
619*1130Szelenkov@nginx.com
620*1130Szelenkov@nginx.com        # 3_4
621*1130Szelenkov@nginx.com
622*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
623*1130Szelenkov@nginx.com
624*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
625*1130Szelenkov@nginx.com        self.ws.frame_write(
626*1130Szelenkov@nginx.com            sock,
627*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
628*1130Szelenkov@nginx.com            payload,
629*1130Szelenkov@nginx.com            rsv3=True,
630*1130Szelenkov@nginx.com            chopsize=1
631*1130Szelenkov@nginx.com        )
632*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
633*1130Szelenkov@nginx.com
634*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
635*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
636*1130Szelenkov@nginx.com
637*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
638*1130Szelenkov@nginx.com
639*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_4')
640*1130Szelenkov@nginx.com        sock.close()
641*1130Szelenkov@nginx.com
642*1130Szelenkov@nginx.com        # 3_5
643*1130Szelenkov@nginx.com
644*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
645*1130Szelenkov@nginx.com
646*1130Szelenkov@nginx.com        self.ws.frame_write(
647*1130Szelenkov@nginx.com            sock,
648*1130Szelenkov@nginx.com            self.ws.OP_BINARY,
649*1130Szelenkov@nginx.com            b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
650*1130Szelenkov@nginx.com            rsv1=True,
651*1130Szelenkov@nginx.com            rsv3=True,
652*1130Szelenkov@nginx.com        )
653*1130Szelenkov@nginx.com
654*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
655*1130Szelenkov@nginx.com
656*1130Szelenkov@nginx.com        # 3_6
657*1130Szelenkov@nginx.com
658*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
659*1130Szelenkov@nginx.com
660*1130Szelenkov@nginx.com        self.ws.frame_write(
661*1130Szelenkov@nginx.com            sock,
662*1130Szelenkov@nginx.com            self.ws.OP_PING,
663*1130Szelenkov@nginx.com            payload,
664*1130Szelenkov@nginx.com            rsv2=True,
665*1130Szelenkov@nginx.com            rsv3=True,
666*1130Szelenkov@nginx.com        )
667*1130Szelenkov@nginx.com
668*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
669*1130Szelenkov@nginx.com
670*1130Szelenkov@nginx.com        # 3_7
671*1130Szelenkov@nginx.com
672*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
673*1130Szelenkov@nginx.com
674*1130Szelenkov@nginx.com        self.ws.frame_write(
675*1130Szelenkov@nginx.com            sock,
676*1130Szelenkov@nginx.com            self.ws.OP_CLOSE,
677*1130Szelenkov@nginx.com            payload,
678*1130Szelenkov@nginx.com            rsv1=True,
679*1130Szelenkov@nginx.com            rsv2=True,
680*1130Szelenkov@nginx.com            rsv3=True,
681*1130Szelenkov@nginx.com        )
682*1130Szelenkov@nginx.com
683*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
684*1130Szelenkov@nginx.com
685*1130Szelenkov@nginx.com    def test_node_websockets_4_1_1__4_2_5(self):
686*1130Szelenkov@nginx.com        self.load('websockets/mirror')
687*1130Szelenkov@nginx.com
688*1130Szelenkov@nginx.com        payload = 'Hello, world!'
689*1130Szelenkov@nginx.com
690*1130Szelenkov@nginx.com        # 4_1_1
691*1130Szelenkov@nginx.com
692*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
693*1130Szelenkov@nginx.com
694*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x03, '')
695*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
696*1130Szelenkov@nginx.com
697*1130Szelenkov@nginx.com        # 4_1_2
698*1130Szelenkov@nginx.com
699*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
700*1130Szelenkov@nginx.com
701*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
702*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
703*1130Szelenkov@nginx.com
704*1130Szelenkov@nginx.com        # 4_1_3
705*1130Szelenkov@nginx.com
706*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
707*1130Szelenkov@nginx.com
708*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
709*1130Szelenkov@nginx.com
710*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
711*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
712*1130Szelenkov@nginx.com
713*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x05, '')
714*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
715*1130Szelenkov@nginx.com
716*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
717*1130Szelenkov@nginx.com
718*1130Szelenkov@nginx.com        # 4_1_4
719*1130Szelenkov@nginx.com
720*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
721*1130Szelenkov@nginx.com
722*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
723*1130Szelenkov@nginx.com
724*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
725*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
726*1130Szelenkov@nginx.com
727*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x06, payload)
728*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
729*1130Szelenkov@nginx.com
730*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
731*1130Szelenkov@nginx.com
732*1130Szelenkov@nginx.com        # 4_1_5
733*1130Szelenkov@nginx.com
734*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
735*1130Szelenkov@nginx.com
736*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
737*1130Szelenkov@nginx.com
738*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
739*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
740*1130Szelenkov@nginx.com
741*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x07, payload, chopsize=1)
742*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
743*1130Szelenkov@nginx.com
744*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
745*1130Szelenkov@nginx.com
746*1130Szelenkov@nginx.com        # 4_2_1
747*1130Szelenkov@nginx.com
748*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
749*1130Szelenkov@nginx.com
750*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0B, '')
751*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
752*1130Szelenkov@nginx.com
753*1130Szelenkov@nginx.com        # 4_2_2
754*1130Szelenkov@nginx.com
755*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
756*1130Szelenkov@nginx.com
757*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
758*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
759*1130Szelenkov@nginx.com
760*1130Szelenkov@nginx.com        # 4_2_3
761*1130Szelenkov@nginx.com
762*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
763*1130Szelenkov@nginx.com
764*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
765*1130Szelenkov@nginx.com
766*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
767*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
768*1130Szelenkov@nginx.com
769*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0D, '')
770*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
771*1130Szelenkov@nginx.com
772*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
773*1130Szelenkov@nginx.com
774*1130Szelenkov@nginx.com        # 4_2_4
775*1130Szelenkov@nginx.com
776*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
777*1130Szelenkov@nginx.com
778*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
779*1130Szelenkov@nginx.com
780*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
781*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
782*1130Szelenkov@nginx.com
783*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0E, payload)
784*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
785*1130Szelenkov@nginx.com
786*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
787*1130Szelenkov@nginx.com
788*1130Szelenkov@nginx.com        # 4_2_5
789*1130Szelenkov@nginx.com
790*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
791*1130Szelenkov@nginx.com
792*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
793*1130Szelenkov@nginx.com
794*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
795*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
796*1130Szelenkov@nginx.com
797*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
798*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
799*1130Szelenkov@nginx.com
800*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
801*1130Szelenkov@nginx.com
802*1130Szelenkov@nginx.com    def test_node_websockets_5_1__5_20(self):
803*1130Szelenkov@nginx.com        self.load('websockets/mirror')
804*1130Szelenkov@nginx.com
805*1130Szelenkov@nginx.com        # 5_1
806*1130Szelenkov@nginx.com
807*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
808*1130Szelenkov@nginx.com
809*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
810*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
811*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
812*1130Szelenkov@nginx.com
813*1130Szelenkov@nginx.com        # 5_2
814*1130Szelenkov@nginx.com
815*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
816*1130Szelenkov@nginx.com
817*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False)
818*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
819*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
820*1130Szelenkov@nginx.com
821*1130Szelenkov@nginx.com        # 5_3
822*1130Szelenkov@nginx.com
823*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
824*1130Szelenkov@nginx.com
825*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
826*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
827*1130Szelenkov@nginx.com
828*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
829*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
830*1130Szelenkov@nginx.com
831*1130Szelenkov@nginx.com        # 5_4
832*1130Szelenkov@nginx.com
833*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
834*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_4')
835*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
836*1130Szelenkov@nginx.com
837*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
838*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
839*1130Szelenkov@nginx.com
840*1130Szelenkov@nginx.com        # 5_5
841*1130Szelenkov@nginx.com
842*1130Szelenkov@nginx.com        self.ws.frame_write(
843*1130Szelenkov@nginx.com            sock,
844*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
845*1130Szelenkov@nginx.com            'fragment1',
846*1130Szelenkov@nginx.com            fin=False,
847*1130Szelenkov@nginx.com            chopsize=1,
848*1130Szelenkov@nginx.com        )
849*1130Szelenkov@nginx.com        self.ws.frame_write(
850*1130Szelenkov@nginx.com            sock,
851*1130Szelenkov@nginx.com            self.ws.OP_CONT,
852*1130Szelenkov@nginx.com            'fragment2',
853*1130Szelenkov@nginx.com            fin=True,
854*1130Szelenkov@nginx.com            chopsize=1,
855*1130Szelenkov@nginx.com        )
856*1130Szelenkov@nginx.com
857*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
858*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
859*1130Szelenkov@nginx.com
860*1130Szelenkov@nginx.com        # 5_6
861*1130Szelenkov@nginx.com
862*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
863*1130Szelenkov@nginx.com
864*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
865*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
866*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
867*1130Szelenkov@nginx.com
868*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
869*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
870*1130Szelenkov@nginx.com
871*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
872*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
873*1130Szelenkov@nginx.com
874*1130Szelenkov@nginx.com        # 5_7
875*1130Szelenkov@nginx.com
876*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
877*1130Szelenkov@nginx.com
878*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
879*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_7')
880*1130Szelenkov@nginx.com
881*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
882*1130Szelenkov@nginx.com
883*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
884*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
885*1130Szelenkov@nginx.com
886*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
887*1130Szelenkov@nginx.com
888*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
889*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
890*1130Szelenkov@nginx.com
891*1130Szelenkov@nginx.com        # 5_8
892*1130Szelenkov@nginx.com
893*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
894*1130Szelenkov@nginx.com
895*1130Szelenkov@nginx.com        self.ws.frame_write(
896*1130Szelenkov@nginx.com            sock,
897*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
898*1130Szelenkov@nginx.com            'fragment1',
899*1130Szelenkov@nginx.com            fin=False,
900*1130Szelenkov@nginx.com            chopsize=1,
901*1130Szelenkov@nginx.com        )
902*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
903*1130Szelenkov@nginx.com        self.ws.frame_write(
904*1130Szelenkov@nginx.com            sock,
905*1130Szelenkov@nginx.com            self.ws.OP_CONT,
906*1130Szelenkov@nginx.com            'fragment2',
907*1130Szelenkov@nginx.com            fin=True,
908*1130Szelenkov@nginx.com            chopsize=1,
909*1130Szelenkov@nginx.com        )
910*1130Szelenkov@nginx.com
911*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
912*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
913*1130Szelenkov@nginx.com
914*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
915*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
916*1130Szelenkov@nginx.com
917*1130Szelenkov@nginx.com        # 5_9
918*1130Szelenkov@nginx.com
919*1130Szelenkov@nginx.com        self.ws.frame_write(
920*1130Szelenkov@nginx.com            sock,
921*1130Szelenkov@nginx.com            self.ws.OP_CONT,
922*1130Szelenkov@nginx.com            'non-continuation payload',
923*1130Szelenkov@nginx.com            fin=True,
924*1130Szelenkov@nginx.com        )
925*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
926*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
927*1130Szelenkov@nginx.com
928*1130Szelenkov@nginx.com        # 5_10
929*1130Szelenkov@nginx.com
930*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
931*1130Szelenkov@nginx.com
932*1130Szelenkov@nginx.com        self.ws.frame_write(
933*1130Szelenkov@nginx.com            sock,
934*1130Szelenkov@nginx.com            self.ws.OP_CONT,
935*1130Szelenkov@nginx.com            'non-continuation payload',
936*1130Szelenkov@nginx.com            fin=True,
937*1130Szelenkov@nginx.com        )
938*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
939*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
940*1130Szelenkov@nginx.com
941*1130Szelenkov@nginx.com        # 5_11
942*1130Szelenkov@nginx.com
943*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
944*1130Szelenkov@nginx.com
945*1130Szelenkov@nginx.com        self.ws.frame_write(
946*1130Szelenkov@nginx.com            sock,
947*1130Szelenkov@nginx.com            self.ws.OP_CONT,
948*1130Szelenkov@nginx.com            'non-continuation payload',
949*1130Szelenkov@nginx.com            fin=True,
950*1130Szelenkov@nginx.com            chopsize=1,
951*1130Szelenkov@nginx.com        )
952*1130Szelenkov@nginx.com        self.ws.frame_write(
953*1130Szelenkov@nginx.com            sock,
954*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
955*1130Szelenkov@nginx.com            'Hello, world!',
956*1130Szelenkov@nginx.com            fin=True,
957*1130Szelenkov@nginx.com            chopsize=1,
958*1130Szelenkov@nginx.com        )
959*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
960*1130Szelenkov@nginx.com
961*1130Szelenkov@nginx.com        # 5_12
962*1130Szelenkov@nginx.com
963*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
964*1130Szelenkov@nginx.com
965*1130Szelenkov@nginx.com        self.ws.frame_write(
966*1130Szelenkov@nginx.com            sock,
967*1130Szelenkov@nginx.com            self.ws.OP_CONT,
968*1130Szelenkov@nginx.com            'non-continuation payload',
969*1130Szelenkov@nginx.com            fin=False,
970*1130Szelenkov@nginx.com        )
971*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
972*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
973*1130Szelenkov@nginx.com
974*1130Szelenkov@nginx.com        # 5_13
975*1130Szelenkov@nginx.com
976*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
977*1130Szelenkov@nginx.com
978*1130Szelenkov@nginx.com        self.ws.frame_write(
979*1130Szelenkov@nginx.com            sock,
980*1130Szelenkov@nginx.com            self.ws.OP_CONT,
981*1130Szelenkov@nginx.com            'non-continuation payload',
982*1130Szelenkov@nginx.com            fin=False,
983*1130Szelenkov@nginx.com        )
984*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
985*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
986*1130Szelenkov@nginx.com
987*1130Szelenkov@nginx.com        # 5_14
988*1130Szelenkov@nginx.com
989*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
990*1130Szelenkov@nginx.com
991*1130Szelenkov@nginx.com        self.ws.frame_write(
992*1130Szelenkov@nginx.com            sock,
993*1130Szelenkov@nginx.com            self.ws.OP_CONT,
994*1130Szelenkov@nginx.com            'non-continuation payload',
995*1130Szelenkov@nginx.com            fin=False,
996*1130Szelenkov@nginx.com            chopsize=1,
997*1130Szelenkov@nginx.com        )
998*1130Szelenkov@nginx.com        self.ws.frame_write(
999*1130Szelenkov@nginx.com            sock,
1000*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
1001*1130Szelenkov@nginx.com            'Hello, world!',
1002*1130Szelenkov@nginx.com            fin=True,
1003*1130Szelenkov@nginx.com            chopsize=1,
1004*1130Szelenkov@nginx.com        )
1005*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1006*1130Szelenkov@nginx.com
1007*1130Szelenkov@nginx.com        # 5_15
1008*1130Szelenkov@nginx.com
1009*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1010*1130Szelenkov@nginx.com
1011*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1012*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
1013*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
1014*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
1015*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1016*1130Szelenkov@nginx.com
1017*1130Szelenkov@nginx.com        # 5_16
1018*1130Szelenkov@nginx.com
1019*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1020*1130Szelenkov@nginx.com
1021*1130Szelenkov@nginx.com        for i in range(0, 2):
1022*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
1023*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
1024*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
1025*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1026*1130Szelenkov@nginx.com
1027*1130Szelenkov@nginx.com        # 5_17
1028*1130Szelenkov@nginx.com
1029*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1030*1130Szelenkov@nginx.com
1031*1130Szelenkov@nginx.com        for i in range(0, 2):
1032*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
1033*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
1034*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
1035*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1036*1130Szelenkov@nginx.com
1037*1130Szelenkov@nginx.com        # 5_18
1038*1130Szelenkov@nginx.com
1039*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1040*1130Szelenkov@nginx.com
1041*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1042*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
1043*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1044*1130Szelenkov@nginx.com
1045*1130Szelenkov@nginx.com        # 5_19
1046*1130Szelenkov@nginx.com
1047*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1048*1130Szelenkov@nginx.com
1049*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1050*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
1051*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
1052*1130Szelenkov@nginx.com
1053*1130Szelenkov@nginx.com        time.sleep(1)
1054*1130Szelenkov@nginx.com
1055*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
1056*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
1057*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
1058*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
1059*1130Szelenkov@nginx.com
1060*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1061*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
1062*1130Szelenkov@nginx.com
1063*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1064*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
1065*1130Szelenkov@nginx.com
1066*1130Szelenkov@nginx.com        self.check_frame(
1067*1130Szelenkov@nginx.com            self.ws.frame_read(sock),
1068*1130Szelenkov@nginx.com            True,
1069*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
1070*1130Szelenkov@nginx.com            'fragment1fragment2fragment3fragment4fragment5',
1071*1130Szelenkov@nginx.com        )
1072*1130Szelenkov@nginx.com
1073*1130Szelenkov@nginx.com        # 5_20
1074*1130Szelenkov@nginx.com
1075*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1076*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
1077*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
1078*1130Szelenkov@nginx.com
1079*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1080*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
1081*1130Szelenkov@nginx.com
1082*1130Szelenkov@nginx.com        time.sleep(1)
1083*1130Szelenkov@nginx.com
1084*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
1085*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
1086*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
1087*1130Szelenkov@nginx.com
1088*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1089*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
1090*1130Szelenkov@nginx.com
1091*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_20')
1092*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
1093*1130Szelenkov@nginx.com
1094*1130Szelenkov@nginx.com        self.check_frame(
1095*1130Szelenkov@nginx.com            self.ws.frame_read(sock),
1096*1130Szelenkov@nginx.com            True,
1097*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
1098*1130Szelenkov@nginx.com            'fragment1fragment2fragment3fragment4fragment5',
1099*1130Szelenkov@nginx.com        )
1100*1130Szelenkov@nginx.com
1101*1130Szelenkov@nginx.com        self.close_connection(sock)
1102*1130Szelenkov@nginx.com
1103*1130Szelenkov@nginx.com    def test_node_websockets_6_1_1__6_4_4(self):
1104*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1105*1130Szelenkov@nginx.com
1106*1130Szelenkov@nginx.com        # 6_1_1
1107*1130Szelenkov@nginx.com
1108*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1109*1130Szelenkov@nginx.com
1110*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '')
1111*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1112*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, '')
1113*1130Szelenkov@nginx.com
1114*1130Szelenkov@nginx.com        # 6_1_2
1115*1130Szelenkov@nginx.com
1116*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1117*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False)
1118*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '')
1119*1130Szelenkov@nginx.com
1120*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1121*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, '')
1122*1130Szelenkov@nginx.com
1123*1130Szelenkov@nginx.com        # 6_1_3
1124*1130Szelenkov@nginx.com
1125*1130Szelenkov@nginx.com        payload = 'middle frame payload'
1126*1130Szelenkov@nginx.com
1127*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1128*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False)
1129*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '')
1130*1130Szelenkov@nginx.com
1131*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1132*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1133*1130Szelenkov@nginx.com
1134*1130Szelenkov@nginx.com        # 6_2_1
1135*1130Szelenkov@nginx.com
1136*1130Szelenkov@nginx.com        payload = 'Hello-µ@ßöäüàá-UTF-8!!'
1137*1130Szelenkov@nginx.com
1138*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1139*1130Szelenkov@nginx.com
1140*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1141*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1142*1130Szelenkov@nginx.com
1143*1130Szelenkov@nginx.com        # 6_2_2
1144*1130Szelenkov@nginx.com
1145*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False)
1146*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:])
1147*1130Szelenkov@nginx.com
1148*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1149*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1150*1130Szelenkov@nginx.com
1151*1130Szelenkov@nginx.com        # 6_2_3
1152*1130Szelenkov@nginx.com
1153*1130Szelenkov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1154*1130Szelenkov@nginx.com
1155*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1156*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1157*1130Szelenkov@nginx.com
1158*1130Szelenkov@nginx.com        # 6_2_4
1159*1130Szelenkov@nginx.com
1160*1130Szelenkov@nginx.com        payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1161*1130Szelenkov@nginx.com
1162*1130Szelenkov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1163*1130Szelenkov@nginx.com
1164*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1165*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1166*1130Szelenkov@nginx.com
1167*1130Szelenkov@nginx.com        self.close_connection(sock)
1168*1130Szelenkov@nginx.com
1169*1130Szelenkov@nginx.com        # Unit does not support UTF-8 validation
1170*1130Szelenkov@nginx.com
1171*1130Szelenkov@nginx.com#        # 6_3_1 FAIL
1172*1130Szelenkov@nginx.com#
1173*1130Szelenkov@nginx.com#        payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1174*1130Szelenkov@nginx.com#        payload_2 = '\xed\xa0\x80'
1175*1130Szelenkov@nginx.com#        payload_3 = '\x65\x64\x69\x74\x65\x64'
1176*1130Szelenkov@nginx.com#
1177*1130Szelenkov@nginx.com#        payload = payload_1 + payload_2 + payload_3
1178*1130Szelenkov@nginx.com#
1179*1130Szelenkov@nginx.com#        self.ws.message(sock, self.ws.OP_TEXT, payload)
1180*1130Szelenkov@nginx.com#        self.check_close(sock, 1007)
1181*1130Szelenkov@nginx.com#
1182*1130Szelenkov@nginx.com#        # 6_3_2 FAIL
1183*1130Szelenkov@nginx.com#
1184*1130Szelenkov@nginx.com#        _, sock, _ = self.ws.upgrade()
1185*1130Szelenkov@nginx.com#
1186*1130Szelenkov@nginx.com#        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1187*1130Szelenkov@nginx.com#        self.check_close(sock, 1007)
1188*1130Szelenkov@nginx.com#
1189*1130Szelenkov@nginx.com#        # 6_4_1 ... 6_4_4 FAIL
1190*1130Szelenkov@nginx.com
1191*1130Szelenkov@nginx.com    def test_node_websockets_7_1_1__7_5_1(self):
1192*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1193*1130Szelenkov@nginx.com
1194*1130Szelenkov@nginx.com        # 7_1_1
1195*1130Szelenkov@nginx.com
1196*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1197*1130Szelenkov@nginx.com
1198*1130Szelenkov@nginx.com        payload = "Hello World!"
1199*1130Szelenkov@nginx.com
1200*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1201*1130Szelenkov@nginx.com
1202*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1203*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1204*1130Szelenkov@nginx.com
1205*1130Szelenkov@nginx.com        self.close_connection(sock)
1206*1130Szelenkov@nginx.com
1207*1130Szelenkov@nginx.com        # 7_1_2
1208*1130Szelenkov@nginx.com
1209*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1210*1130Szelenkov@nginx.com
1211*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1212*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1213*1130Szelenkov@nginx.com
1214*1130Szelenkov@nginx.com        self.check_close(sock)
1215*1130Szelenkov@nginx.com
1216*1130Szelenkov@nginx.com        # 7_1_3
1217*1130Szelenkov@nginx.com
1218*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1219*1130Szelenkov@nginx.com
1220*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1221*1130Szelenkov@nginx.com        self.check_close(sock, no_close = True)
1222*1130Szelenkov@nginx.com
1223*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
1224*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
1225*1130Szelenkov@nginx.com
1226*1130Szelenkov@nginx.com        sock.close()
1227*1130Szelenkov@nginx.com
1228*1130Szelenkov@nginx.com        # 7_1_4
1229*1130Szelenkov@nginx.com
1230*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1231*1130Szelenkov@nginx.com
1232*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1233*1130Szelenkov@nginx.com        self.check_close(sock, no_close = True)
1234*1130Szelenkov@nginx.com
1235*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1236*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
1237*1130Szelenkov@nginx.com
1238*1130Szelenkov@nginx.com        sock.close()
1239*1130Szelenkov@nginx.com
1240*1130Szelenkov@nginx.com        # 7_1_5
1241*1130Szelenkov@nginx.com
1242*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1243*1130Szelenkov@nginx.com
1244*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1245*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1246*1130Szelenkov@nginx.com        self.check_close(sock, no_close = True)
1247*1130Szelenkov@nginx.com
1248*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2')
1249*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
1250*1130Szelenkov@nginx.com
1251*1130Szelenkov@nginx.com        sock.close()
1252*1130Szelenkov@nginx.com
1253*1130Szelenkov@nginx.com        # 7_1_6
1254*1130Szelenkov@nginx.com
1255*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1256*1130Szelenkov@nginx.com
1257*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2**10)
1258*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1259*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1260*1130Szelenkov@nginx.com
1261*1130Szelenkov@nginx.com        self.recvall(sock, read_timeout=1)
1262*1130Szelenkov@nginx.com
1263*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
1264*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
1265*1130Szelenkov@nginx.com
1266*1130Szelenkov@nginx.com        sock.close()
1267*1130Szelenkov@nginx.com
1268*1130Szelenkov@nginx.com        # 7_3_1 # FAIL
1269*1130Szelenkov@nginx.com
1270*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1271*1130Szelenkov@nginx.com
1272*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, '')
1273*1130Szelenkov@nginx.com        self.check_close(sock)
1274*1130Szelenkov@nginx.com
1275*1130Szelenkov@nginx.com        # 7_3_2
1276*1130Szelenkov@nginx.com
1277*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1278*1130Szelenkov@nginx.com
1279*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a')
1280*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1281*1130Szelenkov@nginx.com
1282*1130Szelenkov@nginx.com        # 7_3_3
1283*1130Szelenkov@nginx.com
1284*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1285*1130Szelenkov@nginx.com
1286*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1287*1130Szelenkov@nginx.com        self.check_close(sock)
1288*1130Szelenkov@nginx.com
1289*1130Szelenkov@nginx.com        # 7_3_4
1290*1130Szelenkov@nginx.com
1291*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1292*1130Szelenkov@nginx.com
1293*1130Szelenkov@nginx.com        payload = self.ws.serialize_close(reason = 'Hello World!')
1294*1130Szelenkov@nginx.com
1295*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1296*1130Szelenkov@nginx.com        self.check_close(sock)
1297*1130Szelenkov@nginx.com
1298*1130Szelenkov@nginx.com        # 7_3_5
1299*1130Szelenkov@nginx.com
1300*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1301*1130Szelenkov@nginx.com
1302*1130Szelenkov@nginx.com        payload = self.ws.serialize_close(reason = '*' * 123)
1303*1130Szelenkov@nginx.com
1304*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1305*1130Szelenkov@nginx.com        self.check_close(sock)
1306*1130Szelenkov@nginx.com
1307*1130Szelenkov@nginx.com        # 7_3_6
1308*1130Szelenkov@nginx.com
1309*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1310*1130Szelenkov@nginx.com
1311*1130Szelenkov@nginx.com        payload = self.ws.serialize_close(reason = '*' * 124)
1312*1130Szelenkov@nginx.com
1313*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1314*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1315*1130Szelenkov@nginx.com
1316*1130Szelenkov@nginx.com        # 7_5_1 FAIL Unit does not support UTF-8 validation
1317*1130Szelenkov@nginx.com
1318*1130Szelenkov@nginx.com#        _, sock, _ = self.ws.upgrade()
1319*1130Szelenkov@nginx.com#
1320*1130Szelenkov@nginx.com#        payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \
1321*1130Szelenkov@nginx.com#            '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64')
1322*1130Szelenkov@nginx.com#
1323*1130Szelenkov@nginx.com#        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1324*1130Szelenkov@nginx.com#        self.check_close(sock, 1007)
1325*1130Szelenkov@nginx.com
1326*1130Szelenkov@nginx.com    def test_node_websockets_7_7_X__7_9_X(self):
1327*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1328*1130Szelenkov@nginx.com
1329*1130Szelenkov@nginx.com        valid_codes = [
1330*1130Szelenkov@nginx.com            1000,
1331*1130Szelenkov@nginx.com            1001,
1332*1130Szelenkov@nginx.com            1002,
1333*1130Szelenkov@nginx.com            1003,
1334*1130Szelenkov@nginx.com            1007,
1335*1130Szelenkov@nginx.com            1008,
1336*1130Szelenkov@nginx.com            1009,
1337*1130Szelenkov@nginx.com            1010,
1338*1130Szelenkov@nginx.com            1011,
1339*1130Szelenkov@nginx.com            3000,
1340*1130Szelenkov@nginx.com            3999,
1341*1130Szelenkov@nginx.com            4000,
1342*1130Szelenkov@nginx.com            4999,
1343*1130Szelenkov@nginx.com        ]
1344*1130Szelenkov@nginx.com
1345*1130Szelenkov@nginx.com        invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999]
1346*1130Szelenkov@nginx.com
1347*1130Szelenkov@nginx.com        for code in valid_codes:
1348*1130Szelenkov@nginx.com            _, sock, _ = self.ws.upgrade()
1349*1130Szelenkov@nginx.com
1350*1130Szelenkov@nginx.com            payload = self.ws.serialize_close(code = code)
1351*1130Szelenkov@nginx.com
1352*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1353*1130Szelenkov@nginx.com            self.check_close(sock)
1354*1130Szelenkov@nginx.com
1355*1130Szelenkov@nginx.com        for code in invalid_codes:
1356*1130Szelenkov@nginx.com            _, sock, _ = self.ws.upgrade()
1357*1130Szelenkov@nginx.com
1358*1130Szelenkov@nginx.com            payload = self.ws.serialize_close(code = code)
1359*1130Szelenkov@nginx.com
1360*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1361*1130Szelenkov@nginx.com            self.check_close(sock, 1002)
1362*1130Szelenkov@nginx.com
1363*1130Szelenkov@nginx.com    def test_node_websockets_7_13_1__7_13_2(self):
1364*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1365*1130Szelenkov@nginx.com
1366*1130Szelenkov@nginx.com        # 7_13_1
1367*1130Szelenkov@nginx.com
1368*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1369*1130Szelenkov@nginx.com
1370*1130Szelenkov@nginx.com        payload = self.ws.serialize_close(code = 5000)
1371*1130Szelenkov@nginx.com
1372*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1373*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1374*1130Szelenkov@nginx.com
1375*1130Szelenkov@nginx.com        # 7_13_2
1376*1130Szelenkov@nginx.com
1377*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1378*1130Szelenkov@nginx.com
1379*1130Szelenkov@nginx.com        payload = struct.pack('!I', 65536) + ''.encode('utf-8')
1380*1130Szelenkov@nginx.com
1381*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1382*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1383*1130Szelenkov@nginx.com
1384*1130Szelenkov@nginx.com    def test_node_websockets_9_1_1__9_6_6(self):
1385*1130Szelenkov@nginx.com        if not self.unsafe:
1386*1130Szelenkov@nginx.com            self.skipTest("unsafe, long run")
1387*1130Szelenkov@nginx.com
1388*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1389*1130Szelenkov@nginx.com
1390*1130Szelenkov@nginx.com        self.assertIn(
1391*1130Szelenkov@nginx.com            'success',
1392*1130Szelenkov@nginx.com            self.conf(
1393*1130Szelenkov@nginx.com                {
1394*1130Szelenkov@nginx.com                    'http': {
1395*1130Szelenkov@nginx.com                        'websocket': {
1396*1130Szelenkov@nginx.com                            'max_frame_size': 33554432,
1397*1130Szelenkov@nginx.com                            'keepalive_interval': 0,
1398*1130Szelenkov@nginx.com                        }
1399*1130Szelenkov@nginx.com                    }
1400*1130Szelenkov@nginx.com                },
1401*1130Szelenkov@nginx.com                'settings',
1402*1130Szelenkov@nginx.com            ),
1403*1130Szelenkov@nginx.com            'increase max_frame_size and keepalive_interval',
1404*1130Szelenkov@nginx.com        )
1405*1130Szelenkov@nginx.com
1406*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1407*1130Szelenkov@nginx.com
1408*1130Szelenkov@nginx.com        op_text = self.ws.OP_TEXT
1409*1130Szelenkov@nginx.com        op_binary = self.ws.OP_BINARY
1410*1130Szelenkov@nginx.com
1411*1130Szelenkov@nginx.com        def check_payload(opcode, length, chopsize=None):
1412*1130Szelenkov@nginx.com            if opcode == self.ws.OP_TEXT:
1413*1130Szelenkov@nginx.com                payload = '*' * length
1414*1130Szelenkov@nginx.com            else:
1415*1130Szelenkov@nginx.com                payload = b'*' * length
1416*1130Szelenkov@nginx.com
1417*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
1418*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock, read_timeout=5)
1419*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
1420*1130Szelenkov@nginx.com
1421*1130Szelenkov@nginx.com        def check_message(opcode, f_size):
1422*1130Szelenkov@nginx.com            if opcode == self.ws.OP_TEXT:
1423*1130Szelenkov@nginx.com                payload = '*' * 4 * 2**20
1424*1130Szelenkov@nginx.com            else:
1425*1130Szelenkov@nginx.com                payload = b'*' * 4 * 2**20
1426*1130Szelenkov@nginx.com
1427*1130Szelenkov@nginx.com            self.ws.message(sock, opcode, payload, fragmention_size=f_size)
1428*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock, read_timeout=5)
1429*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
1430*1130Szelenkov@nginx.com
1431*1130Szelenkov@nginx.com        check_payload(op_text, 64 * 2**10)                 # 9_1_1
1432*1130Szelenkov@nginx.com        check_payload(op_text, 256 * 2**10)                # 9_1_2
1433*1130Szelenkov@nginx.com        check_payload(op_text, 2**20)                      # 9_1_3
1434*1130Szelenkov@nginx.com        check_payload(op_text, 4 * 2**20)                  # 9_1_4
1435*1130Szelenkov@nginx.com        check_payload(op_text, 8 * 2**20)                  # 9_1_5
1436*1130Szelenkov@nginx.com        check_payload(op_text, 16 * 2**20)                 # 9_1_6
1437*1130Szelenkov@nginx.com
1438*1130Szelenkov@nginx.com        check_payload(op_binary, 64 * 2**10)               # 9_2_1
1439*1130Szelenkov@nginx.com        check_payload(op_binary, 256 * 2**10)              # 9_2_2
1440*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20)                    # 9_2_3
1441*1130Szelenkov@nginx.com        check_payload(op_binary, 4 * 2**20)                # 9_2_4
1442*1130Szelenkov@nginx.com        check_payload(op_binary, 8 * 2**20)                # 9_2_5
1443*1130Szelenkov@nginx.com        check_payload(op_binary, 16 * 2**20)               # 9_2_6
1444*1130Szelenkov@nginx.com
1445*1130Szelenkov@nginx.com        if self.system != 'Darwin' and self.system != 'FreeBSD':
1446*1130Szelenkov@nginx.com            check_message(op_text, 64)                     # 9_3_1
1447*1130Szelenkov@nginx.com            check_message(op_text, 256)                    # 9_3_2
1448*1130Szelenkov@nginx.com            check_message(op_text, 2**10)                  # 9_3_3
1449*1130Szelenkov@nginx.com            check_message(op_text, 4 * 2**10)              # 9_3_4
1450*1130Szelenkov@nginx.com            check_message(op_text, 16 * 2**10)             # 9_3_5
1451*1130Szelenkov@nginx.com            check_message(op_text, 64 * 2**10)             # 9_3_6
1452*1130Szelenkov@nginx.com            check_message(op_text, 256 * 2**10)            # 9_3_7
1453*1130Szelenkov@nginx.com            check_message(op_text, 2**20)                  # 9_3_8
1454*1130Szelenkov@nginx.com            check_message(op_text, 4 * 2**20)              # 9_3_9
1455*1130Szelenkov@nginx.com
1456*1130Szelenkov@nginx.com            check_message(op_binary, 64)                   # 9_4_1
1457*1130Szelenkov@nginx.com            check_message(op_binary, 256)                  # 9_4_2
1458*1130Szelenkov@nginx.com            check_message(op_binary, 2**10)                # 9_4_3
1459*1130Szelenkov@nginx.com            check_message(op_binary, 4 * 2**10)            # 9_4_4
1460*1130Szelenkov@nginx.com            check_message(op_binary, 16 * 2**10)           # 9_4_5
1461*1130Szelenkov@nginx.com            check_message(op_binary, 64 * 2**10)           # 9_4_6
1462*1130Szelenkov@nginx.com            check_message(op_binary, 256 * 2**10)          # 9_4_7
1463*1130Szelenkov@nginx.com            check_message(op_binary, 2**20)                # 9_4_8
1464*1130Szelenkov@nginx.com            check_message(op_binary, 4 * 2**20)            # 9_4_9
1465*1130Szelenkov@nginx.com
1466*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=64)         # 9_5_1
1467*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=128)        # 9_5_2
1468*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=256)        # 9_5_3
1469*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=512)        # 9_5_4
1470*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=1024)       # 9_5_5
1471*1130Szelenkov@nginx.com        check_payload(op_text, 2**20, chopsize=2048)       # 9_5_6
1472*1130Szelenkov@nginx.com
1473*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=64)       # 9_6_1
1474*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=128)      # 9_6_2
1475*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=256)      # 9_6_3
1476*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=512)      # 9_6_4
1477*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=1024)     # 9_6_5
1478*1130Szelenkov@nginx.com        check_payload(op_binary, 2**20, chopsize=2048)     # 9_6_6
1479*1130Szelenkov@nginx.com
1480*1130Szelenkov@nginx.com        self.close_connection(sock)
1481*1130Szelenkov@nginx.com
1482*1130Szelenkov@nginx.com    def test_node_websockets_10_1_1(self):
1483*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1484*1130Szelenkov@nginx.com
1485*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1486*1130Szelenkov@nginx.com
1487*1130Szelenkov@nginx.com        payload = '*' * 65536
1488*1130Szelenkov@nginx.com
1489*1130Szelenkov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300)
1490*1130Szelenkov@nginx.com
1491*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1492*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1493*1130Szelenkov@nginx.com
1494*1130Szelenkov@nginx.com        self.close_connection(sock)
1495*1130Szelenkov@nginx.com
1496*1130Szelenkov@nginx.com    # settings
1497*1130Szelenkov@nginx.com
1498*1130Szelenkov@nginx.com    def test_node_websockets_max_frame_size(self):
1499*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1500*1130Szelenkov@nginx.com
1501*1130Szelenkov@nginx.com        self.assertIn(
1502*1130Szelenkov@nginx.com            'success',
1503*1130Szelenkov@nginx.com            self.conf(
1504*1130Szelenkov@nginx.com                {'http': {'websocket': {'max_frame_size': 100}}}, 'settings'
1505*1130Szelenkov@nginx.com            ),
1506*1130Szelenkov@nginx.com            'configure max_frame_size',
1507*1130Szelenkov@nginx.com        )
1508*1130Szelenkov@nginx.com
1509*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1510*1130Szelenkov@nginx.com
1511*1130Szelenkov@nginx.com        payload = '*' * 94
1512*1130Szelenkov@nginx.com        opcode = self.ws.OP_TEXT
1513*1130Szelenkov@nginx.com
1514*1130Szelenkov@nginx.com        self.ws.frame_write(sock, opcode, payload)  # frame length is 100
1515*1130Szelenkov@nginx.com
1516*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1517*1130Szelenkov@nginx.com        self.check_frame(frame, True, opcode, payload)
1518*1130Szelenkov@nginx.com
1519*1130Szelenkov@nginx.com        payload = '*' * 95
1520*1130Szelenkov@nginx.com
1521*1130Szelenkov@nginx.com        self.ws.frame_write(sock, opcode, payload)  # frame length is 101
1522*1130Szelenkov@nginx.com        self.check_close(sock, 1009)                # 1009 - CLOSE_TOO_LARGE
1523*1130Szelenkov@nginx.com
1524*1130Szelenkov@nginx.com    def test_node_websockets_read_timeout(self):
1525*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1526*1130Szelenkov@nginx.com
1527*1130Szelenkov@nginx.com        self.assertIn(
1528*1130Szelenkov@nginx.com            'success',
1529*1130Szelenkov@nginx.com            self.conf(
1530*1130Szelenkov@nginx.com                {'http': {'websocket': {'read_timeout': 1}}}, 'settings'
1531*1130Szelenkov@nginx.com            ),
1532*1130Szelenkov@nginx.com            'configure read_timeout',
1533*1130Szelenkov@nginx.com        )
1534*1130Szelenkov@nginx.com
1535*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1536*1130Szelenkov@nginx.com
1537*1130Szelenkov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1538*1130Szelenkov@nginx.com        sock.sendall(frame[:2])
1539*1130Szelenkov@nginx.com
1540*1130Szelenkov@nginx.com        time.sleep(2)
1541*1130Szelenkov@nginx.com
1542*1130Szelenkov@nginx.com        self.check_close(sock, 1001)   # 1001 - CLOSE_GOING_AWAY
1543*1130Szelenkov@nginx.com
1544*1130Szelenkov@nginx.com    def test_node_websockets_keepalive_interval(self):
1545*1130Szelenkov@nginx.com        self.load('websockets/mirror')
1546*1130Szelenkov@nginx.com
1547*1130Szelenkov@nginx.com        self.assertIn(
1548*1130Szelenkov@nginx.com            'success',
1549*1130Szelenkov@nginx.com            self.conf(
1550*1130Szelenkov@nginx.com                {'http': {'websocket': {'keepalive_interval': 1}}}, 'settings'
1551*1130Szelenkov@nginx.com            ),
1552*1130Szelenkov@nginx.com            'configure keepalive_interval',
1553*1130Szelenkov@nginx.com        )
1554*1130Szelenkov@nginx.com
1555*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1556*1130Szelenkov@nginx.com
1557*1130Szelenkov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1558*1130Szelenkov@nginx.com        sock.sendall(frame[:2])
1559*1130Szelenkov@nginx.com
1560*1130Szelenkov@nginx.com        time.sleep(2)
1561*1130Szelenkov@nginx.com
1562*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1563*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PING, '')  # PING frame
1564*1130Szelenkov@nginx.com
1565*1130Szelenkov@nginx.com        sock.close()
1566*1130Szelenkov@nginx.com
1567*1130Szelenkov@nginx.comif __name__ == '__main__':
1568*1130Szelenkov@nginx.com    TestNodeWebsockets.main()
1569