12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Copyright 2011, Google Inc.
22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# All rights reserved.
32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# Redistribution and use in source and binary forms, with or without
52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# modification, are permitted provided that the following conditions are
62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# met:
72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Redistributions of source code must retain the above copyright
92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# notice, this list of conditions and the following disclaimer.
102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Redistributions in binary form must reproduce the above
112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# copyright notice, this list of conditions and the following disclaimer
122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# in the documentation and/or other materials provided with the
132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# distribution.
142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#     * Neither the name of Google Inc. nor the names of its
152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# contributors may be used to endorse or promote products derived from
162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# this software without specific prior written permission.
172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#
182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""Mocks for testing.
322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis"""
332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport Queue
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisimport threading
372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket import common
392da489cd246702bee5938545b18a6f710ed214bcJamie Gennisfrom mod_pywebsocket.stream import StreamHixie75
402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
422da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass _MockConnBase(object):
432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Base class of mocks for mod_python.apache.mp_conn.
442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This enables tests to check what is written to a (mock) mp_conn.
462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self):
492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._write_data = []
502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.remote_addr = 'fake_address'
512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def write(self, data):
532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Override mod_python.apache.mp_conn.write."""
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._write_data.append(data)
562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def written_data(self):
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Get bytes written to this mock."""
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return ''.join(self._write_data)
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MockConn(_MockConnBase):
642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Mock for mod_python.apache.mp_conn.
652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This enables tests to specify what should be read from a (mock) mp_conn as
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    well as to check what is written to it.
682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self, read_data):
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Constructs an instance.
722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Args:
742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            read_data: bytes that should be returned when read* methods are
752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            called.
762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        _MockConnBase.__init__(self)
792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._read_data = read_data
802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._read_pos = 0
812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def readline(self):
832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Override mod_python.apache.mp_conn.readline."""
842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if self._read_pos >= len(self._read_data):
862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            return ''
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        end_index = self._read_data.find('\n', self._read_pos) + 1
882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if not end_index:
892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            end_index = len(self._read_data)
902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return self._read_up_to(end_index)
912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def read(self, length):
932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Override mod_python.apache.mp_conn.read."""
942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if self._read_pos >= len(self._read_data):
962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            return ''
972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        end_index = min(len(self._read_data), self._read_pos + length)
982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return self._read_up_to(end_index)
992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _read_up_to(self, end_index):
1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line = self._read_data[self._read_pos:end_index]
1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._read_pos = end_index
1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return line
1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MockBlockingConn(_MockConnBase):
1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Blocking mock for mod_python.apache.mp_conn.
1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This enables tests to specify what should be read from a (mock) mp_conn as
1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    well as to check what is written to it.
1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    Callers of read* methods will block if there is no bytes available.
1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self):
1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        _MockConnBase.__init__(self)
1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self._queue = Queue.Queue()
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def readline(self):
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Override mod_python.apache.mp_conn.readline."""
1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        line = ''
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        while True:
1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            c = self._queue.get()
1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            line += c
1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            if c == '\n':
1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                return line
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def read(self, length):
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Override mod_python.apache.mp_conn.read."""
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        data = ''
1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for unused in range(length):
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            data += self._queue.get()
1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return data
1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def put_bytes(self, bytes):
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Put bytes to be read from this mock.
1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Args:
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            bytes: bytes to be read.
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for byte in bytes:
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self._queue.put(byte)
1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MockTable(dict):
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Mock table.
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This mimics mod_python mp_table. Note that only the methods used by
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    tests are overridden.
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self, copy_from={}):
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if isinstance(copy_from, dict):
1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            copy_from = copy_from.items()
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for key, value in copy_from:
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            self.__setitem__(key, value)
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __getitem__(self, key):
1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return super(MockTable, self).__getitem__(key.lower())
1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __setitem__(self, key, value):
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        super(MockTable, self).__setitem__(key.lower(), value)
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def get(self, key, def_value=None):
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return super(MockTable, self).get(key.lower(), def_value)
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MockRequest(object):
1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Mock request.
1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    This mimics mod_python request.
1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """
1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self, uri=None, headers_in={}, connection=None, method='GET',
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                 is_https=False):
1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Construct an instance.
1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        Arguments:
1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            uri: URI of the request.
1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            headers_in: Request headers.
1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            connection: Connection used for the request.
1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            method: request method.
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            is_https: Whether this request is over SSL.
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        See the document of mod_python Request for details.
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.uri = uri
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.connection = connection
1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.method = method
1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.headers_in = MockTable(headers_in)
1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # self.is_https_ needs to be accessible from tests.  To avoid name
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        # conflict with self.is_https(), it is named as such.
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.is_https_ = is_https
1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.ws_stream = StreamHixie75(self, True)
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.ws_close_code = None
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.ws_close_reason = None
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.ws_version = common.VERSION_HYBI00
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.ws_deflate = False
2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.drain_received_data_called = False
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def is_https(self):
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        """Return whether this request is over SSL."""
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return self.is_https_
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def _drain_received_data(self):
2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.drain_received_data_called = True
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennisclass MockDispatcher(object):
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    """Mock for dispatch.Dispatcher."""
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def __init__(self):
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.do_extra_handshake_called = False
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def do_extra_handshake(self, conn_context):
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        self.do_extra_handshake_called = True
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    def transfer_data(self, conn_context):
2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        pass
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis# vi:sts=4 sw=4 et
225