BIND 10 #3087: Develop NameAddTransaction class for b10-dhcp-ddns

BIND 10 Development do-not-reply at isc.org
Mon Dec 2 13:23:23 UTC 2013


#3087: Develop NameAddTransaction class for b10-dhcp-ddns
-------------------------------------+-------------------------------------
            Reporter:  tmark         |                        Owner:
                Type:  enhancement   |  marcin
            Priority:  medium        |                       Status:
           Component:  dhcp-ddns     |  reviewing
            Keywords:  Task# 4.2     |                    Milestone:
           Sensitive:  0             |  Sprint-DHCP-20131204
         Sub-Project:  DHCP          |                   Resolution:
Estimated Difficulty:  0             |                 CVSS Scoring:
         Total Hours:  0             |              Defect Severity:  N/A
                                     |  Feature Depending on Ticket:
                                     |          Add Hours to Ticket:  0
                                     |                    Internal?:  0
-------------------------------------+-------------------------------------
Changes (by tmark):

 * owner:  tmark => marcin


Comment:

 Replying to [comment:10 marcin]:
 > Reviewed commit: e6df9bca72feedd92ec08dc43b53dfec632f228c
 >
 > This is a very good work. It nicely fits to the diagrams appended to the
 ticket which is an indication of both that the design is strictly followed
 in the code and that the code is easier to read having the diagrams :)
 >
 > Also, there is a lot of commentary, and almost every function is
 explained very clearly.

 Thank you, kindly.

 >
 > The review follows:
 >
 > '''!ChangeLog'''
 > Please make sure that the changelog formatting (including tabs and
 indents in general) fits the format of other entries.
 >

 Yes, I will:

 {{{
 6xx.    [func]  tmark

         Added the initial implementation of the class, NameAddTransaction,
         to b10-dhcp-ddns.  This class provides the state model logic
 described
         in the DHCP_DDNS design to add or replace forward and reverse DNS
 entries
         for a given FQDN.  It does not yet construct the actual DNS update
         requests, this will be added under Trac# 3241.

         (Trac# 3207, git TBD)
 }}}


 > '''src/bin/d2/d2_messages.mes'''
 > IMHO, the log messages would read better if their structure was the
 following: <message_id> <what> <when> instead of <message_id> <when>
 <what>. So, for example:
 > {{{
 > DHCP_DDNS_FORWARD_ADD_RESP_CORRUPT DHCP_DDNS received a corrupt
 response, while attempting a request to add a forward address mapping to
 DNS server, %1, for FQDN, %2
 > }}}
 > Usually you're mostly interested what happened and when is less
 important.

 I rearranged them as you suggested.  I agree they are clearer this way.

 >
 > Now, a few typos in the individual messages...
 >
 > - DHCP_DDNS_FORWARD_ADD_REJECTED: typo !''itwas!''

 Got it.

 >
 > - DHCP_DDNS_FORWARD_ADD_IO_ERROR: while line wrap before !''against!''
 and !''the same server!''?

 Got it.

 >
 > - DHCP_DDNS_FORWARD_ADD_RESP_CORRUPT: typo in !''to a update request!'',
 should be !''to an update request!''

 Fixed.


 >
 > - DHCP_DDNS_FORWARD_ADD_UNKNOWN_FAILURE: similar as above: should be
 !''an unexpected!''.

 I changed this id to DHCP_DDNS_FORWARD_ADD_BAD_DNSCLIENT_STATUS which is
 more accurate plus fixed wording.

 >
 > - DHCP_DDNS_FORWARD_REPLACE_REJECTED: !''itwas!'' again. Also, why line
 wrap in the last line?
 >

 Fixed.

 > - DHCP_DDNS_REVERSE_REPLACE_IO_ERROR: Why last line wrap?

 Oops.

 >
 > - DHCP_DDNS_TRANS_SEND_EROR: shouldn't it be !''a DNS update!'', not
 !''an DNS update!''?
 >

 Fixed.

 > '''src/bin/d2/d2_queue_mgr.cc'''
 > '''src/bin/d2/d2_update_mgr.cc'''
 > There are no unit tests to check behaviour when IOService pointer is
 NULL.


 Added unit tests.

 >
 > '''src/bin/d2/dns_client.cc'''
 > '''src/bin/d2/dns_client.h'''
 > Tomek would probably say that !''this change is an abuse of pointers!''.
 :) Even if he didn't, I still claim it is. There is no technical reason
 why IOService needs to be a pointer because the IOService is expected to
 be always initialized for this object. There are some cases when we tend
 to use pointers, not references, to differentiate between the cases when
 object is uninitialized vs initialized. But again, this is not the case
 here. Instead, using pointers here has the following drawbacks:
 > - Have to check for NULL IOService object being passed.
 > - Have to write additional unit tests.
 > - Additional reference counting on shared pointer is performed.
 > - New header had to be added.
 >
 > All in all I don't understand why the IOService has to be represented by
 a pointer. I see the drabacks, but I don't see any benefits. As long as
 this code is unit tested I will not argue about this change. If you want
 to leave it as is, fine. I am just afraid, that writing unit tests will
 take as much time as rolling it back, but I leave it up to you.
 >

 I have reverted changes to DNSClient.


 > '''src/bin/d2/nc_add.cc'''
 > addingFwdAddrsHandler: The IO_COMPLETED_EVT event is handled by this
 function (in fact, not only by this function) but this event is not
 emitted from within the class. It would be useful to have a reference to
 the place in the code where event is triggered. Some little comment which
 refers to NameChangeTransaction::operator() would do the trick.
 >

 Commentary added, and then repeated for the forward and reverse replace
 handlers.

 > '''src/bin/d2/nc_add.h'''
 > readyHandler: Typo !''START_EVT.EADY_ST!''.

 Fixed.

 >
 > readHandler: The brief description seems to be truncated.
 >

 Fixed.

 > replacingFwdaddrsHandler: The brief description seems to be truncated.
 >
 > '''src/bin/d2/nc_trans.cc'''
 > '''src/bin/d2/nc_trans.h'''
 > For certain functions you have left the @todo instead of the actual
 documentation for the functions and members:
 > - sendUpdate
 > - verifyTransition
 > - retryTransition
 > - update_attempts_

 I noticed these after I posted this for review, oops. I guess they were
 "todidn'ts".  Fixed.

 I have left commentary off of buildFwdAddressRequest,
 buildReplaceFwdAddressRequest, and buildReplaceRevPtrsRequest.  This is
 taken care of 3241 which is done and waiting to added after this ticket is
 complete.


 >
 > The argument of the setUpdateAttempts could be passed as a const. Same
 for retryTransition.

 Fixed.

 >
 > clearDnsUpdateResponse: Typo in brief: !''respons!''.

 Fixed.

 >
 > setUpdateAttempts: Question... It seems to me that the only use case for
 the update_attempts_ counter is that you increment it by 1. I wonder if
 you could provide the method incrementUpdateAttempts instead of
 setUpdateAttempts, which would provide more restricted write access to the
 variable. Does it make sense?

 Perhaps, except that setUpdateAttempts is only there for unit test
 purposes. I hadn't planned to expose it all except for test purposes.

 >
 > '''src/bin/d2/tests/nc_add_unittests.cc'''
 >
 > The commentary for functions inside of !NameAddStub could be extended.
 At least mention what fakeResponse, selectFwdServer and selectRevServer is
 doing. Especially, the fakeResponse deserves the commentary.
 >
 > NameAddTransactionTest::makedCannedTransaction: Please extend the
 comments inside of this function. I am not clear wha the !''canned!'' term
 means. I am not clear, NCR is created from JSON, not using a constructor.
 >
 > Also, there is quite a lot of conditional code that is not commented on.
 >

 Addressed.

 > NameAddTransactionTest::prepHandlerTest lacks description.

 Addressed.

 >
 > General comments to all the test: it is probably the only test suite
 where we use underscores to name tests. Is it really neccesary?
 >

 I compromised and removed all but one underscore on the handler tests.
 The
 tests are all named <hander>_<scenario>.  It helps me keep track this way.

 > readyHandler: In the test description !''3. Posted event is invalid!''
 should be !''4. Posted event is invalid!''.
 >

 Fixed.

 > I am pretty confident that this part of unit test is invalid:
 > {{{
 >     // Create a transaction which includes both a forward and a reverse
 change.
 >     ASSERT_NO_THROW(name_add =
 >                     prepHandlerTest(NameChangeTransaction::READY_ST,
 >                                     StateModel::START_EVT,
 FORWARD_CHG));
 >     // Run readyHandler.
 >     EXPECT_NO_THROW(name_add->readyHandler());
 >
 >     // Verify that a request requiring both forward and reverse, starts
 with
 >     // the forward change by transitioning to selecting a forward
 server.
 >     EXPECT_EQ(NameChangeTransaction::SELECTING_FWD_SERVER_ST,
 >               name_add->getCurrState());
 >     EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
 >               name_add->getNextEvent());
 > }}}
 > The comment says you should be doing both forward and reverse update,
 while you seem to be doing forward only. Perhaps it is as simple as
 applying the appropriate !''change_mask!'' in the call to prepHandlerTest.
 >

 Good catch! Yes, it was just the wrong mask.


 > selectingFwdServerHandler: Typo !''the a!'' in:
 > {{{
 >     // Post a server IO error event.  This simulates an IO error
 occuring
 >     // and a need to select the a new server.
 >
 > }}}

 Fixed.

 >
 > For completeness of this test I would suggest that the list of servers
 contains two (not just one). This will allow to test that the transaction
 doesn't enter the PROCESS_TRANS_FAILED_ST always when the IO error occurs,
 but it rather loops between two states until IO error doesn't show up or
 the list gets exhausted.
 >

 I have extended the list of servers and the test as suggested.

 > addingFwdAddrsHandler_fwd_only_add_Ok: !''Ok!'' could start with the
 small letter.
 >

 OK. :)

 > Instead of this:
 > {{{
 >     EXPECT_TRUE(!update_msg);
 > }}}
 >
 > you could simply do:
 > {{{
 >     EXPECT_FALSE(update_msg);
 > }}}
 > In fact, you should even use ASSERT_FALSE, because the further part of
 the test relies on this.
 >

 Fixed.

 > Question: in this statement:
 > {{{
 >             // Subsequent passes should reuse the request.
 >             EXPECT_TRUE(prev_msg == curr_msg);
 > }}}
 > do you intend to compare pointers to check that they point to the same
 object, or you intend to check that the messages look the same but they
 can be distinct pointers? I guess, if one of them gets copy constructed
 they may be different pointers. But I don't know what the intent was.
 Perhaps the extending the commentary would be a good idea.

 Added explanatory text here.  The idea is that only upon initial entry
 into a
 state which builds requests, should it construct the request. Retries
 should
 resuse the same request.  This is controlled by doOnEntry() test at the
 top of
 such states, see addingFwdAddrsHandler.  Once we have created the request,
 the pointer value should not change on retries.  This comparison verifies
 the
 overall behavior.

 >
 > The same refers to this test: replacingRevPtrsHandler_time_out.
 >
 > selectingRevServerHandler: suggest that the list of server is extended
 to at least two, to verify that the transaction doesn't always transition
 to the ERROR state when IO error occurs, but it rather loops until a list
 get exhausted.
 >

 Extended as requested.


 > Instead of this:
 > {{{
 >     EXPECT_TRUE(!update_msg);
 > }}}
 >
 > you could simply do:
 > {{{
 >     EXPECT_FALSE(update_msg);
 > }}}
 > In fact, you should even use ASSERT_FALSE, because the further part of
 the test relies on this.
 >
 >

 Fixed this.
 >
 > '''src/bin/d2/tests/nc_trans_unittests.cc'''
 > The new tests: dnsUpdateRequestAccessors and dnsUpdateResponseAccessors
 lack description.
 >

 I cleaned this up.


 > The description of the makeCannedTransaction is somewhat short. The
 !''canned!'' term is not generic enough for me. I don't understand why we
 have to create the !NameChangeRequest from Json, rather than using the
 constructor. Perhaps it is for the completeness of the test, which assumes
 that we are simulating reception of the NCR. But, that could be mentioned.
 Explanation of the !''star!'' sign would be helpful - see the construction
 of the DnsDomain object.
 >

 I added commentary.


 > dnsUpdateRequestAccessors: The comment seems to be truncated or invalid.
 > {{{
 >     // Verify that the DNS update request accessors.
 > }}}
 >
 > This test is inconsistent with respect to use of asserts and expects.
 Take a look at this:
 > {{{
 >     // Post set, we should be able to fetch it.
 >     EXPECT_TRUE(name_change->getDnsUpdateRequest());
 >
 >     // Should be able to clear it.
 >     ASSERT_NO_THROW(name_change->clearDnsUpdateRequest());
 >
 >     // Should be empty again.
 >     EXPECT_FALSE(name_change->getDnsUpdateRequest());
 > }}}
 >
 > If the first statement fails (so as the update request request is false)
 the test will continue. Assume that the second statement doesn't throw an
 exception, the third statement passes because update request has been
 false since or prior to the first statement. However, the fact that the
 third statement passes doesn't really mean that the cleanDnsUpdateRequest
 worked, because in our case the state of the update request hasn't changed
 anyway.
 >
 > On the other hand, if there is something wrong, the function will fail
 sooner or later, giving the indication that something was wrong. So, it is
 not the big deal, I have to admit. But, it just a suggestion to have a
 look into asserts vs expects and possibly there is some room for
 improvement.
 >

 Sorry, this was just sloppy work.
 I cleaned this test up a bit, accounting for your comments. Did the same
 for
 same to be true with dnsUpdateResponseAccessors.

 > Neither sendUpdate, retryTransition nor setUpdateAttempts are unit
 tested. I understand that it may be more involved to test sendUpdate so
 perhaps the reference should be added to unit tests that actually test its
 behaviour (in nc_add_unittests?) to say that it is unit tested there. In
 any case it would be the most appropriate to test sendUpdate in this file.
 >
 >

 There are unit tests for all of these now.  The sendUpdate unit tests
 required
 a fair amount of effort but it is a good thing you commented on it.  It
 uncovered a few things that I have fixed.

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


More information about the bind10-tickets mailing list