Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: third_party/twisted_8_1/twisted/test/test_pb.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for Perspective Broker module.
6
7 TODO: update protocol level tests to use new connection API, leaving
8 only specific tests for old API.
9 """
10
11 # issue1195 TODOs: replace pump.pump() with something involving Deferreds.
12 # Clean up warning suppression. Find a better replacement for the handful of
13 # reactor.callLater(0.1, ..) calls.
14
15 import sys, os, time, gc
16
17 from cStringIO import StringIO
18 from zope.interface import implements, Interface
19
20 from twisted.trial import unittest
21
22 from twisted.spread import pb, util, publish, jelly
23 from twisted.internet import protocol, main, reactor, defer
24 from twisted.internet.error import ConnectionRefusedError
25 from twisted.internet.defer import Deferred, gatherResults
26 from twisted.python import failure, log
27 from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials
28 from twisted.cred import portal, checkers, credentials
29
30
31 class Dummy(pb.Viewable):
32 def view_doNothing(self, user):
33 if isinstance(user, DummyPerspective):
34 return 'hello world!'
35 else:
36 return 'goodbye, cruel world!'
37
38
39 class DummyPerspective(pb.Avatar):
40 def perspective_getDummyViewPoint(self):
41 return Dummy()
42
43
44 class DummyRealm(object):
45 implements(portal.IRealm)
46
47 def requestAvatar(self, avatarId, mind, *interfaces):
48 for iface in interfaces:
49 if iface is pb.IPerspective:
50 return iface, DummyPerspective(), lambda: None
51
52
53 class IOPump:
54 """
55 Utility to pump data between clients and servers for protocol testing.
56
57 Perhaps this is a utility worthy of being in protocol.py?
58 """
59 def __init__(self, client, server, clientIO, serverIO):
60 self.client = client
61 self.server = server
62 self.clientIO = clientIO
63 self.serverIO = serverIO
64
65 def flush(self):
66 """
67 Pump until there is no more input or output. This does not run any
68 timers, so don't use it with any code that calls reactor.callLater.
69 """
70 # failsafe timeout
71 timeout = time.time() + 5
72 while self.pump():
73 if time.time() > timeout:
74 return
75
76 def pump(self):
77 """
78 Move data back and forth.
79
80 Returns whether any data was moved.
81 """
82 self.clientIO.seek(0)
83 self.serverIO.seek(0)
84 cData = self.clientIO.read()
85 sData = self.serverIO.read()
86 self.clientIO.seek(0)
87 self.serverIO.seek(0)
88 self.clientIO.truncate()
89 self.serverIO.truncate()
90 self.client.transport._checkProducer()
91 self.server.transport._checkProducer()
92 for byte in cData:
93 self.server.dataReceived(byte)
94 for byte in sData:
95 self.client.dataReceived(byte)
96 if cData or sData:
97 return 1
98 else:
99 return 0
100
101
102 def connectedServerAndClient():
103 """
104 Returns a 3-tuple: (client, server, pump).
105 """
106 clientBroker = pb.Broker()
107 checker = checkers.InMemoryUsernamePasswordDatabaseDontUse(guest='guest')
108 factory = pb.PBServerFactory(portal.Portal(DummyRealm(), [checker]))
109 serverBroker = factory.buildProtocol(('127.0.0.1',))
110
111 clientTransport = StringIO()
112 serverTransport = StringIO()
113 clientBroker.makeConnection(protocol.FileWrapper(clientTransport))
114 serverBroker.makeConnection(protocol.FileWrapper(serverTransport))
115 pump = IOPump(clientBroker, serverBroker, clientTransport, serverTransport)
116 # Challenge-response authentication:
117 pump.flush()
118 return clientBroker, serverBroker, pump
119
120
121 class SimpleRemote(pb.Referenceable):
122 def remote_thunk(self, arg):
123 self.arg = arg
124 return arg + 1
125
126 def remote_knuth(self, arg):
127 raise Exception()
128
129
130 class NestedRemote(pb.Referenceable):
131 def remote_getSimple(self):
132 return SimpleRemote()
133
134
135 class SimpleCopy(pb.Copyable):
136 def __init__(self):
137 self.x = 1
138 self.y = {"Hello":"World"}
139 self.z = ['test']
140
141
142 class SimpleLocalCopy(pb.RemoteCopy):
143 pass
144
145 pb.setCopierForClass(SimpleCopy, SimpleLocalCopy)
146
147
148 class SimpleFactoryCopy(pb.Copyable):
149 """
150 @cvar allIDs: hold every created instances of this class.
151 @type allIDs: C{dict}
152 """
153 allIDs = {}
154 def __init__(self, id):
155 self.id = id
156 SimpleFactoryCopy.allIDs[id] = self
157
158
159 def createFactoryCopy(state):
160 """
161 Factory of L{SimpleFactoryCopy}, getting a created instance given the
162 C{id} found in C{state}.
163 """
164 stateId = state.get("id", None)
165 if stateId is None:
166 raise RuntimeError("factory copy state has no 'id' member %s" %
167 (repr(state),))
168 if not stateId in SimpleFactoryCopy.allIDs:
169 raise RuntimeError("factory class has no ID: %s" %
170 (SimpleFactoryCopy.allIDs,))
171 inst = SimpleFactoryCopy.allIDs[stateId]
172 if not inst:
173 raise RuntimeError("factory method found no object with id")
174 return inst
175
176 pb.setFactoryForClass(SimpleFactoryCopy, createFactoryCopy)
177
178
179 class NestedCopy(pb.Referenceable):
180 def remote_getCopy(self):
181 return SimpleCopy()
182
183 def remote_getFactory(self, value):
184 return SimpleFactoryCopy(value)
185
186
187
188 class SimpleCache(pb.Cacheable):
189 def __init___(self):
190 self.x = 1
191 self.y = {"Hello":"World"}
192 self.z = ['test']
193
194
195 class NestedComplicatedCache(pb.Referenceable):
196 def __init__(self):
197 self.c = VeryVeryComplicatedCacheable()
198
199 def remote_getCache(self):
200 return self.c
201
202
203 class VeryVeryComplicatedCacheable(pb.Cacheable):
204 def __init__(self):
205 self.x = 1
206 self.y = 2
207 self.foo = 3
208
209 def setFoo4(self):
210 self.foo = 4
211 self.observer.callRemote('foo',4)
212
213 def getStateToCacheAndObserveFor(self, perspective, observer):
214 self.observer = observer
215 return {"x": self.x,
216 "y": self.y,
217 "foo": self.foo}
218
219 def stoppedObserving(self, perspective, observer):
220 log.msg("stopped observing")
221 observer.callRemote("end")
222 if observer == self.observer:
223 self.observer = None
224
225
226 class RatherBaroqueCache(pb.RemoteCache):
227 def observe_foo(self, newFoo):
228 self.foo = newFoo
229
230 def observe_end(self):
231 log.msg("the end of things")
232
233 pb.setCopierForClass(VeryVeryComplicatedCacheable, RatherBaroqueCache)
234
235
236 class SimpleLocalCache(pb.RemoteCache):
237 def setCopyableState(self, state):
238 self.__dict__.update(state)
239
240 def checkMethod(self):
241 return self.check
242
243 def checkSelf(self):
244 return self
245
246 def check(self):
247 return 1
248
249 pb.setCopierForClass(SimpleCache, SimpleLocalCache)
250
251
252 class NestedCache(pb.Referenceable):
253 def __init__(self):
254 self.x = SimpleCache()
255
256 def remote_getCache(self):
257 return [self.x,self.x]
258
259 def remote_putCache(self, cache):
260 return (self.x is cache)
261
262
263 class Observable(pb.Referenceable):
264 def __init__(self):
265 self.observers = []
266
267 def remote_observe(self, obs):
268 self.observers.append(obs)
269
270 def remote_unobserve(self, obs):
271 self.observers.remove(obs)
272
273 def notify(self, obj):
274 for observer in self.observers:
275 observer.callRemote('notify', self, obj)
276
277
278 class DeferredRemote(pb.Referenceable):
279 def __init__(self):
280 self.run = 0
281
282 def runMe(self, arg):
283 self.run = arg
284 return arg + 1
285
286 def dontRunMe(self, arg):
287 assert 0, "shouldn't have been run!"
288
289 def remote_doItLater(self):
290 d = defer.Deferred()
291 d.addCallbacks(self.runMe, self.dontRunMe)
292 self.d = d
293 return d
294
295
296 class Observer(pb.Referenceable):
297 notified = 0
298 obj = None
299 def remote_notify(self, other, obj):
300 self.obj = obj
301 self.notified = self.notified + 1
302 other.callRemote('unobserve',self)
303
304
305 class NewStyleCopy(pb.Copyable, pb.RemoteCopy, object):
306 def __init__(self, s):
307 self.s = s
308 pb.setUnjellyableForClass(NewStyleCopy, NewStyleCopy)
309
310
311 class NewStyleCopy2(pb.Copyable, pb.RemoteCopy, object):
312 allocated = 0
313 initialized = 0
314 value = 1
315
316 def __new__(self):
317 NewStyleCopy2.allocated += 1
318 inst = object.__new__(self)
319 inst.value = 2
320 return inst
321
322 def __init__(self):
323 NewStyleCopy2.initialized += 1
324
325 pb.setUnjellyableForClass(NewStyleCopy2, NewStyleCopy2)
326
327
328 class NewStyleCacheCopy(pb.Cacheable, pb.RemoteCache, object):
329 def getStateToCacheAndObserveFor(self, perspective, observer):
330 return self.__dict__
331
332 pb.setCopierForClass(NewStyleCacheCopy, NewStyleCacheCopy)
333
334
335 class Echoer(pb.Root):
336 def remote_echo(self, st):
337 return st
338
339
340 class CachedReturner(pb.Root):
341 def __init__(self, cache):
342 self.cache = cache
343 def remote_giveMeCache(self, st):
344 return self.cache
345
346
347 class NewStyleTestCase(unittest.TestCase):
348 def setUp(self):
349 """
350 Create a pb server using L{Echoer} protocol and connect a client to it.
351 """
352 self.server = reactor.listenTCP(0, pb.PBServerFactory(Echoer()))
353 clientFactory = pb.PBClientFactory()
354 reactor.connectTCP("localhost", self.server.getHost().port,
355 clientFactory)
356 def gotRoot(ref):
357 self.ref = ref
358 return clientFactory.getRootObject().addCallback(gotRoot)
359
360
361 def tearDown(self):
362 """
363 Close client and server connections, reset values of L{NewStyleCopy2}
364 class variables.
365 """
366 NewStyleCopy2.allocated = 0
367 NewStyleCopy2.initialized = 0
368 NewStyleCopy2.value = 1
369 self.ref.broker.transport.loseConnection()
370 return self.server.stopListening()
371
372 def test_newStyle(self):
373 """
374 Create a new style object, send it over the wire, and check the result.
375 """
376 orig = NewStyleCopy("value")
377 d = self.ref.callRemote("echo", orig)
378 def cb(res):
379 self.failUnless(isinstance(res, NewStyleCopy))
380 self.failUnlessEqual(res.s, "value")
381 self.failIf(res is orig) # no cheating :)
382 d.addCallback(cb)
383 return d
384
385 def test_alloc(self):
386 """
387 Send a new style object and check the number of allocations.
388 """
389 orig = NewStyleCopy2()
390 self.failUnlessEqual(NewStyleCopy2.allocated, 1)
391 self.failUnlessEqual(NewStyleCopy2.initialized, 1)
392 d = self.ref.callRemote("echo", orig)
393 def cb(res):
394 # receiving the response creates a third one on the way back
395 self.failUnless(isinstance(res, NewStyleCopy2))
396 self.failUnlessEqual(res.value, 2)
397 self.failUnlessEqual(NewStyleCopy2.allocated, 3)
398 self.failUnlessEqual(NewStyleCopy2.initialized, 1)
399 self.failIf(res is orig) # no cheating :)
400 # sending the object creates a second one on the far side
401 d.addCallback(cb)
402 return d
403
404
405
406 class ConnectionNotifyServerFactory(pb.PBServerFactory):
407 """
408 A server factory which stores the last connection and fires a
409 L{defer.Deferred} on connection made. This factory can handle only one
410 client connection.
411
412 @ivar protocolInstance: the last protocol instance.
413 @type protocolInstance: C{pb.Broker}
414
415 @ivar connectionMade: the deferred fired upon connection.
416 @type connectionMade: C{defer.Deferred}
417 """
418 protocolInstance = None
419
420 def __init__(self, root):
421 """
422 Initialize the factory.
423 """
424 pb.PBServerFactory.__init__(self, root)
425 self.connectionMade = defer.Deferred()
426
427
428 def clientConnectionMade(self, protocol):
429 """
430 Store the protocol and fire the connection deferred.
431 """
432 self.protocolInstance = protocol
433 self.connectionMade.callback(None)
434
435
436
437 class NewStyleCachedTestCase(unittest.TestCase):
438 def setUp(self):
439 """
440 Create a pb server using L{CachedReturner} protocol and connect a
441 client to it.
442 """
443 self.orig = NewStyleCacheCopy()
444 self.orig.s = "value"
445 self.server = reactor.listenTCP(0,
446 ConnectionNotifyServerFactory(CachedReturner(self.orig)))
447 clientFactory = pb.PBClientFactory()
448 reactor.connectTCP("localhost", self.server.getHost().port,
449 clientFactory)
450 def gotRoot(ref):
451 self.ref = ref
452 d1 = clientFactory.getRootObject().addCallback(gotRoot)
453 d2 = self.server.factory.connectionMade
454 return defer.gatherResults([d1, d2])
455
456
457 def tearDown(self):
458 """
459 Close client and server connections.
460 """
461 self.server.factory.protocolInstance.transport.loseConnection()
462 self.ref.broker.transport.loseConnection()
463 return self.server.stopListening()
464
465
466 def test_newStyleCache(self):
467 """
468 Get the object from the cache, and checks its properties.
469 """
470 d = self.ref.callRemote("giveMeCache", self.orig)
471 def cb(res):
472 self.failUnless(isinstance(res, NewStyleCacheCopy))
473 self.failUnlessEqual(res.s, "value")
474 self.failIf(res is self.orig) # no cheating :)
475 d.addCallback(cb)
476 return d
477
478
479
480 class BrokerTestCase(unittest.TestCase):
481 thunkResult = None
482
483 def tearDown(self):
484 try:
485 # from RemotePublished.getFileName
486 os.unlink('None-None-TESTING.pub')
487 except OSError:
488 pass
489
490 def thunkErrorBad(self, error):
491 self.fail("This should cause a return value, not %s" % (error,))
492
493 def thunkResultGood(self, result):
494 self.thunkResult = result
495
496 def thunkErrorGood(self, tb):
497 pass
498
499 def thunkResultBad(self, result):
500 self.fail("This should cause an error, not %s" % (result,))
501
502 def test_reference(self):
503 c, s, pump = connectedServerAndClient()
504
505 class X(pb.Referenceable):
506 def remote_catch(self,arg):
507 self.caught = arg
508
509 class Y(pb.Referenceable):
510 def remote_throw(self, a, b):
511 a.callRemote('catch', b)
512
513 s.setNameForLocal("y", Y())
514 y = c.remoteForName("y")
515 x = X()
516 z = X()
517 y.callRemote('throw', x, z)
518 pump.pump()
519 pump.pump()
520 pump.pump()
521 self.assertIdentical(x.caught, z, "X should have caught Z")
522
523 # make sure references to remote methods are equals
524 self.assertEquals(y.remoteMethod('throw'), y.remoteMethod('throw'))
525
526 def test_result(self):
527 c, s, pump = connectedServerAndClient()
528 for x, y in (c, s), (s, c):
529 # test reflexivity
530 foo = SimpleRemote()
531 x.setNameForLocal("foo", foo)
532 bar = y.remoteForName("foo")
533 self.expectedThunkResult = 8
534 bar.callRemote('thunk',self.expectedThunkResult - 1
535 ).addCallbacks(self.thunkResultGood, self.thunkErrorBad)
536 # Send question.
537 pump.pump()
538 # Send response.
539 pump.pump()
540 # Shouldn't require any more pumping than that...
541 self.assertEquals(self.thunkResult, self.expectedThunkResult,
542 "result wasn't received.")
543
544 def refcountResult(self, result):
545 self.nestedRemote = result
546
547 def test_tooManyRefs(self):
548 l = []
549 e = []
550 c, s, pump = connectedServerAndClient()
551 foo = NestedRemote()
552 s.setNameForLocal("foo", foo)
553 x = c.remoteForName("foo")
554 for igno in xrange(pb.MAX_BROKER_REFS + 10):
555 if s.transport.closed or c.transport.closed:
556 break
557 x.callRemote("getSimple").addCallbacks(l.append, e.append)
558 pump.pump()
559 expected = (pb.MAX_BROKER_REFS - 1)
560 self.assertTrue(s.transport.closed, "transport was not closed")
561 self.assertEquals(len(l), expected,
562 "expected %s got %s" % (expected, len(l)))
563
564 def test_copy(self):
565 c, s, pump = connectedServerAndClient()
566 foo = NestedCopy()
567 s.setNameForLocal("foo", foo)
568 x = c.remoteForName("foo")
569 x.callRemote('getCopy'
570 ).addCallbacks(self.thunkResultGood, self.thunkErrorBad)
571 pump.pump()
572 pump.pump()
573 self.assertEquals(self.thunkResult.x, 1)
574 self.assertEquals(self.thunkResult.y['Hello'], 'World')
575 self.assertEquals(self.thunkResult.z[0], 'test')
576
577 def test_observe(self):
578 c, s, pump = connectedServerAndClient()
579
580 # this is really testing the comparison between remote objects, to make
581 # sure that you can *UN*observe when you have an observer architecture.
582 a = Observable()
583 b = Observer()
584 s.setNameForLocal("a", a)
585 ra = c.remoteForName("a")
586 ra.callRemote('observe',b)
587 pump.pump()
588 a.notify(1)
589 pump.pump()
590 pump.pump()
591 a.notify(10)
592 pump.pump()
593 pump.pump()
594 self.assertNotIdentical(b.obj, None, "didn't notify")
595 self.assertEquals(b.obj, 1, 'notified too much')
596
597 def test_defer(self):
598 c, s, pump = connectedServerAndClient()
599 d = DeferredRemote()
600 s.setNameForLocal("d", d)
601 e = c.remoteForName("d")
602 pump.pump(); pump.pump()
603 results = []
604 e.callRemote('doItLater').addCallback(results.append)
605 pump.pump(); pump.pump()
606 self.assertFalse(d.run, "Deferred method run too early.")
607 d.d.callback(5)
608 self.assertEquals(d.run, 5, "Deferred method run too late.")
609 pump.pump(); pump.pump()
610 self.assertEquals(results[0], 6, "Incorrect result.")
611
612
613 def test_refcount(self):
614 c, s, pump = connectedServerAndClient()
615 foo = NestedRemote()
616 s.setNameForLocal("foo", foo)
617 bar = c.remoteForName("foo")
618 bar.callRemote('getSimple'
619 ).addCallbacks(self.refcountResult, self.thunkErrorBad)
620
621 # send question
622 pump.pump()
623 # send response
624 pump.pump()
625
626 # delving into internal structures here, because GC is sort of
627 # inherently internal.
628 rluid = self.nestedRemote.luid
629 self.assertIn(rluid, s.localObjects)
630 del self.nestedRemote
631 # nudge the gc
632 if sys.hexversion >= 0x2000000 and os.name != "java":
633 gc.collect()
634 # try to nudge the GC even if we can't really
635 pump.pump()
636 pump.pump()
637 pump.pump()
638 self.assertNotIn(rluid, s.localObjects)
639
640 def test_cache(self):
641 c, s, pump = connectedServerAndClient()
642 obj = NestedCache()
643 obj2 = NestedComplicatedCache()
644 vcc = obj2.c
645 s.setNameForLocal("obj", obj)
646 s.setNameForLocal("xxx", obj2)
647 o2 = c.remoteForName("obj")
648 o3 = c.remoteForName("xxx")
649 coll = []
650 o2.callRemote("getCache"
651 ).addCallback(coll.append).addErrback(coll.append)
652 o2.callRemote("getCache"
653 ).addCallback(coll.append).addErrback(coll.append)
654 complex = []
655 o3.callRemote("getCache").addCallback(complex.append)
656 o3.callRemote("getCache").addCallback(complex.append)
657 pump.flush()
658 # `worst things first'
659 self.assertEquals(complex[0].x, 1)
660 self.assertEquals(complex[0].y, 2)
661 self.assertEquals(complex[0].foo, 3)
662
663 vcc.setFoo4()
664 pump.flush()
665 self.assertEquals(complex[0].foo, 4)
666 self.assertEquals(len(coll), 2)
667 cp = coll[0][0]
668 self.assertIdentical(cp.checkMethod().im_self, cp,
669 "potential refcounting issue")
670 self.assertIdentical(cp.checkSelf(), cp,
671 "other potential refcounting issue")
672 col2 = []
673 o2.callRemote('putCache',cp).addCallback(col2.append)
674 pump.flush()
675 # The objects were the same (testing lcache identity)
676 self.assertTrue(col2[0])
677 # test equality of references to methods
678 self.assertEquals(o2.remoteMethod("getCache"),
679 o2.remoteMethod("getCache"))
680
681 # now, refcounting (similiar to testRefCount)
682 luid = cp.luid
683 baroqueLuid = complex[0].luid
684 self.assertIn(luid, s.remotelyCachedObjects,
685 "remote cache doesn't have it")
686 del coll
687 del cp
688 pump.flush()
689 del complex
690 del col2
691 # extra nudge...
692 pump.flush()
693 # del vcc.observer
694 # nudge the gc
695 if sys.hexversion >= 0x2000000 and os.name != "java":
696 gc.collect()
697 # try to nudge the GC even if we can't really
698 pump.flush()
699 # The GC is done with it.
700 self.assertNotIn(luid, s.remotelyCachedObjects,
701 "Server still had it after GC")
702 self.assertNotIn(luid, c.locallyCachedObjects,
703 "Client still had it after GC")
704 self.assertNotIn(baroqueLuid, s.remotelyCachedObjects,
705 "Server still had complex after GC")
706 self.assertNotIn(baroqueLuid, c.locallyCachedObjects,
707 "Client still had complex after GC")
708 self.assertIdentical(vcc.observer, None, "observer was not removed")
709
710 def test_publishable(self):
711 try:
712 os.unlink('None-None-TESTING.pub') # from RemotePublished.getFileNam e
713 except OSError:
714 pass # Sometimes it's not there.
715 c, s, pump = connectedServerAndClient()
716 foo = GetPublisher()
717 # foo.pub.timestamp = 1.0
718 s.setNameForLocal("foo", foo)
719 bar = c.remoteForName("foo")
720 accum = []
721 bar.callRemote('getPub').addCallbacks(accum.append, self.thunkErrorBad)
722 pump.flush()
723 obj = accum.pop()
724 self.assertEquals(obj.activateCalled, 1)
725 self.assertEquals(obj.isActivated, 1)
726 self.assertEquals(obj.yayIGotPublished, 1)
727 # timestamp's dirty, we don't have a cache file
728 self.assertEquals(obj._wasCleanWhenLoaded, 0)
729 c, s, pump = connectedServerAndClient()
730 s.setNameForLocal("foo", foo)
731 bar = c.remoteForName("foo")
732 bar.callRemote('getPub').addCallbacks(accum.append, self.thunkErrorBad)
733 pump.flush()
734 obj = accum.pop()
735 # timestamp's clean, our cache file is up-to-date
736 self.assertEquals(obj._wasCleanWhenLoaded, 1)
737
738 def gotCopy(self, val):
739 self.thunkResult = val.id
740
741
742 def test_factoryCopy(self):
743 c, s, pump = connectedServerAndClient()
744 ID = 99
745 obj = NestedCopy()
746 s.setNameForLocal("foo", obj)
747 x = c.remoteForName("foo")
748 x.callRemote('getFactory', ID
749 ).addCallbacks(self.gotCopy, self.thunkResultBad)
750 pump.pump()
751 pump.pump()
752 pump.pump()
753 self.assertEquals(self.thunkResult, ID,
754 "ID not correct on factory object %s" % (self.thunkResult,))
755
756
757 bigString = "helloworld" * 50
758
759 callbackArgs = None
760 callbackKeyword = None
761
762 def finishedCallback(*args, **kw):
763 global callbackArgs, callbackKeyword
764 callbackArgs = args
765 callbackKeyword = kw
766
767
768 class Pagerizer(pb.Referenceable):
769 def __init__(self, callback, *args, **kw):
770 self.callback, self.args, self.kw = callback, args, kw
771
772 def remote_getPages(self, collector):
773 util.StringPager(collector, bigString, 100,
774 self.callback, *self.args, **self.kw)
775 self.args = self.kw = None
776
777
778 class FilePagerizer(pb.Referenceable):
779 pager = None
780
781 def __init__(self, filename, callback, *args, **kw):
782 self.filename = filename
783 self.callback, self.args, self.kw = callback, args, kw
784
785 def remote_getPages(self, collector):
786 self.pager = util.FilePager(collector, file(self.filename),
787 self.callback, *self.args, **self.kw)
788 self.args = self.kw = None
789
790
791
792 class PagingTestCase(unittest.TestCase):
793 """
794 Test pb objects sending data by pages.
795 """
796
797 def setUp(self):
798 """
799 Create a file used to test L{util.FilePager}.
800 """
801 self.filename = self.mktemp()
802 fd = file(self.filename, 'w')
803 fd.write(bigString)
804 fd.close()
805
806
807 def test_pagingWithCallback(self):
808 """
809 Test L{util.StringPager}, passing a callback to fire when all pages
810 are sent.
811 """
812 c, s, pump = connectedServerAndClient()
813 s.setNameForLocal("foo", Pagerizer(finishedCallback, 'hello', value=10))
814 x = c.remoteForName("foo")
815 l = []
816 util.getAllPages(x, "getPages").addCallback(l.append)
817 while not l:
818 pump.pump()
819 self.assertEquals(''.join(l[0]), bigString,
820 "Pages received not equal to pages sent!")
821 self.assertEquals(callbackArgs, ('hello',),
822 "Completed callback not invoked")
823 self.assertEquals(callbackKeyword, {'value': 10},
824 "Completed callback not invoked")
825
826
827 def test_pagingWithoutCallback(self):
828 """
829 Test L{util.StringPager} without a callback.
830 """
831 c, s, pump = connectedServerAndClient()
832 s.setNameForLocal("foo", Pagerizer(None))
833 x = c.remoteForName("foo")
834 l = []
835 util.getAllPages(x, "getPages").addCallback(l.append)
836 while not l:
837 pump.pump()
838 self.assertEquals(''.join(l[0]), bigString,
839 "Pages received not equal to pages sent!")
840
841
842 def test_emptyFilePaging(self):
843 """
844 Test L{util.FilePager}, sending an empty file.
845 """
846 filenameEmpty = self.mktemp()
847 fd = file(filenameEmpty, 'w')
848 fd.close()
849 c, s, pump = connectedServerAndClient()
850 pagerizer = FilePagerizer(filenameEmpty, None)
851 s.setNameForLocal("bar", pagerizer)
852 x = c.remoteForName("bar")
853 l = []
854 util.getAllPages(x, "getPages").addCallback(l.append)
855 ttl = 10
856 while not l and ttl > 0:
857 pump.pump()
858 ttl -= 1
859 if not ttl:
860 self.fail('getAllPages timed out')
861 self.assertEquals(''.join(l[0]), '',
862 "Pages received not equal to pages sent!")
863
864
865 def test_filePagingWithCallback(self):
866 """
867 Test L{util.FilePager}, passing a callback to fire when all pages
868 are sent, and verify that the pager doesn't keep chunks in memory.
869 """
870 c, s, pump = connectedServerAndClient()
871 pagerizer = FilePagerizer(self.filename, finishedCallback,
872 'frodo', value = 9)
873 s.setNameForLocal("bar", pagerizer)
874 x = c.remoteForName("bar")
875 l = []
876 util.getAllPages(x, "getPages").addCallback(l.append)
877 while not l:
878 pump.pump()
879 self.assertEquals(''.join(l[0]), bigString,
880 "Pages received not equal to pages sent!")
881 self.assertEquals(callbackArgs, ('frodo',),
882 "Completed callback not invoked")
883 self.assertEquals(callbackKeyword, {'value': 9},
884 "Completed callback not invoked")
885 self.assertEquals(pagerizer.pager.chunks, [])
886
887
888 def test_filePagingWithoutCallback(self):
889 """
890 Test L{util.FilePager} without a callback.
891 """
892 c, s, pump = connectedServerAndClient()
893 pagerizer = FilePagerizer(self.filename, None)
894 s.setNameForLocal("bar", pagerizer)
895 x = c.remoteForName("bar")
896 l = []
897 util.getAllPages(x, "getPages").addCallback(l.append)
898 while not l:
899 pump.pump()
900 self.assertEquals(''.join(l[0]), bigString,
901 "Pages received not equal to pages sent!")
902 self.assertEquals(pagerizer.pager.chunks, [])
903
904
905
906 class DumbPublishable(publish.Publishable):
907 def getStateToPublish(self):
908 return {"yayIGotPublished": 1}
909
910
911 class DumbPub(publish.RemotePublished):
912 def activated(self):
913 self.activateCalled = 1
914
915
916 class GetPublisher(pb.Referenceable):
917 def __init__(self):
918 self.pub = DumbPublishable("TESTING")
919
920 def remote_getPub(self):
921 return self.pub
922
923
924 pb.setCopierForClass(DumbPublishable, DumbPub)
925
926 class DisconnectionTestCase(unittest.TestCase):
927 """
928 Test disconnection callbacks.
929 """
930
931 def error(self, *args):
932 raise RuntimeError("I shouldn't have been called: %s" % (args,))
933
934
935 def gotDisconnected(self):
936 """
937 Called on broker disconnect.
938 """
939 self.gotCallback = 1
940
941 def objectDisconnected(self, o):
942 """
943 Called on RemoteReference disconnect.
944 """
945 self.assertEquals(o, self.remoteObject)
946 self.objectCallback = 1
947
948 def test_badSerialization(self):
949 c, s, pump = connectedServerAndClient()
950 pump.pump()
951 s.setNameForLocal("o", BadCopySet())
952 g = c.remoteForName("o")
953 l = []
954 g.callRemote("setBadCopy", BadCopyable()).addErrback(l.append)
955 pump.flush()
956 self.assertEquals(len(l), 1)
957
958 def test_disconnection(self):
959 c, s, pump = connectedServerAndClient()
960 pump.pump()
961 s.setNameForLocal("o", SimpleRemote())
962
963 # get a client reference to server object
964 r = c.remoteForName("o")
965 pump.pump()
966 pump.pump()
967 pump.pump()
968
969 # register and then unregister disconnect callbacks
970 # making sure they get unregistered
971 c.notifyOnDisconnect(self.error)
972 self.assertIn(self.error, c.disconnects)
973 c.dontNotifyOnDisconnect(self.error)
974 self.assertNotIn(self.error, c.disconnects)
975
976 r.notifyOnDisconnect(self.error)
977 self.assertIn(r._disconnected, c.disconnects)
978 self.assertIn(self.error, r.disconnectCallbacks)
979 r.dontNotifyOnDisconnect(self.error)
980 self.assertNotIn(r._disconnected, c.disconnects)
981 self.assertNotIn(self.error, r.disconnectCallbacks)
982
983 # register disconnect callbacks
984 c.notifyOnDisconnect(self.gotDisconnected)
985 r.notifyOnDisconnect(self.objectDisconnected)
986 self.remoteObject = r
987
988 # disconnect
989 c.connectionLost(failure.Failure(main.CONNECTION_DONE))
990 self.assertTrue(self.gotCallback)
991 self.assertTrue(self.objectCallback)
992
993
994 class FreakOut(Exception):
995 pass
996
997
998 class BadCopyable(pb.Copyable):
999 def getStateToCopyFor(self, p):
1000 raise FreakOut()
1001
1002
1003 class BadCopySet(pb.Referenceable):
1004 def remote_setBadCopy(self, bc):
1005 return None
1006
1007
1008 class LocalRemoteTest(util.LocalAsRemote):
1009 reportAllTracebacks = 0
1010
1011 def sync_add1(self, x):
1012 return x + 1
1013
1014 def async_add(self, x=0, y=1):
1015 return x + y
1016
1017 def async_fail(self):
1018 raise RuntimeError()
1019
1020
1021
1022 class TestRealm(object):
1023 """
1024 A realm which repeatedly gives out a single instance of L{MyPerspective}
1025 for non-anonymous logins and which gives out a new instance of L{Echoer}
1026 for each anonymous login.
1027 """
1028
1029 def __init__(self):
1030 self.p = MyPerspective()
1031
1032 def requestAvatar(self, avatarId, mind, interface):
1033 """
1034 Verify that the mind and interface supplied have the expected values
1035 (this should really be done somewhere else, like inside a test method)
1036 and return an avatar appropriate for the given identifier.
1037 """
1038 assert interface == pb.IPerspective
1039 assert mind == "BRAINS!"
1040 if avatarId is checkers.ANONYMOUS:
1041 return pb.IPerspective, Echoer(), lambda: None
1042 else:
1043 self.p.loggedIn = 1
1044 return pb.IPerspective, self.p, self.p.logout
1045
1046
1047
1048 class MyPerspective(pb.Avatar):
1049
1050 implements(pb.IPerspective)
1051
1052 loggedIn = loggedOut = False
1053
1054 def __init__(self):
1055 pass
1056
1057
1058 def perspective_getViewPoint(self):
1059 return MyView()
1060
1061
1062 def perspective_add(self, a, b):
1063 """
1064 Add the given objects and return the result. This is a method
1065 unavailable on L{Echoer}, so it can only be invoked by authenticated
1066 users who received their avatar from L{TestRealm}.
1067 """
1068 return a + b
1069
1070
1071 def logout(self):
1072 self.loggedOut = True
1073
1074
1075
1076 class MyView(pb.Viewable):
1077
1078 def view_check(self, user):
1079 return isinstance(user, MyPerspective)
1080
1081
1082
1083 class NewCredTestCase(unittest.TestCase):
1084 """
1085 Tests related to the L{twisted.cred} support in PB.
1086 """
1087 def setUp(self):
1088 """
1089 Create a portal with no checkers and wrap it around a simple test
1090 realm. Set up a PB server on a TCP port which serves perspectives
1091 using that portal.
1092 """
1093 self.realm = TestRealm()
1094 self.portal = portal.Portal(self.realm)
1095 self.factory = pb.PBServerFactory(self.portal)
1096 self.port = reactor.listenTCP(0, self.factory, interface="127.0.0.1")
1097 self.portno = self.port.getHost().port
1098
1099
1100 def tearDown(self):
1101 """
1102 Shut down the TCP port created by L{setUp}.
1103 """
1104 return self.port.stopListening()
1105
1106 def getFactoryAndRootObject(self, clientFactory=pb.PBClientFactory):
1107 factory = clientFactory()
1108 rootObjDeferred = factory.getRootObject()
1109 reactor.connectTCP('127.0.0.1', self.portno, factory)
1110 return factory, rootObjDeferred
1111
1112
1113 def test_getRootObject(self):
1114 """
1115 Assert only that L{PBClientFactory.getRootObject}'s Deferred fires with
1116 a L{RemoteReference}.
1117 """
1118 factory, rootObjDeferred = self.getFactoryAndRootObject()
1119
1120 def gotRootObject(rootObj):
1121 self.failUnless(isinstance(rootObj, pb.RemoteReference))
1122 disconnectedDeferred = defer.Deferred()
1123 rootObj.notifyOnDisconnect(disconnectedDeferred.callback)
1124 factory.disconnect()
1125 return disconnectedDeferred
1126
1127 return rootObjDeferred.addCallback(gotRootObject)
1128
1129
1130 def test_deadReferenceError(self):
1131 """
1132 Test that when a connection is lost, calling a method on a
1133 RemoteReference obtained from it raises DeadReferenceError.
1134 """
1135 factory, rootObjDeferred = self.getFactoryAndRootObject()
1136
1137 def gotRootObject(rootObj):
1138 disconnectedDeferred = defer.Deferred()
1139 rootObj.notifyOnDisconnect(disconnectedDeferred.callback)
1140
1141 def lostConnection(ign):
1142 self.assertRaises(
1143 pb.DeadReferenceError,
1144 rootObj.callRemote, 'method')
1145
1146 disconnectedDeferred.addCallback(lostConnection)
1147 factory.disconnect()
1148 return disconnectedDeferred
1149
1150 return rootObjDeferred.addCallback(gotRootObject)
1151
1152
1153 def test_clientConnectionLost(self):
1154 """
1155 Test that if the L{reconnecting} flag is passed with a True value then
1156 a remote call made from a disconnection notification callback gets a
1157 result successfully.
1158 """
1159 class ReconnectOnce(pb.PBClientFactory):
1160 reconnectedAlready = False
1161 def clientConnectionLost(self, connector, reason):
1162 reconnecting = not self.reconnectedAlready
1163 self.reconnectedAlready = True
1164 if reconnecting:
1165 connector.connect()
1166 return pb.PBClientFactory.clientConnectionLost(
1167 self, connector, reason, reconnecting)
1168
1169 factory, rootObjDeferred = self.getFactoryAndRootObject(ReconnectOnce)
1170
1171 def gotRootObject(rootObj):
1172 self.assertIsInstance(rootObj, pb.RemoteReference)
1173
1174 d = defer.Deferred()
1175 rootObj.notifyOnDisconnect(d.callback)
1176 factory.disconnect()
1177
1178 def disconnected(ign):
1179 d = factory.getRootObject()
1180
1181 def gotAnotherRootObject(anotherRootObj):
1182 self.assertIsInstance(anotherRootObj, pb.RemoteReference)
1183
1184 d = defer.Deferred()
1185 anotherRootObj.notifyOnDisconnect(d.callback)
1186 factory.disconnect()
1187 return d
1188 return d.addCallback(gotAnotherRootObject)
1189 return d.addCallback(disconnected)
1190 return rootObjDeferred.addCallback(gotRootObject)
1191
1192
1193 def test_immediateClose(self):
1194 """
1195 Test that if a Broker loses its connection without receiving any bytes,
1196 it doesn't raise any exceptions or log any errors.
1197 """
1198 serverProto = self.factory.buildProtocol(('127.0.0.1', 12345))
1199 serverProto.makeConnection(protocol.FileWrapper(StringIO()))
1200 serverProto.connectionLost(failure.Failure(main.CONNECTION_DONE))
1201
1202
1203 def test_loginConnectionRefused(self):
1204 """
1205 L{PBClientFactory.login} returns a L{Deferred} which is errbacked
1206 with the L{ConnectionRefusedError} if the underlying connection is
1207 refused.
1208 """
1209 clientFactory = pb.PBClientFactory()
1210 loginDeferred = clientFactory.login(
1211 credentials.UsernamePassword("foo", "bar"))
1212 clientFactory.clientConnectionFailed(
1213 None,
1214 failure.Failure(
1215 ConnectionRefusedError("Test simulated refused connection")))
1216 return self.assertFailure(loginDeferred, ConnectionRefusedError)
1217
1218
1219 def test_loginLogout(self):
1220 """
1221 Test that login can be performed with IUsernamePassword credentials and
1222 that when the connection is dropped the avatar is logged out.
1223 """
1224 self.portal.registerChecker(
1225 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1226 factory = pb.PBClientFactory()
1227 creds = credentials.UsernamePassword("user", "pass")
1228
1229 # NOTE: real code probably won't need anything where we have the
1230 # "BRAINS!" argument, passing None is fine. We just do it here to
1231 # test that it is being passed. It is used to give additional info to
1232 # the realm to aid perspective creation, if you don't need that,
1233 # ignore it.
1234 mind = "BRAINS!"
1235
1236 d = factory.login(creds, mind)
1237 def cbLogin(perspective):
1238 self.assertEquals(self.realm.p.loggedIn, 1)
1239 self.assert_(isinstance(perspective, pb.RemoteReference))
1240
1241 factory.disconnect()
1242 d = Deferred()
1243 reactor.callLater(1.0, d.callback, None)
1244 return d
1245 d.addCallback(cbLogin)
1246
1247 def cbLogout(ignored):
1248 self.assertEquals(self.realm.p.loggedOut, 1)
1249 d.addCallback(cbLogout)
1250
1251 reactor.connectTCP("127.0.0.1", self.portno, factory)
1252 return d
1253
1254
1255 def test_badUsernamePasswordLogin(self):
1256 """
1257 Test that a login attempt with an invalid user or invalid password
1258 fails in the appropriate way.
1259 """
1260 self.portal.registerChecker(
1261 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1262 factory = pb.PBClientFactory()
1263
1264 firstLogin = factory.login(
1265 credentials.UsernamePassword('nosuchuser', 'pass'))
1266 secondLogin = factory.login(
1267 credentials.UsernamePassword('user', 'wrongpass'))
1268
1269 self.assertFailure(firstLogin, UnauthorizedLogin)
1270 self.assertFailure(secondLogin, UnauthorizedLogin)
1271 d = gatherResults([firstLogin, secondLogin])
1272
1273 def cleanup(passthrough):
1274 self.flushLoggedErrors(UnauthorizedLogin)
1275 factory.disconnect()
1276 return passthrough
1277 d.addBoth(cleanup)
1278
1279 reactor.connectTCP("127.0.0.1", self.portno, factory)
1280 return d
1281
1282
1283 def test_anonymousLogin(self):
1284 """
1285 Verify that a PB server using a portal configured with an checker which
1286 allows IAnonymous credentials can be logged into using IAnonymous
1287 credentials.
1288 """
1289 self.portal.registerChecker(checkers.AllowAnonymousAccess())
1290 factory = pb.PBClientFactory()
1291 d = factory.login(credentials.Anonymous(), "BRAINS!")
1292
1293 def cbLoggedIn(perspective):
1294 return perspective.callRemote('echo', 123)
1295 d.addCallback(cbLoggedIn)
1296
1297 d.addCallback(self.assertEqual, 123)
1298
1299 def cleanup(passthrough):
1300 factory.disconnect()
1301 d = Deferred()
1302 reactor.callLater(1.0, d.callback, None)
1303 return d
1304 d.addBoth(cleanup)
1305
1306 reactor.connectTCP("127.0.0.1", self.portno, factory)
1307 return d
1308
1309
1310 def test_anonymousLoginNotPermitted(self):
1311 """
1312 Verify that without an anonymous checker set up, anonymous login is
1313 rejected.
1314 """
1315 self.portal.registerChecker(
1316 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1317 factory = pb.PBClientFactory()
1318 d = factory.login(credentials.Anonymous(),"BRAINS!")
1319 self.assertFailure(d, UnhandledCredentials)
1320
1321 def cleanup(passthrough):
1322 self.flushLoggedErrors(UnhandledCredentials)
1323 factory.disconnect()
1324 return passthrough
1325 d.addBoth(cleanup)
1326
1327 reactor.connectTCP('127.0.0.1', self.portno, factory)
1328 return d
1329
1330
1331 def test_anonymousLoginWithMultipleCheckers(self):
1332 """
1333 Like L{test_anonymousLogin} but against a portal with a checker for
1334 both IAnonymous and IUsernamePassword.
1335 """
1336 self.portal.registerChecker(checkers.AllowAnonymousAccess())
1337 self.portal.registerChecker(
1338 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1339 factory = pb.PBClientFactory()
1340 d = factory.login(credentials.Anonymous(), "BRAINS!")
1341
1342 def cbLogin(perspective):
1343 return perspective.callRemote('echo', 123)
1344 d.addCallback(cbLogin)
1345
1346 d.addCallback(self.assertEqual, 123)
1347
1348 def cleanup(passthrough):
1349 factory.disconnect()
1350 return passthrough
1351 d.addBoth(cleanup)
1352
1353 reactor.connectTCP('127.0.0.1', self.portno, factory)
1354 return d
1355
1356
1357 def test_authenticatedLoginWithMultipleCheckers(self):
1358 """
1359 Like L{test_anonymousLoginWithMultipleCheckers} but check that
1360 username/password authentication works.
1361 """
1362 self.portal.registerChecker(checkers.AllowAnonymousAccess())
1363 self.portal.registerChecker(
1364 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1365 factory = pb.PBClientFactory()
1366 d = factory.login(
1367 credentials.UsernamePassword('user', 'pass'), "BRAINS!")
1368
1369 def cbLogin(perspective):
1370 return perspective.callRemote('add', 100, 23)
1371 d.addCallback(cbLogin)
1372
1373 d.addCallback(self.assertEqual, 123)
1374
1375 def cleanup(passthrough):
1376 factory.disconnect()
1377 return passthrough
1378 d.addBoth(cleanup)
1379
1380 reactor.connectTCP('127.0.0.1', self.portno, factory)
1381 return d
1382
1383
1384 def test_view(self):
1385 """
1386 Verify that a viewpoint can be retrieved after authenticating with
1387 cred.
1388 """
1389 self.portal.registerChecker(
1390 checkers.InMemoryUsernamePasswordDatabaseDontUse(user='pass'))
1391 factory = pb.PBClientFactory()
1392 d = factory.login(
1393 credentials.UsernamePassword("user", "pass"), "BRAINS!")
1394
1395 def cbLogin(perspective):
1396 return perspective.callRemote("getViewPoint")
1397 d.addCallback(cbLogin)
1398
1399 def cbView(viewpoint):
1400 return viewpoint.callRemote("check")
1401 d.addCallback(cbView)
1402
1403 d.addCallback(self.failUnless)
1404
1405 def cleanup(passthrough):
1406 factory.disconnect()
1407 d = Deferred()
1408 reactor.callLater(1.0, d.callback, None)
1409 return d
1410 d.addBoth(cleanup)
1411
1412 reactor.connectTCP("127.0.0.1", self.portno, factory)
1413 return d
1414
1415
1416
1417 class NonSubclassingPerspective:
1418 implements(pb.IPerspective)
1419
1420 # IPerspective implementation
1421 def perspectiveMessageReceived(self, broker, message, args, kwargs):
1422 args = broker.unserialize(args, self)
1423 kwargs = broker.unserialize(kwargs, self)
1424 return broker.serialize((message, args, kwargs))
1425
1426 # Methods required by TestRealm
1427 def logout(self):
1428 self.loggedOut = True
1429
1430
1431
1432 class NSPTestCase(unittest.TestCase):
1433 def setUp(self):
1434 self.realm = TestRealm()
1435 self.realm.p = NonSubclassingPerspective()
1436 self.portal = portal.Portal(self.realm)
1437 self.checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
1438 self.checker.addUser("user", "pass")
1439 self.portal.registerChecker(self.checker)
1440 self.factory = pb.PBServerFactory(self.portal)
1441 self.port = reactor.listenTCP(0, self.factory, interface="127.0.0.1")
1442 self.portno = self.port.getHost().port
1443
1444 def tearDown(self):
1445 return self.port.stopListening()
1446
1447 def test_NSP(self):
1448 factory = pb.PBClientFactory()
1449 d = factory.login(credentials.UsernamePassword('user', 'pass'),
1450 "BRAINS!")
1451 reactor.connectTCP('127.0.0.1', self.portno, factory)
1452 d.addCallback(lambda p: p.callRemote('ANYTHING', 'here', bar='baz'))
1453 d.addCallback(self.assertEquals,
1454 ('ANYTHING', ('here',), {'bar': 'baz'}))
1455 d.addCallback(lambda res: factory.disconnect())
1456 return d
1457
1458
1459
1460 class IForwarded(Interface):
1461 """
1462 Interface used for testing L{util.LocalAsyncForwarder}.
1463 """
1464
1465 def forwardMe():
1466 """
1467 Simple synchronous method.
1468 """
1469
1470 def forwardDeferred():
1471 """
1472 Simple asynchronous method.
1473 """
1474
1475
1476 class Forwarded:
1477 """
1478 Test implementation of L{IForwarded}.
1479
1480 @ivar forwarded: set if C{forwardMe} is called.
1481 @type forwarded: C{bool}
1482 @ivar unforwarded: set if C{dontForwardMe} is called.
1483 @type unforwarded: C{bool}
1484 """
1485 implements(IForwarded)
1486 forwarded = False
1487 unforwarded = False
1488
1489 def forwardMe(self):
1490 """
1491 Set a local flag to test afterwards.
1492 """
1493 self.forwarded = True
1494
1495 def dontForwardMe(self):
1496 """
1497 Set a local flag to test afterwards. This should not be called as it's
1498 not in the interface.
1499 """
1500 self.unforwarded = True
1501
1502 def forwardDeferred(self):
1503 """
1504 Asynchronously return C{True}.
1505 """
1506 return defer.succeed(True)
1507
1508
1509 class SpreadUtilTestCase(unittest.TestCase):
1510 """
1511 Tests for L{twisted.spread.util}.
1512 """
1513
1514 def test_sync(self):
1515 """
1516 Call a synchronous method of a L{util.LocalAsRemote} object and check
1517 the result.
1518 """
1519 o = LocalRemoteTest()
1520 self.assertEquals(o.callRemote("add1", 2), 3)
1521
1522 def test_async(self):
1523 """
1524 Call an asynchronous method of a L{util.LocalAsRemote} object and check
1525 the result.
1526 """
1527 o = LocalRemoteTest()
1528 o = LocalRemoteTest()
1529 d = o.callRemote("add", 2, y=4)
1530 self.assertTrue(isinstance(d, defer.Deferred))
1531 d.addCallback(self.assertEquals, 6)
1532 return d
1533
1534 def test_asyncFail(self):
1535 """
1536 Test a asynchronous failure on a remote method call.
1537 """
1538 l = []
1539 o = LocalRemoteTest()
1540 d = o.callRemote("fail")
1541 def eb(f):
1542 self.assertTrue(isinstance(f, failure.Failure))
1543 f.trap(RuntimeError)
1544 d.addCallbacks(lambda res: self.fail("supposed to fail"), eb)
1545 return d
1546
1547 def test_remoteMethod(self):
1548 """
1549 Test the C{remoteMethod} facility of L{util.LocalAsRemote}.
1550 """
1551 o = LocalRemoteTest()
1552 m = o.remoteMethod("add1")
1553 self.assertEquals(m(3), 4)
1554
1555 def test_localAsyncForwarder(self):
1556 """
1557 Test a call to L{util.LocalAsyncForwarder} using L{Forwarded} local
1558 object.
1559 """
1560 f = Forwarded()
1561 lf = util.LocalAsyncForwarder(f, IForwarded)
1562 lf.callRemote("forwardMe")
1563 self.assertTrue(f.forwarded)
1564 lf.callRemote("dontForwardMe")
1565 self.assertFalse(f.unforwarded)
1566 rr = lf.callRemote("forwardDeferred")
1567 l = []
1568 rr.addCallback(l.append)
1569 self.assertEqual(l[0], 1)
1570
1571
1572
1573 class PBWithSecurityOptionsTest(unittest.TestCase):
1574 """
1575 Test security customization.
1576 """
1577
1578 def test_clientDefaultSecurityOptions(self):
1579 """
1580 By default, client broker should use C{jelly.globalSecurity} as
1581 security settings.
1582 """
1583 factory = pb.PBClientFactory()
1584 broker = factory.buildProtocol(None)
1585 self.assertIdentical(broker.security, jelly.globalSecurity)
1586
1587
1588 def test_serverDefaultSecurityOptions(self):
1589 """
1590 By default, server broker should use C{jelly.globalSecurity} as
1591 security settings.
1592 """
1593 factory = pb.PBServerFactory(Echoer())
1594 broker = factory.buildProtocol(None)
1595 self.assertIdentical(broker.security, jelly.globalSecurity)
1596
1597
1598 def test_clientSecurityCustomization(self):
1599 """
1600 Check that the security settings are passed from the client factory to
1601 the broker object.
1602 """
1603 security = jelly.SecurityOptions()
1604 factory = pb.PBClientFactory(security=security)
1605 broker = factory.buildProtocol(None)
1606 self.assertIdentical(broker.security, security)
1607
1608
1609 def test_serverSecurityCustomization(self):
1610 """
1611 Check that the security settings are passed from the server factory to
1612 the broker object.
1613 """
1614 security = jelly.SecurityOptions()
1615 factory = pb.PBServerFactory(Echoer(), security=security)
1616 broker = factory.buildProtocol(None)
1617 self.assertIdentical(broker.security, security)
1618
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/test/test_paths.py ('k') | third_party/twisted_8_1/twisted/test/test_pbfailure.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698