BIND 10 master, updated. fd08a0dc40846f58aaa8a7df7726ac83e5e4c038 Merge branch 'work/authtsig'
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri May 13 08:54:57 UTC 2011
The branch, master has been updated
via fd08a0dc40846f58aaa8a7df7726ac83e5e4c038 (commit)
via d3da4f1f4f00d13962e6f23ff1272269569be5d4 (commit)
via f6e9a1186d00e023021f5853e5a7a1d7c3f838cf (commit)
via 7b25152b5bbbaff6840f88ad7ff2684f8b8062a6 (commit)
via 76a81d33b95b12341515cc6ca5718d72a242ab59 (commit)
via 8339141a4a64043e82685f0e6793b592b7ac820a (commit)
via 36af50328be059026859a09d402ff2d591789dfd (commit)
via f8c763ef2c9eb8343ead481093e2d0024e3f1cd2 (commit)
via f80cdaf115a8ad80184240b283b243ac07bb9739 (commit)
via c2693bb84ea22e3b44617d729d8d2e8dbd99c51c (commit)
via 2f25f64f9f7a1021b67b9c37cfca41e86f5ae032 (commit)
via 14f8767d89d62e0d573a1e6b31fbeea9272e7011 (commit)
via a82432e09cc7f3b22920d9baecba1f8e89332f37 (commit)
from 46629b17783d3ddf624002893af955d525f453a8 (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 fd08a0dc40846f58aaa8a7df7726ac83e5e4c038
Merge: 46629b17783d3ddf624002893af955d525f453a8 d3da4f1f4f00d13962e6f23ff1272269569be5d4
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri May 13 10:49:36 2011 +0200
Merge branch 'work/authtsig'
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 1 +
src/bin/cfgmgr/b10-cfgmgr.py.in | 23 +----
src/bin/cfgmgr/plugins/Makefile.am | 6 +-
.../cfgmgr/plugins}/tests/Makefile.am | 11 +-
src/bin/cfgmgr/plugins/tests/tsig_keys_test.py | 103 ++++++++++++++++++++
src/bin/cfgmgr/plugins/tsig_keys.py | 50 ++++++++++
src/bin/cfgmgr/plugins/tsig_keys.spec | 21 ++++
src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in | 3 +
src/lib/python/bind10_config.py.in | 38 +++++++-
src/lib/python/isc/util/Makefile.am | 2 +-
.../isc/{testutils/parse_args.py => util/file.py} | 21 ++--
src/lib/python/isc/util/tests/Makefile.am | 2 +-
.../parse_args.py => util/tests/file_test.py} | 28 +++---
13 files changed, 254 insertions(+), 55 deletions(-)
copy src/{lib/python/isc/datasrc => bin/cfgmgr/plugins}/tests/Makefile.am (67%)
create mode 100644 src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
create mode 100644 src/bin/cfgmgr/plugins/tsig_keys.py
create mode 100644 src/bin/cfgmgr/plugins/tsig_keys.spec
copy src/lib/python/isc/{testutils/parse_args.py => util/file.py} (64%)
copy src/lib/python/isc/{testutils/parse_args.py => util/tests/file_test.py} (54%)
-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index a2febd2..a8378ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -686,6 +686,7 @@ AC_CONFIG_FILES([Makefile
src/bin/bindctl/tests/Makefile
src/bin/cfgmgr/Makefile
src/bin/cfgmgr/plugins/Makefile
+ src/bin/cfgmgr/plugins/tests/Makefile
src/bin/cfgmgr/tests/Makefile
src/bin/host/Makefile
src/bin/loadzone/Makefile
diff --git a/src/bin/cfgmgr/b10-cfgmgr.py.in b/src/bin/cfgmgr/b10-cfgmgr.py.in
index 16c8f76..d91dfca 100755
--- a/src/bin/cfgmgr/b10-cfgmgr.py.in
+++ b/src/bin/cfgmgr/b10-cfgmgr.py.in
@@ -18,6 +18,7 @@
import sys; sys.path.append ('@@PYTHONPATH@@')
from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError
+import bind10_config
from isc.cc import SessionError
import isc.util.process
import signal
@@ -28,24 +29,10 @@ import os.path
isc.util.process.rename()
-# If B10_FROM_SOURCE is set in the environment, we use data files
-# from a directory relative to the value of that variable, or, if defined,
-# relative to the value of B10_FROM_SOURCE_LOCALSTATEDIR. Otherwise
-# we use the ones installed on the system.
-# B10_FROM_SOURCE_LOCALSTATEDIR is specifically intended to be used for
-# tests where we want to use variuos types of configuration within the test
-# environment. (We may want to make it even more generic so that the path is
-# passed from the boss process)
-if "B10_FROM_SOURCE" in os.environ:
- if "B10_FROM_SOURCE_LOCALSTATEDIR" in os.environ:
- DATA_PATH = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
- else:
- DATA_PATH = os.environ["B10_FROM_SOURCE"]
- PLUGIN_PATHS = [DATA_PATH + '/src/bin/cfgmgr/plugins']
-else:
- PREFIX = "@prefix@"
- DATA_PATH = "@localstatedir@/@PACKAGE@".replace("${prefix}", PREFIX)
- PLUGIN_PATHS = ["@prefix@/share/@PACKAGE@/config_plugins"]
+# Import some paths from our configuration
+DATA_PATH = bind10_config.DATA_PATH
+PLUGIN_PATHS = bind10_config.PLUGIN_PATHS
+PREFIX = bind10_config.PREFIX
DEFAULT_CONFIG_FILE = "b10-config.db"
cm = None
diff --git a/src/bin/cfgmgr/plugins/Makefile.am b/src/bin/cfgmgr/plugins/Makefile.am
index 952fde6..d83c2bb 100644
--- a/src/bin/cfgmgr/plugins/Makefile.am
+++ b/src/bin/cfgmgr/plugins/Makefile.am
@@ -1 +1,5 @@
-EXTRA_DIST = README
+SUBDIRS = tests
+EXTRA_DIST = README tsig_keys.py tsig_keys.spec
+
+config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
+config_plugin_DATA = tsig_keys.py tsig_keys.spec
diff --git a/src/bin/cfgmgr/plugins/tests/Makefile.am b/src/bin/cfgmgr/plugins/tests/Makefile.am
new file mode 100644
index 0000000..48a0393
--- /dev/null
+++ b/src/bin/cfgmgr/plugins/tests/Makefile.am
@@ -0,0 +1,19 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+PYTESTS = tsig_keys_test.py
+
+EXTRA_DIST = $(PYTESTS)
+
+# test using command-line arguments, so use check-local target instead of TESTS
+check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
+ for pytest in $(PYTESTS) ; do \
+ echo Running test: $$pytest ; \
+ env B10_TEST_PLUGIN_DIR=$(abs_srcdir)/..:$(abs_builddir)/.. \
+ env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr:$(abs_top_builddir)/src/lib/dns/python/.libs \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
+ done
+
diff --git a/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
new file mode 100644
index 0000000..be2921c
--- /dev/null
+++ b/src/bin/cfgmgr/plugins/tests/tsig_keys_test.py
@@ -0,0 +1,103 @@
+# Copyright (C) 2011 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Make sure we can load the module, put it into path
+import sys
+import os
+sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
+
+import tsig_keys
+import unittest
+import isc.config.module_spec
+
+class TSigKeysTest(unittest.TestCase):
+ def test_load(self):
+ """
+ Checks the entry point returns the correct values.
+ """
+ (spec, check) = tsig_keys.load()
+ # It returns the checking function
+ self.assertEqual(check, tsig_keys.check)
+ # The plugin stores it's spec
+ self.assertEqual(spec, tsig_keys.spec)
+
+ def test_spec(self):
+ """
+ Checks the spec is looking sane (doesn't do really deep check here).
+ """
+ spec = tsig_keys.spec
+ # In python, we don't generally check the type of something, because
+ # of the duck typing.
+ # But this is unittest, so we check it does what we intend and
+ # supplying that's behaving the same but is different is not our
+ # intention
+ self.assertTrue(isinstance(spec, isc.config.module_spec.ModuleSpec))
+ # Correct name
+ self.assertEqual("tsig_keys", spec.get_module_name())
+ # There are no commands, nobody would handle them anyway
+ self.assertEqual([], spec.get_commands_spec())
+ # There's some nonempty configuration
+ self.assertNotEqual({}, spec.get_config_spec())
+
+ def test_missing_keys(self):
+ """
+ Test that missing keys doesn't kill us. There are just no keys there.
+ """
+ self.assertEqual(None, tsig_keys.check({}))
+
+ def test_data_empty(self):
+ """Check we accept valid config with empty set of tsig keys."""
+ self.assertEqual(None, tsig_keys.check({'keys': []}))
+
+ def test_keys_valid(self):
+ """
+ Check we accept some valid keys (we don't check all the algorithms,
+ that's the job of isc.dns.TSIGKey).
+ """
+ self.assertEqual(None, tsig_keys.check({'keys':
+ ['testkey:QklORCAxMCBpcyBjb29sCg==',
+ 'test.key:QklORCAxMCBpcyBjb29sCg==:hmac-sha1']}))
+
+ def test_keys_same_name(self):
+ """
+ Test we reject when we have multiple keys with the same name.
+ """
+ self.assertEqual("Multiple TSIG keys with name 'test.key.'",
+ tsig_keys.check({'keys':
+ ['test.key:QklORCAxMCBpcyBjb29sCg==',
+ 'test.key:b3RoZXIK']}))
+
+ def test_invalid_key(self):
+ """
+ Test we reject invalid key.
+ """
+ self.assertEqual("TSIG: Invalid TSIG key string: invalid.key",
+ tsig_keys.check({'keys': ['invalid.key']}))
+ self.assertEqual(
+ "TSIG: attempt to decode a value not in base64 char set",
+ tsig_keys.check({'keys': ['invalid.key:123']}))
+
+ def test_bad_format(self):
+ """
+ Test we fail on bad format. We don't really care much how here, though,
+ as this should not get in trough config manager anyway.
+ """
+ self.assertNotEqual(None, tsig_keys.check({'bad_name': {}}))
+ self.assertNotEqual(None, tsig_keys.check({'keys': 'not_list'}))
+ self.assertNotEqual(None, tsig_keys.check({'keys': 42}))
+ self.assertNotEqual(None, tsig_keys.check({'keys': {}}))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/bin/cfgmgr/plugins/tsig_keys.py b/src/bin/cfgmgr/plugins/tsig_keys.py
new file mode 100644
index 0000000..d57e645
--- /dev/null
+++ b/src/bin/cfgmgr/plugins/tsig_keys.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2011 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# This is the plugin for tsig_keys configuration section. The TSIG keyring
+# lives there (eg. all the shared secrets, with some exceptions where there
+# are some TSIG keys elsewhere, but these should be removed soon). We do
+# sanity checking of user configuration here, simply by trying to construct
+# all the keys here.
+
+from isc.config.module_spec import module_spec_from_file
+from isc.util.file import path_search
+from pydnspp import TSIGKey, InvalidParameter
+from bind10_config import PLUGIN_PATHS
+spec = module_spec_from_file(path_search('tsig_keys.spec', PLUGIN_PATHS))
+
+def check(config):
+ # Check the data layout first
+ errors=[]
+ if not spec.validate_config(False, config, errors):
+ return ' '.join(errors)
+ # Get the list of keys, if any
+ keys = config.get('keys', [])
+ # Run through them, check they can be constructed and there are no
+ # duplicates
+ keyNames = set()
+ for key in keys:
+ try:
+ name = str(TSIGKey(key).get_key_name())
+ except InvalidParameter as e:
+ return "TSIG: " + str(e)
+ if name in keyNames:
+ return "Multiple TSIG keys with name '" + name + "'"
+ keyNames.add(name)
+ # No error found, so let's assume it's OK
+ return None
+
+def load():
+ return (spec, check)
diff --git a/src/bin/cfgmgr/plugins/tsig_keys.spec b/src/bin/cfgmgr/plugins/tsig_keys.spec
new file mode 100644
index 0000000..e558dd2
--- /dev/null
+++ b/src/bin/cfgmgr/plugins/tsig_keys.spec
@@ -0,0 +1,21 @@
+{
+ "module_spec": {
+ "module_name": "tsig_keys",
+ "module_description": "The TSIG keyring is stored here",
+ "config_data": [
+ {
+ "item_name": "keys",
+ "item_type": "list",
+ "item_optional": false,
+ "item_default": [],
+ "list_item_spec": {
+ "item_name": "key",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ }
+ }
+ ],
+ "commands": []
+ }
+}
diff --git a/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in
index 37cd0f5..ea5fc8b 100644
--- a/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in
+++ b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in
@@ -20,6 +20,7 @@
import unittest
import os
import sys
+import bind10_config
from isc.testutils.parse_args import OptsError, TestOptParser
class MyConfigManager:
@@ -110,6 +111,7 @@ class TestConfigManagerStartup(unittest.TestCase):
env_var = os.environ["B10_FROM_SOURCE"]
os.environ["B10_FROM_SOURCE"] = tmp_env_var
+ bind10_config.reload()
b = __import__("b10-cfgmgr", globals(), locals())
b.PLUGIN_PATH = [] # It's enough to test plugins in one test
b.ConfigManager = MyConfigManager
@@ -117,6 +119,7 @@ class TestConfigManagerStartup(unittest.TestCase):
if env_var != None:
os.environ["B10_FROM_SOURCE"] = env_var
+ bind10_config.reload()
sys.modules.pop("b10-cfgmgr")
diff --git a/src/lib/python/bind10_config.py.in b/src/lib/python/bind10_config.py.in
index 3f2947d..fe4adb5 100644
--- a/src/lib/python/bind10_config.py.in
+++ b/src/lib/python/bind10_config.py.in
@@ -17,7 +17,37 @@
# variables to python scripts and libraries.
import os
-BIND10_MSGQ_SOCKET_FILE = os.path.join("@localstatedir@",
- "@PACKAGE_NAME@",
- "msgq_socket").replace("${prefix}",
- "@prefix@")
+def reload():
+ # In a function, for testing purposes
+ global BIND10_MSGQ_SOCKET_FILE
+ global DATA_PATH
+ global PLUGIN_PATHS
+ global PREFIX
+ BIND10_MSGQ_SOCKET_FILE = os.path.join("@localstatedir@",
+ "@PACKAGE_NAME@",
+ "msgq_socket").replace("${prefix}",
+ "@prefix@")
+
+ # If B10_FROM_SOURCE is set in the environment, we use data files
+ # from a directory relative to the value of that variable, or, if defined,
+ # relative to the value of B10_FROM_SOURCE_LOCALSTATEDIR. Otherwise
+ # we use the ones installed on the system.
+ # B10_FROM_SOURCE_LOCALSTATEDIR is specifically intended to be used for
+ # tests where we want to use variuos types of configuration within the test
+ # environment. (We may want to make it even more generic so that the path is
+ # passed from the boss process)
+ if "B10_FROM_SOURCE" in os.environ:
+ if "B10_FROM_SOURCE_LOCALSTATEDIR" in os.environ:
+ DATA_PATH = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
+ else:
+ DATA_PATH = os.environ["B10_FROM_SOURCE"]
+ PLUGIN_PATHS = [DATA_PATH + '/src/bin/cfgmgr/plugins']
+ else:
+ PREFIX = "@prefix@"
+ DATA_PATH = "@localstatedir@/@PACKAGE@".replace("${prefix}", PREFIX)
+ PLUGIN_PATHS = ["@prefix@/share/@PACKAGE@/config_plugins"]
+ # For testing the plugins so they can find their own spec files
+ if "B10_TEST_PLUGIN_DIR" in os.environ:
+ PLUGIN_PATHS = os.environ["B10_TEST_PLUGIN_DIR"].split(':')
+
+reload()
diff --git a/src/lib/python/isc/util/Makefile.am b/src/lib/python/isc/util/Makefile.am
index 7ab8048..f6cbb78 100644
--- a/src/lib/python/isc/util/Makefile.am
+++ b/src/lib/python/isc/util/Makefile.am
@@ -1,5 +1,5 @@
SUBDIRS = . tests
-python_PYTHON = __init__.py process.py socketserver_mixin.py
+python_PYTHON = __init__.py process.py socketserver_mixin.py file.py
pythondir = $(pyexecdir)/isc/util
diff --git a/src/lib/python/isc/util/file.py b/src/lib/python/isc/util/file.py
new file mode 100644
index 0000000..faef9a8
--- /dev/null
+++ b/src/lib/python/isc/util/file.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2011 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""Various functions for working with files and directories."""
+
+from os.path import exists, join
+
+def path_search(filename, paths):
+ """
+ Searches list of paths to find filename in one of them. The found one will
+ be returned or IOError will be returned if it isn't found.
+ """
+ for p in paths:
+ f = join(p, filename)
+ if exists(f):
+ return f
+ raise IOError("'" + filename + "' not found in " + str(paths))
diff --git a/src/lib/python/isc/util/tests/Makefile.am b/src/lib/python/isc/util/tests/Makefile.am
index f32fda0..0ce96de 100644
--- a/src/lib/python/isc/util/tests/Makefile.am
+++ b/src/lib/python/isc/util/tests/Makefile.am
@@ -1,5 +1,5 @@
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
-PYTESTS = process_test.py socketserver_mixin_test.py
+PYTESTS = process_test.py socketserver_mixin_test.py file_test.py
EXTRA_DIST = $(PYTESTS)
# test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/python/isc/util/tests/file_test.py b/src/lib/python/isc/util/tests/file_test.py
new file mode 100644
index 0000000..fb765d7
--- /dev/null
+++ b/src/lib/python/isc/util/tests/file_test.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2011 Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import isc.util.file
+import unittest
+
+class FileTest(unittest.TestCase):
+ def test_search_path_find(self):
+ """Test it returns the first occurence of the file"""
+ self.assertEqual('./Makefile',
+ isc.util.file.path_search('Makefile',
+ ['/no/such/directory/', '.',
+ '../tests/']))
+
+ def test_search_path_notfound(self):
+ """Test it throws an exception when the file can't be found"""
+ self.assertRaises(IOError, isc.util.file.path_search, 'no file', ['/no/such/directory'])
+
+if __name__ == "__main__":
+ unittest.main()
More information about the bind10-changes
mailing list