• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2009, Google Inc.
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met:
7#
8#     * Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10#     * Redistributions in binary form must reproduce the above
11# copyright notice, this list of conditions and the following disclaimer
12# in the documentation and/or other materials provided with the
13# distribution.
14#     * Neither the name of Google Inc. nor the names of its
15# contributors may be used to endorse or promote products derived from
16# this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31"""Mocks for testing.
32"""
33
34
35import Queue
36import threading
37
38
39class _MockConnBase(object):
40    """Base class of mocks for mod_python.apache.mp_conn.
41
42    This enables tests to check what is written to a (mock) mp_conn.
43    """
44
45    def __init__(self):
46        self._write_data = []
47
48    def write(self, data):
49        """Override mod_python.apache.mp_conn.write."""
50
51        self._write_data.append(data)
52
53    def written_data(self):
54        """Get bytes written to this mock."""
55
56        return ''.join(self._write_data)
57
58
59class MockConn(_MockConnBase):
60    """Mock for mod_python.apache.mp_conn.
61
62    This enables tests to specify what should be read from a (mock) mp_conn as
63    well as to check what is written to it.
64    """
65
66    def __init__(self, read_data):
67        """Constructs an instance.
68
69        Args:
70            read_data: bytes that should be returned when read* methods are
71            called.
72        """
73
74        _MockConnBase.__init__(self)
75        self._read_data = read_data
76        self._read_pos = 0
77
78    def readline(self):
79        """Override mod_python.apache.mp_conn.readline."""
80
81        if self._read_pos >= len(self._read_data):
82            return ''
83        end_index = self._read_data.find('\n', self._read_pos) + 1
84        if not end_index:
85            end_index = len(self._read_data)
86        return self._read_up_to(end_index)
87
88    def read(self, length):
89        """Override mod_python.apache.mp_conn.read."""
90
91        if self._read_pos >= len(self._read_data):
92            return ''
93        end_index = min(len(self._read_data), self._read_pos + length)
94        return self._read_up_to(end_index)
95
96    def _read_up_to(self, end_index):
97        line = self._read_data[self._read_pos:end_index]
98        self._read_pos = end_index
99        return line
100
101
102class MockBlockingConn(_MockConnBase):
103    """Blocking mock for mod_python.apache.mp_conn.
104
105    This enables tests to specify what should be read from a (mock) mp_conn as
106    well as to check what is written to it.
107    Callers of read* methods will block if there is no bytes available.
108    """
109
110    def __init__(self):
111        _MockConnBase.__init__(self)
112        self._queue = Queue.Queue()
113
114    def readline(self):
115        """Override mod_python.apache.mp_conn.readline."""
116        line = ''
117        while True:
118            c = self._queue.get()
119            line += c
120            if c == '\n':
121                return line
122
123    def read(self, length):
124        """Override mod_python.apache.mp_conn.read."""
125
126        data = ''
127        for unused in range(length):
128            data += self._queue.get()
129        return data
130
131    def put_bytes(self, bytes):
132        """Put bytes to be read from this mock.
133
134        Args:
135            bytes: bytes to be read.
136        """
137
138        for byte in bytes:
139            self._queue.put(byte)
140
141
142class MockTable(dict):
143    """Mock table.
144
145    This mimics mod_python mp_table. Note that only the methods used by
146    tests are overridden.
147    """
148
149    def __init__(self, copy_from={}):
150        if isinstance(copy_from, dict):
151            copy_from = copy_from.items()
152        for key, value in copy_from:
153            self.__setitem__(key, value)
154
155    def __getitem__(self, key):
156        return super(MockTable, self).__getitem__(key.lower())
157
158    def __setitem__(self, key, value):
159        super(MockTable, self).__setitem__(key.lower(), value)
160
161    def get(self, key, def_value=None):
162        return super(MockTable, self).get(key.lower(), def_value)
163
164
165class MockRequest(object):
166    """Mock request.
167
168    This mimics mod_python request.
169    """
170
171    def __init__(self, uri=None, headers_in={}, connection=None,
172                 is_https=False):
173        """Construct an instance.
174
175        Arguments:
176            uri: URI of the request.
177            headers_in: Request headers.
178            connection: Connection used for the request.
179            is_https: Whether this request is over SSL.
180
181        See the document of mod_python Request for details.
182        """
183        self.uri = uri
184        self.connection = connection
185        self.headers_in = MockTable(headers_in)
186        # self.is_https_ needs to be accessible from tests.  To avoid name
187        # conflict with self.is_https(), it is named as such.
188        self.is_https_ = is_https
189
190    def is_https(self):
191        """Return whether this request is over SSL."""
192        return self.is_https_
193
194
195class MockDispatcher(object):
196    """Mock for dispatch.Dispatcher."""
197
198    def do_extra_handshake(self, conn_context):
199        pass
200
201    def transfer_data(self, conn_context):
202        pass
203
204
205# vi:sts=4 sw=4 et
206