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"""Test for end-to-end."""
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport logging
372da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport os
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport signal
392da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport socket
402da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport subprocess
412da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport sys
422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport time
432da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport unittest
442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport set_sys_path  # Update sys.path to locate mod_pywebsocket module.
462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
472da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom test import client_for_testing
482da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom test import mux_client_for_testing
492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Special message that tells the echo server to start closing handshake
522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_GOODBYE_MESSAGE = 'Goodbye'
532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# If you want to use external server to run end to end tests, set following
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# parameters correctly.
562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_use_external_server = False
572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis_external_server_port = 0
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Test body functions
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _echo_check_procedure(client):
622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.connect()
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('test')
652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive('test')
662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('helloworld')
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive('helloworld')
682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_close()
702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive_close()
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_connection_closed()
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
752da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _echo_check_procedure_with_binary(client):
762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.connect()
772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('binary', binary=True)
792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive('binary', binary=True)
802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('\x00\x80\xfe\xff\x00\x80', binary=True)
812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive('\x00\x80\xfe\xff\x00\x80', binary=True)
822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_close()
842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive_close()
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_connection_closed()
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
892da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _echo_check_procedure_with_goodbye(client):
902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.connect()
912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('test')
932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive('test')
942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message(_GOODBYE_MESSAGE)
962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive(_GOODBYE_MESSAGE)
972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive_close()
992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_close()
1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_connection_closed()
1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _echo_check_procedure_with_code_and_reason(client, code, reason):
1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.connect()
1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_close(code, reason)
1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive_close(code, reason)
1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_connection_closed()
1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _unmasked_frame_check_procedure(client):
1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.connect()
1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.send_message('test', mask=False)
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_receive_close(client_for_testing.STATUS_PROTOCOL_ERROR, '')
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    client.assert_connection_closed()
1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennisdef _mux_echo_check_procedure(mux_client):
1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.connect()
1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_flow_control(1, 1024)
1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    logical_channel_options = client_for_testing.ClientOptions()
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    logical_channel_options.server_host = 'localhost'
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    logical_channel_options.server_port = 80
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    logical_channel_options.origin = 'http://localhost'
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    logical_channel_options.resource = '/echo'
1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.add_channel(2, logical_channel_options)
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_flow_control(2, 1024)
1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_message(2, 'test')
1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_receive(2, 'test')
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.add_channel(3, logical_channel_options)
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_flow_control(3, 1024)
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_message(2, 'hello')
1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_message(3, 'world')
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_receive(2, 'hello')
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_receive(3, 'world')
1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # Don't send close message on channel id 1 so that server-initiated
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # closing handshake won't occur.
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_close(2)
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_close(3)
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_receive_close(2)
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_receive_close(3)
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.send_physical_connection_close()
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    mux_client.assert_physical_connection_receive_close()
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass EndToEndTest(unittest.TestCase):
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """An end-to-end test that launches pywebsocket standalone server as a
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    separate process, connects to it using the client_for_testing module, and
1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    checks if the server behaves correctly by exchanging opening handshake and
1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    frames over a TCP connection.
1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def setUp(self):
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.server_stderr = None
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.top_dir = os.path.join(os.path.split(__file__)[0], '..')
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        os.putenv('PYTHONPATH', os.path.pathsep.join(sys.path))
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.standalone_command = os.path.join(
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self.top_dir, 'mod_pywebsocket', 'standalone.py')
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.document_root = os.path.join(self.top_dir, 'example')
1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        s = socket.socket()
1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        s.bind(('localhost', 0))
1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        (_, self.test_port) = s.getsockname()
1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        s.close()
1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options = client_for_testing.ClientOptions()
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options.server_host = 'localhost'
1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options.origin = 'http://localhost'
1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options.resource = '/echo'
1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # TODO(toyoshim): Eliminate launching a standalone server on using
1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # external server.
1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if _use_external_server:
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._options.server_port = _external_server_port
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._options.server_port = self.test_port
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_python_command(self, commandline, stdout=None, stderr=None):
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return subprocess.Popen([sys.executable] + commandline, close_fds=True,
1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                stdout=stdout, stderr=stderr)
1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_server(self, allow_draft75=False):
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        args = [self.standalone_command,
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                '-H', 'localhost',
1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                '-V', 'localhost',
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                '-p', str(self.test_port),
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                '-P', str(self.test_port),
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                '-d', self.document_root]
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Inherit the level set to the root logger by test runner.
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        root_logger = logging.getLogger()
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        log_level = root_logger.getEffectiveLevel()
2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if log_level != logging.NOTSET:
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args.append('--log-level')
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args.append(logging.getLevelName(log_level).lower())
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if allow_draft75:
2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args.append('--allow-draft75')
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return self._run_python_command(args,
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                        stderr=self.server_stderr)
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _kill_process(self, pid):
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if sys.platform in ('win32', 'cygwin'):
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            subprocess.call(
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                ('taskkill.exe', '/f', '/pid', str(pid)), close_fds=True)
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        else:
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            os.kill(pid, signal.SIGKILL)
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_test_with_client_options(self, test_function, options):
2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # TODO(tyoshino): add some logic to poll the server until it
2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # becomes ready
2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client(options)
2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_test(self, test_function):
2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test_with_client_options(test_function, self._options)
2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_deflate_test(self, test_function):
2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._options.enable_deflate_stream()
2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client(self._options)
2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_deflate_frame_test(self, test_function):
2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._options.enable_deflate_frame()
2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client(self._options)
2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_close_with_code_and_reason_test(self, test_function, code,
2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                                  reason):
2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client(self._options)
2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client, code, reason)
2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_http_fallback_test(self, options, status):
2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client(options)
2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.connect()
2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                self.fail('Could not catch HttpStatusException')
2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            except client_for_testing.HttpStatusException, e:
2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                self.assertEqual(status, e.status)
2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            except Exception, e:
2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                self.fail('Catch unexpected exception')
2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi_mux_test(self, test_function):
2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = mux_client_for_testing.MuxClient(self._options)
3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo(self):
3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(_echo_check_procedure)
3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_binary(self):
3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(_echo_check_procedure_with_binary)
3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_server_close(self):
3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(_echo_check_procedure_with_goodbye)
3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_unmasked_frame(self):
3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(_unmasked_frame_check_procedure)
3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_deflate(self):
3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_deflate_test(_echo_check_procedure)
3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_deflate_server_close(self):
3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_deflate_test(_echo_check_procedure_with_goodbye)
3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_deflate_frame(self):
3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_deflate_frame_test(_echo_check_procedure)
3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_deflate_frame_server_close(self):
3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_deflate_frame_test(
3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            _echo_check_procedure_with_goodbye)
3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_close_with_code_and_reason(self):
3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options.resource = '/close'
3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_close_with_code_and_reason_test(
3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            _echo_check_procedure_with_code_and_reason, 3333, 'sunsunsunsun')
3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_close_with_empty_body(self):
3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._options.resource = '/close'
3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_close_with_code_and_reason_test(
3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            _echo_check_procedure_with_code_and_reason, None, '')
3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_mux_echo(self):
3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_mux_test(_mux_echo_check_procedure)
3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_close_on_protocol_error(self):
3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the server sends a close frame with protocol error status
3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        code when the client sends data with some protocol error.
3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        def test_function(client):
3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.connect()
3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # Intermediate frame without any preceding start of fragmentation
3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # frame.
3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_frame_of_arbitrary_bytes('\x80\x80', '')
3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive_close(
3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client_for_testing.STATUS_PROTOCOL_ERROR)
3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(test_function)
3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_close_on_unsupported_frame(self):
3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the server sends a close frame with unsupported operation
3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        status code when the client sends data asking some operation that is
3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        not supported by the server.
3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        def test_function(client):
3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.connect()
3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # Text frame with RSV3 bit raised.
3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_frame_of_arbitrary_bytes('\x91\x80', '')
3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive_close(
3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client_for_testing.STATUS_UNSUPPORTED_DATA)
3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(test_function)
3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_close_on_invalid_frame(self):
3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the server sends a close frame with invalid frame payload
3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        data status code when the client sends an invalid frame like containing
3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        invalid UTF-8 character.
3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        def test_function(client):
3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.connect()
3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # Text frame with invalid UTF-8 string.
3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_message('\x80', raw=True)
3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive_close(
3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client_for_testing.STATUS_INVALID_FRAME_PAYLOAD_DATA)
3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test(test_function)
3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hybi00_test(self, test_function):
3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client_hybi00(self._options)
4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_hybi00(self):
4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi00_test(_echo_check_procedure)
4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_server_close_hybi00(self):
4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi00_test(_echo_check_procedure_with_goodbye)
4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _run_hixie75_test(self, test_function):
4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server(allow_draft75=True)
4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = client_for_testing.create_client_hixie75(self._options)
4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            try:
4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                test_function(client)
4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            finally:
4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                client.close_socket()
4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_hixie75(self):
4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the server can talk draft-hixie-thewebsocketprotocol-75
4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        protocol.
4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        def test_function(client):
4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.connect()
4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_message('test')
4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive('test')
4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hixie75_test(test_function)
4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_echo_server_close_hixie75(self):
4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the server can talk draft-hixie-thewebsocketprotocol-75
4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        protocol. At the end of message exchanging, the client sends a keyword
4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        message that requests the server to close the connection, and then
4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        checks if the connection is really closed.
4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        def test_function(client):
4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.connect()
4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_message('test')
4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive('test')
4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.send_message(_GOODBYE_MESSAGE)
4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client.assert_receive(_GOODBYE_MESSAGE)
4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hixie75_test(test_function)
4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # TODO(toyoshim): Add tests to verify invalid absolute uri handling like
4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # host unmatch, port unmatch and invalid port description (':' without port
4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    # number).
4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_absolute_uri(self):
4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests absolute uri request."""
4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options = self._options
4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options.resource = 'ws://localhost:%d/echo' % options.server_port
4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_test_with_client_options(_echo_check_procedure, options)
4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_origin_check(self):
4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests http fallback on origin check fail."""
4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options = self._options
4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options.resource = '/origin_check'
4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # Server shows warning message for http 403 fallback. This warning
4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # message is confusing. Following pipe disposes warning messages.
4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.server_stderr = subprocess.PIPE
4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_http_fallback_test(options, 403)
4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_version_check(self):
4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests http fallback on version check fail."""
4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options = self._options
4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        options.version = 99
4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.server_stderr = subprocess.PIPE
4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._run_hybi_http_fallback_test(options, 400)
4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _check_example_echo_client_result(
4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self, expected, stdoutdata, stderrdata):
4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        actual = stdoutdata.decode("utf-8")
4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if actual != expected:
4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            raise Exception('Unexpected result on example echo client: '
4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                            '%r (expected) vs %r (actual)' %
4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                            (expected, actual))
4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if stderrdata is not None:
4972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            raise Exception('Unexpected error message on example echo '
4982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                            'client: %r' % stderrdata)
4992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def test_example_echo_client(self):
5012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Tests that the echo_client.py example can talk with the server."""
5022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        server = self._run_server()
5042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        try:
5052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            time.sleep(0.2)
5062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client_command = os.path.join(
5082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                self.top_dir, 'example', 'echo_client.py')
5092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args = [client_command,
5112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    '-p', str(self._options.server_port)]
5122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = self._run_python_command(args, stdout=subprocess.PIPE)
5132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            stdoutdata, stderrdata = client.communicate()
5142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            expected = ('Send: Hello\n' 'Recv: Hello\n'
5152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                u'Send: \u65e5\u672c\n' u'Recv: \u65e5\u672c\n'
5162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                'Send close\n' 'Recv ack\n')
5172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._check_example_echo_client_result(
5182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                expected, stdoutdata, stderrdata)
5192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # Process a big message for which extended payload length is used.
5212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # To handle extended payload length, ws_version attribute will be
5222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            # accessed. This test checks that ws_version is correctly set.
5232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            big_message = 'a' * 1024
5242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            args = [client_command,
5252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    '-p', str(self._options.server_port),
5262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                    '-m', big_message]
5272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            client = self._run_python_command(args, stdout=subprocess.PIPE)
5282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            stdoutdata, stderrdata = client.communicate()
5292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            expected = ('Send: %s\nRecv: %s\nSend close\nRecv ack\n' %
5302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                        (big_message, big_message))
5312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._check_example_echo_client_result(
5322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                expected, stdoutdata, stderrdata)
5332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        finally:
5342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._kill_process(server.pid)
5352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5372da489cd246702bee5938545b18a6f710ed214bcJamie Gennisif __name__ == '__main__':
5382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    unittest.main()
5392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# vi:sts=4 sw=4 et
542