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