[svn] commit: r911 - in /trunk/src: bin/auth/ lib/cc/cpp/ lib/config/cpp/ lib/config/python/isc/config/
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Feb 22 12:42:15 UTC 2010
Author: jelte
Date: Mon Feb 22 12:42:15 2010
New Revision: 911
Log:
added error feedback to config_validate() and option to validate partial configurations in cpp version
fixed a bug in Mapelement->str() (it can now print empty map elements)
added tests for python config_data module and fixed a few bugs there
Modified:
trunk/src/bin/auth/auth_srv.cc
trunk/src/lib/cc/cpp/data.cc
trunk/src/lib/cc/cpp/data.h
trunk/src/lib/config/cpp/ccsession.cc
trunk/src/lib/config/cpp/module_spec.cc
trunk/src/lib/config/cpp/module_spec.h
trunk/src/lib/config/python/isc/config/cfgmgr.py
trunk/src/lib/config/python/isc/config/config_data.py
trunk/src/lib/config/python/isc/config/config_data_test.py
Modified: trunk/src/bin/auth/auth_srv.cc
==============================================================================
--- trunk/src/bin/auth/auth_srv.cc (original)
+++ trunk/src/bin/auth/auth_srv.cc Mon Feb 22 12:42:15 2010
@@ -122,7 +122,11 @@
// todo: what to do with port change. restart automatically?
// ignore atm
//}
- std::cout << "[XX] auth: new config " << config << std::endl;
+ if (config) {
+ std::cout << "[XX] auth: new config " << config << std::endl;
+ } else {
+ std::cout << "[XX] auth: new config empty" << std::endl;
+ }
return isc::config::createAnswer(0);
}
Modified: trunk/src/lib/cc/cpp/data.cc
==============================================================================
--- trunk/src/lib/cc/cpp/data.cc (original)
+++ trunk/src/lib/cc/cpp/data.cc Mon Feb 22 12:42:15 2010
@@ -487,7 +487,11 @@
ss << ", ";
}
ss << "\"" << (*it).first << "\": ";
- ss << (*it).second->str();
+ if ((*it).second) {
+ ss << (*it).second->str();
+ } else {
+ ss << "None";
+ }
}
ss << "}";
return ss.str();
Modified: trunk/src/lib/cc/cpp/data.h
==============================================================================
--- trunk/src/lib/cc/cpp/data.h (original)
+++ trunk/src/lib/cc/cpp/data.h Mon Feb 22 12:42:15 2010
@@ -409,7 +409,7 @@
using Element::setValue;
bool setValue(std::map<std::string, ElementPtr>& v) { m = v; return true; };
using Element::get;
- ElementPtr get(const std::string& s) { return m[s]; };
+ ElementPtr get(const std::string& s) { if (contains(s)) { return m[s]; } else { return ElementPtr();} };
using Element::set;
void set(const std::string& s, ElementPtr p) { m[s] = p; };
using Element::remove;
Modified: trunk/src/lib/config/cpp/ccsession.cc
==============================================================================
--- trunk/src/lib/config/cpp/ccsession.cc (original)
+++ trunk/src/lib/config/cpp/ccsession.cc Mon Feb 22 12:42:15 2010
@@ -172,12 +172,20 @@
ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
{
ElementPtr answer;
+ ElementPtr errors = Element::createFromString("[]");
+ std::cout << "handleConfigUpdate " << new_config << std::endl;
if (!config_handler_) {
answer = createAnswer(1, module_name_ + " does not have a config handler");
- } else if (!module_specification_.validate_config(new_config)) {
- answer = createAnswer(2, "Error in config validation");
+ } else if (!module_specification_.validate_config(new_config, false, errors)) {
+ std::stringstream ss;
+ ss << "Error in config validation: ";
+ BOOST_FOREACH(ElementPtr error, errors->listValue()) {
+ ss << error->stringValue();
+ }
+ answer = createAnswer(2, ss.str());
} else {
// handle config update
+ std::cout << "handleConfigUpdate " << new_config << std::endl;
answer = config_handler_(new_config);
int rcode;
parseAnswer(rcode, answer);
@@ -185,6 +193,7 @@
config_ = new_config;
}
}
+ std::cout << "end handleConfigUpdate " << new_config << std::endl;
return answer;
}
Modified: trunk/src/lib/config/cpp/module_spec.cc
==============================================================================
--- trunk/src/lib/config/cpp/module_spec.cc (original)
+++ trunk/src/lib/config/cpp/module_spec.cc Mon Feb 22 12:42:15 2010
@@ -209,10 +209,17 @@
}
bool
-ModuleSpec::validate_config(const ElementPtr data)
+ModuleSpec::validate_config(const ElementPtr data, const bool full)
{
ElementPtr spec = module_specification->find("module_spec/config_data");
- return validate_spec_list(spec, data);
+ return validate_spec_list(spec, data, full, ElementPtr());
+}
+
+bool
+ModuleSpec::validate_config(const ElementPtr data, const bool full, ElementPtr errors)
+{
+ ElementPtr spec = module_specification->find("module_spec/config_data");
+ return validate_spec_list(spec, data, full, errors);
}
ModuleSpec
@@ -279,28 +286,34 @@
}
bool
-ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data) {
+ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
if (!check_type(spec, data)) {
// we should do some proper error feedback here
// std::cout << "type mismatch; not " << spec->get("item_type") << ": " << data << std::endl;
// std::cout << spec << std::endl;
+ if (errors) {
+ errors->add(Element::create("Type mismatch"));
+ }
return false;
}
if (data->getType() == Element::list) {
ElementPtr list_spec = spec->get("list_item_spec");
BOOST_FOREACH(ElementPtr list_el, data->listValue()) {
if (!check_type(list_spec, list_el)) {
+ if (errors) {
+ errors->add(Element::create("Type mismatch"));
+ }
return false;
}
if (list_spec->get("item_type")->stringValue() == "map") {
- if (!validate_item(list_spec, list_el)) {
+ if (!validate_item(list_spec, list_el, full, errors)) {
return false;
}
}
}
}
if (data->getType() == Element::map) {
- if (!validate_spec_list(spec->get("map_item_spec"), data)) {
+ if (!validate_spec_list(spec->get("map_item_spec"), data, full, errors)) {
return false;
}
}
@@ -309,18 +322,21 @@
// spec is a map with item_name etc, data is a map
bool
-ModuleSpec::validate_spec(const ElementPtr spec, const ElementPtr data) {
+ModuleSpec::validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
std::string item_name = spec->get("item_name")->stringValue();
bool optional = spec->get("item_optional")->boolValue();
ElementPtr data_el;
+ data_el = data->get(item_name);
- data_el = data->get(item_name);
if (data_el) {
- if (!validate_item(spec, data_el)) {
+ if (!validate_item(spec, data_el, full, errors)) {
return false;
}
} else {
- if (!optional) {
+ if (!optional && full) {
+ if (errors) {
+ errors->add(Element::create("Non-optional value missing"));
+ }
return false;
}
}
@@ -329,11 +345,11 @@
// spec is a list of maps, data is a map
bool
-ModuleSpec::validate_spec_list(const ElementPtr spec, const ElementPtr data) {
+ModuleSpec::validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
ElementPtr cur_data_el;
std::string cur_item_name;
BOOST_FOREACH(ElementPtr cur_spec_el, spec->listValue()) {
- if (!validate_spec(cur_spec_el, data)) {
+ if (!validate_spec(cur_spec_el, data, full, errors)) {
return false;
}
}
Modified: trunk/src/lib/config/cpp/module_spec.h
==============================================================================
--- trunk/src/lib/config/cpp/module_spec.h (original)
+++ trunk/src/lib/config/cpp/module_spec.h Mon Feb 22 12:42:15 2010
@@ -83,12 +83,15 @@
/// \param data The base \c Element of the data to check
/// \return true if the data conforms to the specification,
/// false otherwise.
- bool validate_config(const ElementPtr data);
+ bool validate_config(const ElementPtr data, const bool full = false);
+
+ /// errors must be of type ListElement
+ bool validate_config(const ElementPtr data, const bool full, ElementPtr errors);
private:
- bool validate_item(const ElementPtr spec, const ElementPtr data);
- bool validate_spec(const ElementPtr spec, const ElementPtr data);
- bool validate_spec_list(const ElementPtr spec, const ElementPtr data);
+ bool validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
+ bool validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
+ bool validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
ElementPtr module_specification;
};
Modified: trunk/src/lib/config/python/isc/config/cfgmgr.py
==============================================================================
--- trunk/src/lib/config/python/isc/config/cfgmgr.py (original)
+++ trunk/src/lib/config/python/isc/config/cfgmgr.py Mon Feb 22 12:42:15 2010
@@ -230,6 +230,8 @@
# todo: use api (and check the data against the definition?)
module_name = cmd[1]
conf_part = data.find_no_exc(self.config.data, module_name)
+ print("[XX] cfgmgr conf part:")
+ print(conf_part)
if conf_part:
data.merge(conf_part, cmd[2])
self.cc.group_sendmsg({ "config_update": conf_part }, module_name)
@@ -246,6 +248,7 @@
self.write_config()
elif len(cmd) == 2:
# todo: use api (and check the data against the definition?)
+ old_data = self.config.data.copy()
data.merge(self.config.data, cmd[1])
# send out changed info
got_error = False
@@ -262,8 +265,8 @@
self.write_config()
answer = isc.config.ccsession.create_answer(0)
else:
- # TODO rollback changes that did get through?
- # feed back *all* errors?
+ # TODO rollback changes that did get through, should we re-send update?
+ self.config.data = old_data
answer = isc.config.ccsession.create_answer(1, " ".join(err_list))
else:
answer = isc.config.ccsession.create_answer(1, "Wrong number of arguments")
Modified: trunk/src/lib/config/python/isc/config/config_data.py
==============================================================================
--- trunk/src/lib/config/python/isc/config/config_data.py (original)
+++ trunk/src/lib/config/python/isc/config/config_data.py Mon Feb 22 12:42:15 2010
@@ -26,9 +26,10 @@
class ConfigDataError(Exception): pass
def check_type(spec_part, value):
- """Returns true if the value is of the correct type given the
- specification part relevant for the value. spec_part can be
- retrieved with find_spec()"""
+ """Does nothing if the value is of the correct type given the
+ specification part relevant for the value. Raises an
+ isc.cc.data.DataTypeError exception if not. spec_part can be
+ retrieved with find_spec_part()"""
if type(spec_part) == list:
data_type = "list"
else:
@@ -36,9 +37,9 @@
if data_type == "integer" and type(value) != int:
raise isc.cc.data.DataTypeError(str(value) + " is not an integer")
- elif data_type == "real" and type(value) != double:
+ elif data_type == "real" and type(value) != float:
raise isc.cc.data.DataTypeError(str(value) + " is not a real")
- elif data_type == "boolean" and type(value) != boolean:
+ elif data_type == "boolean" and type(value) != bool:
raise isc.cc.data.DataTypeError(str(value) + " is not a boolean")
elif data_type == "string" and type(value) != str:
raise isc.cc.data.DataTypeError(str(value) + " is not a string")
@@ -52,7 +53,7 @@
# todo: check types of map contents too
raise isc.cc.data.DataTypeError(str(value) + " is not a map")
-def find_spec(element, identifier):
+def find_spec_part(element, identifier):
"""find the data definition for the given identifier
returns either a map with 'item_name' etc, or a list of those"""
if identifier == "":
@@ -65,6 +66,14 @@
cur_el = cur_el[id]
elif type(cur_el) == dict and 'item_name' in cur_el.keys() and cur_el['item_name'] == id:
pass
+ elif type(cur_el) == dict and 'map_item_spec' in cur_el.keys():
+ found = False
+ for cur_el_item in cur_el['map_item_spec']:
+ if cur_el_item['item_name'] == id:
+ cur_el = cur_el_item
+ found = True
+ if not found:
+ raise isc.cc.data.DataNotFoundError(id + " in " + str(cur_el))
elif type(cur_el) == list:
found = False
for cur_el_item in cur_el:
@@ -84,23 +93,29 @@
if prefix != "" and not prefix.endswith("/"):
prefix += "/"
if type(spec) == dict:
- for name in spec:
- result.append(prefix + name + "/")
- if recurse:
- result.extend(spec_name_list(spec[name],name, recurse))
+ if 'map_item_spec' in spec:
+ for map_el in spec['map_item_spec']:
+ name = map_el['item_name']
+ if map_el['item_type'] == 'map':
+ name += "/"
+ result.append(prefix + name)
+ else:
+ for name in spec:
+ result.append(prefix + name + "/")
+ if recurse:
+ print("[XX] recurse1")
+ result.extend(spec_name_list(spec[name],name, recurse))
elif type(spec) == list:
for list_el in spec:
if 'item_name' in list_el:
- if list_el['item_type'] == dict:
- if recurse:
- result.extend(spec_name_list(list_el['map_item_spec'], prefix + list_el['item_name'], recurse))
+ if list_el['item_type'] == "map" and recurse:
+ result.extend(spec_name_list(list_el['map_item_spec'], prefix + list_el['item_name'], recurse))
else:
name = list_el['item_name']
if list_el['item_type'] in ["list", "map"]:
name += "/"
- result.append(name)
+ result.append(prefix + name)
return result
-
class ConfigData:
"""This class stores the module specs and the current non-default
@@ -118,11 +133,12 @@
def get_value(self, identifier):
"""Returns a tuple where the first item is the value at the
given identifier, and the second item is a bool which is
- true if the value is an unset default"""
+ true if the value is an unset default. Raises an
+ isc.cc.data.DataNotFoundError if the identifier is bad"""
value = isc.cc.data.find_no_exc(self.data, identifier)
- if value:
+ if value != None:
return value, False
- spec = find_spec(self.specification.get_config_spec(), identifier)
+ spec = find_spec_part(self.specification.get_config_spec(), identifier)
if spec and 'item_default' in spec:
return spec['item_default'], True
return None, False
@@ -144,7 +160,7 @@
all 'sub'options at the given identifier. If recurse is True,
it will also add all identifiers of all children, if any"""
if identifier:
- spec = find_spec(self.specification.get_config_spec(), identifier, recurse)
+ spec = find_spec_part(self.specification.get_config_spec(), identifier)
return spec_name_list(spec, identifier + "/")
return spec_name_list(self.specification.get_config_spec(), "", recurse)
@@ -183,7 +199,8 @@
self._specifications[spec.get_module_name()] = spec
def get_module_spec(self, module):
- """Returns the ModuleSpec for the module with the given name"""
+ """Returns the ModuleSpec for the module with the given name.
+ If there is no such module, it returns None"""
if module in self._specifications:
return self._specifications[module]
else:
@@ -193,13 +210,15 @@
"""Returns the specification for the item at the given
identifier, or None if not found. The first part of the
identifier (up to the first /) is interpreted as the module
- name."""
+ name. Returns None if not found."""
if identifier[0] == '/':
identifier = identifier[1:]
module, sep, id = identifier.partition("/")
try:
- return find_spec(self._specifications[module].get_config_spec(), id)
+ return find_spec_part(self._specifications[module].get_config_spec(), id)
except isc.cc.data.DataNotFoundError as dnfe:
+ return None
+ except KeyError as ke:
return None
# this function should only be called by __request_config
@@ -252,7 +271,7 @@
identifier = identifier[1:]
module, sep, id = identifier.partition("/")
try:
- spec = find_spec(self._specifications[module].get_config_spec(), id)
+ spec = find_spec_part(self._specifications[module].get_config_spec(), id)
if 'item_default' in spec:
return spec['item_default']
else:
@@ -268,13 +287,13 @@
(local change, current setting, default as specified by the
specification, or not found at all)."""
value = self.get_local_value(identifier)
- if value:
+ if value != None:
return value, self.LOCAL
value = self.get_current_value(identifier)
- if value:
+ if value != None:
return value, self.CURRENT
value = self.get_default_value(identifier)
- if value:
+ if value != None:
return value, self.DEFAULT
return None, self.NONE
@@ -305,7 +324,7 @@
module, sep, id = identifier.partition('/')
spec = self.get_module_spec(module)
if spec:
- spec_part = find_spec(spec.get_config_spec(), id)
+ spec_part = find_spec_part(spec.get_config_spec(), id)
print(spec_part)
if type(spec_part) == list:
for item in spec_part:
@@ -357,12 +376,15 @@
return result
def set_value(self, identifier, value):
- """Set the local value at the given identifier to value"""
+ """Set the local value at the given identifier to value. If
+ there is a specification for the given identifier, the type
+ is checked."""
spec_part = self.find_spec_part(identifier)
- check_type(spec_part, value)
+ if spec_part != None:
+ check_type(spec_part, value)
isc.cc.data.set(self._local_changes, identifier, value)
- def get_config_item_list(self, identifier = None):
+ def get_config_item_list(self, identifier = None, recurse = False):
"""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
@@ -370,6 +392,12 @@
module name"""
if identifier:
spec = self.find_spec_part(identifier)
- return spec_name_list(spec, identifier + "/")
- else:
- return self._specifications.keys()
+ return spec_name_list(spec, identifier + "/", recurse)
+ else:
+ if recurse:
+ id_list = []
+ for module in self._specifications:
+ id_list.extend(spec_name_list(self._specifications[module], module, recurse))
+ return id_list
+ else:
+ return list(self._specifications.keys())
Modified: trunk/src/lib/config/python/isc/config/config_data_test.py
==============================================================================
--- trunk/src/lib/config/python/isc/config/config_data_test.py (original)
+++ trunk/src/lib/config/python/isc/config/config_data_test.py Mon Feb 22 12:42:15 2010
@@ -28,13 +28,261 @@
self.data_path = os.environ['CONFIG_TESTDATA_PATH']
else:
self.data_path = "../../../testdata"
-
- def test_module_spec_from_file(self):
- spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")
- cd = ConfigData(spec)
- self.assertEqual(cd.specification, spec)
- self.assertEqual(cd.data, {})
- self.assertRaises(ConfigDataError, ConfigData, 1)
+ spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.cd = ConfigData(spec)
+
+ #def test_module_spec_from_file(self):
+ # spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")
+ # cd = ConfigData(spec)
+ # self.assertEqual(cd.specification, spec)
+ # self.assertEqual(cd.data, {})
+ # self.assertRaises(ConfigDataError, ConfigData, 1)
+
+ def test_check_type(self):
+ config_spec = self.cd.get_module_spec().get_config_spec()
+ spec_part = find_spec_part(config_spec, "item1")
+ check_type(spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "item2")
+ check_type(spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "item3")
+ check_type(spec_part, True)
+ check_type(spec_part, False)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "item4")
+ check_type(spec_part, "asdf")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "item5")
+ check_type(spec_part, ["a", "b"])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "a": 1 })
+
+ spec_part = find_spec_part(config_spec, "item6")
+ check_type(spec_part, { "value1": "aaa", "value2": 2 })
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, 1.1)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, True)
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, "a")
+ self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, [ 1, 2 ])
+ #self.assertRaises(isc.cc.data.DataTypeError, check_type, spec_part, { "value1": 1 })
+
+ def test_find_spec_part(self):
+ config_spec = self.cd.get_module_spec().get_config_spec()
+ spec_part = find_spec_part(config_spec, "item1")
+ self.assertEqual({'item_name': 'item1', 'item_type': 'integer', 'item_optional': False, 'item_default': 1, }, spec_part)
+ self.assertRaises(isc.cc.data.DataNotFoundError, find_spec_part, config_spec, "no_such_item")
+ self.assertRaises(isc.cc.data.DataNotFoundError, find_spec_part, config_spec, "no_such_item/multilevel")
+ spec_part = find_spec_part(config_spec, "item6/value1")
+ #print(spec_part)
+ self.assertEqual({'item_name': 'value1', 'item_type': 'string', 'item_optional': True, 'item_default': 'default'}, spec_part)
+
+ def test_spec_name_list(self):
+ name_list = spec_name_list(self.cd.get_module_spec().get_config_spec())
+ self.assertEqual(['item1', 'item2', 'item3', 'item4', 'item5/', 'item6/'], name_list)
+ name_list = spec_name_list(self.cd.get_module_spec().get_config_spec(), "", True)
+ self.assertEqual(['item1', 'item2', 'item3', 'item4', 'item5/', 'item6/value1', 'item6/value2'], name_list)
+
+ def test_get_value(self):
+ value, default = self.cd.get_value("item1")
+ self.assertEqual(1, value)
+ self.assertEqual(True, default)
+ value, default = self.cd.get_value("item2")
+ self.assertEqual(1.1, value)
+ self.assertEqual(True, default)
+ value, default = self.cd.get_value("item3")
+ self.assertEqual(True, value)
+ self.assertEqual(True, default)
+ value, default = self.cd.get_value("item4")
+ self.assertEqual("test", value)
+ self.assertEqual(True, default)
+ value, default = self.cd.get_value("item5")
+ self.assertEqual(["a", "b"], value)
+ self.assertEqual(True, default)
+ value, default = self.cd.get_value("item6")
+ self.assertEqual({}, value)
+ self.assertEqual(True, default)
+ self.assertRaises(isc.cc.data.DataNotFoundError, self.cd.get_value, "no_such_item")
+ value, default = self.cd.get_value("item6/value2")
+ self.assertEqual(None, value)
+ self.assertEqual(False, default)
+
+ def test_set_local_config(self):
+ self.cd.set_local_config({"item1": 2})
+ value, default = self.cd.get_value("item1")
+ self.assertEqual(2, value)
+ self.assertEqual(False, default)
+
+ def test_get_local_config(self):
+ local_config = self.cd.get_local_config()
+ self.assertEqual({}, local_config)
+ my_config = { "item1": 2, "item2": 2.2, "item3": False, "item4": "asdf", "item5": [ "c", "d" ] }
+ self.cd.set_local_config(my_config)
+ self.assertEqual(my_config, self.cd.get_local_config())
+
+ def test_get_item_list(self):
+ name_list = self.cd.get_item_list()
+ self.assertEqual(['item1', 'item2', 'item3', 'item4', 'item5/', 'item6/'], name_list)
+ name_list = self.cd.get_item_list("", True)
+ self.assertEqual(['item1', 'item2', 'item3', 'item4', 'item5/', 'item6/value1', 'item6/value2'], name_list)
+ name_list = self.cd.get_item_list("item6", False)
+ self.assertEqual(['item6/value1', 'item6/value2'], name_list)
+
+ def test_get_full_config(self):
+ full_config = self.cd.get_full_config()
+ self.assertEqual({ "item1": 1, "item2": 1.1, "item3": True, "item4": "test", "item5/": ['a', 'b'], "item6/value1": 'default', 'item6/value2': None}, full_config)
+ my_config = { "item1": 2, "item2": 2.2, "item3": False, "item4": "asdf", "item5": [ "c", "d" ] }
+ self.cd.set_local_config(my_config)
+ full_config = self.cd.get_full_config()
+ self.assertEqual({ "item1": 2, "item2": 2.2, "item3": False, "item4": "asdf", "item5/": [ "c", "d" ], "item6/value1": 'default', 'item6/value2': None}, full_config)
+
+class TestMultiConfigData(unittest.TestCase):
+ def setUp(self):
+ if 'CONFIG_TESTDATA_PATH' in os.environ:
+ self.data_path = os.environ['CONFIG_TESTDATA_PATH']
+ else:
+ self.data_path = "../../../testdata"
+ self.mcd = MultiConfigData()
+
+ def test_init(self):
+ self.assertEqual({}, self.mcd._specifications)
+ self.assertEqual({}, self.mcd._current_config)
+ self.assertEqual({}, self.mcd._local_changes)
+
+ def test_set_specification(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")
+ self.mcd.set_specification(module_spec)
+ self.assert_(module_spec.get_module_name() in self.mcd._specifications)
+ self.assertEquals(module_spec, self.mcd._specifications[module_spec.get_module_name()])
+
+ def test_get_module_spec(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec1.spec")
+ self.mcd.set_specification(module_spec)
+ module_spec2 = self.mcd.get_module_spec(module_spec.get_module_name())
+ self.assertEqual(module_spec, module_spec2)
+ module_spec3 = self.mcd.get_module_spec("no_such_module")
+ self.assertEqual(None, module_spec3)
+
+ def test_find_spec_part(self):
+ spec_part = self.mcd.find_spec_part("Spec2/item1")
+ self.assertEqual(None, spec_part)
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ spec_part = self.mcd.find_spec_part("Spec2/item1")
+ self.assertEqual({'item_name': 'item1', 'item_type': 'integer', 'item_optional': False, 'item_default': 1, }, spec_part)
+
+ def test_get_local_changes(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ local_changes = self.mcd.get_local_changes()
+ self.assertEqual({}, local_changes)
+ self.mcd.set_value("Spec2/item1", 2)
+ local_changes = self.mcd.get_local_changes()
+ self.assertEqual({"Spec2": { "item1": 2}}, local_changes)
+
+
+ def test_clear_local_changes(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ self.mcd.set_value("Spec2/item1", 2)
+ self.mcd.clear_local_changes()
+ local_changes = self.mcd.get_local_changes()
+ self.assertEqual({}, local_changes)
+ pass
+
+ def test_get_local_value(self):
+ value = self.mcd.get_local_value("Spec2/item1")
+ self.assertEqual(None, value)
+ self.mcd.set_value("Spec2/item1", 2)
+ value = self.mcd.get_local_value("Spec2/item1")
+ self.assertEqual(2, value)
+
+ def test_get_current_value(self):
+ value = self.mcd.get_current_value("Spec2/item1")
+ self.assertEqual(None, value)
+ self.mcd._current_config = { "Spec2": { "item1": 3 } }
+ value = self.mcd.get_current_value("Spec2/item1")
+ self.assertEqual(3, value)
+ pass
+
+ def test_get_default_value(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ value = self.mcd.get_default_value("Spec2/item1")
+ self.assertEqual(1, value)
+ value = self.mcd.get_default_value("Spec2/item6/value1")
+ self.assertEqual('default', value)
+ value = self.mcd.get_default_value("Spec2/item6/value2")
+ self.assertEqual(None, value)
+ value = self.mcd.get_default_value("Spec2/no_such_item/asdf")
+ self.assertEqual(None, value)
+
+ def test_get_value(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ self.mcd.set_value("Spec2/item1", 2)
+ value,status = self.mcd.get_value("Spec2/item1")
+ self.assertEqual(2, value)
+ self.assertEqual(MultiConfigData.LOCAL, status)
+ value,status = self.mcd.get_value("Spec2/item2")
+ self.assertEqual(1.1, value)
+ self.assertEqual(MultiConfigData.DEFAULT, status)
+ self.mcd._current_config = { "Spec2": { "item3": False } }
+ value,status = self.mcd.get_value("Spec2/item3")
+ self.assertEqual(False, value)
+ self.assertEqual(MultiConfigData.CURRENT, status)
+ value,status = self.mcd.get_value("Spec2/no_such_item")
+ self.assertEqual(None, value)
+ self.assertEqual(MultiConfigData.NONE, status)
+
+ def test_get_value_maps(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ maps = self.mcd.get_value_maps()
+ self.assertEqual([{'default': False, 'type': 'module', 'name': 'Spec2', 'value': None, 'modified': False}], maps)
+
+ def test_set_value(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ self.mcd.set_value("Spec2/item1", 2)
+ self.assertRaises(isc.cc.data.DataTypeError, self.mcd.set_value, "Spec2/item1", "asdf")
+ self.mcd.set_value("Spec2/no_such_item", 4)
+
+ def test_get_config_item_list(self):
+ config_items = self.mcd.get_config_item_list()
+ self.assertEqual([], config_items)
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
+ config_items = self.mcd.get_config_item_list()
+ self.assertEqual(['Spec2'], config_items)
+ config_items = self.mcd.get_config_item_list("Spec2")
+ self.assertEqual(['Spec2/item1', 'Spec2/item2', 'Spec2/item3', 'Spec2/item4', 'Spec2/item5/', 'Spec2/item6/'], config_items)
+ config_items = self.mcd.get_config_item_list("Spec2", True)
+ self.assertEqual(['Spec2/item1', 'Spec2/item2', 'Spec2/item3', 'Spec2/item4', 'Spec2/item5/', 'Spec2/item6/value1', 'Spec2/item6/value2'], config_items)
if __name__ == '__main__':
unittest.main()
More information about the bind10-changes
mailing list