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