BIND 10 trac1175, updated. a001d339b3bdc5eac0082f6ed6374043705dcb9b [1175] add #1175

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Aug 22 09:20:08 UTC 2011


The branch, trac1175 has been updated
       via  a001d339b3bdc5eac0082f6ed6374043705dcb9b (commit)
       via  5d8481fd0871f35ed9da1df461b3fdc6e74357aa (commit)
       via  283bb29ee59cf135e74baccf6739f2bcd9cab37b (commit)
       via  74e80d4978c660e5b0512062c89a0ca15816d07b (commit)
      from  741c20363aae173fac3539b6f08cc4c659259fb5 (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 a001d339b3bdc5eac0082f6ed6374043705dcb9b
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:20:39 2011 +0900

    [1175] add #1175

commit 5d8481fd0871f35ed9da1df461b3fdc6e74357aa
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:18:47 2011 +0900

    [1175]
    - don't use time.sleep for waiting threads are starting or finishing
    - correct shutting down of mock modules
    - use _started (threading.Event) where command_handler is invoked
    - add implementation to changing contents of specfile of MyStatsHttpd
    - set "BIND10_MSGQ_SOCKET_FILE" only when it's not set yet

commit 283bb29ee59cf135e74baccf6739f2bcd9cab37b
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:10:25 2011 +0900

    [1175]
    - add function get_availaddr to get available address and port on the platform
    - add function is_ipv6enabled to check ipv6 enabled on the platform
    - add miscellaneous changes to refactor unittest

commit 74e80d4978c660e5b0512062c89a0ca15816d07b
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Mon Aug 22 18:05:57 2011 +0900

    [1175]
    - don't use DEFAULT_CONFIG
    - move up mccs.start and open_httpd to __init__(). It takes time to do these
    functions, and an extra sleep is needed in unittests.
    - set running to False in http stopping
    - use validate_config in module_spec class
    - don't close/open http before it's opened

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

Summary of changes:
 ChangeLog                                   |    2 +-
 src/bin/stats/stats_httpd.py.in             |   45 ++--
 src/bin/stats/tests/b10-stats-httpd_test.py |  440 ++++++++++++++-------------
 src/bin/stats/tests/b10-stats_test.py       |   32 ++-
 src/bin/stats/tests/test_utils.py           |   89 ++++---
 5 files changed, 326 insertions(+), 282 deletions(-)

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 3631bc7..399e647 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,7 +3,7 @@ xxx.    [func]          naokikambe
 	Stats module can read these through the config manager. Stats
 	module and stats httpd report statistics data and statistics
 	schema by each module via both bindctl and HTTP/XML.
-	(Trac #928,#929,#930, git TBD)
+	(Trac #928,#929,#930,#1175, git TBD)
 
 279.	[func]		jerry
 	libdns++: Implement the AFSDB rrtype according to RFC1183.
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
index f8a09e5..f8d80a5 100644
--- a/src/bin/stats/stats_httpd.py.in
+++ b/src/bin/stats/stats_httpd.py.in
@@ -68,7 +68,6 @@ XSD_URL_PATH = '/bind10/statistics/xsd'
 XSL_URL_PATH = '/bind10/statistics/xsl'
 # TODO: This should be considered later.
 XSD_NAMESPACE = 'http://bind10.isc.org' + XSD_URL_PATH
-DEFAULT_CONFIG = dict(version=0, listen_on=[('127.0.0.1', 8000)])
 
 # Assign this process name
 isc.util.process.rename()
@@ -159,7 +158,11 @@ class StatsHttpd:
         self.mccs = None
         self.httpd = []
         self.open_mccs()
+        self.config = {}
         self.load_config()
+        self.http_addrs = []
+        self.mccs.start()
+        self.open_httpd()
 
     def open_mccs(self):
         """Opens a ModuleCCSession object"""
@@ -182,18 +185,19 @@ class StatsHttpd:
         """Loads configuration from spec file or new configuration
         from the config manager"""
         # load config
-        if len(new_config) > 0:
-            self.config.update(new_config)
-        else:
-            self.config = DEFAULT_CONFIG
-            self.config.update(
-                dict([
-                        (itm['item_name'], self.mccs.get_value(itm['item_name'])[0])
-                        for itm in self.mccs.get_module_spec().get_config_spec()
-                        ])
-                )
+        if len(self.config) == 0:
+            self.config = dict([
+                (itm['item_name'], self.mccs.get_value(itm['item_name'])[0])
+                for itm in self.mccs.get_module_spec().get_config_spec()
+                ])
+        self.config.update(new_config)
         # set addresses and ports for HTTP
-        self.http_addrs = [ (cf['address'], cf['port']) for cf in self.config['listen_on'] ]
+        addrs = []
+        if 'listen_on' in self.config:
+            for cf in self.config['listen_on']:
+                if 'address' in cf and 'port' in cf:
+                    addrs.append((cf['address'], cf['port']))
+        self.http_addrs = addrs
 
     def open_httpd(self):
         """Opens sockets for HTTP. Iterating each HTTP address to be
@@ -235,8 +239,6 @@ class StatsHttpd:
     def start(self):
         """Starts StatsHttpd objects to run. Waiting for client
         requests by using select.select functions"""
-        self.open_httpd()
-        self.mccs.start()
         self.running = True
         while self.running:
             try:
@@ -269,6 +271,7 @@ class StatsHttpd:
         logger.info(STATHTTPD_SHUTDOWN)
         self.close_httpd()
         self.close_mccs()
+        self.running = False
 
     def get_sockets(self):
         """Returns sockets to select.select"""
@@ -285,15 +288,19 @@ class StatsHttpd:
         addresses and ports to listen HTTP requests on."""
         logger.debug(DBG_STATHTTPD_MESSAGING, STATHTTPD_HANDLE_CONFIG,
                    new_config)
-        for key in new_config.keys():
-            if key not in DEFAULT_CONFIG and key != "version":
-                logger.error(STATHTTPD_UNKNOWN_CONFIG_ITEM, key)
+        errors = []
+        if not self.mccs.get_module_spec().\
+                validate_config(False, new_config, errors):
                 return isc.config.ccsession.create_answer(
-                    1, "Unknown known config: %s" % key)
+                    1, ", ".join(errors))
         # backup old config
         old_config = self.config.copy()
-        self.close_httpd()
         self.load_config(new_config)
+        # If the http sockets aren't opened or
+        # if new_config doesn't have'listen_on', it returns
+        if len(self.httpd) == 0 or 'listen_on' not in new_config:
+            return isc.config.ccsession.create_answer(0)
+        self.close_httpd()
         try:
             self.open_httpd()
         except HttpServerError as err:
diff --git a/src/bin/stats/tests/b10-stats-httpd_test.py b/src/bin/stats/tests/b10-stats-httpd_test.py
index 8c84277..79631f4 100644
--- a/src/bin/stats/tests/b10-stats-httpd_test.py
+++ b/src/bin/stats/tests/b10-stats-httpd_test.py
@@ -36,7 +36,7 @@ import xml.etree.ElementTree
 import isc
 import stats_httpd
 import stats
-from test_utils import BaseModules, ThreadingServerManager, MyStats, MyStatsHttpd, TIMEOUT_SEC
+from test_utils import BaseModules, ThreadingServerManager, MyStats, MyStatsHttpd, send_shutdown
 
 # set test name for logger
 isc.log.init("b10-stats-httpd_test")
@@ -58,35 +58,61 @@ DUMMY_DATA = {
         }
     }
 
+def get_availaddr(address='127.0.0.1'):
+    """returns tuple of address and port available on the
+    platform. default range of port is from 65535 to 50000"""
+    for port in range(65535, 50000, -1):
+        try:
+            if is_ipv6_enabled(address):
+                sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+            else :
+                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.bind((address, port))
+            sock.close()
+            return (address, port)
+        except socket.error:
+            pass
+
+def is_ipv6_enabled(address='::1', port=8000):
+    """checks IPv6 enabled on the platform"""
+    try:
+        sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+        sock.bind((address, port))
+        sock.close()
+        return True
+    except socket.error:
+        return False
+
 class TestHttpHandler(unittest.TestCase):
     """Tests for HttpHandler class"""
-
     def setUp(self):
         self.base = BaseModules()
         self.stats_server = ThreadingServerManager(MyStats)
         self.stats = self.stats_server.server
         self.stats_server.run()
+        (self.address, self.port) = get_availaddr()
+        self.stats_httpd_server = ThreadingServerManager(MyStatsHttpd, (self.address, self.port))
+        self.stats_httpd = self.stats_httpd_server.server
+        self.stats_httpd_server.run()
+        self.client = http.client.HTTPConnection(self.address, self.port)
+        self.client._http_vsn_str = 'HTTP/1.0\n'
+        self.client.connect()
 
     def tearDown(self):
+        self.client.close()
+        self.stats_httpd_server.shutdown()
         self.stats_server.shutdown()
         self.base.shutdown()
 
     def test_do_GET(self):
-        (address, port) = ('127.0.0.1', 65450)
-        statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        self.stats_httpd = statshttpd_server.server
-        self.stats_httpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
         self.assertTrue(type(self.stats_httpd.httpd) is list)
-        self.assertEqual(len(self.stats_httpd.httpd), 0)
-        statshttpd_server.run()
-        client = http.client.HTTPConnection(address, port)
-        client._http_vsn_str = 'HTTP/1.0\n'
-        client.connect()
+        self.assertEqual(len(self.stats_httpd.httpd), 1)
+        self.assertEqual((self.address, self.port), self.stats_httpd.http_addrs[0])
 
         # URL is '/bind10/statistics/xml'
-        client.putrequest('GET', stats_httpd.XML_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XML_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.getheader("Content-type"), "text/xml")
         self.assertTrue(int(response.getheader("Content-Length")) > 0)
         self.assertEqual(response.status, 200)
@@ -100,9 +126,9 @@ class TestHttpHandler(unittest.TestCase):
                 self.assertIsNotNone(root.find(mod + '/' + item))
 
         # URL is '/bind10/statitics/xsd'
-        client.putrequest('GET', stats_httpd.XSD_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSD_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.getheader("Content-type"), "text/xml")
         self.assertTrue(int(response.getheader("Content-Length")) > 0)
         self.assertEqual(response.status, 200)
@@ -120,9 +146,9 @@ class TestHttpHandler(unittest.TestCase):
             self.assertTrue(elm.attrib['name'] in DUMMY_DATA)
 
         # URL is '/bind10/statitics/xsl'
-        client.putrequest('GET', stats_httpd.XSL_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSL_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.getheader("Content-type"), "text/xml")
         self.assertTrue(int(response.getheader("Content-Length")) > 0)
         self.assertEqual(response.status, 200)
@@ -147,114 +173,83 @@ class TestHttpHandler(unittest.TestCase):
                                 [ tds[0].text+'/'+item for item in DUMMY_DATA[tds[0].text].keys() ])
 
         # 302 redirect
