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