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