#! /usr/bin/python
from twisted.trial import unittest
import schema, pb
from tokens import BananaError, Violation, INT, STRING, OPEN
from slicer import UnbananaFailure
class TestBroker(pb.Broker):
def gotAnswer(self, req, results):
self.answers.append((True, req, results))
def gotError(self, req, f):
self.answers.append((False, req, f))
def abandonUnslicer(self, failure, leaf=None):
pass
def freeRemoteReference(self, refID):
pass
class TestReferenceUnslicer(unittest.TestCase):
# OPEN(reference), INT(refid), [STR(interfacename), INT(version)]... CLOSE
def setUp(self):
self.broker = TestBroker()
def newUnslicer(self):
unslicer = pb.ReferenceUnslicer()
unslicer.broker = self.broker
unslicer.opener = self.broker.rootUnslicer
return unslicer
def testReject(self):
u = self.newUnslicer()
self.failUnlessRaises(BananaError, u.checkToken, STRING)
u = self.newUnslicer()
self.failUnlessRaises(BananaError, u.checkToken, OPEN)
def testNoInterfaces(self):
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12)
self.failUnless(u.wantInterfaceList)
rr1 = u.receiveClose()
rr2 = self.broker.remoteReferences.get(12)
self.failUnless(rr2)
self.failUnless(isinstance(rr2, pb.RemoteReference))
self.failUnlessEqual(rr2.broker, self.broker)
self.failUnlessEqual(rr2.refID, 12)
self.failUnlessEqual(rr2.interfaces, None)
def testInterfaces(self):
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12)
self.failUnless(u.wantInterfaceList)
u.checkToken(OPEN)
# pretend we did a u.doOpen("list") here
interfaces = [("IFoo", 1), ("IBar", 2)]
u.receiveChild(interfaces)
rr1 = u.receiveClose()
rr2 = self.broker.remoteReferences.get(12)
self.failUnless(rr2)
self.failUnlessIdentical(rr1, rr2)
self.failUnless(isinstance(rr2, pb.RemoteReference))
self.failUnlessEqual(rr2.broker, self.broker)
self.failUnlessEqual(rr2.refID, 12)
self.failUnlessEqual(rr2.interfaces, interfaces)
class TestAnswer(unittest.TestCase):
# OPEN(answer), INT(reqID), [answer], CLOSE
def setUp(self):
self.broker = TestBroker()
self.broker.answers = []
def newUnslicer(self):
unslicer = pb.AnswerUnslicer()
unslicer.broker = self.broker
unslicer.opener = self.broker.rootUnslicer
unslicer.protocol = self.broker
return unslicer
def testAccept1(self):
req = pb.PendingRequest()
self.broker.waitingForAnswers[12] = req
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12) # causes broker.getRequest
u.checkToken(STRING)
u.receiveChild("results")
self.failIf(self.broker.answers)
u.receiveClose() # causes broker.gotAnswer
self.failUnlessEqual(self.broker.answers, [(True, req, "results")])
def testAccept2(self):
req = pb.PendingRequest()
req.setConstraint(schema.makeConstraint(str))
self.broker.waitingForAnswers[12] = req
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12) # causes broker.getRequest
u.checkToken(STRING)
u.receiveChild("results")
self.failIf(self.broker.answers)
u.receiveClose() # causes broker.gotAnswer
self.failUnlessEqual(self.broker.answers, [(True, req, "results")])
def testReject1(self):
# answer a non-existent request
req = pb.PendingRequest()
self.broker.waitingForAnswers[12] = req
u = self.newUnslicer()
u.checkToken(INT)
self.failUnlessRaises(BananaError, u.receiveChild, 13)
def testReject2(self):
# answer a request with a result that violates the constraint
req = pb.PendingRequest()
req.setConstraint(schema.makeConstraint(int))
self.broker.waitingForAnswers[12] = req
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12)
self.failUnlessRaises(Violation, u.checkToken, STRING)
# this will also errback the request
self.failUnlessEqual(len(self.broker.answers), 1)
err = self.broker.answers[0]
self.failIf(err[0])
self.failUnlessEqual(err[1], req)
f = err[2]
self.failUnless(f.check(Violation))
def testReject3(self):
# answer a request but explode before the CLOSE token is received
req = pb.PendingRequest()
self.broker.waitingForAnswers[12] = req
u = self.newUnslicer()
u.checkToken(INT)
u.receiveChild(12)
u.checkToken(STRING)
u.receiveChild("results")
self.failIf(self.broker.answers)
u.receiveChild(UnbananaFailure()) # abandons unslicer, does errback
self.failUnlessEqual(len(self.broker.answers), 1)
err = self.broker.answers[0]
self.failIf(err[0])
self.failUnlessEqual(err[1], req)
f = err[2]
self.failUnless(isinstance(f,UnbananaFailure))
# close would be ignored, but we had to bypass abandonUnslicer, so
# that code path won't work
#u.receiveClose() # should be ignored
#self.failUnlessEqual(len(self.broker.answers), 1)
#from twisted.internet import interfaces
class Loopback:
# __implements__ = interfaces.ITransport
def write(self, data):
self.peer.dataReceived(data)
class Target:
def __init__(self):
self.calls = []
def getMethodSchema(self, methodname):
return None
def remote_add(self, a, b):
self.calls.append((a,b))
return a+b
class TestCall(unittest.TestCase):
def setUp(self):
self.targetBroker = pb.Broker()
self.callingBroker = pb.Broker()
self.targetTransport = Loopback()
self.targetTransport.peer = self.callingBroker
self.targetBroker.transport = self.targetTransport
self.callingTransport = Loopback()
self.callingTransport.peer = self.targetBroker
self.callingBroker.transport = self.callingTransport
def setupTarget(self):
target = Target()
objID = self.targetBroker.putObj(target)
rr = self.callingBroker.registerRemoteReference(objID, None)
return rr, target
def testCall1(self):
rr, target = self.setupTarget()
d = rr.callRemote("add", a=1, b=2)
self.failUnlessEqual(target.calls, [(1,2)])
r = unittest.deferredResult(d)
self.failUnlessEqual(r, 3)
# the caller still holds the RemoteReference
self.failUnless(self.callingBroker.remoteReferences.has_key(1))
# release the RemoteReference. This does two things: 1) the
# callingBroker will forget about it. 2) they will send a decref to
# the targetBroker so *they* can forget about it.
del rr # this fires a DecRef
import gc; gc.collect() # make sure
self.failIf(self.callingBroker.remoteReferences.has_key(1))
self.failIf(self.targetBroker.localObjects.has_key(1))
def testFail1(self):
rr, target = self.setupTarget()
d = rr.callRemote("add", a=1, b=2, c=3)
self.failIf(target.calls)
f = unittest.deferredError(d)
self.failUnless(str(f).find("remote_add() got an unexpected keyword argument 'c'") != -1)
syntax highlighted by Code2HTML, v. 0.9.1