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