BIND 10 trac2856, updated. 37753c0dc215875538463720a5bdd68afdb4fc4e [2856] Add test for "load" command to builder

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jul 12 06:38:09 UTC 2013


The branch, trac2856 has been updated
       via  37753c0dc215875538463720a5bdd68afdb4fc4e (commit)
       via  cca0075f103ef62c5b8413bb19a90c03d7bd4e04 (commit)
      from  377e88195e5f86ad60bf02bf02dcbd202daa9fa0 (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 37753c0dc215875538463720a5bdd68afdb4fc4e
Author: Mukund Sivaraman <muks at isc.org>
Date:   Fri Jul 12 11:39:20 2013 +0530

    [2856] Add test for "load" command to builder

commit cca0075f103ef62c5b8413bb19a90c03d7bd4e04
Author: Mukund Sivaraman <muks at isc.org>
Date:   Fri Jul 12 10:27:14 2013 +0530

    [2856] Rename env variable

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

Summary of changes:
 configure.ac                                       |    1 +
 src/lib/python/isc/memmgr/builder.py               |   22 ++--
 src/lib/python/isc/memmgr/tests/Makefile.am        |    4 +-
 src/lib/python/isc/memmgr/tests/builder_tests.py   |  115 +++++++++++++++++++-
 .../python/isc/memmgr/tests/datasrc_info_tests.py  |    6 +-
 .../python/isc/memmgr/tests/testdata/Makefile.am   |    2 +
 .../tests/testdata/example.com.zone}               |    0
 7 files changed, 136 insertions(+), 14 deletions(-)
 create mode 100644 src/lib/python/isc/memmgr/tests/testdata/Makefile.am
 copy src/lib/python/isc/{datasrc/tests/testdata/example.com => memmgr/tests/testdata/example.com.zone} (100%)

-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 8a0118e..7410f24 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1279,6 +1279,7 @@ AC_CONFIG_FILES([Makefile
                  src/lib/python/isc/ddns/tests/Makefile
                  src/lib/python/isc/memmgr/Makefile
                  src/lib/python/isc/memmgr/tests/Makefile
+                 src/lib/python/isc/memmgr/tests/testdata/Makefile
                  src/lib/python/isc/xfrin/Makefile
                  src/lib/python/isc/xfrin/tests/Makefile
                  src/lib/python/isc/server_common/Makefile
diff --git a/src/lib/python/isc/memmgr/builder.py b/src/lib/python/isc/memmgr/builder.py
index 07dd4a8..5aa23dc 100644
--- a/src/lib/python/isc/memmgr/builder.py
+++ b/src/lib/python/isc/memmgr/builder.py
@@ -13,6 +13,7 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+import json
 from isc.datasrc import ConfigurableClientList
 from isc.memmgr.datasrc_info import SegmentInfo
 
@@ -90,9 +91,10 @@ class MemorySegmentBuilder:
 
         clist = dsrc_info.clients_map[rrclass]
         sgmt_info = dsrc_info.segment_info_map[(rrclass, dsrc_name)]
+        params = json.dumps(sgmt_info.get_reset_param(SegmentInfo.WRITER))
         clist.reset_memory_segment(dsrc_name,
-                                   ConfigurableClientList.READ_ONLY,
-                                   sgmt_info.get_reset_param(SegmentInfo.WRITER))
+                                   ConfigurableClientList.READ_WRITE,
+                                   params)
 
         if zone_name is not None:
             zones = [(None, zone_name)]
@@ -100,9 +102,13 @@ class MemorySegmentBuilder:
             zones = clist.get_zone_table_accessor(dsrc_name, True)
 
         for _, zone_name in zones:
-            cache_load_error = (zone_name is None) # install empty zone initially
-            writer = clist.get_cached_zone_writer(zone_name, catch_load_error,
-                                                  dsrc_name)
+            catch_load_error = (zone_name is None) # install empty zone initially
+            result, writer = clist.get_cached_zone_writer(zone_name, catch_load_error,
+                                                          dsrc_name)
+            if result != ConfigurableClientList.CACHE_STATUS_ZONE_SUCCESS:
+                # FIXME: log the error
+                continue
+
             try:
                 error = writer.load()
                 if error is not None:
@@ -119,7 +125,7 @@ class MemorySegmentBuilder:
         # public API to just clear the segment)
         clist.reset_memory_segment(dsrc_name,
                                    ConfigurableClientList.READ_ONLY,
-                                   sgmt_info.get_reset_param(SegmentInfo.WRITER))
+                                   params)
 
         self._response_queue.append(('load-completed', dsrc_info, rrclass,
                                      dsrc_name))
