Parcourir la source

updated tests, fixed a few bugs, updated docs

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jelte-configuration@828 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen il y a 15 ans
Parent
commit
ae08d2a7bb

+ 2 - 2
src/lib/config/python/isc/config/ccsession.py

@@ -57,10 +57,10 @@ def create_answer(rcode, arg = None):
         raise CCSessionError("rcode in create_answer() must be an integer")
     if rcode != 0 and type(arg) != str:
         raise CCSessionError("arg in create_answer for rcode != 0 must be a string describing the error")
-    if arg:
+    if arg != None:
         return { 'result': [ rcode, arg ] }
     else:
-        return { 'result': [ 0 ] }
+        return { 'result': [ rcode ] }
 
 class CCSession:
     """This class maintains a connection to the command channel, as

+ 12 - 4
src/lib/config/python/isc/config/cfgmgr.py

@@ -209,7 +209,7 @@ class ConfigManager:
         return answer
 
     def _handle_set_config(self, cmd):
-        answer = {}
+        answer = None
         if len(cmd) == 3:
             # todo: use api (and check the data against the definition?)
             module_name = cmd[1]
@@ -224,7 +224,7 @@ class ConfigManager:
                 # send out changed info
                 self.cc.group_sendmsg({ "config_update": conf_part[module_name] }, module_name)
                 # replace 'our' answer with that of the module
-                answer, env = selc.cc.group_recvmsg(False)
+                answer, env = self.cc.group_recvmsg(False)
                 print("[XX] module responded with")
                 print(answer)
             rcode, val = isc.config.ccsession.parse_answer(answer)
@@ -235,6 +235,7 @@ class ConfigManager:
             data.merge(self.config.data, cmd[1])
             # send out changed info
             got_error = False
+            err_list = []
             for module in self.config.data:
                 if module != "version":
                     self.cc.group_sendmsg({ "config_update": self.config.data[module] }, module)
@@ -244,12 +245,19 @@ class ConfigManager:
                     rcode, val = isc.config.ccsession.parse_answer(answer)
                     if rcode != 0:
                         got_error = True
+                        err_list.append(val)
             if not got_error:
                 self.write_config()
-            # TODO rollback changes that did get through?
-            # feed back *all* errors?
+                answer = isc.config.ccsession.create_answer(0)
+            else:
+                # TODO rollback changes that did get through?
+                # feed back *all* errors?
+                answer = isc.config.ccsession.create_answer(1, " ".join(err_list))
         else:
             answer = isc.config.ccsession.create_answer(1, "Wrong number of arguments")
+        if not answer:
+            answer = isc.config.ccsession.create_answer(1, "Error handling set_config command")
+            
         return answer
 
     def _handle_data_specification(self, spec):

+ 16 - 1
src/lib/config/python/isc/config/cfgmgr_test.py

@@ -87,6 +87,13 @@ class FakeCCSession:
     def group_sendmsg(self, msg, channel, target = None):
         self.message_queue.append([ channel, target, msg ])
 
+    def group_recvmsg(self, blocking):
+        for qm in self.message_queue:
+            if qm[0] in self.subscriptions and (qm[1] == None or qm[1] in self.subscriptions[qm[0]]):
+                self.message_queue.remove(qm)
+                return qm[2], {}
+        return None, None
+
     def get_message(self, channel, target = None):
         for qm in self.message_queue:
             if qm[0] == channel and qm[1] == target:
@@ -147,13 +154,21 @@ class TestConfigManager(unittest.TestCase):
         self._handle_msg_helper({ "command": [ "set_config", {} ] },
                                 {'result': [0]})
         self.assertEqual(len(self.fake_session.message_queue), 0)
+
+        # the targets of some of these tests expect specific answers, put
+        # those in our fake msgq first.
+        my_ok_answer = { 'result': [ 0 ] }
+
+        self.fake_session.group_sendmsg(my_ok_answer, "ConfigManager")
         self._handle_msg_helper({ "command": [ "set_config", self.name, { "test": 123 } ] },
-                                {'result': [0]})
+                                my_ok_answer)
         self.assertEqual(len(self.fake_session.message_queue), 1)
+        self.fake_session.group_sendmsg(my_ok_answer, "ConfigManager")
         self.assertEqual({'config_update': {'test': 123}},
                          self.fake_session.get_message(self.name, None))
         self._handle_msg_helper({ "command": [ "set_config", self.name, { "test": 124 } ] },
                                 {'result': [0]})
+
         #print(self.fake_session.message_queue)
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.assertEqual({'config_update': {'test': 124}},

+ 8 - 4
src/lib/config/python/isc/config/config_data.py

@@ -158,7 +158,8 @@ class ConfigData:
 
 class MultiConfigData:
     """This class stores the datadefinitions, current non-default
