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