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