BIND 10 trac2676, updated. 6667c5c3485db2ec1da350d4b90896b871e07bad [2676] Error handling in the rpc_call

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Feb 14 09:54:33 UTC 2013


The branch, trac2676 has been updated
       via  6667c5c3485db2ec1da350d4b90896b871e07bad (commit)
       via  488d42f3ae5c7f97ef144370036b5c9b7736a9d1 (commit)
      from  4b678e1d42ea66fae49f2248b4c4cfeb32fe0a09 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6667c5c3485db2ec1da350d4b90896b871e07bad
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Feb 14 10:54:07 2013 +0100

    [2676] Error handling in the rpc_call

commit 488d42f3ae5c7f97ef144370036b5c9b7736a9d1
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Feb 14 10:34:16 2013 +0100

    [2676] Further tests for rpc_call
    
    An unusual case and a malformed answer.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/python/isc/config/ccsession.py            |   29 +++++++++++
 src/lib/python/isc/config/tests/ccsession_test.py |   55 ++++++++++++++++++---
 2 files changed, 76 insertions(+), 8 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index c5c8a89..529408c 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -51,6 +51,31 @@ logger = isc.log.Logger("config")
 
 class ModuleCCSessionError(Exception): pass
 
+class RPCError(ModuleCCSessionError):
+    """
+    An exception raised by rpc_call in case the remote side reports
+    an error. It can be used to distinguish remote errors from protocol errors.
+    Also, it holds the code as well as the error message.
+    """
+    def __init__(self, code, message):
+        ModuleCCSessionError.__init__(self, message)
+        self.__code = code
+
+    def code(self):
+        """
+        The code as sent over the CC.
+        """
+        return self.__code
+
+class RPCRecipientMissing(RPCError):
+    """
+    Special version of the RPCError, for cases the recipient of the call
+    isn't connected to the bus. The code is always
+    isc.cc.proto_defs.CC_REPLY_NO_RECPT.
+    """
+    def __init__(self, message):
+        RPCError.__init__(self, CC_REPLY_NO_RECPT, message)
+
 def parse_answer(msg):
     """Returns a tuple (rcode, value), where value depends on the
        command that was called. If rcode != 0, value is a string
@@ -484,6 +509,10 @@ class ModuleCCSession(ConfigData):
         # works)
         reply, rheaders = self._session.group_recvmsg(nonblock=False, seq=seq)
         code, value = parse_answer(reply)
+        if code == CC_REPLY_NO_RECPT:
+            raise RPCRecipientMissing(value)
+        elif code != 0:
+            raise RPCError(code, value)
         return value
 
 class UIModuleCCSession(MultiConfigData):
diff --git a/src/lib/python/isc/config/tests/ccsession_test.py b/src/lib/python/isc/config/tests/ccsession_test.py
index 0f772ff..cc81526 100644
--- a/src/lib/python/isc/config/tests/ccsession_test.py
+++ b/src/lib/python/isc/config/tests/ccsession_test.py
@@ -289,26 +289,65 @@ class TestModuleCCSession(unittest.TestCase):
         fake_session.close()
         mccs.__del__() # with closed fake_session
 
-    def test_rpc_call_success(self):
-        """
-        Test we can send an RPC (command) and get an answer. The answer is
-        success in this case.
-        """
+    def rpc_check(self, reply):
         fake_session = FakeModuleCCSession()
         mccs = self.create_session("spec1.spec", None, None, fake_session)
         fake_session.message_queue = [
-            ["Spec1", None, {"result": [0, {"Hello": "a"}]}, False]
+            ["Spec1", None, reply, False]
         ]
-        result = mccs.rpc_call("test", "Spec2", param1="Param 1",
-                               param2="Param 2")
+        exception = None
+        try:
+            result = mccs.rpc_call("test", "Spec2", param1="Param 1",
+                                   param2="Param 2")
+        except Exception as e:
+            # We first want to check the value sent, raise the exception
+            # afterwards. So store it for a short while.
+            exception = e
         self.assertEqual([
                 ["Spec2", "*", {"command": ["test", {
                     "param1": "Param 1",
                     "param2": "Param 2"
                 }]}, True]
             ], fake_session.message_queue)
+        if exception is not None:
+            raise exception
+        return result
+
+    def test_rpc_call_success(self):
+        """
+        Test we can send an RPC (command) and get an answer. The answer is
+        success in this case.
+        """
+        result = self.rpc_check({"result": [0, {"Hello": "a"}]})
         self.assertEqual({"Hello": "a"}, result)
 
+    def test_rpc_call_success_none(self):
+        """
+        Test the success case of RPC command, but the answer is empty
+        (eg. a "void" function on the remote side).
+        """
+        self.assertIsNone(self.rpc_check({"result": [0]}))
+
+    def test_rpc_call_malformed_answer(self):
+        """
+        Test it successfully raises ModuleCCSessionError when a malformed
+        reply is sent.
+        """
+        self.assertRaises(ModuleCCSessionError, self.rpc_check, ["Nonsense"])
+
+    def test_rpc_call_error(self):
+        """
+        Test it raises an exception when the remote side reports an error.
+        """
+        self.assertRaises(RPCError, self.rpc_check, {"result": [1, "Error"]})
+
+    def test_rpc_call_no_recpt(self):
+        """
+        Test RPC raises an error when the recipient is not there.
+        """
+        self.assertRaises(RPCRecipientMissing, self.rpc_check,
+                          {"result": [-1, "Error"]})
+
     def my_config_handler_ok(self, new_config):
         return isc.config.ccsession.create_answer(0)
 



More information about the bind10-changes mailing list