Commit ae08d2a7 authored by Jelte Jansen's avatar Jelte Jansen

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
parent fad19e22
......@@ -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
......
......@@ -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):
......
......@@ -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}},
......
......@@ -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 + "/")
......
......@@ -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")
......
......@@ -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"))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment