Package gofer :: Package rmi :: Module mock
[hide private]
[frames] | no frames]

Source Code for Module gofer.rmi.mock

  1  # 
  2  # Copyright (c) 2011 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU Lesser General Public 
  5  # License as published by the Free Software Foundation; either version 
  6  # 2 of the License (LGPLv2) or (at your option) any later version. 
  7  # There is NO WARRANTY for this software, express or implied, 
  8  # including the implied warranties of MERCHANTABILITY, 
  9  # NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should 
 10  # have received a copy of LGPLv2 along with this software; if not, see 
 11  # http://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt. 
 12  # 
 13  # Jeff Ortel <jortel@redhat.com> 
 14  # 
 15   
 16  import inspect 
 17  from gofer import proxy 
 18  from gofer import Singleton 
 19  from gofer.messaging import Options 
 20  from gofer.rmi.stub import Stub 
 21  from threading import RLock 
22 23 24 -def agent(uuid, **options):
25 """ 26 Get a (mock) proxy for the remote Agent. 27 @param uuid: An agent ID. 28 @type uuid: str 29 @return: A (mock) agent proxy. 30 @rtype: L{MockContainer} 31 """ 32 return MockContainer(uuid, None, **options)
33
34 -def register(**mocks):
35 """ 36 Register (mock) stubs. 37 """ 38 Factory.register(**mocks)
39
40 -def purge():
41 """ 42 Purge (mock) stubs 43 """ 44 Factory.purge()
45
46 -def install():
47 """ 48 Install the mock agent. 49 """ 50 proxy.Agent = agent 51 proxy.agent = agent
52
53 -def reset():
54 """ 55 Reset (mock) container singletons. 56 """ 57 MockContainer.reset()
58
59 -def all():
60 """ 61 Get all mock container instances. 62 @return: A list of mock container instances. 63 @rtype: L{MockContainer} 64 """ 65 return MockContainer.all()
66
67 68 -class MetaContainer(Singleton):
69 """ 70 Mock container singleton by uuid only. 71 """ 72 73 @classmethod
74 - def key(cls, t, d):
75 if t: 76 return t[0] 77 else: 78 return None
79
80 81 -class MockContainer:
82 """ 83 The (mock) stub container 84 @ivar __id: The peer ID. 85 @type __id: str 86 @ivar __options: Container options. 87 @type __options: L{Options} 88 @ivar __stubs: A cache of stubs. 89 @type __stubs: dict 90 """ 91 92 __metaclass__ = MetaContainer 93
94 - def __init__(self, uuid, producer=None, **options):
95 """ 96 @param uuid: The peer ID. 97 @type uuid: str 98 @param producer: An AMQP producer (unused). 99 @type producer: L{gofer.messaging.producer.Producer} 100 @param options: keyword options. 101 @type options: dict 102 """ 103 self.__id = uuid 104 self.__options = Options() 105 self.__options += options 106 self.__stubs = {}
107
108 - def __getattr__(self, name):
109 """ 110 Get a stub by name. 111 @param name: The name of a stub class. 112 @type name: str 113 @return: A stub object. 114 @rtype: L{MockStub} 115 """ 116 stub = self.__stubs.get(name) 117 if stub is None: 118 stub = Factory.stub(name) 119 if not stub: 120 raise AttributeError(name) 121 self.__stubs[name] = stub 122 return stub
123
124 - def __getitem__(self, name):
125 """ 126 Get a stub by name. 127 @param name: The name of a stub class. 128 @type name: str 129 @return: A stub object. 130 @rtype: L{MockStub} 131 """ 132 return getattr(self, name)
133
134 - def __str__(self):
135 return '{%s/%s} opt:%s' % \ 136 (id(self), 137 self.__id, 138 repr(self.__options))
139
140 - def __repr__(self):
141 return str(self)
142
143 144 -class Call:
145 """ 146 Call object. 147 @ivar call: The call tuple (args,kwargs) 148 @type call: tuple 149 """ 150
151 - def __init__(self, call):
152 """ 153 @param call: The call tuple. 154 @type call: tuple 155 """ 156 self.call = call
157 158 @property
159 - def args(self):
160 """ 161 Get the call argument list. 162 """ 163 return self.call[0]
164 165 @property
166 - def kwargs(self):
167 """ 168 Get the keyword arguments. 169 """ 170 return self.call[1]
171
172 - def __getitem__(self, n):
173 return self.call[n]
174
175 - def __iter__(self):
176 return iter(self.call)
177
178 - def __str__(self):
179 return str(self.call)
180
181 - def __repr__(self):
182 return repr(self.call)
183
184 185 -class Stub:
186 """ 187 Mock stub. 188 """ 189 190 @classmethod
191 - def __instrumented(cls, inst):
192 for m in inspect.getmembers(inst, inspect.ismethod): 193 setattr(inst, m[0], Method(m[1])) 194 return inst
195
196 - def __init__(self, stub):
197 if inspect.isclass(stub): 198 stub = stub() 199 self.__inst = self.__instrumented(stub)
200
201 - def __call__(self, *args, **options):
202 return self.__inst
203
204 - def __getattr__(self, name):
205 return getattr(self.__inst, name)
206
207 - def __getitem__(self, name):
208 return getattr(self, name)
209
210 - def __str__(self):
211 return str(self.__inst)
212
213 - def __repr__(self):
214 return repr(self.__inst)
215
216 217 -class Method:
218 """ 219 Method wrapper. 220 @ivar __method: The (wrapped) method. 221 @type __method: instancemethod 222 @ivar __history: The call history 223 @type __history: list 224 @ivar __mutex: The object mutex 225 @type __mutex: RLock 226 """ 227
228 - def __init__(self, method):
229 """ 230 @param method: A (wrapped) method. 231 @type method: instancemethod 232 """ 233 self.__method = [method] 234 self.__history = [] 235 self.__mutex = RLock()
236
237 - def __call__(self, *args, **options):
238 self.__lock() 239 try: 240 call = (args, options) 241 self.__history.append(call) 242 method = self.pop() 243 return method(*args, **options) 244 finally: 245 self.__unlock()
246
247 - def push(self, method):
248 """ 249 Push a function, exception to be evaluated on next call. 250 @param method: A function/exception 251 @type method: function/exception 252 """ 253 self.__lock() 254 try: 255 self.__method.append(method) 256 finally: 257 self.__unlock()
258
259 - def pop(self):
260 """ 261 Pop the next method to be executed. 262 It could be an exception in which case, it is raised. 263 @return: The next method. 264 @rtype: callable 265 """ 266 self.__lock() 267 try: 268 method = self.__method[0] 269 if len(self.__method) > 1: 270 method = self.__method.pop() 271 if isinstance(method, Exception): 272 raise method 273 return method 274 finally: 275 self.__unlock()
276
277 - def purge(self):
278 """ 279 Purge the call history. 280 """ 281 self.__lock() 282 try: 283 self.__history = [] 284 finally: 285 self.__unlock()
286
287 - def history(self):
288 """ 289 Get the call history. 290 @return: A list of L{Call} 291 @rtype: list 292 """ 293 self.__lock() 294 try: 295 history = [] 296 for h in self.__history: 297 history.append(Call(h)) 298 return history 299 finally: 300 self.__unlock()
301
302 - def __lock(self):
303 self.__mutex.acquire()
304
305 - def __unlock(self):
306 self.__mutex.release()
307
308 309 -class Factory:
310 """ 311 Stub factory 312 @cvar mocks: The registered stubs. 313 @type mocks: dict 314 """ 315 316 mocks = {} 317 318 @classmethod
319 - def register(cls, **mocks):
320 """ 321 Register an I{mock} to be used instead of 322 creating a real stub. 323 """ 324 cls.mocks.update(mocks)
325 326 @classmethod
327 - def purge(cls):
328 """ 329 purge registered mocks. 330 """ 331 mocks = {}
332 333 @classmethod
334 - def stub(cls, name):
335 """ 336 Get a (mock) stub by name. 337 @param name: The stub class (or module) name. 338 @type name: str 339 @return: A stub instance. 340 @rtype: L{Stub} 341 """ 342 stub = cls.mocks.get(name) 343 if stub: 344 return Stub(stub) 345 else: 346 return None
347