def testAccept2(self): req = TestRequest(12) req.setConstraint(schema.makeConstraint(str)) self.broker.addRequest(req) u = self.newUnslicer() u.checkToken(INT, 0) u.receiveChild(12) # causes broker.getRequest u.checkToken(STRING, 15) u.receiveChild("results") self.failIf(req.answers) u.receiveClose() # causes broker.gotAnswer self.failUnlessEqual(req.answers, [(True, "results")])
def testReject2(self): req = TestRequest(12) req.setConstraint(schema.makeConstraint(int)) self.broker.addRequest(req) u = self.newUnslicer() u.checkToken(INT, 0) u.receiveChild(12) self.failUnlessRaises(Violation, u.checkToken, STRING, 42) self.failIf(req.answers) v = Violation("icky") v.setLocation("here") u.reportViolation(BananaFailure(v)) self.failUnlessEqual(len(req.answers), 1) err = req.answers[0] self.failIf(err[0]) f = err[1] self.failUnless(f.check(Violation))
def callRemote(self, _name, *args, **kwargs): req = None broker = self.tracker.broker methodConstraintOverride = kwargs.get("_methodConstraint", "none") resultConstraint = kwargs.get("_resultConstraint", "none") useSchema = kwargs.get("_useSchema", True) if "_methodConstraint" in kwargs: del kwargs["_methodConstraint"] if "_resultConstraint" in kwargs: del kwargs["_resultConstraint"] if "_useSchema" in kwargs: del kwargs["_useSchema"] try: reqID = broker.newRequestID() except: return defer.fail() try: req = call.PendingRequest(reqID, self) (methodName, methodSchema) = self._getMethodInfo(_name) req.methodName = methodName # for debugging if methodConstraintOverride != "none": methodSchema = methodConstraintOverride if useSchema and methodSchema: argsdict = methodSchema.mapArguments(args, kwargs) methodSchema.checkAllArgs(kwargs) req.setConstraint(methodSchema.getResponseConstraint()) else: if args: why = "positional arguments require a RemoteInterface" why += " for %s.%s()" % (self, methodName) raise tokens.BananaError(why) argsdict = kwargs if resultConstraint != "none": req.setConstraint(schema.makeConstraint(resultConstraint)) except: # TODO: merge this with the next try/except clause req.fail(failure.Failure()) return req.deferred try: self.tracker.broker.addRequest(req) slicer = call.CallSlicer(reqID, self.tracker.clid, methodName, argsdict) d = broker.send(slicer) except: req.fail(failure.Failure()) return req.deferred d.addErrback(req.fail) return req.deferred
def testReject2(self): # answer a request with a result that violates the constraint req = TestRequest(12) req.setConstraint(schema.makeConstraint(int)) self.broker.addRequest(req) u = self.newUnslicer() u.checkToken(INT, 0) u.receiveChild(12) self.failUnlessRaises(Violation, u.checkToken, STRING, 42) # this does not yet errback the request self.failIf(req.answers) # it gets errbacked when banana reports the violation v = Violation("icky") v.setLocation("here") u.reportViolation(BananaFailure(v)) self.failUnlessEqual(len(req.answers), 1) err = req.answers[0] self.failIf(err[0]) f = err[1] self.failUnless(f.check(Violation))
def callRemote(self, _name, *args, **kwargs): # Note: for consistency, *all* failures are reported asynchronously. req = None broker = self.tracker.broker # remember that "none" is not a valid constraint, so we use it to # mean "not set by the caller", which means we fall back to whatever # the RemoteInterface says. Using None would mean an AnyConstraint, # which is not the same thing. methodConstraintOverride = kwargs.get("_methodConstraint", "none") resultConstraint = kwargs.get("_resultConstraint", "none") useSchema = kwargs.get("_useSchema", True) if "_methodConstraint" in kwargs: del kwargs["_methodConstraint"] if "_resultConstraint" in kwargs: del kwargs["_resultConstraint"] if "_useSchema" in kwargs: del kwargs["_useSchema"] try: # newRequestID() could fail with a DeadReferenceError reqID = broker.newRequestID() except: return defer.fail() try: # in this clause, we validate the outbound arguments against our # notion of what the other end will accept (the RemoteInterface) req = call.PendingRequest(reqID, self) # first, figure out which method they want to invoke (methodName, methodSchema) = self._getMethodInfo(_name) req.methodName = methodName # for debugging if methodConstraintOverride != "none": methodSchema = methodConstraintOverride if useSchema and methodSchema: # turn positional arguments into kwargs. mapArguments() could # fail for bad argument names or missing required parameters argsdict = methodSchema.mapArguments(args, kwargs) # check args against the arg constraint. This could fail if # any arguments are of the wrong type methodSchema.checkAllArgs(kwargs) # the Interface gets to constraint the return value too, so # make a note of it to use later req.setConstraint(methodSchema.getResponseConstraint()) else: if args: why = "positional arguments require a RemoteInterface" why += " for %s.%s()" % (self, methodName) raise tokens.BananaError(why) argsdict = kwargs # if the caller specified a _resultConstraint, that overrides # the schema's one if resultConstraint != "none": # overrides schema req.setConstraint(schema.makeConstraint(resultConstraint)) except: # TODO: merge this with the next try/except clause # we have not yet sent anything to the far end. A failure here # is entirely local: stale broker, bad method name, bad # arguments. We abandon the PendingRequest, but errback the # Deferred it was going to use req.fail(failure.Failure()) return req.deferred try: # once we start sending the CallSlicer, we could get either a # local or a remote failure, so we must be prepared to accept an # answer. After this point, we assign all responsibility to the # PendingRequest structure. self.tracker.broker.addRequest(req) # TODO: there is a decidability problem here: if the reqID made # it through, the other end will send us an answer (possibly an # error if the remaining slices were aborted). If not, we will # not get an answer. To decide whether we should remove our # broker.waitingForAnswers[] entry, we need to know how far the # slicing process made it. slicer = call.CallSlicer(reqID, self.tracker.clid, methodName, argsdict) # this could fail if any of the arguments (or their children) # are unsliceable d = broker.send(slicer) # d will fire when the last argument has been serialized. It # will errback if the arguments could not be serialized. We need # to catch this case and errback the caller. except: req.fail(failure.Failure()) return req.deferred # if we got here, we have been able to start serializing the # arguments. If serialization fails, the PendingRequest needs to be # flunked (because we aren't guaranteed that the far end will do it). d.addErrback(req.fail) # the remote end could send back an error response for many reasons: # bad method name # bad argument types (violated their schema) # exception during method execution # method result violated the results schema # something else could occur to cause an errback: # connection lost before response completely received # exception during deserialization of the response # [but only if it occurs after the reqID is received] # method result violated our results schema # if none of those occurred, the callback will be run return req.deferred