BIND 10 #1175: find another solution to synchronize between threads used in unittests for stats

BIND 10 Development do-not-reply at isc.org
Wed Sep 21 20:14:55 UTC 2011


#1175: find another solution to synchronize between threads used in unittests for
stats
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:  naokikambe
  naokikambe                         |                Status:  reviewing
                       Type:         |             Milestone:
  defect                             |  Sprint-20110927
                   Priority:  major  |            Resolution:
                  Component:         |             Sensitive:  0
  statistics                         |           Sub-Project:  DNS
                   Keywords:         |  Estimated Difficulty:  5
            Defect Severity:  N/A    |           Total Hours:  0
Feature Depending on Ticket:         |
        Add Hours to Ticket:  0      |
                  Internal?:  0      |
-------------------------------------+-------------------------------------
Changes (by vorner):

 * owner:  vorner => naokikambe


Comment:

 Hello

 Indeed the patch did contain many changes not directly or obviously
 related to the topic of the ticket. While I agree they are useful, they
 could have been potentially separated under a different ticket. Anyway, no
 need to do anything about it now, as I got through them already.

 So, some comments and questions:
  * This part returs if there are no listen addresses configured or if the
 binding failed. Why is it so? What is the purpose of the code? Shouldn't
 it fail if it can't bind? (Not that I'd say it's wrong, I just don't
 really understand)
 {{{#!python
         # 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()
 }}}
  * The description here might need some improvement. It's not clear that
 the port is first one tried and it goes up until it finds one that's free.
 {{{#!python
 def get_availaddr(address='127.0.0.1', port=8001):
     """returns tuple of address and port available to listen on the
     platform. Default port range is between 8001 and 65535. If port is
     over flow(greater than 65535), OverflowError is thrown"""
 }}}
  * Is this really needed? Isn't it enough for the garbage collector to
 claim and close the socket? (your way might be cleaner anyway, but I'm
 interested)
 {{{#!python
         finally:
             if sock: sock.close()
 }}}
  * This is not related to this branch, but I noticed you're sending
 absolute redirects. Would relative ones be better? For example if there's
 a redirected port in address translator, the absolute redirect may be
 wrong:
 {{{
                           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))
 }}}
  * Aestetical: two hash signs
 {{{#!python
 # # 404 NotFound
 }}}
  * You set up the SIGALRM in `setUp` and call `signal.alarm` to schedule
 one. That is OK to stop a test that run for too long. But you don't cancel
 the alarm in tearDown, so if there's bunch of long-running tests some time
 after that, the alarm may come to a wrong test (if that test does not set
 its own alarm). That would make a completely different test fail. I
 suggest that you properly cancel the alarm in `tearDown` to prevent any
 possible future surprises.
  * This code looks strange:
 {{{#!python
 # dual stack (address is ipv4)
 if self.ipv6_enabled:
         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))

 # only-ipv4 single stack
 if not self.ipv6_enabled:
         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))
 }}}
    For one, the two conditions look complement to each other, therefore an
 if-else might look more natural. But what surprises me more is that both
 branches look the same. That is confusing, because then everyone who reads
 the code spends some time trying to figure out why there are two versions
 and what is the trick. So, unless there actually is a trick I did not
 notice, I think it would be better to simplify it and have only one copy
 without the conditions.
  * Talking about `is_ipv6_enabled` ‒ why isn't `socket.has_ipv6` enough?
  * `test_select_failure2` ‒ does that test that the code does _not_ fail?
 If so, maybe a better name or comment could be used.
  * This looks scary. I think this would deserve a comment why the retries
 are necessary.
 {{{#!python
     def __init__(self, server, *args, **kwargs):
         self.server = None
         n = 0
         while True:
             try:
                 self.server = server(*args, **kwargs)
             except isc.cc.session.SessionTimeout:
                 if self.server is not None:
                     self.server.shutdown()
                 # retrying until 3 times
                 if n >2: raise
                 n = n + 1
                 continue
             else: break
 }}}

-- 
Ticket URL: <http://bind10.isc.org/ticket/1175#comment:12>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list