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