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