BIND 10 #2353: write tests for all methods of Bob

BIND 10 Development do-not-reply at isc.org
Thu Dec 6 04:06:10 UTC 2012


#2353: write tests for all methods of Bob
-------------------------------------+-------------------------------------
            Reporter:  jinmei        |                        Owner:
                Type:  defect        |  jinmei
            Priority:  medium        |                       Status:
           Component:  Boss of BIND  |  reviewing
            Keywords:                |                    Milestone:
           Sensitive:  0             |  Sprint-20121218
         Sub-Project:  DNS           |                   Resolution:
Estimated Difficulty:  8             |                 CVSS Scoring:
         Total Hours:  0             |              Defect Severity:  N/A
                                     |  Feature Depending on Ticket:
                                     |          Add Hours to Ticket:  0
                                     |                    Internal?:  0
-------------------------------------+-------------------------------------
Changes (by muks):

 * owner:  muks => jinmei


Comment:

 Hi Jinmei

 Replying to [comment:10 jinmei]:
 > '''bind10_src.py.in'''
 >
 > - start_msgq: this hack doesn't look clean:
 > {{{#!python
 >             # this is only used by unittests
 >             if self.msgq_timeout == 0:
 >                 break
 > ...
 >         if self.cc_session is not None:
 > }}}
 >   in particular, the relationship between the test-only hack and the
 >   additional `if` is not immediately clear.  I'd primarily avoid the
 >   hack; if it's too difficult, I'd at least avoid the `if` (from a
 >   quick look it seems possible); if even it's too difficult I'd at
 >   least clarify the relationship in comment (last resort).

 I've retained the hack in just `start_msgq()` so that testing is a bit
 cleaner.
 But this now uses a different variable `run_under_unittests` and does not
 overload any others.

 The other use of such a hack is gone.

 > - I'd add description for `_make_process_info`, especially about its
 >   purpose, and why it's "protected".

 Done.

 > - start_cfgmgr: is this safe?
 > {{{#!cpp
 >         # wait_time is set to 0 only by unittests
 >         if self.wait_time > 0 and not self.process_running(msg,
 >
 "ConfigManager"):
 >
 > }}}
 >   At least this comment isn't true because wait_time can be set via
 >   command line option.  And when set to 0, it bypasses the check for
 >   process_running().  In general, I'd avoid changing the semantics of
 >   the tested code this way.  As this case indicates, it's often not
 >   immediately clear whether the added behavior doesn't interfere with
 >   the non test case.

 This hack is gone.

 > - start_ccsession: is it necessary to modify it to return self.ccs?
 >   can't the test just inspect bob.ccs?

 Done.

 > '''bind10_test.py.in'''
 >
 > - test_get_processes: a minor point, but why this?
 > {{{#!python
 >         pids = []
 >         pids.extend(range(0, 20))
 > }}}
 >   it seems we can simply do `pids = list(range(0, 20))`

 Done. :)

 > - test_reap_children: isn't it better to check this as a list?
 > {{{#!python
 >         #self.assertFalse(bob.components_to_restart)
 >         self.assertEqual([], bob.components_to_restart)
 > }}}

 Done.

 > - what's the purpose of `with`?
 > {{{#!python
 >         with self.assertRaises(OSError):
 >             bob.reap_children()
 > }}}
 >   can't we simply call assertRaises directly?
 > {{{#!python
 >         self.assertRaises(OSError, bob.reap_children)
 > }}}

 I prefer the former syntax actually. :) For any kind of assertRaises()
 which may check a block of code for an exception, the `with` is
 consistent syntax.

 > - test_kill_started_components: I guess I commented about this in the
 >   previous cycle, but: isn't it better to check the value of
 >   components directly, rather than indirect check via get_processes?
 > {{{#!python
 >         self.assertEqual([[53, 'test', 'Test']], bob.get_processes())
 > ...
 >         self.assertFalse(bob.get_processes())
 > }}}
 >   (besides, `assertFalse` doesn't seem to be a good choice for non
 >   boolean object)

 Done. This True/False check works similar to how we test for true/false
 in `scoped_ptr`, etc. in C++. Anyway, the suggested syntax makes it
 clearer.

 > - test_start_msgq: I'd use a non trivial (non empty) value for pi.env:
 > {{{#!python
 >         self.assertEqual({}, pi.env)
 > }}}
 >    this applies to other similar cases.

 All are fixed.

 > - test_start_msgq_timeout: isn't it better to completely control the
 >   behavior of time.time() (e.g. return i on i-th call) and
 >   time.sleep()?  Then we can avoid making it time consuming regardless
 >   of the number of retries, and can make the test more deterministic
 >   and reliable.

 Done.

 > - test_start_msgq_timeout: doesn't seem to check isc.cc.Session() is
 >   called
 > - test_start_msgq_timeout (or the test without "timeout"): likewise,
 >   doesn't seem to check group_subscribe() is called.

 We check now.

 > - test_start_msgq_timeout: see also the comment on the main code.  I
 >   guess we can avoid intruding the main code if we control the timing
 >   completely.

 Intrusions are gone, except for that one `run_under_unittests` boolean
 which helps to split the unittests into two.

 > - test_start_msgq_timeout: why not just use `assertRaises`?
 > {{{#!python
 >         thrown = False
 >         # An exception will be thrown here when it eventually times out.
 >         try:
 >             pi = bob.start_msgq()
 >         except bind10_src.CChannelConnectError as e:
 >             thrown = True
 >         # We just check that an exception was thrown, and that several
 >         # attempts were made to connect.
 >         self.assertTrue(thrown)
 > }}}

 *facepalm*. Fixed. :)

 > - test_start_msgq_timeout: I think it's safer to restore time.time in
 >   tearDown().

 Done.

 > - test_start_cfgmgr: I think `DummySession` should return a real
 >   message from group_recvmsg() and the test confirms the behavior
 >   explicitly, rather than by tweaking wait_time and bypassing the
 >   check (it's cheating).

 Agreed and fixed.

 > - test_start_cfgmgr_timeout: same sense of comments applies as the
 >   msgq counterpart.  also about the comment on the main code.

 Done.

 > - test_start_ccsession: it's probably safer to restore
 >   `isc.config.ModuleCCSession` in `tearDown`.

 Done.

 > - test_register_process: I'd check the value of `self.components[53]`,
 too.

 Done.

 > - test_start_auth: the env parameter doesn't seem to be checked.

 Checked.

 > - test_start_auth, etc: btw, I see a similar pattern of 'non-verbose'
 >   and 'verbose' is repeating for various components.  They are mostly
 >   a mere copy.  I'd consider unifying them.

 Unified. But the code still uses separate checkers per each tested method.
 Otherwise the test code gets a bit ugly with more unification.

 > - test_start_resolver: same for test_start_auth.  and, hmm, I see
 >   some possibilities of cleaning up the tested method...but that
 >   should probably go to a separate ticket.

 Done.

 > - test_start_cmdctl: c_channel_env doesn't seem to be checked.

 Checked now.

 > - test_socket_data: what's the rationale of the magic number of 15?
 > {{{#!python
 >                 if self.throw and self.i > 15:
 >                     raise socket.error(errno.EAGAIN, 'Try again')
 > }}}

 This has been clarified with a comment. It's just to check that it saves
 back the read data when `EAGAIN` is returned.

 > - test_socket_data: I'd use `assertEqual` with `{}`:
 > {{{#!python
 >         self.assertFalse(bob._unix_sockets)
 > }}}

 Done.

 > - test_startup: `BoB.c_channel_env` isn't checked (either {} or
 >   containing BIND10_MSGQ_SOCKET_FILE, depending on
 self.msgq_socket_file).

 Updated.

 > - test_startup: this case isn't tested:
 > {{{#!python
 >             logger.fatal(BIND10_MSGQ_ALREADY_RUNNING)
 >             return "b10-msgq already running, or socket file not cleaned
 , cannot start"
 > }}}
 > - test_startup: related to the previous point, does this test use the
 >   real `isc.cc.Session` class? if so, it's probably not a good idea as
 >   it involves network communication.

 These two are also fixed now.

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


More information about the bind10-tickets mailing list