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