-        client._http_vsn_str = 'HTTP/1.1'
-        client.putrequest('GET', '/')
-        client.putheader('Host', address)
-        client.endheaders()
-        response = client.getresponse()
+        self.client._http_vsn_str = 'HTTP/1.1'
+        self.client.putrequest('GET', '/')
+        self.client.putheader('Host', self.address)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 302)
         self.assertEqual(response.getheader('Location'),
-                         "http://%s:%d%s" % (address, port, stats_httpd.XML_URL_PATH))
+                         "http://%s:%d%s" % (self.address, self.port, stats_httpd.XML_URL_PATH))
 
         # # 404 NotFound
-        client._http_vsn_str = 'HTTP/1.0'
-        client.putrequest('GET', '/path/to/foo/bar')
-        client.endheaders()
-        response = client.getresponse()
+        self.client._http_vsn_str = 'HTTP/1.0'
+        self.client.putrequest('GET', '/path/to/foo/bar')
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 404)
 
-        client.close()
-        statshttpd_server.shutdown()
 
     def test_do_GET_failed1(self):
-        # failure case(connection with Stats is down)
-        (address, port) = ('127.0.0.1', 65451)
-        statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        statshttpd = statshttpd_server.server
-        statshttpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
-        statshttpd_server.run()
-        self.assertTrue(self.stats_server.server.running)
-        self.stats_server.shutdown()
-        self.assertFalse(self.stats_server.server.running)
-        statshttpd.cc_session.set_timeout(milliseconds=TIMEOUT_SEC/1000)
-        client = http.client.HTTPConnection(address, port)
-        client.connect()
+        # failure case(Stats is down)
+        self.assertTrue(self.stats.running)
+        send_shutdown("Stats") # Stats is down
+        self.assertFalse(self.stats.running)
+        self.stats_httpd.cc_session.set_timeout(milliseconds=100)
 
         # request XML
