1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """testsuite base classes and helpers for diffing strings
19 """
20
21 from twisted.spread import pb
22 from twisted.internet import reactor, defer, selectreactor, pollreactor
23 from twisted.scripts import trial
24 from twisted.trial import unittest, util
25
26 from flumotion.common import log
27 from flumotion.configure import configure
28
29 __version__ = "$Rev$"
30
31
32 try:
33 _getConfig = trial.getConfig
34 except AttributeError:
35
36 _getConfig = dict
37
38
39 -def attr(*args, **kwargs):
40 """Decorator that adds attributes to objects.
41
42 It can be used to set the 'slow', 'skip', or 'todo' flags in test cases.
43 """
44
45 def wrap(func):
46 for name in args:
47
48 setattr(func, name, True)
49 for name, value in kwargs.items():
50 setattr(func, name, value)
51 return func
52 return wrap
53
54
55 -class TestCase(unittest.TestCase, log.Loggable):
56
57
58
59
60 supportedReactors = [selectreactor.SelectReactor, pollreactor.PollReactor]
61
62
63 if not hasattr(unittest.TestCase, 'failUnlessFailure'):
64
66
67 def _cb(result):
68 self.fail("did not catch an error, instead got %r" %
69 (result, ))
70
71 def _eb(failure):
72 failure.trap(*expectedFailures)
73 return failure.value
74 return deferred.addCallbacks(_cb, _eb)
75 assertFailure = failUnlessFailure
76
77
78
79
80 - def __init__(self, methodName=' impossible-name '):
125
127 """
128 Return whether this test has been marked as slow. Checks on the
129 instance first, then the class, then the module, then packages. As
130 soon as it finds something with a C{slow} attribute, returns that.
131 Returns C{False} if it cannot find anything.
132 """
133 return util.acquireAttribute(self._parents, 'slow', False)
134
135
136
137 - def debug(self, *args, **kwargs):
139
140
141
142
143
144
146
147 type = "client"
148 remoteRoot = None
149
150 - def run(self, port):
151 """
152 Start the client by connecting to the server on the given port.
153
154 @type port: int
155
156 @rtype: L{twisted.internet.defer.Deferred}
157 """
158 self._f = pb.PBClientFactory()
159 self._p = reactor.connectTCP("127.0.0.1", port, self._f)
160 d = self._f.getRootObject()
161 d.addCallback(self._gotRootObject)
162 return d
163
165 """
166 Stop the client.
167
168 @rtype: L{twisted.internet.defer.Deferred}
169 """
170 self._p.disconnect()
171 return self._dDisconnect
172
182
184
185 self.object = object
186
187
190
191
194
195
197 logCategory = "testmanagerroot"
198
200 """
201 Called by a TestClient to announce the type of client, and give
202 a reference.
203 """
204 self.debug('remote_identify: who %r, ref %r' % (who, reference))
205 key = who + 'Reference'
206 setattr(self, key, reference)
207
209
210 self.object = object
211
212
214
215 - def run(self, rootClass):
216 """
217 Run the test manager. Return port it is listening on.
218
219 @type rootClass: subclass of L{TestManagerRoot}
220
221 @rtype: int
222 """
223 self.root = rootClass()
224 factory = pb.PBServerFactory(self.root)
225 factory.unsafeTracebacks = 1
226 self._p = reactor.listenTCP(0, factory, interface="127.0.0.1")
227 port = self._p.getHost().port
228 return port
229
231 """
232 Stop the server.
233 """
234 return self._p.stopListening()
235
236
238 """
239 I combine a manager and a client to test passing back and forth objects.
240 """
241 logCategory = "testpb"
242
246
250
252 d = self.manager.stop()
253 d.addCallback(lambda r: self.client.stop())
254 return d
255
256 - def send(self, object):
257 """
258 Send the object from client to server.
259 Return the server's idea of the object.
260 """
261 self.debug('sending object %r from broker %r' % (
262 object, self.client.remoteRoot.broker))
263 d = self.client.remoteRoot.callRemote('receive', object)
264 d.addCallback(lambda r: self.manager.root.object)
265 return d
266
268 """
269 Receive the object from server to client.
270 Return the client's idea of the object.
271 """
272 self.debug('receiving object %r' % object)
273 d = self.manager.root.clientReference.callRemote('receive', object)
274 d.addCallback(lambda r: self.client.object)
275 return d
276
277
279
281 from flumotion.twisted import pb
282 from flumotion.common import server, connection
283 from flumotion.manager import manager, config
284 from StringIO import StringIO
285
286 managerConf = """
287 <planet>
288 <manager name="planet">
289 <host>localhost</host>
290 <port>0</port>
291 <transport>tcp</transport>
292 <component name="manager-bouncer" type="htpasswdcrypt-bouncer">
293 <property name="data"><![CDATA[
294 user:PSfNpHTkpTx1M
295 ]]></property>
296 </component>
297 </manager>
298 </planet>
299 """
300
301 conf = config.ManagerConfigParser(StringIO(managerConf)).manager
302 self.vishnu = manager.Vishnu(conf.name,
303 unsafeTracebacks=True)
304 self.vishnu.loadManagerConfigurationXML(StringIO(managerConf))
305 s = server.Server(self.vishnu)
306 if conf.transport == "ssl":
307 p = s.startSSL(conf.host, conf.port, conf.certificate,
308 configure.configdir)
309 elif conf.transport == "tcp":
310 p = s.startTCP(conf.host, conf.port)
311 self.tport = p
312 self.port = p.getHost().port
313 i = connection.PBConnectionInfo('localhost', self.port,
314 conf.transport == 'ssl',
315 pb.Authenticator(username='user',
316 password='test'))
317 self.connectionInfo = i
318
320
321 try:
322 self.flushLoggedErrors(*types)
323 except AttributeError:
324 from twisted.python import log as tlog
325 tlog.flushErrors(*types)
326
334
335
336 -def _diff(old, new, desc):
337 import difflib
338 lines = difflib.unified_diff(old, new)
339 lines = list(lines)
340 if not lines:
341 return
342 output = ''
343 for line in lines:
344 output += '%s: %s\n' % (desc, line[:-1])
345
346 raise AssertionError(
347 ("\nError while comparing strings:\n"
348 "%s") % (output, ))
349
350
352
353 def _tolines(s):
354 return [line + '\n' for line in s.split('\n')]
355
356 return _diff(_tolines(orig),
357 _tolines(new),
358 desc=desc)
359