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