xref: /unit/test/test_node_websockets.py (revision 1635:97afbb6c5a15)
1import struct
2import time
3
4import pytest
5
6from conftest import option
7from conftest import skip_alert
8from unit.applications.lang.node import TestApplicationNode
9from unit.applications.websockets import TestApplicationWebsocket
10
11
12class TestNodeWebsockets(TestApplicationNode):
13    prerequisites = {'modules': {'node': 'any'}}
14
15    ws = TestApplicationWebsocket()
16
17    def setup_method(self):
18        super().setup_method()
19
20        assert 'success' in self.conf(
21            {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
22        ), 'clear keepalive_interval'
23
24        skip_alert(r'socket close\(\d+\) failed')
25
26    def close_connection(self, sock):
27        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
28
29        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
30
31        self.check_close(sock)
32
33    def check_close(self, sock, code=1000, no_close=False):
34        frame = self.ws.frame_read(sock)
35
36        assert frame['fin'] == True, 'close fin'
37        assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode'
38        assert frame['code'] == code, 'close code'
39
40        if not no_close:
41            sock.close()
42
43    def check_frame(self, frame, fin, opcode, payload, decode=True):
44        if opcode == self.ws.OP_BINARY or not decode:
45            data = frame['data']
46        else:
47            data = frame['data'].decode('utf-8')
48
49        assert frame['fin'] == fin, 'fin'
50        assert frame['opcode'] == opcode, 'opcode'
51        assert data == payload, 'payload'
52
53    def test_node_websockets_handshake(self):
54        self.load('websockets/mirror')
55
56        resp, sock, key = self.ws.upgrade()
57        sock.close()
58
59        assert resp['status'] == 101, 'status'
60        assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
61        assert resp['headers']['Connection'] == 'Upgrade', 'connection'
62        assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
63            key
64        ), 'key'
65
66    def test_node_websockets_mirror(self):
67        self.load('websockets/mirror')
68
69        message = 'blah'
70
71        _, sock, _ = self.ws.upgrade()
72
73        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
74        frame = self.ws.frame_read(sock)
75
76        assert message == frame['data'].decode('utf-8'), 'mirror'
77
78        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
79        frame = self.ws.frame_read(sock)
80
81        assert message == frame['data'].decode('utf-8'), 'mirror 2'
82
83        sock.close()
84
85    def test_node_websockets_no_mask(self):
86        self.load('websockets/mirror')
87
88        message = 'blah'
89
90        _, sock, _ = self.ws.upgrade()
91
92        self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
93
94        frame = self.ws.frame_read(sock)
95
96        assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode'
97        assert frame['code'] == 1002, 'no mask close code'
98
99        sock.close()
100
101    def test_node_websockets_fragmentation(self):
102        self.load('websockets/mirror')
103
104        message = 'blah'
105
106        _, sock, _ = self.ws.upgrade()
107
108        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
109        self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
110        self.ws.frame_write(sock, self.ws.OP_CONT, message)
111
112        frame = self.ws.frame_read(sock)
113
114        assert message + ' ' + message == frame['data'].decode(
115            'utf-8'
116        ), 'mirror framing'
117
118        sock.close()
119
120    def test_node_websockets_frame_fragmentation_invalid(self):
121        self.load('websockets/mirror')
122
123        message = 'blah'
124
125        _, sock, _ = self.ws.upgrade()
126
127        self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
128
129        frame = self.ws.frame_read(sock)
130
131        frame.pop('data')
132        assert frame == {
133            'fin': True,
134            'rsv1': False,
135            'rsv2': False,
136            'rsv3': False,
137            'opcode': self.ws.OP_CLOSE,
138            'mask': 0,
139            'code': 1002,
140            'reason': 'Fragmented control frame',
141        }, 'close frame'
142
143        sock.close()
144
145    def test_node_websockets_large(self):
146        self.load('websockets/mirror_fragmentation')
147
148        message = '0123456789' * 3000
149
150        _, sock, _ = self.ws.upgrade()
151
152        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
153
154        frame = self.ws.frame_read(sock)
155        data = frame['data'].decode('utf-8')
156
157        frame = self.ws.frame_read(sock)
158        data += frame['data'].decode('utf-8')
159
160        assert message == data, 'large'
161
162        sock.close()
163
164    def test_node_websockets_two_clients(self):
165        self.load('websockets/mirror')
166
167        message1 = 'blah1'
168        message2 = 'blah2'
169
170        _, sock1, _ = self.ws.upgrade()
171        _, sock2, _ = self.ws.upgrade()
172
173        self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
174        self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
175
176        frame1 = self.ws.frame_read(sock1)
177        frame2 = self.ws.frame_read(sock2)
178
179        assert message1 == frame1['data'].decode('utf-8'), 'client 1'
180        assert message2 == frame2['data'].decode('utf-8'), 'client 2'
181
182        sock1.close()
183        sock2.close()
184
185    @pytest.mark.skip('not yet')
186    def test_node_websockets_handshake_upgrade_absent(
187        self
188    ):  # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
189        self.load('websockets/mirror')
190
191        resp = self.get(
192            headers={
193                'Host': 'localhost',
194                'Connection': 'Upgrade',
195                'Sec-WebSocket-Key': self.ws.key(),
196                'Sec-WebSocket-Protocol': 'chat',
197                'Sec-WebSocket-Version': 13,
198            },
199        )
200
201        assert resp['status'] == 400, 'upgrade absent'
202
203    def test_node_websockets_handshake_case_insensitive(self):
204        self.load('websockets/mirror')
205
206        resp, sock, _ = self.ws.upgrade(
207            headers={
208                'Host': 'localhost',
209                'Upgrade': 'WEBSOCKET',
210                'Connection': 'UPGRADE',
211                'Sec-WebSocket-Key': self.ws.key(),
212                'Sec-WebSocket-Protocol': 'chat',
213                'Sec-WebSocket-Version': 13,
214            }
215        )
216        sock.close()
217
218        assert resp['status'] == 101, 'status'
219
220    @pytest.mark.skip('not yet')
221    def test_node_websockets_handshake_connection_absent(self):  # FAIL
222        self.load('websockets/mirror')
223
224        resp = self.get(
225            headers={
226                'Host': 'localhost',
227                'Upgrade': 'websocket',
228                'Sec-WebSocket-Key': self.ws.key(),
229                'Sec-WebSocket-Protocol': 'chat',
230                'Sec-WebSocket-Version': 13,
231            },
232        )
233
234        assert resp['status'] == 400, 'status'
235
236    def test_node_websockets_handshake_version_absent(self):
237        self.load('websockets/mirror')
238
239        resp = self.get(
240            headers={
241                'Host': 'localhost',
242                'Upgrade': 'websocket',
243                'Connection': 'Upgrade',
244                'Sec-WebSocket-Key': self.ws.key(),
245                'Sec-WebSocket-Protocol': 'chat',
246            },
247        )
248
249        assert resp['status'] == 426, 'status'
250
251    @pytest.mark.skip('not yet')
252    def test_node_websockets_handshake_key_invalid(self):
253        self.load('websockets/mirror')
254
255        resp = self.get(
256            headers={
257                'Host': 'localhost',
258                'Upgrade': 'websocket',
259                'Connection': 'Upgrade',
260                'Sec-WebSocket-Key': '!',
261                'Sec-WebSocket-Protocol': 'chat',
262                'Sec-WebSocket-Version': 13,
263            },
264        )
265
266        assert resp['status'] == 400, 'key length'
267
268        key = self.ws.key()
269        resp = self.get(
270            headers={
271                'Host': 'localhost',
272                'Upgrade': 'websocket',
273                'Connection': 'Upgrade',
274                'Sec-WebSocket-Key': [key, key],
275                'Sec-WebSocket-Protocol': 'chat',
276                'Sec-WebSocket-Version': 13,
277            },
278        )
279
280        assert resp['status'] == 400, '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        self.check_close(sock, 1002)
888
889        # 5_16
890
891        _, sock, _ = self.ws.upgrade()
892
893        for i in range(0, 2):
894            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
895            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
896            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
897        self.check_close(sock, 1002)
898
899        # 5_17
900
901        _, sock, _ = self.ws.upgrade()
902
903        for i in range(0, 2):
904            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
905            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
906            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
907        self.check_close(sock, 1002)
908
909        # 5_18
910
911        _, sock, _ = self.ws.upgrade()
912
913        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
914        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
915        self.check_close(sock, 1002)
916
917        # 5_19
918
919        _, sock, _ = self.ws.upgrade()
920
921        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
922        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
923        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
924
925        time.sleep(1)
926
927        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
928        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
929        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
930        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
931
932        frame = self.ws.frame_read(sock)
933        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
934
935        frame = self.ws.frame_read(sock)
936        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
937
938        self.check_frame(
939            self.ws.frame_read(sock),
940            True,
941            self.ws.OP_TEXT,
942            'fragment1fragment2fragment3fragment4fragment5',
943        )
944
945        # 5_20
946
947        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
948        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
949        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
950
951        frame = self.ws.frame_read(sock)
952        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
953
954        time.sleep(1)
955
956        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
957        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
958        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
959
960        frame = self.ws.frame_read(sock)
961        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
962
963        assert self.recvall(sock, read_timeout=0.1) == b'', '5_20'
964        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
965
966        self.check_frame(
967            self.ws.frame_read(sock),
968            True,
969            self.ws.OP_TEXT,
970            'fragment1fragment2fragment3fragment4fragment5',
971        )
972
973        self.close_connection(sock)
974
975    def test_node_websockets_6_1_1__6_4_4(self):
976        self.load('websockets/mirror')
977
978        # 6_1_1
979
980        _, sock, _ = self.ws.upgrade()
981
982        self.ws.frame_write(sock, self.ws.OP_TEXT, '')
983        frame = self.ws.frame_read(sock)
984        self.check_frame(frame, True, self.ws.OP_TEXT, '')
985
986        # 6_1_2
987
988        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
989        self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False)
990        self.ws.frame_write(sock, self.ws.OP_CONT, '')
991
992        frame = self.ws.frame_read(sock)
993        self.check_frame(frame, True, self.ws.OP_TEXT, '')
994
995        # 6_1_3
996
997        payload = 'middle frame payload'
998
999        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1000        self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False)
1001        self.ws.frame_write(sock, self.ws.OP_CONT, '')
1002
1003        frame = self.ws.frame_read(sock)
1004        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1005
1006        # 6_2_1
1007
1008        payload = 'Hello-µ@ßöäüàá-UTF-8!!'
1009
1010        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1011
1012        frame = self.ws.frame_read(sock)
1013        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1014
1015        # 6_2_2
1016
1017        self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False)
1018        self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:])
1019
1020        frame = self.ws.frame_read(sock)
1021        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1022
1023        # 6_2_3
1024
1025        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1026
1027        frame = self.ws.frame_read(sock)
1028        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1029
1030        # 6_2_4
1031
1032        payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
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        self.close_connection(sock)
1040
1041#        Unit does not support UTF-8 validation
1042#
1043#        # 6_3_1 FAIL
1044#
1045#        payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1046#        payload_2 = '\xed\xa0\x80'
1047#        payload_3 = '\x65\x64\x69\x74\x65\x64'
1048#
1049#        payload = payload_1 + payload_2 + payload_3
1050#
1051#        self.ws.message(sock, self.ws.OP_TEXT, payload)
1052#        self.check_close(sock, 1007)
1053#
1054#        # 6_3_2 FAIL
1055#
1056#        _, sock, _ = self.ws.upgrade()
1057#
1058#        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1059#        self.check_close(sock, 1007)
1060#
1061#        # 6_4_1 ... 6_4_4 FAIL
1062
1063    def test_node_websockets_7_1_1__7_5_1(self):
1064        self.load('websockets/mirror')
1065
1066        # 7_1_1
1067
1068        _, sock, _ = self.ws.upgrade()
1069
1070        payload = "Hello World!"
1071
1072        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1073
1074        frame = self.ws.frame_read(sock)
1075        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1076
1077        self.close_connection(sock)
1078
1079        # 7_1_2
1080
1081        _, sock, _ = self.ws.upgrade()
1082
1083        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1084        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1085
1086        self.check_close(sock)
1087
1088        # 7_1_3
1089
1090        _, sock, _ = self.ws.upgrade()
1091
1092        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1093        self.check_close(sock, no_close=True)
1094
1095        self.ws.frame_write(sock, self.ws.OP_PING, '')
1096        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1097
1098        sock.close()
1099
1100        # 7_1_4
1101
1102        _, sock, _ = self.ws.upgrade()
1103
1104        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1105        self.check_close(sock, no_close=True)
1106
1107        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1108        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1109
1110        sock.close()
1111
1112        # 7_1_5
1113
1114        _, sock, _ = self.ws.upgrade()
1115
1116        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1117        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1118        self.check_close(sock, no_close=True)
1119
1120        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2')
1121        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1122
1123        sock.close()
1124
1125        # 7_1_6
1126
1127        _, sock, _ = self.ws.upgrade()
1128
1129        self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10)
1130        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1131        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1132
1133        self.recvall(sock, read_timeout=1)
1134
1135        self.ws.frame_write(sock, self.ws.OP_PING, '')
1136        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1137
1138        sock.close()
1139
1140        # 7_3_1
1141
1142        _, sock, _ = self.ws.upgrade()
1143
1144        self.ws.frame_write(sock, self.ws.OP_CLOSE, '')
1145        self.check_close(sock)
1146
1147        # 7_3_2
1148
1149        _, sock, _ = self.ws.upgrade()
1150
1151        self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a')
1152        self.check_close(sock, 1002)
1153
1154        # 7_3_3
1155
1156        _, sock, _ = self.ws.upgrade()
1157
1158        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1159        self.check_close(sock)
1160
1161        # 7_3_4
1162
1163        _, sock, _ = self.ws.upgrade()
1164
1165        payload = self.ws.serialize_close(reason='Hello World!')
1166
1167        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1168        self.check_close(sock)
1169
1170        # 7_3_5
1171
1172        _, sock, _ = self.ws.upgrade()
1173
1174        payload = self.ws.serialize_close(reason='*' * 123)
1175
1176        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1177        self.check_close(sock)
1178
1179        # 7_3_6
1180
1181        _, sock, _ = self.ws.upgrade()
1182
1183        payload = self.ws.serialize_close(reason='*' * 124)
1184
1185        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1186        self.check_close(sock, 1002)
1187
1188#        # 7_5_1 FAIL Unit does not support UTF-8 validation
1189#
1190#        _, sock, _ = self.ws.upgrade()
1191#
1192#        payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \
1193#            '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64')
1194#
1195#        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1196#        self.check_close(sock, 1007)
1197
1198    def test_node_websockets_7_7_X__7_9_X(self):
1199        self.load('websockets/mirror')
1200
1201        valid_codes = [
1202            1000,
1203            1001,
1204            1002,
1205            1003,
1206            1007,
1207            1008,
1208            1009,
1209            1010,
1210            1011,
1211            3000,
1212            3999,
1213            4000,
1214            4999,
1215        ]
1216
1217        invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999]
1218
1219        for code in valid_codes:
1220            _, sock, _ = self.ws.upgrade()
1221
1222            payload = self.ws.serialize_close(code=code)
1223
1224            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1225            self.check_close(sock)
1226
1227        for code in invalid_codes:
1228            _, sock, _ = self.ws.upgrade()
1229
1230            payload = self.ws.serialize_close(code=code)
1231
1232            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1233            self.check_close(sock, 1002)
1234
1235    def test_node_websockets_7_13_1__7_13_2(self):
1236        self.load('websockets/mirror')
1237
1238        # 7_13_1
1239
1240        _, sock, _ = self.ws.upgrade()
1241
1242        payload = self.ws.serialize_close(code=5000)
1243
1244        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1245        self.check_close(sock, 1002)
1246
1247        # 7_13_2
1248
1249        _, sock, _ = self.ws.upgrade()
1250
1251        payload = struct.pack('!I', 65536) + ''.encode('utf-8')
1252
1253        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1254        self.check_close(sock, 1002)
1255
1256    def test_node_websockets_9_1_1__9_6_6(self, is_unsafe):
1257        if not is_unsafe:
1258            pytest.skip('unsafe, long run')
1259
1260        self.load('websockets/mirror')
1261
1262        assert 'success' in self.conf(
1263            {
1264                'http': {
1265                    'websocket': {
1266                        'max_frame_size': 33554432,
1267                        'keepalive_interval': 0,
1268                    }
1269                }
1270            },
1271            'settings',
1272        ), 'increase max_frame_size and keepalive_interval'
1273
1274        _, sock, _ = self.ws.upgrade()
1275
1276        op_text = self.ws.OP_TEXT
1277        op_binary = self.ws.OP_BINARY
1278
1279        def check_payload(opcode, length, chopsize=None):
1280            if opcode == self.ws.OP_TEXT:
1281                payload = '*' * length
1282            else:
1283                payload = b'*' * length
1284
1285            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
1286            frame = self.ws.frame_read(sock, read_timeout=5)
1287            self.check_frame(frame, True, opcode, payload)
1288
1289        def check_message(opcode, f_size):
1290            if opcode == self.ws.OP_TEXT:
1291                payload = '*' * 4 * 2 ** 20
1292            else:
1293                payload = b'*' * 4 * 2 ** 20
1294
1295            self.ws.message(sock, opcode, payload, fragmention_size=f_size)
1296            frame = self.ws.frame_read(sock, read_timeout=5)
1297            self.check_frame(frame, True, opcode, payload)
1298
1299        check_payload(op_text, 64 * 2 ** 10)              # 9_1_1
1300        check_payload(op_text, 256 * 2 ** 10)             # 9_1_2
1301        check_payload(op_text, 2 ** 20)                   # 9_1_3
1302        check_payload(op_text, 4 * 2 ** 20)               # 9_1_4
1303        check_payload(op_text, 8 * 2 ** 20)               # 9_1_5
1304        check_payload(op_text, 16 * 2 ** 20)              # 9_1_6
1305
1306        check_payload(op_binary, 64 * 2 ** 10)            # 9_2_1
1307        check_payload(op_binary, 256 * 2 ** 10)           # 9_2_2
1308        check_payload(op_binary, 2 ** 20)                 # 9_2_3
1309        check_payload(op_binary, 4 * 2 ** 20)             # 9_2_4
1310        check_payload(op_binary, 8 * 2 ** 20)             # 9_2_5
1311        check_payload(op_binary, 16 * 2 ** 20)            # 9_2_6
1312
1313        if option.system != 'Darwin' and option.system != 'FreeBSD':
1314            check_message(op_text, 64)                    # 9_3_1
1315            check_message(op_text, 256)                   # 9_3_2
1316            check_message(op_text, 2 ** 10)               # 9_3_3
1317            check_message(op_text, 4 * 2 ** 10)           # 9_3_4
1318            check_message(op_text, 16 * 2 ** 10)          # 9_3_5
1319            check_message(op_text, 64 * 2 ** 10)          # 9_3_6
1320            check_message(op_text, 256 * 2 ** 10)         # 9_3_7
1321            check_message(op_text, 2 ** 20)               # 9_3_8
1322            check_message(op_text, 4 * 2 ** 20)           # 9_3_9
1323
1324            check_message(op_binary, 64)                  # 9_4_1
1325            check_message(op_binary, 256)                 # 9_4_2
1326            check_message(op_binary, 2 ** 10)             # 9_4_3
1327            check_message(op_binary, 4 * 2 ** 10)         # 9_4_4
1328            check_message(op_binary, 16 * 2 ** 10)        # 9_4_5
1329            check_message(op_binary, 64 * 2 ** 10)        # 9_4_6
1330            check_message(op_binary, 256 * 2 ** 10)       # 9_4_7
1331            check_message(op_binary, 2 ** 20)             # 9_4_8
1332            check_message(op_binary, 4 * 2 ** 20)         # 9_4_9
1333
1334        check_payload(op_text, 2 ** 20, chopsize=64)      # 9_5_1
1335        check_payload(op_text, 2 ** 20, chopsize=128)     # 9_5_2
1336        check_payload(op_text, 2 ** 20, chopsize=256)     # 9_5_3
1337        check_payload(op_text, 2 ** 20, chopsize=512)     # 9_5_4
1338        check_payload(op_text, 2 ** 20, chopsize=1024)    # 9_5_5
1339        check_payload(op_text, 2 ** 20, chopsize=2048)    # 9_5_6
1340
1341        check_payload(op_binary, 2 ** 20, chopsize=64)    # 9_6_1
1342        check_payload(op_binary, 2 ** 20, chopsize=128)   # 9_6_2
1343        check_payload(op_binary, 2 ** 20, chopsize=256)   # 9_6_3
1344        check_payload(op_binary, 2 ** 20, chopsize=512)   # 9_6_4
1345        check_payload(op_binary, 2 ** 20, chopsize=1024)  # 9_6_5
1346        check_payload(op_binary, 2 ** 20, chopsize=2048)  # 9_6_6
1347
1348        self.close_connection(sock)
1349
1350    def test_node_websockets_10_1_1(self):
1351        self.load('websockets/mirror')
1352
1353        _, sock, _ = self.ws.upgrade()
1354
1355        payload = '*' * 65536
1356
1357        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300)
1358
1359        frame = self.ws.frame_read(sock)
1360        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1361
1362        self.close_connection(sock)
1363
1364    # settings
1365
1366    def test_node_websockets_max_frame_size(self):
1367        self.load('websockets/mirror')
1368
1369        assert 'success' in self.conf(
1370            {'http': {'websocket': {'max_frame_size': 100}}}, 'settings'
1371        ), 'configure max_frame_size'
1372
1373        _, sock, _ = self.ws.upgrade()
1374
1375        payload = '*' * 94
1376        opcode = self.ws.OP_TEXT
1377
1378        self.ws.frame_write(sock, opcode, payload)  # frame length is 100
1379
1380        frame = self.ws.frame_read(sock)
1381        self.check_frame(frame, True, opcode, payload)
1382
1383        payload = '*' * 95
1384
1385        self.ws.frame_write(sock, opcode, payload)  # frame length is 101
1386        self.check_close(sock, 1009)  # 1009 - CLOSE_TOO_LARGE
1387
1388    def test_node_websockets_read_timeout(self):
1389        self.load('websockets/mirror')
1390
1391        assert 'success' in self.conf(
1392            {'http': {'websocket': {'read_timeout': 5}}}, 'settings'
1393        ), 'configure read_timeout'
1394
1395        _, sock, _ = self.ws.upgrade()
1396
1397        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1398        sock.sendall(frame[:2])
1399
1400        time.sleep(2)
1401
1402        self.check_close(sock, 1001)  # 1001 - CLOSE_GOING_AWAY
1403
1404    def test_node_websockets_keepalive_interval(self):
1405        self.load('websockets/mirror')
1406
1407        assert 'success' in self.conf(
1408            {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings'
1409        ), 'configure keepalive_interval'
1410
1411        _, sock, _ = self.ws.upgrade()
1412
1413        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1414        sock.sendall(frame[:2])
1415
1416        time.sleep(2)
1417
1418        frame = self.ws.frame_read(sock)
1419        self.check_frame(frame, True, self.ws.OP_PING, '')  # PING frame
1420
1421        sock.close()
1422