-        client.putrequest('GET', stats_httpd.XML_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XML_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
         # request XSD
-        client.putrequest('GET', stats_httpd.XSD_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSD_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
         # request XSL
-        client.putrequest('GET', stats_httpd.XSL_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSL_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
-        client.close()
-        statshttpd_server.shutdown()
-
     def test_do_GET_failed2(self):
-        # failure case(connection with Stats is down)
-        (address, port) = ('127.0.0.1', 65452)
-        statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        self.stats_httpd = statshttpd_server.server
-        self.stats_httpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
-        statshttpd_server.run()
+        # failure case(Stats replies an error)
         self.stats.mccs.set_command_handler(
             lambda cmd, args: \
                 isc.config.ccsession.create_answer(1, "I have an error.")
             )
-        client = http.client.HTTPConnection(address, port)
-        client.connect()
 
         # request XML
-        client.putrequest('GET', stats_httpd.XML_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XML_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
         # request XSD
-        client.putrequest('GET', stats_httpd.XSD_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSD_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
         # request XSL
-        client.putrequest('GET', stats_httpd.XSL_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('GET', stats_httpd.XSL_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 500)
 
-        client.close()
-        statshttpd_server.shutdown()
-
     def test_do_HEAD(self):
-        (address, port) = ('127.0.0.1', 65453)
-        statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        self.stats_httpd = statshttpd_server.server
-        self.stats_httpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
-        statshttpd_server.run()
-        client = http.client.HTTPConnection(address, port)
-        client.connect()
-        client.putrequest('HEAD', stats_httpd.XML_URL_PATH)
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('HEAD', stats_httpd.XML_URL_PATH)
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 200)
 
-        client.putrequest('HEAD', '/path/to/foo/bar')
-        client.endheaders()
-        response = client.getresponse()
+        self.client.putrequest('HEAD', '/path/to/foo/bar')
+        self.client.endheaders()
+        response = self.client.getresponse()
         self.assertEqual(response.status, 404)
-        client.close()
-        statshttpd_server.shutdown()
 
 class TestHttpServerError(unittest.TestCase):
     """Tests for HttpServerError exception"""
@@ -273,9 +268,12 @@ class TestHttpServer(unittest.TestCase):
         self.base.shutdown()
 
     def test_httpserver(self):
-        statshttpd = stats_httpd.StatsHttpd()
-        self.assertEqual(type(statshttpd.httpd), list)
-        self.assertEqual(len(statshttpd.httpd), 0)
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.assertEqual(type(self.stats_httpd.httpd), list)
+        self.assertEqual(len(self.stats_httpd.httpd), 1)
+        for httpd in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(httpd, stats_httpd.HttpServer))
+        self.stats_httpd.stop()
 
 class TestStatsHttpdError(unittest.TestCase):
     """Tests for StatsHttpdError exception"""
@@ -292,28 +290,20 @@ class TestStatsHttpd(unittest.TestCase):
     def setUp(self):
         self.base = BaseModules()
         self.stats_server = ThreadingServerManager(MyStats)
-        self.stats = self.stats_server.server
         self.stats_server.run()
-        self.stats_httpd = stats_httpd.StatsHttpd()
-
         # checking IPv6 enabled on this platform
-        self.ipv6_enabled = True
-        try:
-            sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
-            sock.bind(("::1",8000))
-            sock.close()
-        except socket.error:
-            self.ipv6_enabled = False
+        self.ipv6_enabled = is_ipv6_enabled()
 
     def tearDown(self):
-        self.stats_httpd.stop()
         self.stats_server.shutdown()
         self.base.shutdown()
 
     def test_init(self):
+        server_address = get_availaddr()
+        self.stats_httpd = MyStatsHttpd(server_address)
         self.assertEqual(self.stats_httpd.running, False)
         self.assertEqual(self.stats_httpd.poll_intval, 0.5)
-        self.assertEqual(self.stats_httpd.httpd, [])
+        self.assertNotEqual(len(self.stats_httpd.httpd), 0)
         self.assertEqual(type(self.stats_httpd.mccs), isc.config.ModuleCCSession)
         self.assertEqual(type(self.stats_httpd.cc_session), isc.cc.Session)
         self.assertEqual(len(self.stats_httpd.config), 2)
@@ -321,144 +311,164 @@ class TestStatsHttpd(unittest.TestCase):
         self.assertEqual(len(self.stats_httpd.config['listen_on']), 1)
         self.assertTrue('address' in self.stats_httpd.config['listen_on'][0])
         self.assertTrue('port' in self.stats_httpd.config['listen_on'][0])
-        self.assertTrue(('127.0.0.1', 8000) in set(self.stats_httpd.http_addrs))
+        self.assertTrue(server_address in set(self.stats_httpd.http_addrs))
+        self.stats_httpd.stop()
 
     def test_openclose_mccs(self):
-        statshttpd = stats_httpd.StatsHttpd()
-        statshttpd.close_mccs()
-        self.assertEqual(statshttpd.mccs, None)
-        statshttpd.open_mccs()
-        self.assertIsNotNone(statshttpd.mccs)
-        statshttpd.mccs = None
-        self.assertEqual(statshttpd.mccs, None)
-        self.assertEqual(statshttpd.close_mccs(), None)
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.stats_httpd.close_mccs()
+        self.assertEqual(self.stats_httpd.mccs, None)
+        self.stats_httpd.open_mccs()
+        self.assertIsNotNone(self.stats_httpd.mccs)
+        self.stats_httpd.mccs = None
+        self.assertEqual(self.stats_httpd.mccs, None)
+        self.assertEqual(self.stats_httpd.close_mccs(), None)
+        self.stats_httpd.stop()
 
     def test_mccs(self):
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
         self.assertIsNotNone(self.stats_httpd.mccs.get_socket())
         self.assertTrue(
             isinstance(self.stats_httpd.mccs.get_socket(), socket.socket))
         self.assertTrue(
             isinstance(self.stats_httpd.cc_session, isc.cc.session.Session))
-        self.statistics_spec = self.stats_httpd.get_stats_spec()
+        statistics_spec = self.stats_httpd.get_stats_spec()
         for mod in DUMMY_DATA:
-            self.assertTrue(mod in self.statistics_spec)
-            for cfg in self.statistics_spec[mod]:
+            self.assertTrue(mod in statistics_spec)
+            for cfg in statistics_spec[mod]:
                 self.assertTrue('item_name' in cfg)
                 self.assertTrue(cfg['item_name'] in DUMMY_DATA[mod])
-            self.assertTrue(len(self.statistics_spec[mod]), len(DUMMY_DATA[mod]))
+            self.assertTrue(len(statistics_spec[mod]), len(DUMMY_DATA[mod]))
         self.stats_httpd.close_mccs()
         self.assertIsNone(self.stats_httpd.mccs)
+        self.stats_httpd.stop()
 
     def test_httpd(self):
         # dual stack (addresses is ipv4 and ipv6)
         if self.ipv6_enabled:
-            self.assertTrue(('127.0.0.1', 8000) in set(self.stats_httpd.http_addrs))
-            self.stats_httpd.http_addrs = [ ('::1', 8000), ('127.0.0.1', 8000) ]
-            self.assertTrue(
-                stats_httpd.HttpServer.address_family in set([socket.AF_INET, socket.AF_INET6]))
-            self.stats_httpd.open_httpd()
+            server_addresses = (get_availaddr('::1'), get_availaddr())
+            self.stats_httpd = MyStatsHttpd(*server_addresses)
             for ht in self.stats_httpd.httpd:
+                self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+                self.assertTrue(ht.address_family in set([socket.AF_INET, socket.AF_INET6]))
                 self.assertTrue(isinstance(ht.socket, socket.socket))
-            self.stats_httpd.close_httpd()
+            self.stats_httpd.stop()
 
         # dual stack (address is ipv6)
         if self.ipv6_enabled:
-            self.stats_httpd.http_addrs = [ ('::1', 8000) ]
-            self.stats_httpd.open_httpd()
+            server_addresses = get_availaddr('::1')
+            self.stats_httpd = MyStatsHttpd(server_addresses)
             for ht in self.stats_httpd.httpd:
+                self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+                self.assertEqual(ht.address_family, socket.AF_INET6)
                 self.assertTrue(isinstance(ht.socket, socket.socket))
-            self.stats_httpd.close_httpd()
+            self.stats_httpd.stop()
 
         # dual stack (address is ipv4)
         if self.ipv6_enabled:
-            self.stats_httpd.http_addrs = [ ('127.0.0.1', 8000) ]
-            self.stats_httpd.open_httpd()
+            server_addresses = get_availaddr()
+            self.stats_httpd = MyStatsHttpd(server_addresses)
             for ht in self.stats_httpd.httpd:
+                self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+                self.assertEqual(ht.address_family, socket.AF_INET)
                 self.assertTrue(isinstance(ht.socket, socket.socket))
-            self.stats_httpd.close_httpd()
+            self.stats_httpd.stop()
 
         # only-ipv4 single stack
         if not self.ipv6_enabled:
-            self.stats_httpd.http_addrs = [ ('127.0.0.1', 8000) ]
-            self.stats_httpd.open_httpd()
+            server_addresses = get_availaddr()
+            self.stats_httpd = MyStatsHttpd(server_addresses)
             for ht in self.stats_httpd.httpd:
+                self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+                self.assertEqual(ht.address_family, socket.AF_INET)
                 self.assertTrue(isinstance(ht.socket, socket.socket))
-            self.stats_httpd.close_httpd()
+            self.stats_httpd.stop()
 
-        # only-ipv4 single stack (force set ipv6 )
-        if not self.ipv6_enabled:
-            self.stats_httpd.http_addrs = [ ('::1', 8000) ]
-            self.assertRaises(stats_httpd.HttpServerError,
-                              self.stats_httpd.open_httpd)
+        # any address (IPv4)
+        server_addresses = get_availaddr(address='0.0.0.0')
+        self.stats_httpd = MyStatsHttpd(server_addresses)
+        for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+            self.assertEqual(ht.address_family,socket.AF_INET)
+            self.assertTrue(isinstance(ht.socket, socket.socket))
+        self.stats_httpd.stop()
+
+        # any address (IPv6)
+        if self.ipv6_enabled:
+            server_addresses = get_availaddr(address='::')
+            self.stats_httpd = MyStatsHttpd(server_addresses)
+            for ht in self.stats_httpd.httpd:
+                self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+                self.assertEqual(ht.address_family,socket.AF_INET6)
+                self.assertTrue(isinstance(ht.socket, socket.socket))
+            self.stats_httpd.stop()
 
         # hostname
-        self.stats_httpd.http_addrs = [ ('localhost', 8000) ]
-        self.stats_httpd.open_httpd()
+        server_addresses = get_availaddr(address='localhost')
+        self.stats_httpd = MyStatsHttpd(server_addresses)
         for ht in self.stats_httpd.httpd:
+            self.assertTrue(isinstance(ht, stats_httpd.HttpServer))
+            self.assertTrue(ht.address_family in set([socket.AF_INET, socket.AF_INET6]))
             self.assertTrue(isinstance(ht.socket, socket.socket))
-        self.stats_httpd.close_httpd()
+        self.stats_httpd.stop()
 
-        self.stats_httpd.http_addrs = [ ('my.host.domain', 8000) ]
-        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
-        self.assertEqual(type(self.stats_httpd.httpd), list)
-        self.assertEqual(len(self.stats_httpd.httpd), 0)
-        self.stats_httpd.close_httpd()
+        # nonexistent hostname
+        self.assertRaises(stats_httpd.HttpServerError, MyStatsHttpd, ('my.host.domain', 8000))
 
         # over flow of port number
-        self.stats_httpd.http_addrs = [ ('', 80000) ]
-        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+        self.assertRaises(stats_httpd.HttpServerError, MyStatsHttpd, ('127.0.0.1', 80000))
 
         # negative
-        self.stats_httpd.http_addrs = [ ('', -8000) ]
-        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+        self.assertRaises(stats_httpd.HttpServerError, MyStatsHttpd, ('127.0.0.1', -8000))
 
         # alphabet
-        self.stats_httpd.http_addrs = [ ('', 'ABCDE') ]
-        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
+        self.assertRaises(stats_httpd.HttpServerError, MyStatsHttpd, ('127.0.0.1', 'ABCDE'))
 
         # Address already in use
-        self.statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        self.statshttpd_server.server.load_config({'listen_on' : [{ 'address': '127.0.0.1', 'port' : 65454 }]})
-        self.statshttpd_server.run()
-        self.stats_httpd.load_config({'listen_on' : [{ 'address': '127.0.0.1', 'port' : 65454 }]})
-        self.assertRaises(stats_httpd.HttpServerError, self.stats_httpd.open_httpd)
-        self.statshttpd_server.shutdown()
+        server_addresses = get_availaddr()
+        self.stats_httpd_server = ThreadingServerManager(MyStatsHttpd, server_addresses)
+        self.stats_httpd_server.run()
+        self.assertRaises(stats_httpd.HttpServerError, MyStatsHttpd, server_addresses)
+        self.stats_httpd_server.shutdown()
 
     def test_running(self):
+        self.stats_httpd_server = ThreadingServerManager(MyStatsHttpd, get_availaddr())
+        self.stats_httpd = self.stats_httpd_server.server
         self.assertFalse(self.stats_httpd.running)
-        self.statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        self.stats_httpd = self.statshttpd_server.server
-        self.stats_httpd.load_config({'listen_on' : [{ 'address': '127.0.0.1', 'port' : 65455 }]})
-        self.statshttpd_server.run()
+        self.stats_httpd_server.run()
         self.assertTrue(self.stats_httpd.running)
-        self.statshttpd_server.shutdown()
+        send_shutdown("StatsHttpd")
         self.assertFalse(self.stats_httpd.running)
+        self.stats_httpd_server.shutdown()
 
         # failure case
-        self.stats_httpd = stats_httpd.StatsHttpd()
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
         self.stats_httpd.cc_session.close()
-        self.assertRaises(
-            isc.cc.session.SessionError, self.stats_httpd.start)
+        self.assertRaises(ValueError, self.stats_httpd.start)
+        self.stats_httpd.stop()
 
-    def test_select_failure(self):
+    def test_select_failure1(self):
         def raise_select_except(*args):
             raise select.error('dummy error')
-        def raise_select_except_with_errno(*args):
+        orig_select = stats_httpd.select.select
+        stats_httpd.select.select = raise_select_except
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.assertRaises(select.error, self.stats_httpd.start)
+        self.stats_httpd.stop()
+        stats_httpd.select.select = orig_select
+
+    def test_select_failure2(self):
+        def raise_select_except(*args):
             raise select.error(errno.EINTR)
-        (address, port) = ('127.0.0.1', 65456)
+        orig_select = stats_httpd.select.select
         stats_httpd.select.select = raise_select_except
-        statshttpd = stats_httpd.StatsHttpd()
-        statshttpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
-        self.assertRaises(select.error, statshttpd.start)
-        statshttpd.stop()
-        stats_httpd.select.select = raise_select_except_with_errno
-        statshttpd_server = ThreadingServerManager(MyStatsHttpd)
-        statshttpd = statshttpd_server.server
-        statshttpd.load_config({'listen_on' : [{ 'address': address, 'port' : port }]})
-        statshttpd_server.run()
-        statshttpd_server.shutdown()
+        self.stats_httpd_server = ThreadingServerManager(MyStatsHttpd, get_availaddr())
+        self.stats_httpd_server.run()
+        self.stats_httpd_server.shutdown()
+        stats_httpd.select.select = orig_select
 
     def test_open_template(self):
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
         # successful conditions
         tmpl = self.stats_httpd.open_template(stats_httpd.XML_TEMPLATE_LOCATION)
         self.assertTrue(isinstance(tmpl, string.Template))
@@ -490,8 +500,10 @@ class TestStatsHttpd(unittest.TestCase):
         self.assertRaises(
             IOError,
             self.stats_httpd.open_template, '/path/to/foo/bar')
+        self.stats_httpd.stop()
 
     def test_commands(self):
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
         self.assertEqual(self.stats_httpd.command_handler("status", None),
                          isc.config.ccsession.create_answer(
                 0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")"))
@@ -504,75 +516,81 @@ class TestStatsHttpd(unittest.TestCase):
             self.stats_httpd.command_handler("__UNKNOWN_COMMAND__", None),
             isc.config.ccsession.create_answer(
                 1, "Unknown command: __UNKNOWN_COMMAND__"))
+        self.stats_httpd.stop()
 
     def test_config(self):
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
         self.assertEqual(
             self.stats_httpd.config_handler(dict(_UNKNOWN_KEY_=None)),
             isc.config.ccsession.create_answer(
-                1, "Unknown known config: _UNKNOWN_KEY_"))
+                1, "unknown item _UNKNOWN_KEY_"))
 
+        addresses = get_availaddr()
         self.assertEqual(
             self.stats_httpd.config_handler(
-                dict(listen_on=[dict(address="127.0.0.1",port=8000)])),
+                dict(listen_on=[dict(address=addresses[0],port=addresses[1])])),
             isc.config.ccsession.create_answer(0))
         self.assertTrue("listen_on" in self.stats_httpd.config)
         for addr in self.stats_httpd.config["listen_on"]:
             self.assertTrue("address" in addr)
             self.assertTrue("port" in addr)
