11130Szelenkov@nginx.comimport time
21130Szelenkov@nginx.comimport struct
31130Szelenkov@nginx.comimport unittest
41130Szelenkov@nginx.comfrom unit.applications.lang.node import TestApplicationNode
51130Szelenkov@nginx.comfrom unit.applications.websockets import TestApplicationWebsocket
61130Szelenkov@nginx.com
7*1150Szelenkov@nginx.com
81130Szelenkov@nginx.comclass TestNodeWebsockets(TestApplicationNode):
91130Szelenkov@nginx.com    prerequisites = ['node']
101130Szelenkov@nginx.com
111130Szelenkov@nginx.com    ws = TestApplicationWebsocket()
121130Szelenkov@nginx.com
131133Szelenkov@nginx.com    def setUp(self):
141133Szelenkov@nginx.com        super().setUp()
151133Szelenkov@nginx.com
161138Szelenkov@nginx.com        self.assertIn(
171138Szelenkov@nginx.com            'success',
181138Szelenkov@nginx.com            self.conf(
191138Szelenkov@nginx.com                {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
201138Szelenkov@nginx.com            ),
211138Szelenkov@nginx.com            'clear keepalive_interval',
221138Szelenkov@nginx.com        )
231138Szelenkov@nginx.com
241133Szelenkov@nginx.com        self.skip_alerts.extend(
25*1150Szelenkov@nginx.com            [r'last message send failed', r'socket close\(\d+\) failed']
261133Szelenkov@nginx.com        )
271130Szelenkov@nginx.com
281130Szelenkov@nginx.com    def close_connection(self, sock):
291130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
301130Szelenkov@nginx.com
311130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
321130Szelenkov@nginx.com
331130Szelenkov@nginx.com        self.check_close(sock)
341130Szelenkov@nginx.com
35*1150Szelenkov@nginx.com    def check_close(self, sock, code=1000, no_close=False):
361130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
371130Szelenkov@nginx.com
381130Szelenkov@nginx.com        self.assertEqual(frame['fin'], True, 'close fin')
391130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'close opcode')
401130Szelenkov@nginx.com        self.assertEqual(frame['code'], code, 'close code')
411130Szelenkov@nginx.com
421130Szelenkov@nginx.com        if not no_close:
431130Szelenkov@nginx.com            sock.close()
441130Szelenkov@nginx.com
451130Szelenkov@nginx.com    def check_frame(self, frame, fin, opcode, payload, decode=True):
461130Szelenkov@nginx.com        if opcode == self.ws.OP_BINARY or not decode:
471130Szelenkov@nginx.com            data = frame['data']
481130Szelenkov@nginx.com        else:
491130Szelenkov@nginx.com            data = frame['data'].decode('utf-8')
501130Szelenkov@nginx.com
511130Szelenkov@nginx.com        self.assertEqual(frame['fin'], fin, 'fin')
521130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], opcode, 'opcode')
531130Szelenkov@nginx.com        self.assertEqual(data, payload, 'payload')
541130Szelenkov@nginx.com
551130Szelenkov@nginx.com    def test_node_websockets_handshake(self):
561130Szelenkov@nginx.com        self.load('websockets/mirror')
571130Szelenkov@nginx.com
581130Szelenkov@nginx.com        resp, sock, key = self.ws.upgrade()
591130Szelenkov@nginx.com        sock.close()
601130Szelenkov@nginx.com
611130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
62*1150Szelenkov@nginx.com        self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade')
631130Szelenkov@nginx.com        self.assertEqual(
641130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
651130Szelenkov@nginx.com        )
661130Szelenkov@nginx.com        self.assertEqual(
671130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
681130Szelenkov@nginx.com        )
691130Szelenkov@nginx.com
701130Szelenkov@nginx.com    def test_node_websockets_mirror(self):
711130Szelenkov@nginx.com        self.load('websockets/mirror')
721130Szelenkov@nginx.com
731130Szelenkov@nginx.com        message = 'blah'
741130Szelenkov@nginx.com
751130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
761130Szelenkov@nginx.com
771130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
781130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
791130Szelenkov@nginx.com
80*1150Szelenkov@nginx.com        self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror')
811130Szelenkov@nginx.com
821130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
831130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
841130Szelenkov@nginx.com
85*1150Szelenkov@nginx.com        self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror 2')
861130Szelenkov@nginx.com
871130Szelenkov@nginx.com        sock.close()
881130Szelenkov@nginx.com
891130Szelenkov@nginx.com    def test_node_websockets_no_mask(self):
901130Szelenkov@nginx.com        self.load('websockets/mirror')
911130Szelenkov@nginx.com
921130Szelenkov@nginx.com        message = 'blah'
931130Szelenkov@nginx.com
941130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
951130Szelenkov@nginx.com
961130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
971130Szelenkov@nginx.com
981130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
991130Szelenkov@nginx.com
1001130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'no mask opcode')
1011130Szelenkov@nginx.com        self.assertEqual(frame['code'], 1002, 'no mask close code')
1021130Szelenkov@nginx.com
1031130Szelenkov@nginx.com        sock.close()
1041130Szelenkov@nginx.com
1051130Szelenkov@nginx.com    def test_node_websockets_fragmentation(self):
1061130Szelenkov@nginx.com        self.load('websockets/mirror')
1071130Szelenkov@nginx.com
1081130Szelenkov@nginx.com        message = 'blah'
1091130Szelenkov@nginx.com
1101130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1111130Szelenkov@nginx.com
1121130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
1131130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
1141130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
1151130Szelenkov@nginx.com
1161130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1171130Szelenkov@nginx.com
1181130Szelenkov@nginx.com        self.assertEqual(
1191130Szelenkov@nginx.com            message + ' ' + message,
1201130Szelenkov@nginx.com            frame['data'].decode('utf-8'),
1211130Szelenkov@nginx.com            'mirror framing',
1221130Szelenkov@nginx.com        )
1231130Szelenkov@nginx.com
1241130Szelenkov@nginx.com        sock.close()
1251130Szelenkov@nginx.com
1261130Szelenkov@nginx.com    def test_node_websockets_frame_fragmentation_invalid(self):
1271130Szelenkov@nginx.com        self.load('websockets/mirror')
1281130Szelenkov@nginx.com
1291130Szelenkov@nginx.com        message = 'blah'
1301130Szelenkov@nginx.com
1311130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1321130Szelenkov@nginx.com
1331130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
1341130Szelenkov@nginx.com
1351130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1361130Szelenkov@nginx.com
1371130Szelenkov@nginx.com        frame.pop('data')
1381130Szelenkov@nginx.com        self.assertDictEqual(
1391130Szelenkov@nginx.com            frame,
1401130Szelenkov@nginx.com            {
1411130Szelenkov@nginx.com                'fin': True,
1421130Szelenkov@nginx.com                'rsv1': False,
1431130Szelenkov@nginx.com                'rsv2': False,
1441130Szelenkov@nginx.com                'rsv3': False,
1451130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
1461130Szelenkov@nginx.com                'mask': 0,
1471130Szelenkov@nginx.com                'code': 1002,
1481130Szelenkov@nginx.com                'reason': 'Fragmented control frame',
1491130Szelenkov@nginx.com            },
1501130Szelenkov@nginx.com            'close frame',
1511130Szelenkov@nginx.com        )
1521130Szelenkov@nginx.com
1531130Szelenkov@nginx.com        sock.close()
1541130Szelenkov@nginx.com
1551130Szelenkov@nginx.com    def test_node_websockets_partial_send(self):
1561130Szelenkov@nginx.com        self.load('websockets/mirror')
1571130Szelenkov@nginx.com
1581130Szelenkov@nginx.com        message = 'blah'
1591130Szelenkov@nginx.com
1601130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1611130Szelenkov@nginx.com
1621130Szelenkov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, message)
1631130Szelenkov@nginx.com        sock.sendall(frame[:1])
1641130Szelenkov@nginx.com        sock.sendall(frame[1:2])
1651130Szelenkov@nginx.com        sock.sendall(frame[2:3])
1661130Szelenkov@nginx.com        sock.sendall(frame[3:])
1671130Szelenkov@nginx.com
1681130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1691130Szelenkov@nginx.com
1701130Szelenkov@nginx.com        self.assertEqual(
171*1150Szelenkov@nginx.com            message, frame['data'].decode('utf-8'), 'partial send'
1721130Szelenkov@nginx.com        )
1731130Szelenkov@nginx.com
1741130Szelenkov@nginx.com        sock.close()
1751130Szelenkov@nginx.com
1761130Szelenkov@nginx.com    def test_node_websockets_large(self):
1771130Szelenkov@nginx.com        self.load('websockets/mirror_fragmentation')
1781130Szelenkov@nginx.com
1791130Szelenkov@nginx.com        message = '0123456789' * 3000
1801130Szelenkov@nginx.com
1811130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1821130Szelenkov@nginx.com
1831130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
1841130Szelenkov@nginx.com
1851130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1861130Szelenkov@nginx.com        data = frame['data'].decode('utf-8')
1871130Szelenkov@nginx.com
1881130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1891130Szelenkov@nginx.com        data += frame['data'].decode('utf-8')
1901130Szelenkov@nginx.com
1911130Szelenkov@nginx.com        self.assertEqual(message, data, 'large')
1921130Szelenkov@nginx.com
1931130Szelenkov@nginx.com        sock.close()
1941130Szelenkov@nginx.com
1951130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode(self):
1961130Szelenkov@nginx.com        self.load('websockets/mirror')
1971130Szelenkov@nginx.com
1981130Szelenkov@nginx.com        message = 'blah'
1991130Szelenkov@nginx.com
2001130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
2011130Szelenkov@nginx.com
2021130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
2031130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
2041130Szelenkov@nginx.com
2051130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
2061130Szelenkov@nginx.com
2071130Szelenkov@nginx.com        frame.pop('data')
2081130Szelenkov@nginx.com        frame.pop('reason')
2091130Szelenkov@nginx.com        self.assertDictEqual(
2101130Szelenkov@nginx.com            frame,
2111130Szelenkov@nginx.com            {
2121130Szelenkov@nginx.com                'fin': True,
2131130Szelenkov@nginx.com                'rsv1': False,
2141130Szelenkov@nginx.com                'rsv2': False,
2151130Szelenkov@nginx.com                'rsv3': False,
2161130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
2171130Szelenkov@nginx.com                'mask': 0,
2181130Szelenkov@nginx.com                'code': 1002,
2191130Szelenkov@nginx.com            },
2201130Szelenkov@nginx.com            'close frame',
2211130Szelenkov@nginx.com        )
2221130Szelenkov@nginx.com
2231130Szelenkov@nginx.com        sock.close()
2241130Szelenkov@nginx.com
2251130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode_2(self):
2261130Szelenkov@nginx.com        self.load('websockets/mirror')
2271130Szelenkov@nginx.com
2281130Szelenkov@nginx.com        message = 'blah'
2291130Szelenkov@nginx.com
2301130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
2311130Szelenkov@nginx.com
2321130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
2331130Szelenkov@nginx.com
2341130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
2351130Szelenkov@nginx.com
2361130Szelenkov@nginx.com        frame.pop('data')
2371130Szelenkov@nginx.com        self.assertDictEqual(
2381130Szelenkov@nginx.com            frame,
2391130Szelenkov@nginx.com            {
2401130Szelenkov@nginx.com                'fin': True,
2411130Szelenkov@nginx.com                'rsv1': False,
2421130Szelenkov@nginx.com                'rsv2': False,
2431130Szelenkov@nginx.com                'rsv3': False,
2441130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
2451130Szelenkov@nginx.com                'mask': 0,
2461130Szelenkov@nginx.com                'code': 1002,
2471130Szelenkov@nginx.com                'reason': 'Unrecognized opcode 0',
2481130Szelenkov@nginx.com            },
2491130Szelenkov@nginx.com            'close frame',
2501130Szelenkov@nginx.com        )
2511130Szelenkov@nginx.com
2521130Szelenkov@nginx.com        sock.close()
2531130Szelenkov@nginx.com
2541130Szelenkov@nginx.com    def test_node_websockets_two_clients(self):
2551130Szelenkov@nginx.com        self.load('websockets/mirror')
2561130Szelenkov@nginx.com
2571130Szelenkov@nginx.com        message1 = 'blah1'
2581130Szelenkov@nginx.com        message2 = 'blah2'
2591130Szelenkov@nginx.com
2601130Szelenkov@nginx.com        _, sock1, _ = self.ws.upgrade()
2611130Szelenkov@nginx.com        _, sock2, _ = self.ws.upgrade()
2621130Szelenkov@nginx.com
2631130Szelenkov@nginx.com        self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
2641130Szelenkov@nginx.com        self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
2651130Szelenkov@nginx.com
2661130Szelenkov@nginx.com        frame1 = self.ws.frame_read(sock1)
2671130Szelenkov@nginx.com        frame2 = self.ws.frame_read(sock2)
2681130Szelenkov@nginx.com
269*1150Szelenkov@nginx.com        self.assertEqual(message1, frame1['data'].decode('utf-8'), 'client 1')
270*1150Szelenkov@nginx.com        self.assertEqual(message2, frame2['data'].decode('utf-8'), 'client 2')
2711130Szelenkov@nginx.com
2721130Szelenkov@nginx.com        sock1.close()
2731130Szelenkov@nginx.com        sock2.close()
2741130Szelenkov@nginx.com
2751130Szelenkov@nginx.com    @unittest.skip('not yet')
276*1150Szelenkov@nginx.com    def test_node_websockets_handshake_upgrade_absent(
277*1150Szelenkov@nginx.com        self
278*1150Szelenkov@nginx.com    ):  # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
2791130Szelenkov@nginx.com        self.load('websockets/mirror')
2801130Szelenkov@nginx.com
2811130Szelenkov@nginx.com        key = self.ws.key()
282*1150Szelenkov@nginx.com        resp = self.get(
283*1150Szelenkov@nginx.com            headers={
284*1150Szelenkov@nginx.com                'Host': 'localhost',
285*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
286*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
287*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
288*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
289*1150Szelenkov@nginx.com            },
290*1150Szelenkov@nginx.com            read_timeout=1,
291*1150Szelenkov@nginx.com        )
2921130Szelenkov@nginx.com
2931130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'upgrade absent')
2941130Szelenkov@nginx.com
2951130Szelenkov@nginx.com    def test_node_websockets_handshake_case_insensitive(self):
2961130Szelenkov@nginx.com        self.load('websockets/mirror')
2971130Szelenkov@nginx.com
2981130Szelenkov@nginx.com        key = self.ws.key()
299*1150Szelenkov@nginx.com        resp = self.get(
300*1150Szelenkov@nginx.com            headers={
301*1150Szelenkov@nginx.com                'Host': 'localhost',
302*1150Szelenkov@nginx.com                'Upgrade': 'WEBSOCKET',
303*1150Szelenkov@nginx.com                'Connection': 'UPGRADE',
304*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
305*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
306*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
307*1150Szelenkov@nginx.com            },
308*1150Szelenkov@nginx.com            read_timeout=1,
309*1150Szelenkov@nginx.com        )
3101130Szelenkov@nginx.com
3111130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
3121130Szelenkov@nginx.com
3131130Szelenkov@nginx.com    @unittest.skip('not yet')
314*1150Szelenkov@nginx.com    def test_node_websockets_handshake_connection_absent(self):  # FAIL
3151130Szelenkov@nginx.com        self.load('websockets/mirror')
3161130Szelenkov@nginx.com
3171130Szelenkov@nginx.com        key = self.ws.key()
318*1150Szelenkov@nginx.com        resp = self.get(
319*1150Szelenkov@nginx.com            headers={
320*1150Szelenkov@nginx.com                'Host': 'localhost',
321*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
322*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
323*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
324*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
325*1150Szelenkov@nginx.com            },
326*1150Szelenkov@nginx.com            read_timeout=1,
327*1150Szelenkov@nginx.com        )
3281130Szelenkov@nginx.com
3291130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
3301130Szelenkov@nginx.com
3311130Szelenkov@nginx.com    def test_node_websockets_handshake_version_absent(self):
3321130Szelenkov@nginx.com        self.load('websockets/mirror')
3331130Szelenkov@nginx.com
3341130Szelenkov@nginx.com        key = self.ws.key()
335*1150Szelenkov@nginx.com        resp = self.get(
336*1150Szelenkov@nginx.com            headers={
337*1150Szelenkov@nginx.com                'Host': 'localhost',
338*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
339*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
340*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
341*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
342*1150Szelenkov@nginx.com            },
343*1150Szelenkov@nginx.com            read_timeout=1,
344*1150Szelenkov@nginx.com        )
3451130Szelenkov@nginx.com
3461130Szelenkov@nginx.com        self.assertEqual(resp['status'], 426, 'status')
3471130Szelenkov@nginx.com
3481130Szelenkov@nginx.com    @unittest.skip('not yet')
3491130Szelenkov@nginx.com    def test_node_websockets_handshake_key_invalid(self):
3501130Szelenkov@nginx.com        self.load('websockets/mirror')
3511130Szelenkov@nginx.com
352*1150Szelenkov@nginx.com        resp = self.get(
353*1150Szelenkov@nginx.com            headers={
354*1150Szelenkov@nginx.com                'Host': 'localhost',
355*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
356*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
357*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': '!',
358*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
359*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
360*1150Szelenkov@nginx.com            },
361*1150Szelenkov@nginx.com            read_timeout=1,
362*1150Szelenkov@nginx.com        )
3631130Szelenkov@nginx.com
3641130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'key length')
3651130Szelenkov@nginx.com
3661130Szelenkov@nginx.com        key = self.ws.key()
367*1150Szelenkov@nginx.com        resp = self.get(
368*1150Szelenkov@nginx.com            headers={
369*1150Szelenkov@nginx.com                'Host': 'localhost',
370*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
371*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
372*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': [key, key],
373*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
374*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
375*1150Szelenkov@nginx.com            },
376*1150Szelenkov@nginx.com            read_timeout=1,
377*1150Szelenkov@nginx.com        )
3781130Szelenkov@nginx.com
379*1150Szelenkov@nginx.com        self.assertEqual(
380*1150Szelenkov@nginx.com            resp['status'], 400, 'key double'
381*1150Szelenkov@nginx.com        )  # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
3821130Szelenkov@nginx.com
3831130Szelenkov@nginx.com    def test_node_websockets_handshake_method_invalid(self):
3841130Szelenkov@nginx.com        self.load('websockets/mirror')
3851130Szelenkov@nginx.com
3861130Szelenkov@nginx.com        key = self.ws.key()
387*1150Szelenkov@nginx.com        resp = self.post(
388*1150Szelenkov@nginx.com            headers={
389*1150Szelenkov@nginx.com                'Host': 'localhost',
390*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
391*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
392*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
393*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
394*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
395*1150Szelenkov@nginx.com            },
396*1150Szelenkov@nginx.com            read_timeout=1,
397*1150Szelenkov@nginx.com        )
3981130Szelenkov@nginx.com
3991130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
4001130Szelenkov@nginx.com
4011130Szelenkov@nginx.com    def test_node_websockets_handshake_http_10(self):
4021130Szelenkov@nginx.com        self.load('websockets/mirror')
4031130Szelenkov@nginx.com
4041130Szelenkov@nginx.com        key = self.ws.key()
405*1150Szelenkov@nginx.com        resp = self.get(
406*1150Szelenkov@nginx.com            headers={
407*1150Szelenkov@nginx.com                'Host': 'localhost',
408*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
409*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
410*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
411*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
412*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
413*1150Szelenkov@nginx.com            },
414*1150Szelenkov@nginx.com            http_10=True,
415*1150Szelenkov@nginx.com            read_timeout=1,
416*1150Szelenkov@nginx.com        )
4171130Szelenkov@nginx.com
4181130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
4191130Szelenkov@nginx.com
4201130Szelenkov@nginx.com    def test_node_websockets_handshake_uri_invalid(self):
4211130Szelenkov@nginx.com        self.load('websockets/mirror')
4221130Szelenkov@nginx.com
4231130Szelenkov@nginx.com        key = self.ws.key()
424*1150Szelenkov@nginx.com        resp = self.get(
425*1150Szelenkov@nginx.com            headers={
426*1150Szelenkov@nginx.com                'Host': 'localhost',
427*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
428*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
429*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
430*1150Szelenkov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
431*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
432*1150Szelenkov@nginx.com            },
433*1150Szelenkov@nginx.com            url='!',
434*1150Szelenkov@nginx.com            read_timeout=1,
435*1150Szelenkov@nginx.com        )
4361130Szelenkov@nginx.com
4371130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
4381130Szelenkov@nginx.com
4391130Szelenkov@nginx.com    def test_node_websockets_protocol_absent(self):
4401130Szelenkov@nginx.com        self.load('websockets/mirror')
4411130Szelenkov@nginx.com
4421130Szelenkov@nginx.com        key = self.ws.key()
443*1150Szelenkov@nginx.com        resp = self.get(
444*1150Szelenkov@nginx.com            headers={
445*1150Szelenkov@nginx.com                'Host': 'localhost',
446*1150Szelenkov@nginx.com                'Upgrade': 'websocket',
447*1150Szelenkov@nginx.com                'Connection': 'Upgrade',
448*1150Szelenkov@nginx.com                'Sec-WebSocket-Key': key,
449*1150Szelenkov@nginx.com                'Sec-WebSocket-Version': 13,
450*1150Szelenkov@nginx.com            },
451*1150Szelenkov@nginx.com            read_timeout=1,
452*1150Szelenkov@nginx.com        )
4531130Szelenkov@nginx.com
4541130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
455*1150Szelenkov@nginx.com        self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade')
4561130Szelenkov@nginx.com        self.assertEqual(
4571130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
4581130Szelenkov@nginx.com        )
4591130Szelenkov@nginx.com        self.assertEqual(
4601130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
4611130Szelenkov@nginx.com        )
4621130Szelenkov@nginx.com
4631130Szelenkov@nginx.com    # autobahn-testsuite
464*1150Szelenkov@nginx.com    #
4651130Szelenkov@nginx.com    # Some following tests fail because of Unit does not support UTF-8
4661130Szelenkov@nginx.com    # validation for websocket frames.  It should be implemented
4671130Szelenkov@nginx.com    # by application, if necessary.
4681130Szelenkov@nginx.com
4691133Szelenkov@nginx.com    @unittest.skip('not yet')
4701130Szelenkov@nginx.com    def test_node_websockets_1_1_1__1_1_8(self):
4711130Szelenkov@nginx.com        self.load('websockets/mirror')
4721130Szelenkov@nginx.com
4731130Szelenkov@nginx.com        opcode = self.ws.OP_TEXT
4741130Szelenkov@nginx.com
4751130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
4761130Szelenkov@nginx.com
4771130Szelenkov@nginx.com        def check_length(length, chopsize=None):
4781130Szelenkov@nginx.com            payload = '*' * length
4791130Szelenkov@nginx.com
4801130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
4811130Szelenkov@nginx.com
4821130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
4831130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
4841130Szelenkov@nginx.com
4851130Szelenkov@nginx.com        check_length(0)                      # 1_1_1
4861130Szelenkov@nginx.com        check_length(125)                    # 1_1_2
4871130Szelenkov@nginx.com        check_length(126)                    # 1_1_3
4881130Szelenkov@nginx.com        check_length(127)                    # 1_1_4
4891130Szelenkov@nginx.com        check_length(128)                    # 1_1_5
4901130Szelenkov@nginx.com        check_length(65535)                  # 1_1_6
4911130Szelenkov@nginx.com        check_length(65536)                  # 1_1_7
4921130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_1_8
4931130Szelenkov@nginx.com
4941130Szelenkov@nginx.com        self.close_connection(sock)
4951130Szelenkov@nginx.com
4961133Szelenkov@nginx.com    @unittest.skip('not yet')
4971130Szelenkov@nginx.com    def test_node_websockets_1_2_1__1_2_8(self):
4981130Szelenkov@nginx.com        self.load('websockets/mirror')
4991130Szelenkov@nginx.com
5001130Szelenkov@nginx.com        opcode = self.ws.OP_BINARY
5011130Szelenkov@nginx.com
5021130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
5031130Szelenkov@nginx.com
5041130Szelenkov@nginx.com        def check_length(length, chopsize=None):
5051130Szelenkov@nginx.com            payload = b'\xfe' * length
5061130Szelenkov@nginx.com
5071130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
5081130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
5091130Szelenkov@nginx.com
5101130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
5111130Szelenkov@nginx.com
5121130Szelenkov@nginx.com        check_length(0)                      # 1_2_1
5131130Szelenkov@nginx.com        check_length(125)                    # 1_2_2
5141130Szelenkov@nginx.com        check_length(126)                    # 1_2_3
5151130Szelenkov@nginx.com        check_length(127)                    # 1_2_4
5161130Szelenkov@nginx.com        check_length(128)                    # 1_2_5
5171130Szelenkov@nginx.com        check_length(65535)                  # 1_2_6
5181130Szelenkov@nginx.com        check_length(65536)                  # 1_2_7
5191130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_2_8
5201130Szelenkov@nginx.com
5211130Szelenkov@nginx.com        self.close_connection(sock)
5221130Szelenkov@nginx.com
5231130Szelenkov@nginx.com    def test_node_websockets_2_1__2_6(self):
5241130Szelenkov@nginx.com        self.load('websockets/mirror')
5251130Szelenkov@nginx.com
5261130Szelenkov@nginx.com        op_ping = self.ws.OP_PING
5271130Szelenkov@nginx.com        op_pong = self.ws.OP_PONG
5281130Szelenkov@nginx.com
5291130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
5301130Szelenkov@nginx.com
5311130Szelenkov@nginx.com        def check_ping(payload, chopsize=None, decode=True):
5321130Szelenkov@nginx.com            self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
5331130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
5341130Szelenkov@nginx.com
5351130Szelenkov@nginx.com            self.check_frame(frame, True, op_pong, payload, decode=decode)
5361130Szelenkov@nginx.com
5371130Szelenkov@nginx.com        check_ping('')                                                 # 2_1
5381130Szelenkov@nginx.com        check_ping('Hello, world!')                                    # 2_2
5391130Szelenkov@nginx.com        check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False)  # 2_3
5401130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, decode=False)                        # 2_4
5411130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, chopsize=1, decode=False)            # 2_6
5421130Szelenkov@nginx.com
5431130Szelenkov@nginx.com        self.close_connection(sock)
5441130Szelenkov@nginx.com
5451130Szelenkov@nginx.com        # 2_5
5461130Szelenkov@nginx.com
5471130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
5481130Szelenkov@nginx.com
5491130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
5501130Szelenkov@nginx.com        self.check_close(sock, 1002)
5511130Szelenkov@nginx.com
5521130Szelenkov@nginx.com    def test_node_websockets_2_7__2_9(self):
5531130Szelenkov@nginx.com        self.load('websockets/mirror')
5541130Szelenkov@nginx.com
5551130Szelenkov@nginx.com        # 2_7
5561130Szelenkov@nginx.com
5571130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
5581130Szelenkov@nginx.com
5591130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, '')
5601130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_7')
5611130Szelenkov@nginx.com
5621130Szelenkov@nginx.com        # 2_8
5631130Szelenkov@nginx.com
5641130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
5651130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_8')
5661130Szelenkov@nginx.com
5671130Szelenkov@nginx.com        # 2_9
5681130Szelenkov@nginx.com
5691130Szelenkov@nginx.com        payload = 'ping payload'
5701130Szelenkov@nginx.com
5711130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
5721130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, payload)
5731130Szelenkov@nginx.com
5741130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
5751130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, payload)
5761130Szelenkov@nginx.com
5771130Szelenkov@nginx.com        self.close_connection(sock)
5781130Szelenkov@nginx.com
5791130Szelenkov@nginx.com    def test_node_websockets_2_10__2_11(self):
5801130Szelenkov@nginx.com        self.load('websockets/mirror')
5811130Szelenkov@nginx.com
5821130Szelenkov@nginx.com        # 2_10
5831130Szelenkov@nginx.com
5841130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
5851130Szelenkov@nginx.com
5861130Szelenkov@nginx.com        for i in range(0, 10):
5871130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
5881130Szelenkov@nginx.com
5891130Szelenkov@nginx.com        for i in range(0, 10):
5901130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
5911130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
5921130Szelenkov@nginx.com
5931130Szelenkov@nginx.com        # 2_11
5941130Szelenkov@nginx.com
5951130Szelenkov@nginx.com        for i in range(0, 10):
5961130Szelenkov@nginx.com            opcode = self.ws.OP_PING
5971130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
5981130Szelenkov@nginx.com
5991130Szelenkov@nginx.com        for i in range(0, 10):
6001130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
6011130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
6021130Szelenkov@nginx.com
6031130Szelenkov@nginx.com        self.close_connection(sock)
6041130Szelenkov@nginx.com
6051130Szelenkov@nginx.com    @unittest.skip('not yet')
6061130Szelenkov@nginx.com    def test_node_websockets_3_1__3_7(self):
6071130Szelenkov@nginx.com        self.load('websockets/mirror')
6081130Szelenkov@nginx.com
6091130Szelenkov@nginx.com        payload = 'Hello, world!'
6101130Szelenkov@nginx.com
6111130Szelenkov@nginx.com        # 3_1
6121130Szelenkov@nginx.com
6131130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6141130Szelenkov@nginx.com
6151130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
6161130Szelenkov@nginx.com        self.check_close(sock, 1002)
6171130Szelenkov@nginx.com
6181130Szelenkov@nginx.com        # 3_2
6191130Szelenkov@nginx.com
6201130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6211130Szelenkov@nginx.com
6221130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
6231130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
6241130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
6251130Szelenkov@nginx.com
6261130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
6271130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6281130Szelenkov@nginx.com
629*1150Szelenkov@nginx.com        self.check_close(sock, 1002, no_close=True)
6301130Szelenkov@nginx.com
6311130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_2')
6321130Szelenkov@nginx.com        sock.close()
6331130Szelenkov@nginx.com
6341130Szelenkov@nginx.com        # 3_3
6351130Szelenkov@nginx.com
6361130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6371130Szelenkov@nginx.com
6381130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
6391130Szelenkov@nginx.com
6401130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
6411130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6421130Szelenkov@nginx.com
6431130Szelenkov@nginx.com        self.ws.frame_write(
644*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True
6451130Szelenkov@nginx.com        )
6461130Szelenkov@nginx.com
647*1150Szelenkov@nginx.com        self.check_close(sock, 1002, no_close=True)
6481130Szelenkov@nginx.com
6491130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_3')
6501130Szelenkov@nginx.com        sock.close()
6511130Szelenkov@nginx.com
6521130Szelenkov@nginx.com        # 3_4
6531130Szelenkov@nginx.com
6541130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6551130Szelenkov@nginx.com
6561130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
6571130Szelenkov@nginx.com        self.ws.frame_write(
658*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1
6591130Szelenkov@nginx.com        )
6601130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
6611130Szelenkov@nginx.com
6621130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
6631130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6641130Szelenkov@nginx.com
665*1150Szelenkov@nginx.com        self.check_close(sock, 1002, no_close=True)
6661130Szelenkov@nginx.com
6671130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_4')
6681130Szelenkov@nginx.com        sock.close()
6691130Szelenkov@nginx.com
6701130Szelenkov@nginx.com        # 3_5
6711130Szelenkov@nginx.com
6721130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6731130Szelenkov@nginx.com
6741130Szelenkov@nginx.com        self.ws.frame_write(
6751130Szelenkov@nginx.com            sock,
6761130Szelenkov@nginx.com            self.ws.OP_BINARY,
6771130Szelenkov@nginx.com            b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
6781130Szelenkov@nginx.com            rsv1=True,
6791130Szelenkov@nginx.com            rsv3=True,
6801130Szelenkov@nginx.com        )
6811130Szelenkov@nginx.com
6821130Szelenkov@nginx.com        self.check_close(sock, 1002)
6831130Szelenkov@nginx.com
6841130Szelenkov@nginx.com        # 3_6
6851130Szelenkov@nginx.com
6861130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6871130Szelenkov@nginx.com
6881130Szelenkov@nginx.com        self.ws.frame_write(
689*1150Szelenkov@nginx.com            sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True
6901130Szelenkov@nginx.com        )
6911130Szelenkov@nginx.com
6921130Szelenkov@nginx.com        self.check_close(sock, 1002)
6931130Szelenkov@nginx.com
6941130Szelenkov@nginx.com        # 3_7
6951130Szelenkov@nginx.com
6961130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
6971130Szelenkov@nginx.com
6981130Szelenkov@nginx.com        self.ws.frame_write(
699*1150Szelenkov@nginx.com            sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True
7001130Szelenkov@nginx.com        )
7011130Szelenkov@nginx.com
7021130Szelenkov@nginx.com        self.check_close(sock, 1002)
7031130Szelenkov@nginx.com
7041130Szelenkov@nginx.com    def test_node_websockets_4_1_1__4_2_5(self):
7051130Szelenkov@nginx.com        self.load('websockets/mirror')
7061130Szelenkov@nginx.com
7071130Szelenkov@nginx.com        payload = 'Hello, world!'
7081130Szelenkov@nginx.com
7091130Szelenkov@nginx.com        # 4_1_1
7101130Szelenkov@nginx.com
7111130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7121130Szelenkov@nginx.com
7131130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x03, '')
7141130Szelenkov@nginx.com        self.check_close(sock, 1002)
7151130Szelenkov@nginx.com
7161130Szelenkov@nginx.com        # 4_1_2
7171130Szelenkov@nginx.com
7181130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7191130Szelenkov@nginx.com
7201130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
7211130Szelenkov@nginx.com        self.check_close(sock, 1002)
7221130Szelenkov@nginx.com
7231130Szelenkov@nginx.com        # 4_1_3
7241130Szelenkov@nginx.com
7251130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7261130Szelenkov@nginx.com
7271130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7281130Szelenkov@nginx.com
7291130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
7301130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7311130Szelenkov@nginx.com
7321130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x05, '')
7331130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7341130Szelenkov@nginx.com
7351130Szelenkov@nginx.com        self.check_close(sock, 1002)
7361130Szelenkov@nginx.com
7371130Szelenkov@nginx.com        # 4_1_4
7381130Szelenkov@nginx.com
7391130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7401130Szelenkov@nginx.com
7411130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7421130Szelenkov@nginx.com
7431130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
7441130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7451130Szelenkov@nginx.com
7461130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x06, payload)
7471130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7481130Szelenkov@nginx.com
7491130Szelenkov@nginx.com        self.check_close(sock, 1002)
7501130Szelenkov@nginx.com
7511130Szelenkov@nginx.com        # 4_1_5
7521130Szelenkov@nginx.com
7531130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7541130Szelenkov@nginx.com
7551130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
7561130Szelenkov@nginx.com
7571130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
7581130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7591130Szelenkov@nginx.com
7601130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x07, payload, chopsize=1)
7611130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7621130Szelenkov@nginx.com
7631130Szelenkov@nginx.com        self.check_close(sock, 1002)
7641130Szelenkov@nginx.com
7651130Szelenkov@nginx.com        # 4_2_1
7661130Szelenkov@nginx.com
7671130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7681130Szelenkov@nginx.com
7691130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0B, '')
7701130Szelenkov@nginx.com        self.check_close(sock, 1002)
7711130Szelenkov@nginx.com
7721130Szelenkov@nginx.com        # 4_2_2
7731130Szelenkov@nginx.com
7741130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7751130Szelenkov@nginx.com
7761130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
7771130Szelenkov@nginx.com        self.check_close(sock, 1002)
7781130Szelenkov@nginx.com
7791130Szelenkov@nginx.com        # 4_2_3
7801130Szelenkov@nginx.com
7811130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7821130Szelenkov@nginx.com
7831130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7841130Szelenkov@nginx.com
7851130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
7861130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7871130Szelenkov@nginx.com
7881130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0D, '')
7891130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7901130Szelenkov@nginx.com
7911130Szelenkov@nginx.com        self.check_close(sock, 1002)
7921130Szelenkov@nginx.com
7931130Szelenkov@nginx.com        # 4_2_4
7941130Szelenkov@nginx.com
7951130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
7961130Szelenkov@nginx.com
7971130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7981130Szelenkov@nginx.com
7991130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8001130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
8011130Szelenkov@nginx.com
8021130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0E, payload)
8031130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
8041130Szelenkov@nginx.com
8051130Szelenkov@nginx.com        self.check_close(sock, 1002)
8061130Szelenkov@nginx.com
8071130Szelenkov@nginx.com        # 4_2_5
8081130Szelenkov@nginx.com
8091130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
8101130Szelenkov@nginx.com
8111130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
8121130Szelenkov@nginx.com
8131130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8141130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
8151130Szelenkov@nginx.com
8161130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
8171130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
8181130Szelenkov@nginx.com
8191130Szelenkov@nginx.com        self.check_close(sock, 1002)
8201130Szelenkov@nginx.com
8211133Szelenkov@nginx.com    @unittest.skip('not yet')
8221130Szelenkov@nginx.com    def test_node_websockets_5_1__5_20(self):
8231130Szelenkov@nginx.com        self.load('websockets/mirror')
8241130Szelenkov@nginx.com
8251130Szelenkov@nginx.com        # 5_1
8261130Szelenkov@nginx.com
8271130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
8281130Szelenkov@nginx.com
8291130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
8301130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8311130Szelenkov@nginx.com        self.check_close(sock, 1002)
8321130Szelenkov@nginx.com
8331130Szelenkov@nginx.com        # 5_2
8341130Szelenkov@nginx.com
8351130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
8361130Szelenkov@nginx.com
8371130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False)
8381130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8391130Szelenkov@nginx.com        self.check_close(sock, 1002)
8401130Szelenkov@nginx.com
8411130Szelenkov@nginx.com        # 5_3
8421130Szelenkov@nginx.com
8431130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
8441130Szelenkov@nginx.com
8451130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8461130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8471130Szelenkov@nginx.com
8481130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8491130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8501130Szelenkov@nginx.com
8511130Szelenkov@nginx.com        # 5_4
8521130Szelenkov@nginx.com
8531130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8541130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_4')
8551130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8561130Szelenkov@nginx.com
8571130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8581130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8591130Szelenkov@nginx.com
8601130Szelenkov@nginx.com        # 5_5
8611130Szelenkov@nginx.com
8621130Szelenkov@nginx.com        self.ws.frame_write(
863*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
8641130Szelenkov@nginx.com        )
8651130Szelenkov@nginx.com        self.ws.frame_write(
866*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
8671130Szelenkov@nginx.com        )
8681130Szelenkov@nginx.com
8691130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8701130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8711130Szelenkov@nginx.com
8721130Szelenkov@nginx.com        # 5_6
8731130Szelenkov@nginx.com
8741130Szelenkov@nginx.com        ping_payload = 'ping payload'
8751130Szelenkov@nginx.com
8761130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8771130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
8781130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8791130Szelenkov@nginx.com
8801130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8811130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
8821130Szelenkov@nginx.com
8831130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8841130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8851130Szelenkov@nginx.com
8861130Szelenkov@nginx.com        # 5_7
8871130Szelenkov@nginx.com
8881130Szelenkov@nginx.com        ping_payload = 'ping payload'
8891130Szelenkov@nginx.com
8901130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8911130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_7')
8921130Szelenkov@nginx.com
8931130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
8941130Szelenkov@nginx.com
8951130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
8961130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
8971130Szelenkov@nginx.com
8981130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8991130Szelenkov@nginx.com
9001130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
9011130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
9021130Szelenkov@nginx.com
9031130Szelenkov@nginx.com        # 5_8
9041130Szelenkov@nginx.com
9051130Szelenkov@nginx.com        ping_payload = 'ping payload'
9061130Szelenkov@nginx.com
9071130Szelenkov@nginx.com        self.ws.frame_write(
908*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
9091130Szelenkov@nginx.com        )
9101130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
9111130Szelenkov@nginx.com        self.ws.frame_write(
912*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
9131130Szelenkov@nginx.com        )
9141130Szelenkov@nginx.com
9151130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
9161130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
9171130Szelenkov@nginx.com
9181130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
9191130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
9201130Szelenkov@nginx.com
9211130Szelenkov@nginx.com        # 5_9
9221130Szelenkov@nginx.com
9231130Szelenkov@nginx.com        self.ws.frame_write(
924*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
9251130Szelenkov@nginx.com        )
9261130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
9271130Szelenkov@nginx.com        self.check_close(sock, 1002)
9281130Szelenkov@nginx.com
9291130Szelenkov@nginx.com        # 5_10
9301130Szelenkov@nginx.com
9311130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9321130Szelenkov@nginx.com
9331130Szelenkov@nginx.com        self.ws.frame_write(
934*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
9351130Szelenkov@nginx.com        )
9361130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
9371130Szelenkov@nginx.com        self.check_close(sock, 1002)
9381130Szelenkov@nginx.com
9391130Szelenkov@nginx.com        # 5_11
9401130Szelenkov@nginx.com
9411130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9421130Szelenkov@nginx.com
9431130Szelenkov@nginx.com        self.ws.frame_write(
9441130Szelenkov@nginx.com            sock,
9451130Szelenkov@nginx.com            self.ws.OP_CONT,
9461130Szelenkov@nginx.com            'non-continuation payload',
9471130Szelenkov@nginx.com            fin=True,
9481130Szelenkov@nginx.com            chopsize=1,
9491130Szelenkov@nginx.com        )
9501130Szelenkov@nginx.com        self.ws.frame_write(
951*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
9521130Szelenkov@nginx.com        )
9531130Szelenkov@nginx.com        self.check_close(sock, 1002)
9541130Szelenkov@nginx.com
9551130Szelenkov@nginx.com        # 5_12
9561130Szelenkov@nginx.com
9571130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9581130Szelenkov@nginx.com
9591130Szelenkov@nginx.com        self.ws.frame_write(
960*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
9611130Szelenkov@nginx.com        )
9621130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
9631130Szelenkov@nginx.com        self.check_close(sock, 1002)
9641130Szelenkov@nginx.com
9651130Szelenkov@nginx.com        # 5_13
9661130Szelenkov@nginx.com
9671130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9681130Szelenkov@nginx.com
9691130Szelenkov@nginx.com        self.ws.frame_write(
970*1150Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
9711130Szelenkov@nginx.com        )
9721130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
9731130Szelenkov@nginx.com        self.check_close(sock, 1002)
9741130Szelenkov@nginx.com
9751130Szelenkov@nginx.com        # 5_14
9761130Szelenkov@nginx.com
9771130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9781130Szelenkov@nginx.com
9791130Szelenkov@nginx.com        self.ws.frame_write(
9801130Szelenkov@nginx.com            sock,
9811130Szelenkov@nginx.com            self.ws.OP_CONT,
9821130Szelenkov@nginx.com            'non-continuation payload',
9831130Szelenkov@nginx.com            fin=False,
9841130Szelenkov@nginx.com            chopsize=1,
9851130Szelenkov@nginx.com        )
9861130Szelenkov@nginx.com        self.ws.frame_write(
987*1150Szelenkov@nginx.com            sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
9881130Szelenkov@nginx.com        )
9891130Szelenkov@nginx.com        self.check_close(sock, 1002)
9901130Szelenkov@nginx.com
9911130Szelenkov@nginx.com        # 5_15
9921130Szelenkov@nginx.com
9931130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
9941130Szelenkov@nginx.com
9951130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
9961130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
9971130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
9981130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
9991130Szelenkov@nginx.com        self.check_close(sock, 1002)
10001130Szelenkov@nginx.com
10011130Szelenkov@nginx.com        # 5_16
10021130Szelenkov@nginx.com
10031130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
10041130Szelenkov@nginx.com
10051130Szelenkov@nginx.com        for i in range(0, 2):
10061130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
10071130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
10081130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
10091130Szelenkov@nginx.com        self.check_close(sock, 1002)
10101130Szelenkov@nginx.com
10111130Szelenkov@nginx.com        # 5_17
10121130Szelenkov@nginx.com
10131130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
10141130Szelenkov@nginx.com
10151130Szelenkov@nginx.com        for i in range(0, 2):
10161130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
10171130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
10181130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
10191130Szelenkov@nginx.com        self.check_close(sock, 1002)
10201130Szelenkov@nginx.com
10211130Szelenkov@nginx.com        # 5_18
10221130Szelenkov@nginx.com
10231130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
10241130Szelenkov@nginx.com
10251130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
10261130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
10271130Szelenkov@nginx.com        self.check_close(sock, 1002)
10281130Szelenkov@nginx.com
10291130Szelenkov@nginx.com        # 5_19
10301130Szelenkov@nginx.com
10311130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
10321130Szelenkov@nginx.com
10331130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
10341130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
10351130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
10361130Szelenkov@nginx.com
10371130Szelenkov@nginx.com        time.sleep(1)
10381130Szelenkov@nginx.com
10391130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
10401130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
10411130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
10421130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
10431130Szelenkov@nginx.com
10441130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
10451130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
10461130Szelenkov@nginx.com
10471130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
1048