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