BIND 10 trac924, updated. 224c7b9aeb3000e11790a2c667f0ee45c9481f17 Merge branch 'master' into trac924

BIND 10 source code commits bind10-changes at lists.isc.org
Fri May 13 11:36:31 UTC 2011


The branch, trac924 has been updated
       via  224c7b9aeb3000e11790a2c667f0ee45c9481f17 (commit)
       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  98f5e0e604e60fead409c28645b064510b8fc8de (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 224c7b9aeb3000e11790a2c667f0ee45c9481f17
Merge: 98f5e0e604e60fead409c28645b064510b8fc8de fd08a0dc40846f58aaa8a7df7726ac83e5e4c038
Author: Shane Kerr <shane at isc.org>
Date:   Fri May 13 13:35:54 2011 +0200

    Merge branch 'master' into trac924

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

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