-       configuration values and 'local' (uncommitted) changes."""
+       configuration values and 'local' (uncommitted) changes for
+       multiple modules"""
     LOCAL   = 1
     CURRENT = 2
     DEFAULT = 3
@@ -181,7 +182,8 @@ class MultiConfigData:
             return None
 
     def find_spec_part(self, identifier):
-        """returns the default value, or None if there is no default"""
+        """returns the specification for the item at the given
+           identifier, or None if not found"""
         if identifier[0] == '/':
             identifier = identifier[1:]
         module, sep, id = identifier.partition("/")
@@ -229,7 +231,8 @@ class MultiConfigData:
     def get_value(self, identifier):
         """Returns a tuple containing value,status. Status is either
            LOCAL, CURRENT, DEFAULT or NONE, corresponding to the
-           source of the value"""
+           source of the value (local change, current setting, default
+           as specified by the specification, or not found at all)."""
         value = self.get_local_value(identifier)
         if value:
             return value, self.LOCAL
@@ -332,7 +335,8 @@ class MultiConfigData:
         """Returns a list of strings containing the item_names of
            the child items at the given identifier. If no identifier is
            specified, returns a list of module names. The first part of
-           the identifier is interpreted as the module name"""
+           the identifier (up to the first /) is interpreted as the
+           module name"""
         if identifier:
             spec = self.find_spec_part(identifier)
             return spec_name_list(spec, identifier + "/")

+ 4 - 4
src/lib/config/python/isc/config/datadefinition.py

@@ -232,7 +232,7 @@ def _validate_type(spec, value, errors):
     else:
         return True
 
-def _validate_item(spec, data, errors):
+def _validate_item(spec, full, data, errors):
     if not _validate_type(spec, data, errors):
         return False
     elif type(data) == list:
@@ -241,10 +241,10 @@ def _validate_item(spec, data, errors):
             if not _validate_type(list_spec, data_el, errors):
                 return False
             if list_spec['item_type'] == "map":
-                if not _validate_item(list_spec, data_el, errors):
+                if not _validate_item(list_spec, full, data_el, errors):
                     return False
     elif type(data) == dict:
-        if not _validate_spec_list(spec['map_item_spec'], data, errors):
+        if not _validate_spec_list(spec['map_item_spec'], full, data, errors):
             return False
     return True
 
@@ -253,7 +253,7 @@ def _validate_spec(spec, full, data, errors):
     item_optional = spec['item_optional']
 
     if item_name in data:
-        return _validate_item(spec, data[item_name], errors)
+        return _validate_item(spec, full, data[item_name], errors)
     elif full and not item_optional:
         if errors != None:
             errors.append("non-optional item " + item_name + " missing")

+ 1 - 1
src/lib/config/python/isc/config/datadefinition_test.py

@@ -76,7 +76,7 @@ class TestDataDefinition(unittest.TestCase):
         data_file = open(self.spec_file(datafile_name))
         data_str = data_file.read()
         data = isc.cc.data.parse_value_str(data_str)
-        return dd.validate(data)
+        return dd.validate(True, data)
         
     def test_data_validation(self):
         self.assertEqual(True, self.validate_data("spec22.spec", "data22_1.data"))