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