@@ -154,8 +160,8 @@ class MemorySegmentBuilder:
                         # See the comments for __handle_load() for
                         # details of the tuple passed to the "load"
                         # command.
-                        self.__handle_load(command_tuple[1], command_tuple[2],
-                                           command_tuple[3], command_tuple[4])
+                        _, zone_name, dsrc_info, rrclass, dsrc_name = command_tuple
+                        self.__handle_load(zone_name, dsrc_info, rrclass, dsrc_name)
                     elif command == 'shutdown':
                         self.__handle_shutdown()
                         # When the shutdown command is received, we do
diff --git a/src/lib/python/isc/memmgr/tests/Makefile.am b/src/lib/python/isc/memmgr/tests/Makefile.am
index 7a85083..b171cb1 100644
--- a/src/lib/python/isc/memmgr/tests/Makefile.am
+++ b/src/lib/python/isc/memmgr/tests/Makefile.am
@@ -1,3 +1,4 @@
+SUBDIRS = testdata
 PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = builder_tests.py datasrc_info_tests.py
 EXTRA_DIST = $(PYTESTS)
@@ -26,7 +27,8 @@ endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
-	TESTDATA_PATH=$(builddir) \
+	TESTDATA_PATH=$(abs_srcdir)/testdata \
+	TESTDATA_WRITE_PATH=$(builddir) \
 	B10_FROM_BUILD=$(abs_top_builddir) \
 	HAVE_SHARED_MEMORY=$(HAVE_SHARED_MEMORY) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/lib/dns/python/.libs \
diff --git a/src/lib/python/isc/memmgr/tests/builder_tests.py b/src/lib/python/isc/memmgr/tests/builder_tests.py
index 94cb8e1..249b5d0 100644
--- a/src/lib/python/isc/memmgr/tests/builder_tests.py
+++ b/src/lib/python/isc/memmgr/tests/builder_tests.py
@@ -14,12 +14,28 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import unittest
+import os
 import socket
 import select
 import threading
 
 import isc.log
+from isc.dns import *
+import isc.datasrc
 from isc.memmgr.builder import *
+from isc.server_common.datasrc_clients_mgr import DataSrcClientsMgr
+from isc.memmgr.datasrc_info import *
+
+TESTDATA_PATH = os.environ['TESTDATA_PATH'] + os.sep
+
+# Defined for easier tests with DataSrcClientsMgr.reconfigure(), which
+# only needs get_value() method
+class MockConfigData:
+    def __init__(self, data):
+        self.__data = data
+
+    def get_value(self, identifier):
+        return self.__data[identifier], False
 
 class TestMemorySegmentBuilder(unittest.TestCase):
     def _create_builder_thread(self):
@@ -29,7 +45,8 @@ class TestMemorySegmentBuilder(unittest.TestCase):
         self._builder_command_queue = []
         self._builder_response_queue = []
 