-            self.assertTrue(addr["address"] == "127.0.0.1")
-            self.assertTrue(addr["port"] == 8000)
+            self.assertTrue(addr["address"] == addresses[0])
+            self.assertTrue(addr["port"] == addresses[1])
 
         if self.ipv6_enabled:
+            addresses = get_availaddr("::1")
             self.assertEqual(
                 self.stats_httpd.config_handler(
-                    dict(listen_on=[dict(address="::1",port=8000)])),
+                dict(listen_on=[dict(address=addresses[0],port=addresses[1])])),
                 isc.config.ccsession.create_answer(0))
             self.assertTrue("listen_on" in self.stats_httpd.config)
             for addr in self.stats_httpd.config["listen_on"]:
                 self.assertTrue("address" in addr)
                 self.assertTrue("port" in addr)
-                self.assertTrue(addr["address"] == "::1")
-                self.assertTrue(addr["port"] == 8000)
+                self.assertTrue(addr["address"] == addresses[0])
+                self.assertTrue(addr["port"] == addresses[1])
 
+        addresses = get_availaddr()
         self.assertEqual(
             self.stats_httpd.config_handler(
-                        dict(listen_on=[dict(address="127.0.0.1",port=54321)])),
+                dict(listen_on=[dict(address=addresses[0],port=addresses[1])])),
             isc.config.ccsession.create_answer(0))
         self.assertTrue("listen_on" in self.stats_httpd.config)
         for addr in self.stats_httpd.config["listen_on"]:
             self.assertTrue("address" in addr)
             self.assertTrue("port" in addr)
