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