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