-            self.assertTrue(addr["address"] == "127.0.0.1")
-            self.assertTrue(addr["port"] == 54321)
+            self.assertTrue(addr["address"] == addresses[0])
+            self.assertTrue(addr["port"] == addresses[1])
         (ret, arg) = isc.config.ccsession.parse_answer(
             self.stats_httpd.config_handler(
                 dict(listen_on=[dict(address="1.2.3.4",port=543210)]))
             )
         self.assertEqual(ret, 1)
+        self.stats_httpd.stop()
 
     def test_xml_handler(self):
-        orig_get_stats_data = stats_httpd.StatsHttpd.get_stats_data
-        stats_httpd.StatsHttpd.get_stats_data = lambda x: \
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.stats_httpd.get_stats_data = lambda: \
             { 'Dummy' : { 'foo':'bar' } }
-        xml_body1 = stats_httpd.StatsHttpd().open_template(
+        xml_body1 = self.stats_httpd.open_template(
             stats_httpd.XML_TEMPLATE_LOCATION).substitute(
             xml_string='<Dummy><foo>bar</foo></Dummy>',
             xsd_namespace=stats_httpd.XSD_NAMESPACE,
             xsd_url_path=stats_httpd.XSD_URL_PATH,
             xsl_url_path=stats_httpd.XSL_URL_PATH)
-        xml_body2 = stats_httpd.StatsHttpd().xml_handler()
+        xml_body2 = self.stats_httpd.xml_handler()
         self.assertEqual(type(xml_body1), str)
         self.assertEqual(type(xml_body2), str)
         self.assertEqual(xml_body1, xml_body2)
-        stats_httpd.StatsHttpd.get_stats_data = lambda x: \
+        self.stats_httpd.get_stats_data = lambda: \
             { 'Dummy' : {'bar':'foo'} }
-        xml_body2 = stats_httpd.StatsHttpd().xml_handler()
+        xml_body2 = self.stats_httpd.xml_handler()
         self.assertNotEqual(xml_body1, xml_body2)
-        stats_httpd.StatsHttpd.get_stats_data = orig_get_stats_data
+        self.stats_httpd.stop()
 
     def test_xsd_handler(self):
-        orig_get_stats_spec = stats_httpd.StatsHttpd.get_stats_spec
-        stats_httpd.StatsHttpd.get_stats_spec = lambda x: \
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.stats_httpd.get_stats_spec = lambda: \
             { "Dummy" :
                   [{
                         "item_name": "foo",
@@ -583,7 +601,7 @@ class TestStatsHttpd(unittest.TestCase):
                         "item_title": "Foo"
                         }]
               }
-        xsd_body1 = stats_httpd.StatsHttpd().open_template(
+        xsd_body1 = self.stats_httpd.open_template(
             stats_httpd.XSD_TEMPLATE_LOCATION).substitute(
             xsd_string=\
                 '<all><element name="Dummy"><complexType><all>' \
@@ -593,11 +611,11 @@ class TestStatsHttpd(unittest.TestCase):
                 + '</annotation></element></all>' \
                 + '</complexType></element></all>',
             xsd_namespace=stats_httpd.XSD_NAMESPACE)
-        xsd_body2 = stats_httpd.StatsHttpd().xsd_handler()
+        xsd_body2 = self.stats_httpd.xsd_handler()
         self.assertEqual(type(xsd_body1), str)
         self.assertEqual(type(xsd_body2), str)
         self.assertEqual(xsd_body1, xsd_body2)
-        stats_httpd.StatsHttpd.get_stats_spec = lambda x: \
+        self.stats_httpd.get_stats_spec = lambda: \
             { "Dummy" :
                   [{
                         "item_name": "bar",
@@ -608,13 +626,13 @@ class TestStatsHttpd(unittest.TestCase):
                         "item_title": "bar"
                         }]
               }
-        xsd_body2 = stats_httpd.StatsHttpd().xsd_handler()
+        xsd_body2 = self.stats_httpd.xsd_handler()
         self.assertNotEqual(xsd_body1, xsd_body2)
-        stats_httpd.StatsHttpd.get_stats_spec = orig_get_stats_spec
+        self.stats_httpd.stop()
 
     def test_xsl_handler(self):
-        orig_get_stats_spec = stats_httpd.StatsHttpd.get_stats_spec
-        stats_httpd.StatsHttpd.get_stats_spec = lambda x: \
+        self.stats_httpd = MyStatsHttpd(get_availaddr())
+        self.stats_httpd.get_stats_spec = lambda: \
             { "Dummy" :
                   [{
                         "item_name": "foo",
@@ -625,7 +643,7 @@ class TestStatsHttpd(unittest.TestCase):
                         "item_title": "Foo"
                         }]
               }
-        xsl_body1 = stats_httpd.StatsHttpd().open_template(
+        xsl_body1 = self.stats_httpd.open_template(
             stats_httpd.XSL_TEMPLATE_LOCATION).substitute(
             xsl_string='<xsl:template match="*"><tr>' \
                 + '<td>Dummy</td>' \
@@ -633,11 +651,11 @@ class TestStatsHttpd(unittest.TestCase):
                 + '<td><xsl:value-of select="Dummy/foo" /></td>' \
                 + '</tr></xsl:template>',
             xsd_namespace=stats_httpd.XSD_NAMESPACE)
-        xsl_body2 = stats_httpd.StatsHttpd().xsl_handler()
+        xsl_body2 = self.stats_httpd.xsl_handler()
         self.assertEqual(type(xsl_body1), str)
         self.assertEqual(type(xsl_body2), str)
         self.assertEqual(xsl_body1, xsl_body2)
-        stats_httpd.StatsHttpd.get_stats_spec = lambda x: \
+        self.stats_httpd.get_stats_spec = lambda: \
             { "Dummy" :
                   [{
                         "item_name": "bar",
@@ -648,9 +666,9 @@ class TestStatsHttpd(unittest.TestCase):
                         "item_title": "bar"
                         }]
               }
-        xsl_body2 = stats_httpd.StatsHttpd().xsl_handler()
+        xsl_body2 = self.stats_httpd.xsl_handler()
         self.assertNotEqual(xsl_body1, xsl_body2)
-        stats_httpd.StatsHttpd.get_stats_spec = orig_get_stats_spec
+        self.stats_httpd.stop()
 
     def test_for_without_B10_FROM_SOURCE(self):
         # just lets it go through the code without B10_FROM_SOURCE env
diff --git a/src/bin/stats/tests/b10-stats_test.py b/src/bin/stats/tests/b10-stats_test.py
index 7cf4f7e..c8065e0 100644
--- a/src/bin/stats/tests/b10-stats_test.py
+++ b/src/bin/stats/tests/b10-stats_test.py
@@ -30,7 +30,7 @@ import imp
 
 import stats
 import isc.cc.session
-from test_utils import BaseModules, ThreadingServerManager, MyStats, send_command, TIMEOUT_SEC
+from test_utils import BaseModules, ThreadingServerManager, MyStats, send_command, send_shutdown
 
 # set test name for logger
 isc.log.init("b10-stats_test")
@@ -189,27 +189,31 @@ class TestStats(unittest.TestCase):
 
     def test_start(self):
         # start without err
-        statsserver = ThreadingServerManager(MyStats)
-        statsd = statsserver.server
-        self.assertFalse(statsd.running)
-        statsserver.run()
-        self.assertTrue(statsd.running)
-        statsserver.shutdown()
-        self.assertFalse(statsd.running)
+        self.stats_server = ThreadingServerManager(MyStats)
+        self.stats = self.stats_server.server
+        self.assertFalse(self.stats.running)
+        self.stats_server.run()
+        self.assertTrue(self.stats.running)
+        send_shutdown("Stats")
+        self.assertFalse(self.stats.running)
+        self.stats_server.shutdown()
 
         # start with err
-        statsd = stats.Stats()
-        statsd.update_statistics_data = lambda x,**y: ['an error']
-        self.assertRaises(stats.StatsError, statsd.start)
+        self.stats = stats.Stats()
+        self.stats.update_statistics_data = lambda x,**y: ['an error']
+        self.assertRaises(stats.StatsError, self.stats.start)
 
     def test_handlers(self):
+        self.stats_server = ThreadingServerManager(MyStats)
+        self.stats = self.stats_server.server
+        self.stats_server.run()
         # config_handler
         self.assertEqual(self.stats.config_handler({'foo':'bar'}),
                          isc.config.create_answer(0))
 
         # command_handler
-        statsserver = ThreadingServerManager(MyStats)
-        statsserver.run()
+        self.base.boss.server._started.wait()
+        self.base.boss.server._started.clear()
         self.assertEqual(
             send_command(
                 'show', 'Stats',
@@ -279,7 +283,7 @@ class TestStats(unittest.TestCase):
             send_command('__UNKNOWN__', 'Stats'),
             (1, "Unknown command: '__UNKNOWN__'"))
 
-        statsserver.shutdown()
+        self.stats_server.shutdown()
 
     def test_update_modules(self):
         self.assertEqual(len(self.stats.modules), 0)
diff --git a/src/bin/stats/tests/test_utils.py b/src/bin/stats/tests/test_utils.py
index e79db48..e3c8cdc 100644
--- a/src/bin/stats/tests/test_utils.py
+++ b/src/bin/stats/tests/test_utils.py
@@ -8,22 +8,21 @@ import time
 import sys
 import threading
 import tempfile
+import json
 
 import msgq
 import isc.config.cfgmgr
 import stats
 import stats_httpd
 
-# TODO: consider appropriate timeout seconds
-TIMEOUT_SEC = 0.05
-
-def send_command(command_name, module_name, params=None, session=None, nonblock=False, timeout=TIMEOUT_SEC):
-    if not session:
-        cc_session = isc.cc.Session()
-    else:
+def send_command(command_name, module_name, params=None, session=None, nonblock=False, timeout=None):
+    if session is not None:
         cc_session = session
-    orig_timeout = cc_session.get_timeout()
-    cc_session.set_timeout(timeout * 1000)
+    else:
+        cc_session = isc.cc.Session()
+    if timeout is not None:
+        orig_timeout = cc_session.get_timeout()
+        cc_session.set_timeout(timeout * 1000)
     command = isc.config.ccsession.create_command(command_name, params)
     seq = cc_session.group_sendmsg(command, module_name)
     try:
@@ -33,38 +32,35 @@ def send_command(command_name, module_name, params=None, session=None, nonblock=
     except isc.cc.SessionTimeout:
         pass
     finally:
-        if not session:
-            cc_session.close()
-        else:
+        if timeout is not None:
             cc_session.set_timeout(orig_timeout)
+        if session is None:
+            cc_session.close()
 
-def send_shutdown(module_name):
-    return send_command("shutdown", module_name)
+def send_shutdown(module_name, **kwargs):
+    return send_command("shutdown", module_name, **kwargs)
 
 class ThreadingServerManager:
-    def __init__(self, server_class):
-        self.server_class = server_class
-        self.server_class_name = server_class.__name__
-        self.server = self.server_class()
+    def __init__(self, server, *args, **kwargs):
+        self.server = server(*args, **kwargs)
+        self.server_name = server.__name__
         self.server._thread = threading.Thread(
-            name=self.server_class_name, target=self.server.run)
+            name=self.server_name, target=self.server.run)
         self.server._thread.daemon = True
 
     def run(self):
         self.server._thread.start()
         self.server._started.wait()
         self.server._started.clear()
-        # waiting for the server's being ready for listening
-        time.sleep(TIMEOUT_SEC)
 
     def shutdown(self):
         self.server.shutdown()
-        self.server._thread.join(TIMEOUT_SEC)
+        self.server._thread.join(0) # timeout is 0
 
 class MockMsgq:
     def __init__(self):
         self._started = threading.Event()
-        self.msgq = msgq.MsgQ(None)
+        self.msgq = msgq.MsgQ(verbose=True)
         result = self.msgq.setup()
         if result:
             sys.exit("Error on Msgq startup: %s" % result)
@@ -72,11 +68,14 @@ class MockMsgq:
     def run(self):
         self._started.set()
         try:
+            # any message is written to /dev/null
+            sys.stderr = open(os.devnull, "w")
             self.msgq.run()
+            sys.stderr.close()
         except Exception:
             pass
         finally:
-            self.shutdown()
+            self.msgq.shutdown()
 
     def shutdown(self):
         self.msgq.shutdown()
@@ -90,10 +89,7 @@ class MockCfgmgr:
 
     def run(self):
         self._started.set()
-        try:
-            self.cfgmgr.run()
-        finally:
-            self.shutdown()
+        self.cfgmgr.run()
 
     def shutdown(self):
         self.cfgmgr.running = False
@@ -155,6 +151,7 @@ class MockBoss:
         return isc.config.create_answer(0)
 
     def command_handler(self, command, *args, **kwargs):
+        self._started.set()
         self.got_command_name = command
         if command == 'sendstats':
             params = { "owner": "Boss",
@@ -244,29 +241,47 @@ class MyStats(stats.Stats):
 
     def run(self):
         self._started.set()
-        stats.Stats.start(self)
+        self.start()
 
     def shutdown(self):
-        send_shutdown("Stats")
+        self.command_shutdown()
 
 class MyStatsHttpd(stats_httpd.StatsHttpd):
-    def __init__(self):
+    ORIG_SPECFILE_LOCATION = stats_httpd.SPECFILE_LOCATION
+    def __init__(self, *server_address):
         self._started = threading.Event()
-        stats_httpd.StatsHttpd.__init__(self)
+        if server_address:
+            stats_httpd.SPECFILE_LOCATION = self.get_specfile(*server_address)
+            try:
+                stats_httpd.StatsHttpd.__init__(self)
+            finally:
+                stats_httpd.SPECFILE_LOCATION.close()
+                stats_httpd.SPECFILE_LOCATION = self.ORIG_SPECFILE_LOCATION
+        else:
+            stats_httpd.StatsHttpd.__init__(self)
+
+    def get_specfile(self, *server_address):
+        spec = json.load(open(self.ORIG_SPECFILE_LOCATION))
+        config = spec['module_spec']['config_data']
+        for i in range(len(config)):
+            if config[i]['item_name'] == 'listen_on':
+                config[i]['item_default'] = \
+                    [ dict(address=a[0], port=a[1]) for a in server_address ]
+                break
+        return io.StringIO(json.dumps(spec))
 
     def run(self):
         self._started.set()
-        stats_httpd.StatsHttpd.start(self)
+        self.start()
 
     def shutdown(self):
-        send_shutdown("StatsHttpd")
+        self.stop()
 
 class BaseModules:
     def __init__(self):
-        self.class_name = BaseModules.__name__
-
         # Change value of BIND10_MSGQ_SOCKET_FILE in environment variables
-        os.environ['BIND10_MSGQ_SOCKET_FILE'] = tempfile.mktemp(prefix='unix_socket.')
+        if 'BIND10_MSGQ_SOCKET_FILE' not in os.environ:
+            os.environ['BIND10_MSGQ_SOCKET_FILE'] = tempfile.mktemp(prefix='msgq_socket_')
         # MockMsgq
         self.msgq = ThreadingServerManager(MockMsgq)
         self.msgq.run()




More information about the bind10-changes mailing list