12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#!/usr/bin/env python 22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Copyright 2012, Google Inc. 42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# All rights reserved. 52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Redistribution and use in source and binary forms, with or without 72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# modification, are permitted provided that the following conditions are 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# met: 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Redistributions of source code must retain the above copyright 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# notice, this list of conditions and the following disclaimer. 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Redistributions in binary form must reproduce the above 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# copyright notice, this list of conditions and the following disclaimer 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# in the documentation and/or other materials provided with the 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# distribution. 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# * Neither the name of Google Inc. nor the names of its 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# contributors may be used to endorse or promote products derived from 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# this software without specific prior written permission. 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""Tests for msgutil module.""" 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport array 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport Queue 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport struct 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport unittest 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport zlib 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport set_sys_path # Update sys.path to locate mod_pywebsocket module. 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket import common 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.extensions import DeflateFrameExtensionProcessor 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.extensions import PerFrameCompressionExtensionProcessor 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.extensions import PerMessageCompressionExtensionProcessor 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket import msgutil 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.stream import InvalidUTF8Exception 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.stream import Stream 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.stream import StreamHixie75 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.stream import StreamOptions 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket import util 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom test import mock 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# We use one fixed nonce for testing instead of cryptographically secure PRNG. 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_MASKING_NONCE = 'ABCD' 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _mask_hybi(frame): 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis frame_key = map(ord, _MASKING_NONCE) 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis frame_key_len = len(frame_key) 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result = array.array('B') 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result.fromstring(frame) 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis count = 0 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for i in xrange(len(result)): 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis result[i] ^= frame_key[count] 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis count = (count + 1) % frame_key_len 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return _MASKING_NONCE + result.tostring() 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _install_extension_processor(processor, request, stream_options): 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis response = processor.get_extension_response() 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if response is not None: 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor.setup_stream_options(stream_options) 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.ws_extension_processors.append(processor) 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _create_request_from_rawdata( 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis read_data, deflate_stream=False, deflate_frame_request=None, 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis perframe_compression_request=None, permessage_compression_request=None): 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req = mock.MockRequest(connection=mock.MockConn(''.join(read_data))) 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_version = common.VERSION_HYBI_LATEST 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis stream_options = StreamOptions() 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis stream_options.deflate_stream = deflate_stream 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_extension_processors = [] 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if deflate_frame_request is not None: 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(deflate_frame_request) 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis _install_extension_processor(processor, req, stream_options) 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elif perframe_compression_request is not None: 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = PerFrameCompressionExtensionProcessor( 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis perframe_compression_request) 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis _install_extension_processor(processor, req, stream_options) 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elif permessage_compression_request is not None: 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = PerMessageCompressionExtensionProcessor( 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis permessage_compression_request) 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis _install_extension_processor(processor, req, stream_options) 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_stream = Stream(req, stream_options) 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return req 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _create_request(*frames): 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Creates MockRequest using data given as frames. 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis frames will be returned on calling request.connection.read() where request 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis is MockRequest returned by this function. 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis read_data = [] 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (header, body) in frames: 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis read_data.append(header + _mask_hybi(body)) 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return _create_request_from_rawdata(read_data) 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _create_blocking_request(): 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Creates MockRequest. 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Data written to a MockRequest can be read out by calling 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data(). 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req = mock.MockRequest(connection=mock.MockBlockingConn()) 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_version = common.VERSION_HYBI_LATEST 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis stream_options = StreamOptions() 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_stream = Stream(req, stream_options) 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return req 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _create_request_hixie75(read_data=''): 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req = mock.MockRequest(connection=mock.MockConn(read_data)) 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_stream = StreamHixie75(req) 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return req 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _create_blocking_request_hixie75(): 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req = mock.MockRequest(connection=mock.MockBlockingConn()) 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis req.ws_stream = StreamHixie75(req) 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return req 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageTest(unittest.TestCase): 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Tests for Stream 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message(self): 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x05Hello', request.connection.written_data()) 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * 125 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, payload) 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x7d' + payload, 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_medium_message(self): 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * 126 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, payload) 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x7e\x00\x7e' + payload, 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * ((1 << 16) - 1) 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, payload) 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x7e\xff\xff' + payload, 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_large_message(self): 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * (1 << 16) 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, payload) 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x7f\x00\x00\x00\x00\x00\x01\x00\x00' + payload, 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_unicode(self): 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, u'\u65e5') 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # U+65e5 is encoded as e6,97,a5 in UTF-8 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x03\xe6\x97\xa5', 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_fragments(self): 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello', False) 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, ' ', False) 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'World', False) 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, '!', True) 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x01\x05Hello\x00\x01 \x00\x05World\x80\x01!', 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_fragments_immediate_zero_termination(self): 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello World!', False) 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, '', True) 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x01\x0cHello World!\x80\x00', 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_deflate_stream(self): 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata('', deflate_stream=True) 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = compress.compress('\x81\x05Hello') 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compress.flush(zlib.Z_SYNC_FLUSH) 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(expected, request.connection.written_data()) 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_deflate_frame(self): 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '', deflate_frame_request=extension) 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'World') 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = '' 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_hello) 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_hello 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_world) 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_world 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(expected, request.connection.written_data()) 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_deflate_frame_comp_bit(self): 2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '', deflate_frame_request=extension) 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEquals(1, len(request.ws_extension_processors)) 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis deflate_frame_processor = request.ws_extension_processors[0] 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis deflate_frame_processor.disable_outgoing_compression() 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis deflate_frame_processor.enable_outgoing_compression() 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = '' 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_hello) 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_hello 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\x81\x05Hello' 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello = compress.compress('Hello') 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello += compress.flush(zlib.Z_SYNC_FLUSH) 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello = compressed_2nd_hello[:-4] 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_2nd_hello) 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_2nd_hello 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(expected, request.connection.written_data()) 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_deflate_frame_no_context_takeover_parameter(self): 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('no_context_takeover', None) 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '', deflate_frame_request=extension) 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for i in xrange(3): 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_message = compress.compress('Hello') 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_message += compress.flush(zlib.Z_SYNC_FLUSH) 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_message = compressed_message[:-4] 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = '\xc1%c' % len(compressed_message) 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_message 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual( 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected + expected + expected, request.connection.written_data()) 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_deflate_frame_bad_request_parameters(self): 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests that if there's anything wrong with deflate-frame extension 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request, deflate-frame is rejected. 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # max_window_bits less than 8 is illegal. 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('max_window_bits', '7') 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, processor.get_extension_response()) 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # max_window_bits greater than 15 is illegal. 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('max_window_bits', '16') 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, processor.get_extension_response()) 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Non integer max_window_bits is illegal. 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('max_window_bits', 'foobar') 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, processor.get_extension_response()) 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # no_context_takeover must not have any value. 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('no_context_takeover', 'foobar') 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, processor.get_extension_response()) 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_deflate_frame_response_parameters(self): 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor.set_response_window_bits(8) 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis response = processor.get_extension_response() 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue(response.has_parameter('max_window_bits')) 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('8', response.get_parameter_value('max_window_bits')) 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor = DeflateFrameExtensionProcessor(extension) 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis processor.set_response_no_context_takeover(True) 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis response = processor.get_extension_response() 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue(response.has_parameter('no_context_takeover')) 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue( 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis response.get_parameter_value('no_context_takeover') is None) 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_perframe_compress_deflate(self): 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter( 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis common.PERFRAME_COMPRESSION_EXTENSION) 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('method', 'deflate') 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '', perframe_compression_request=extension) 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'World') 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = '' 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_hello) 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_hello 3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_world) 3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_world 3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(expected, request.connection.written_data()) 3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_permessage_compress_deflate(self): 3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter( 3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis common.PERMESSAGE_COMPRESSION_EXTENSION) 3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('method', 'deflate') 3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '', permessage_compression_request=extension) 3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'World') 3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected = '' 3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_hello) 3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_hello 3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += '\xc1%c' % len(compressed_world) 3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis expected += compressed_world 3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(expected, request.connection.written_data()) 3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message(self): 3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x81\x85', 'Hello'), ('\x81\x86', 'World!')) 3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World!', msgutil.receive_message(request)) 3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * 125 3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x81\xfd', payload)) 3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_medium_message(self): 4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * 126 4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x81\xfe\x00\x7e', payload)) 4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * ((1 << 16) - 1) 4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x81\xfe\xff\xff', payload)) 4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_large_message(self): 4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' * (1 << 16) 4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x81\xff\x00\x00\x00\x00\x00\x01\x00\x00', payload)) 4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_length_not_encoded_using_minimal_number_of_bytes(self): 4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Log warning on receiving bad payload length field that doesn't use 4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # minimal number of bytes but continue processing. 4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'a' 4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # 1 byte can be represented without extended payload length field. 4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x81\xff\x00\x00\x00\x00\x00\x00\x00\x01', payload)) 4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_unicode(self): 4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x81\x83', '\xe6\x9c\xac')) 4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # U+672c is encoded as e6,9c,ac in UTF-8 4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(u'\u672c', msgutil.receive_message(request)) 4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_erroneous_unicode(self): 4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # \x80 and \x81 are invalid as UTF-8. 4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x81\x82', '\x80\x81')) 4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Invalid characters should raise InvalidUTF8Exception 4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(InvalidUTF8Exception, 4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments(self): 4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x01\x85', 'Hello'), 4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x00\x81', ' '), 4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x00\x85', 'World'), 4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x80\x81', '!')) 4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello World!', msgutil.receive_message(request)) 4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments_unicode(self): 4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # UTF-8 encodes U+6f22 into e6bca2 and U+5b57 into e5ad97. 4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x01\x82', '\xe6\xbc'), 4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x00\x82', '\xa2\xe5'), 4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x80\x82', '\xad\x97')) 4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(u'\u6f22\u5b57', msgutil.receive_message(request)) 4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments_immediate_zero_termination(self): 4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x01\x8c', 'Hello World!'), ('\x80\x80', '')) 4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello World!', msgutil.receive_message(request)) 4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments_duplicate_start(self): 4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x01\x85', 'Hello'), ('\x01\x85', 'World')) 4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments_intermediate_but_not_started(self): 4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x00\x85', 'Hello')) 4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_fragments_end_but_not_started(self): 4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x80\x85', 'Hello')) 4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_discard(self): 4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x8f\x86', 'IGNORE'), ('\x81\x85', 'Hello'), 4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x8f\x89', 'DISREGARD'), ('\x81\x86', 'World!')) 4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.UnsupportedFrameException, 4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, request) 4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.UnsupportedFrameException, 4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, request) 4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World!', msgutil.receive_message(request)) 4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_close(self): 4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x88\x8a', struct.pack('!H', 1000) + 'Good bye')) 4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(1000, request.ws_close_code) 4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Good bye', request.ws_close_reason) 4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_deflate_stream(self): 4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 4972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 4982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = compress.compress('\x81\x85' + _mask_hybi('Hello')) 5002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.flush(zlib.Z_SYNC_FLUSH) 5012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.compress('\x81\x89' + _mask_hybi('WebSocket')) 5022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.flush(zlib.Z_FINISH) 5032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 5052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 5062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.compress('\x81\x85' + _mask_hybi('World')) 5082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.flush(zlib.Z_SYNC_FLUSH) 5092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Close frame 5102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.compress( 5112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')) 5122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += compress.flush(zlib.Z_SYNC_FLUSH) 5132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata(data, deflate_stream=True) 5152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 5162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('WebSocket', msgutil.receive_message(request)) 5172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 5182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertFalse(request.drain_received_data_called) 5202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 5222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue(request.drain_received_data_called) 5242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_deflate_frame(self): 5262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 5272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 5282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 5302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 5322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 5332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 5342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_hello) | 0x80) 5352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello) 5362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket = compress.compress('WebSocket') 5382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket += compress.flush(zlib.Z_FINISH) 5392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket += '\x00' 5402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_websocket) | 0x80) 5412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_websocket) 5422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 5442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 5452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 5472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 5482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 5492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_world) | 0x80) 5502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_world) 5512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Close frame 5532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye') 5542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 5562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 5572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data, deflate_frame_request=extension) 5582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 5592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('WebSocket', msgutil.receive_message(request)) 5602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 5612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 5632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_deflate_frame_client_using_smaller_window(self): 5652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Test that frames coming from a client which is using smaller window 5662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis size that the server are correctly received. 5672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """ 5682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Using the smallest window bits of 8 for generating input frames. 5702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 5712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -8) 5722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 5742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Use a frame whose content is bigger than the clients' DEFLATE window 5762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # size before compression. The content mainly consists of 'a' but 5772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # repetition of 'b' is put at the head and tail so that if the window 5782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # size is big, the head is back-referenced but if small, not. 5792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis payload = 'b' * 64 + 'a' * 1024 + 'b' * 64 5802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress(payload) 5812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 5822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 5832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_hello) | 0x80) 5842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello) 5852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Close frame 5872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye') 5882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 5902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 5912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data, deflate_frame_request=extension) 5922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(payload, msgutil.receive_message(request)) 5932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 5952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_deflate_frame_comp_bit(self): 5972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 5982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 5992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 6012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 6032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 6042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 6052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_hello) | 0x80) 6062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello) 6072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x81\x85' + _mask_hybi('Hello') 6092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 6112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 6122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello = compress.compress('Hello') 6142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello += compress.flush(zlib.Z_SYNC_FLUSH) 6152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_2nd_hello = compressed_2nd_hello[:-4] 6162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_2nd_hello) | 0x80) 6172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_2nd_hello) 6182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION) 6202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 6212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data, deflate_frame_request=extension) 6222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for i in xrange(3): 6232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 6242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_perframe_compression_frame(self): 6262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 6272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 6282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 6302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('Hello') 6322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 6332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 6342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_hello) | 0x80) 6352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello) 6362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket = compress.compress('WebSocket') 6382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket += compress.flush(zlib.Z_FINISH) 6392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_websocket += '\x00' 6402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_websocket) | 0x80) 6412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_websocket) 6422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 6442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 6452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 6472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 6482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 6492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_world) | 0x80) 6502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_world) 6512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Close frame 6532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye') 6542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter( 6562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis common.PERFRAME_COMPRESSION_EXTENSION) 6572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('method', 'deflate') 6582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 6592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data, perframe_compression_request=extension) 6602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 6612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('WebSocket', msgutil.receive_message(request)) 6622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 6632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 6652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_permessage_deflate_compression(self): 6672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 6682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 6692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data = '' 6712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compress.compress('HelloWebSocket') 6732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH) 6742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_hello = compressed_hello[:-4] 6752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis split_position = len(compressed_hello) / 2 6762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x41%c' % (split_position | 0x80) 6772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello[:split_position]) 6782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x80%c' % ((len(compressed_hello) - split_position) | 0x80) 6802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_hello[split_position:]) 6812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compress = zlib.compressobj( 6832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS) 6842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compress.compress('World') 6862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world += compress.flush(zlib.Z_SYNC_FLUSH) 6872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis compressed_world = compressed_world[:-4] 6882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\xc1%c' % (len(compressed_world) | 0x80) 6892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += _mask_hybi(compressed_world) 6902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Close frame 6922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye') 6932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension = common.ExtensionParameter( 6952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis common.PERMESSAGE_COMPRESSION_EXTENSION) 6962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis extension.add_parameter('method', 'deflate') 6972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_from_rawdata( 6982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis data, permessage_compression_request=extension) 6992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('HelloWebSocket', msgutil.receive_message(request)) 7002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 7012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, msgutil.receive_message(request)) 7032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_longest_close(self): 7052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis reason = 'a' * 123 7062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 7072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x88\xfd', 7082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis struct.pack('!H', common.STATUS_NORMAL_CLOSURE) + reason)) 7092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.ws_stream.close_connection(common.STATUS_NORMAL_CLOSURE, 7102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis reason) 7112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(request.ws_close_code, common.STATUS_NORMAL_CLOSURE) 7122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(request.ws_close_reason, reason) 7132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_close_too_long(self): 7152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 7162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.BadOperationException, 7172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Stream.close_connection, 7182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.ws_stream, 7192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis common.STATUS_NORMAL_CLOSURE, 7202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'a' * 124) 7212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_close_inconsistent_code_and_reason(self): 7232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 7242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # reason parameter must not be specified when code is None. 7252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.BadOperationException, 7262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Stream.close_connection, 7272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.ws_stream, 7282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis None, 7292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'a') 7302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_ping(self): 7322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 7332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_ping(request, 'Hello World!') 7342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x89\x0cHello World!', 7352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 7362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_longest_ping(self): 7382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 7392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_ping(request, 'a' * 125) 7402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x89\x7d' + 'a' * 125, 7412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 7422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_ping_too_long(self): 7442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request() 7452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.BadOperationException, 7462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_ping, 7472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request, 7482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'a' * 126) 7492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_ping(self): 7512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests receiving a ping control frame.""" 7522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def handler(request, message): 7542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.called = True 7552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Stream automatically respond to ping with pong without any action 7572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # by application layer. 7582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 7592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x89\x85', 'Hello'), ('\x81\x85', 'World')) 7602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 7612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x8a\x05Hello', 7622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 7632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 7652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x89\x85', 'Hello'), ('\x81\x85', 'World')) 7662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.on_ping_handler = handler 7672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 7682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue(request.called) 7692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_longest_ping(self): 7712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 7722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x89\xfd', 'a' * 125), ('\x81\x85', 'World')) 7732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 7742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x8a\x7d' + 'a' * 125, 7752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 7762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_ping_too_long(self): 7782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x89\xfe\x00\x7e', 'a' * 126)) 7792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 7802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 7812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 7822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_pong(self): 7842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests receiving a pong control frame.""" 7852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def handler(request, message): 7872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.called = True 7882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 7892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 7902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x8a\x85', 'Hello'), ('\x81\x85', 'World')) 7912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.on_pong_handler = handler 7922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_ping(request, 'Hello') 7932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x89\x05Hello', 7942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 7952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Valid pong is received, but receive_message won't return for it. 7962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World', msgutil.receive_message(request)) 7972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Check that nothing was written after receive_message call. 7982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x89\x05Hello', 7992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 8002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertTrue(request.called) 8022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_unsolicited_pong(self): 8042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Unsolicited pong is allowed from HyBi 07. 8052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 8062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x8a\x85', 'Hello'), ('\x81\x85', 'World')) 8072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message(request) 8082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request( 8102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ('\x8a\x85', 'Hello'), ('\x81\x85', 'World')) 8112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_ping(request, 'Jumbo') 8122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Body mismatch. 8132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message(request) 8142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_ping_cannot_be_fragmented(self): 8162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x09\x85', 'Hello')) 8172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 8182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 8192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 8202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_ping_with_too_long_payload(self): 8222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request(('\x89\xfe\x01\x00', 'a' * 256)) 8232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertRaises(msgutil.InvalidFrameException, 8242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.receive_message, 8252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request) 8262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8282da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageTestHixie75(unittest.TestCase): 8292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests for draft-hixie-thewebsocketprotocol-76 stream class.""" 8302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message(self): 8322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75() 8332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, 'Hello') 8342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x00Hello\xff', request.connection.written_data()) 8352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_message_unicode(self): 8372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75() 8382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis msgutil.send_message(request, u'\u65e5') 8392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # U+65e5 is encoded as e6,97,a5 in UTF-8 8402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x00\xe6\x97\xa5\xff', 8412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.written_data()) 8422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message(self): 8442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75('\x00Hello\xff\x00World!\xff') 8452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 8462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World!', msgutil.receive_message(request)) 8472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_unicode(self): 8492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75('\x00\xe6\x9c\xac\xff') 8502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # U+672c is encoded as e6,9c,ac in UTF-8 8512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(u'\u672c', msgutil.receive_message(request)) 8522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_erroneous_unicode(self): 8542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # \x80 and \x81 are invalid as UTF-8. 8552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75('\x00\x80\x81\xff') 8562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Invalid characters should be replaced with 8572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # U+fffd REPLACEMENT CHARACTER 8582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(u'\ufffd\ufffd', msgutil.receive_message(request)) 8592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_receive_message_discard(self): 8612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_request_hixie75('\x80\x06IGNORE\x00Hello\xff' 8622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '\x01DISREGARD\xff\x00World!\xff') 8632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello', msgutil.receive_message(request)) 8642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('World!', msgutil.receive_message(request)) 8652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8672da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageReceiverTest(unittest.TestCase): 8682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests the Stream class using MessageReceiver.""" 8692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_queue(self): 8712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request() 8722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis receiver = msgutil.MessageReceiver(request) 8732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, receiver.receive_nowait()) 8752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.put_bytes('\x81\x86' + _mask_hybi('Hello!')) 8772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello!', receiver.receive()) 8782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_onmessage(self): 8802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onmessage_queue = Queue.Queue() 8812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def onmessage_handler(message): 8832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onmessage_queue.put(message) 8842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request() 8862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis receiver = msgutil.MessageReceiver(request, onmessage_handler) 8872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.put_bytes('\x81\x86' + _mask_hybi('Hello!')) 8892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello!', onmessage_queue.get()) 8902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8922da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageReceiverHixie75Test(unittest.TestCase): 8932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests the StreamHixie75 class using MessageReceiver.""" 8942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_queue(self): 8962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request_hixie75() 8972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis receiver = msgutil.MessageReceiver(request) 8982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 8992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual(None, receiver.receive_nowait()) 9002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.put_bytes('\x00Hello!\xff') 9022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello!', receiver.receive()) 9032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_onmessage(self): 9052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onmessage_queue = Queue.Queue() 9062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def onmessage_handler(message): 9082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onmessage_queue.put(message) 9092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request_hixie75() 9112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis receiver = msgutil.MessageReceiver(request, onmessage_handler) 9122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.put_bytes('\x00Hello!\xff') 9142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('Hello!', onmessage_queue.get()) 9152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9172da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageSenderTest(unittest.TestCase): 9182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests the Stream class using MessageSender.""" 9192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send(self): 9212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request() 9222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender = msgutil.MessageSender(request) 9232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send('World') 9252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x05World', request.connection.written_data()) 9262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_nowait(self): 9282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Use a queue to check the bytes written by MessageSender. 9292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # request.connection.written_data() cannot be used here because 9302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # MessageSender runs in a separate thread. 9312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis send_queue = Queue.Queue() 9322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def write(bytes): 9342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis send_queue.put(bytes) 9352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request() 9372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.write = write 9382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender = msgutil.MessageSender(request) 9402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send_nowait('Hello') 9422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send_nowait('World') 9432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x05Hello', send_queue.get()) 9442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x81\x05World', send_queue.get()) 9452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9472da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MessageSenderHixie75Test(unittest.TestCase): 9482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis """Tests the StreamHixie75 class using MessageSender.""" 9492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send(self): 9512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request_hixie75() 9522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender = msgutil.MessageSender(request) 9532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send('World') 9552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x00World\xff', request.connection.written_data()) 9562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def test_send_nowait(self): 9582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # Use a queue to check the bytes written by MessageSender. 9592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # request.connection.written_data() cannot be used here because 9602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis # MessageSender runs in a separate thread. 9612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis send_queue = Queue.Queue() 9622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis def write(bytes): 9642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis send_queue.put(bytes) 9652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request = _create_blocking_request_hixie75() 9672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis request.connection.write = write 9682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender = msgutil.MessageSender(request) 9702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send_nowait('Hello') 9722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sender.send_nowait('World') 9732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x00Hello\xff', send_queue.get()) 9742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis self.assertEqual('\x00World\xff', send_queue.get()) 9752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9772da489cd246702bee5938545b18a6f710ed214bcJamie Gennisif __name__ == '__main__': 9782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unittest.main() 9792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 9812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# vi:sts=4 sw=4 et 982