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