-        self._builder_cv = threading.Condition()
+        self._builder_lock = threading.Lock()
+        self._builder_cv = threading.Condition(lock=self._builder_lock)
 
         self._builder = MemorySegmentBuilder(self._builder_sock,
                                              self._builder_cv,
@@ -95,7 +112,7 @@ class TestMemorySegmentBuilder(unittest.TestCase):
 
         self._builder_thread.start()
 
-        # Now that the builder thread is running, send it the shutdown
+        # Now that the builder thread is running, send it the "shutdown"
         # command. The thread should exit its main loop and be joinable.
         with self._builder_cv:
             self._builder_command_queue.append(('shutdown',))
@@ -115,6 +132,100 @@ class TestMemorySegmentBuilder(unittest.TestCase):
         self.assertEqual(len(self._builder_command_queue), 0)
         self.assertEqual(len(self._builder_response_queue), 0)
 
+    @unittest.skipIf(os.environ['HAVE_SHARED_MEMORY'] != 'yes',
+                     'shared memory is not available')
+    def test_load(self):
+        """
+        Test "load" command.
+        """
+
+        mapped_file_dir = os.environ['TESTDATA_WRITE_PATH']
+        mgr_config = {'mapped_file_dir': mapped_file_dir}
+
+        cfg_data = MockConfigData(
+            {"classes":
+                 {"IN": [{"type": "MasterFiles",
+                          "params": { "example.com": TESTDATA_PATH + "example.com.zone" },
+                          "cache-enable": True,
+                          "cache-type": "mapped"}]
+                  }
+             })
+        cmgr = DataSrcClientsMgr(use_cache=True)
+        cmgr.reconfigure({}, cfg_data)
+
+        genid, clients_map = cmgr.get_clients_map()
+        datasrc_info = DataSrcInfo(genid, clients_map, mgr_config)
+
+        self.assertEqual(1, datasrc_info.gen_id)
+        self.assertEqual(clients_map, datasrc_info.clients_map)
+        self.assertEqual(1, len(datasrc_info.segment_info_map))
+        sgmt_info = datasrc_info.segment_info_map[(RRClass.IN, 'MasterFiles')]
+        self.assertIsNone(sgmt_info.get_reset_param(SegmentInfo.READER))
+        self.assertIsNotNone(sgmt_info.get_reset_param(SegmentInfo.WRITER))
+
+        self._builder_thread.start()
+
+        # Now that the builder thread is running, send it the "load"
+        # command. We should be notified when the load operation is
+        # complete.
+        with self._builder_cv:
+            self._builder_command_queue.append(('load',
+                                                isc.dns.Name("example.com"),
+                                                datasrc_info, RRClass.IN,
+                                                'MasterFiles'))
+            self._builder_cv.notify_all()
+
+        # Wait 60 seconds to receive a notification on the socket from
+        # the builder.
+        (reads, _, _) = select.select([self._master_sock], [], [], 60)
+        self.assertTrue(self._master_sock in reads)
+
+        # Reading 1 byte should not block us here, especially as the
+        # socket is ready to read. It's a hack, but this is just a
+        # testcase.
+        got = self._master_sock.recv(1)
+        self.assertEqual(got, b'x')
+
+        with self._builder_lock:
+            # The command queue must be cleared, and the response queue
+            # must contain a response that a bad command was sent. The
+            # thread is no longer running, so we can use the queues
+            # without a lock.
+            self.assertEqual(len(self._builder_command_queue), 0)
+            self.assertEqual(len(self._builder_response_queue), 1)
+
+            response = self._builder_response_queue[0]
+            self.assertTrue(isinstance(response, tuple))
+            self.assertTupleEqual(response, ('load-completed', datasrc_info,
+                                             RRClass.IN, 'MasterFiles'))
+            del self._builder_response_queue[:]
+
+        # Now try looking for some loaded data
+        clist = datasrc_info.clients_map[RRClass.IN]
+        dsrc, finder, exact = clist.find(isc.dns.Name("example.com"))
+        self.assertIsNotNone(dsrc)
+        self.assertTrue(isinstance(dsrc, isc.datasrc.DataSourceClient))
+        self.assertIsNotNone(finder)
+        self.assertTrue(isinstance(finder, isc.datasrc.ZoneFinder))
+        self.assertTrue(exact)
+
+        # Send the builder thread the "shutdown" command. The thread
+        # should exit its main loop and be joinable.
+        with self._builder_cv:
+            self._builder_command_queue.append(('shutdown',))
+            self._builder_cv.notify_all()
+
+        # Wait 5 seconds at most for the main loop of the builder to
+        # exit.
+        self._builder_thread.join(5)
+        self.assertFalse(self._builder_thread.isAlive())
+
+        # The command queue must be cleared, and the response queue must
+        # be untouched (we don't use it in this test). The thread is no
+        # longer running, so we can use the queues without a lock.
+        self.assertEqual(len(self._builder_command_queue), 0)
+        self.assertEqual(len(self._builder_response_queue), 0)
+
 if __name__ == "__main__":
     isc.log.init("bind10-test")
     isc.log.resetUnitTestRootLogger()
diff --git a/src/lib/python/isc/memmgr/tests/datasrc_info_tests.py b/src/lib/python/isc/memmgr/tests/datasrc_info_tests.py
index 8c8e5e2..ee2b794 100644
--- a/src/lib/python/isc/memmgr/tests/datasrc_info_tests.py
+++ b/src/lib/python/isc/memmgr/tests/datasrc_info_tests.py
@@ -34,7 +34,7 @@ class MockConfigData:
 
 class TestSegmentInfo(unittest.TestCase):
     def setUp(self):
-        self.__mapped_file_dir = os.environ['TESTDATA_PATH']
+        self.__mapped_file_dir = os.environ['TESTDATA_WRITE_PATH']
         self.__sgmt_info = SegmentInfo.create('mapped', 0, RRClass.IN,
                                               'sqlite3',
                                               {'mapped_file_dir':
@@ -372,9 +372,9 @@ class MockClientList:
 
 class TestDataSrcInfo(unittest.TestCase):
     def setUp(self):
-        self.__mapped_file_dir = os.environ['TESTDATA_PATH']
+        self.__mapped_file_dir = os.environ['TESTDATA_WRITE_PATH']
         self.__mgr_config = {'mapped_file_dir': self.__mapped_file_dir}
-        self.__sqlite3_dbfile = os.environ['TESTDATA_PATH'] + '/' + 'zone.db'
+        self.__sqlite3_dbfile = os.environ['TESTDATA_WRITE_PATH'] + '/' + 'zone.db'
         self.__clients_map = {
             # mixture of 'local' and 'mapped' and 'unused' (type =None)
             # segments
diff --git a/src/lib/python/isc/memmgr/tests/testdata/Makefile.am b/src/lib/python/isc/memmgr/tests/testdata/Makefile.am
new file mode 100644
index 0000000..22e7ce3
--- /dev/null
+++ b/src/lib/python/isc/memmgr/tests/testdata/Makefile.am
@@ -0,0 +1,2 @@
+EXTRA_DIST = \
+	example.com.zone
diff --git a/src/lib/python/isc/memmgr/tests/testdata/example.com.zone b/src/lib/python/isc/memmgr/tests/testdata/example.com.zone
new file mode 100644
index 0000000..24e22e1
--- /dev/null
+++ b/src/lib/python/isc/memmgr/tests/testdata/example.com.zone
@@ -0,0 +1,8 @@
+example.com.         1000  IN  SOA a.dns.example.com. mail.example.com. 1 1 1 1 1
+example.com.         1000  IN  NS  a.dns.example.com.
+example.com.         1000  IN  NS  b.dns.example.com.
+example.com.         1000  IN  NS  c.dns.example.com.
+a.dns.example.com.   1000  IN  A    1.1.1.1
+b.dns.example.com.   1000  IN  A    3.3.3.3
+b.dns.example.com.   1000  IN  AAAA 4:4::4:4
+b.dns.example.com.   1000  IN  AAAA 5:5::5:5



More information about the bind10-changes mailing list