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