test_handshake.py (6933B)
1 #!/usr/bin/env python 2 # 3 # Copyright 2012, Google Inc. 4 # All rights reserved. 5 # 6 # Redistribution and use in source and binary forms, with or without 7 # modification, are permitted provided that the following conditions are 8 # met: 9 # 10 # * Redistributions of source code must retain the above copyright 11 # notice, this list of conditions and the following disclaimer. 12 # * Redistributions in binary form must reproduce the above 13 # copyright notice, this list of conditions and the following disclaimer 14 # in the documentation and/or other materials provided with the 15 # distribution. 16 # * Neither the name of Google Inc. nor the names of its 17 # contributors may be used to endorse or promote products derived from 18 # this software without specific prior written permission. 19 # 20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 """Tests for handshake.base module.""" 32 33 from __future__ import absolute_import 34 35 import unittest 36 37 import set_sys_path # Update sys.path to locate pywebsocket3 module. 38 from pywebsocket3.common import ( 39 ExtensionParameter, 40 ExtensionParsingException, 41 format_extensions, 42 parse_extensions, 43 ) 44 from pywebsocket3.handshake.base import HandshakeException, validate_subprotocol 45 46 47 class ValidateSubprotocolTest(unittest.TestCase): 48 """A unittest for validate_subprotocol method.""" 49 def test_validate_subprotocol(self): 50 # Should succeed. 51 validate_subprotocol('sample') 52 validate_subprotocol('Sample') 53 validate_subprotocol('sample\x7eprotocol') 54 55 # Should fail. 56 self.assertRaises(HandshakeException, validate_subprotocol, '') 57 self.assertRaises(HandshakeException, validate_subprotocol, 58 'sample\x09protocol') 59 self.assertRaises(HandshakeException, validate_subprotocol, 60 'sample\x19protocol') 61 self.assertRaises(HandshakeException, validate_subprotocol, 62 'sample\x20protocol') 63 self.assertRaises(HandshakeException, validate_subprotocol, 64 'sample\x7fprotocol') 65 self.assertRaises( 66 HandshakeException, 67 validate_subprotocol, 68 # "Japan" in Japanese 69 u'\u65e5\u672c') 70 71 72 _TEST_TOKEN_EXTENSION_DATA = [ 73 ('foo', [('foo', [])]), 74 ('foo; bar', [('foo', [('bar', None)])]), 75 ('foo; bar=baz', [('foo', [('bar', 'baz')])]), 76 ('foo; bar=baz; car=cdr', [('foo', [('bar', 'baz'), ('car', 'cdr')])]), 77 ('foo; bar=baz, car; cdr', [('foo', [('bar', 'baz')]), 78 ('car', [('cdr', None)])]), 79 ('a, b, c, d', [('a', []), ('b', []), ('c', []), ('d', [])]), 80 ] 81 82 _TEST_QUOTED_EXTENSION_DATA = [ 83 ('foo; bar=""', [('foo', [('bar', '')])]), 84 ('foo; bar=" baz "', [('foo', [('bar', ' baz ')])]), 85 ('foo; bar=",baz;"', [('foo', [('bar', ',baz;')])]), 86 ('foo; bar="\\\r\\\nbaz"', [('foo', [('bar', '\r\nbaz')])]), 87 ('foo; bar="\\"baz"', [('foo', [('bar', '"baz')])]), 88 ('foo; bar="\xbbbaz"', [('foo', [('bar', '\xbbbaz')])]), 89 ] 90 91 _TEST_REDUNDANT_TOKEN_EXTENSION_DATA = [ 92 ('foo \t ', [('foo', [])]), 93 ('foo; \r\n bar', [('foo', [('bar', None)])]), 94 ('foo; bar=\r\n \r\n baz', [('foo', [('bar', 'baz')])]), 95 ('foo ;bar = baz ', [('foo', [('bar', 'baz')])]), 96 ('foo,bar,,baz', [('foo', []), ('bar', []), ('baz', [])]), 97 ] 98 99 _TEST_REDUNDANT_QUOTED_EXTENSION_DATA = [ 100 ('foo; bar="\r\n \r\n baz"', [('foo', [('bar', ' baz')])]), 101 ] 102 103 104 class ExtensionsParserTest(unittest.TestCase): 105 def _verify_extension_list(self, expected_list, actual_list): 106 """Verifies that ExtensionParameter objects in actual_list have the 107 same members as extension definitions in expected_list. Extension 108 definition used in this test is a pair of an extension name and a 109 parameter dictionary. 110 """ 111 112 self.assertEqual(len(expected_list), len(actual_list)) 113 for expected, actual in zip(expected_list, actual_list): 114 (name, parameters) = expected 115 self.assertEqual(name, actual._name) 116 self.assertEqual(parameters, actual._parameters) 117 118 def test_parse(self): 119 for formatted_string, definition in _TEST_TOKEN_EXTENSION_DATA: 120 self._verify_extension_list(definition, 121 parse_extensions(formatted_string)) 122 123 def test_parse_quoted_data(self): 124 for formatted_string, definition in _TEST_QUOTED_EXTENSION_DATA: 125 self._verify_extension_list(definition, 126 parse_extensions(formatted_string)) 127 128 def test_parse_redundant_data(self): 129 for (formatted_string, 130 definition) in _TEST_REDUNDANT_TOKEN_EXTENSION_DATA: 131 self._verify_extension_list(definition, 132 parse_extensions(formatted_string)) 133 134 def test_parse_redundant_quoted_data(self): 135 for (formatted_string, 136 definition) in _TEST_REDUNDANT_QUOTED_EXTENSION_DATA: 137 self._verify_extension_list(definition, 138 parse_extensions(formatted_string)) 139 140 def test_parse_bad_data(self): 141 _TEST_BAD_EXTENSION_DATA = [ 142 ('foo; ; '), 143 ('foo; a a'), 144 ('foo foo'), 145 (',,,'), 146 ('foo; bar='), 147 ('foo; bar="hoge'), 148 ('foo; bar="a\r"'), 149 ('foo; bar="\\\xff"'), 150 ('foo; bar=\ra'), 151 ] 152 153 for formatted_string in _TEST_BAD_EXTENSION_DATA: 154 self.assertRaises(ExtensionParsingException, parse_extensions, 155 formatted_string) 156 157 158 class FormatExtensionsTest(unittest.TestCase): 159 def test_format_extensions(self): 160 for formatted_string, definitions in _TEST_TOKEN_EXTENSION_DATA: 161 extensions = [] 162 for definition in definitions: 163 (name, parameters) = definition 164 extension = ExtensionParameter(name) 165 extension._parameters = parameters 166 extensions.append(extension) 167 self.assertEqual(formatted_string, format_extensions(extensions)) 168 169 170 if __name__ == '__main__': 171 unittest.main() 172 173 # vi:sts=4 sw=4 et