virtual ~NameAddStub() {
}
-
+
/// @brief Simulates sending update requests to the DNS server
/// Allows state handlers which conduct IO to be tested without a server.
virtual void sendUpdate(bool /* use_tsig_ = false */) {
postNextEvent(StateModel::NOP_EVT);
}
- void fakeResponse(const DNSClient::Status& status,
+ void fakeResponse(const DNSClient::Status& status,
const dns::Rcode& rcode) {
D2UpdateMessagePtr msg(new D2UpdateMessage(D2UpdateMessage::OUTBOUND));
setDnsUpdateStatus(status);
virtual ~NameAddTransactionTest() {
}
- /// @brief Instantiates a NameAddTransaction built around a canned
- /// NameChangeRequest.
+ /// @brief Instantiates a NameAddStub test transaction
+ /// The transaction is constructed around a predefined (i.e "canned")
+ /// NameChangeRequest. The request has both forward and reverse DNS
+ /// changes requested. Based upon the change mask, the transaction
+ /// will have either the forward, reverse, or both domains populated.
+ ///
+ /// @param change_mask determines which change directions are requested
NameAddStubPtr makeCannedTransaction(int change_mask=FWD_AND_REV_CHG) {
const char* msg_str =
"{"
" \"lease_length\" : 1300 "
"}";
- dhcp_ddns::NameChangeRequestPtr ncr;
-
- DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
- DnsServerInfoPtr server;
-
- ncr = dhcp_ddns::NameChangeRequest::fromJSON(msg_str);
+ // Create NameChangeRequest from JSON string.
+ dhcp_ddns::NameChangeRequestPtr ncr = dhcp_ddns::NameChangeRequest::
+ fromJSON(msg_str);
+ // If the change mask does not include a forward change clear the
+ // forward domain; otherise create the domain and its servers.
if (!(change_mask & FORWARD_CHG)) {
ncr->setForwardChange(false);
forward_domain_.reset();
} else {
- // make forward server list
- server.reset(new DnsServerInfo("forward.example.com",
+ // Create the forward domain and then its servers.
+ DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
+ DnsServerInfoPtr server(new DnsServerInfo("forward.example.com",
isc::asiolink::IOAddress("1.1.1.1")));
servers->push_back(server);
- forward_domain_.reset(new DdnsDomain("*", "", servers));
+ server.reset(new DnsServerInfo("forward2.example.com",
+ isc::asiolink::IOAddress("1.1.1.2")));
+ servers->push_back(server);
+ forward_domain_.reset(new DdnsDomain("example.com.", "", servers));
}
+ // If the change mask does not include a reverse change clear the
+ // reverse domain; otherise create the domain and its servers.
if (!(change_mask & REVERSE_CHG)) {
ncr->setReverseChange(false);
reverse_domain_.reset();
} else {
- // make reverse server list
- servers->clear();
- server.reset(new DnsServerInfo("reverse.example.com",
- isc::asiolink::IOAddress("2.2.2.2")));
+ // Create the reverse domain and its server.
+ DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
+ DnsServerInfoPtr server(new DnsServerInfo("reverse.example.com",
+ isc::asiolink::
+ IOAddress("2.2.2.2")));
+ servers->push_back(server);
+ server.reset(new DnsServerInfo("reverse2.example.com",
+ isc::asiolink::
+ IOAddress("2.2.2.3")));
servers->push_back(server);
- reverse_domain_.reset(new DdnsDomain("*", "", servers));
+ reverse_domain_.reset(new DdnsDomain("2.168.192.in.addr.arpa.",
+ "", servers));
}
+ // Now create the test transaction as would occur in update manager.
return (NameAddStubPtr(new NameAddStub(io_service_, ncr,
forward_domain_, reverse_domain_)));
}
+ /// @brief Create a test transaction at a known point in the state model.
+ ///
+ /// Method prepares a new test transaction and sets its state and next
+ /// event values to those given. This makes the transaction appear to
+ /// be at that point in the state model without having to transition it
+ /// through prerequiste states. It also provides the ability to set
+ /// which change directions are requested: forward change only, reverse
+ /// change only, or both.
+ ///
+ /// @param state value to set as the current state
+ /// @param event value to post as the next event
+ /// @param change_mask determines which change directions are requested
NameAddStubPtr prepHandlerTest(unsigned int state, unsigned int event,
unsigned int change_mask = FWD_AND_REV_CHG) {
NameAddStubPtr name_add = makeCannedTransaction(change_mask);
// It verifies behavior for the following scenarios:
//
// 1. Posted event is START_EVT and request includes only a forward change
-// 2. Posted event is START_EVT and request includes both a forward and a
+// 2. Posted event is START_EVT and request includes both a forward and a
// reverse change
-// 3. Posted event is START_EVT and request includes only a reverse change
+// 3. Posted event is START_EVT and request includes only a reverse change
// 3. Posted event is invalid
//
TEST_F(NameAddTransactionTest, readyHandler) {
NameAddStubPtr name_add;
// Create a transaction which includes only a forward change.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameChangeTransaction::READY_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameChangeTransaction::READY_ST,
StateModel::START_EVT, FORWARD_CHG));
- // Run readyHandler.
+ // Run readyHandler.
EXPECT_NO_THROW(name_add->readyHandler());
- // Verify that a request requiring only a forward change, transitions to
+ // Verify that a request requiring only a forward change, transitions to
// selecting a forward server.
- EXPECT_EQ(NameChangeTransaction::SELECTING_FWD_SERVER_ST,
+ EXPECT_EQ(NameChangeTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
+ EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
name_add->getNextEvent());
// 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.
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameChangeTransaction::READY_ST,
+ StateModel::START_EVT, FWD_AND_REV_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,
+ EXPECT_EQ(NameChangeTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
+ EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
name_add->getNextEvent());
// Create and prep a reverse only transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameChangeTransaction::READY_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameChangeTransaction::READY_ST,
StateModel::START_EVT, REVERSE_CHG));
- // Run readyHandler.
+ // Run readyHandler.
EXPECT_NO_THROW(name_add->readyHandler());
- // Verify that a request requiring only a reverse change, transitions to
+ // Verify that a request requiring only a reverse change, transitions to
// selecting a reverse server.
- EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
+ EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
+ EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
name_add->getNextEvent());
// Create and prep transaction, poised to run the handler but with an
// invalid event.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameChangeTransaction::READY_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameChangeTransaction::READY_ST,
StateModel::NOP_EVT));
- // Running the readyHandler should throw.
+ // Running the readyHandler should throw.
EXPECT_THROW(name_add->readyHandler(), NameAddTransactionError);
}
// Tests the selectingFwdServerHandler functionality.
// It verifies behavior for the following scenarios:
//
-// 1. Posted event is SELECT_SERVER_EVT
-// 2. Posted event is SERVER_IO_ERROR_EVT
+// 1. Posted event is SELECT_SERVER_EVT
+// 2. Posted event is SERVER_IO_ERROR_EVT
// 3. Posted event is invalid
//
TEST_F(NameAddTransactionTest, selectingFwdServerHandler) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
- SELECTING_FWD_SERVER_ST,
+ SELECTING_FWD_SERVER_ST,
NameChangeTransaction::SELECT_SERVER_EVT));
-
- // Run selectingFwdServerHandler.
- EXPECT_NO_THROW(name_add->selectingFwdServerHandler());
- // Verify that a server was selected.
- EXPECT_TRUE(name_add->getCurrentServer());
+ // Call selectingFwdServerHandler enough times to select all of the
+ // servers in it's current domain. The first time, it will be with
+ // next event of SELECT_SERVER_EVT. Thereafter it will be with a next
+ // event of SERVER_IO_ERROR_EVT.
+ int num_servers = name_add->getForwardDomain()->getServers()->size();
+ for (int i = 0; i < num_servers; i++) {
+ // Run selectingFwdServerHandler.
+ EXPECT_NO_THROW(name_add->selectingFwdServerHandler());
- // Verify that we transitioned correctly.
- EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ // Verify that a server was selected.
+ EXPECT_TRUE(name_add->getCurrentServer());
+
+ // Verify that we transitioned correctly.
+ EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
- // Post a server IO error event. This simulates an IO error occuring
- // and a need to select the a new server.
- ASSERT_NO_THROW(name_add->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT));
+ // Post a server IO error event. This simulates an IO error occuring
+ // and a need to select the new server.
+ ASSERT_NO_THROW(name_add->postNextEvent(NameChangeTransaction::
+ SERVER_IO_ERROR_EVT));
+ }
- // Run selectingFwdServerHandler.
+ // We should have exhausted the list of servers. Processing another
+ // SERVER_IO_ERROR_EVT should transition us to failure.
EXPECT_NO_THROW(name_add->selectingFwdServerHandler());
-
- // Test domain only has 1 server, so we should have exhausted server
- // list. Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::NO_MORE_SERVERS_EVT,
+ EXPECT_EQ(NameChangeTransaction::NO_MORE_SERVERS_EVT,
name_add->getNextEvent());
// Create and prep transaction, poised to run the handler but with an
// invalid event.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
- SELECTING_FWD_SERVER_ST,
+ SELECTING_FWD_SERVER_ST,
StateModel::NOP_EVT));
- // Running the handler should throw.
- EXPECT_THROW(name_add->selectingFwdServerHandler(),
+ // Running the handler should throw.
+ EXPECT_THROW(name_add->selectingFwdServerHandler(),
NameAddTransactionError);
}
// ************************ addingFwdAddrHandler Tests *****************
// Tests that addingFwdAddrsHandler rejects invalid events.
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_invalid_event) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_InvalidEvent) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler but with
// an invalid event.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
StateModel::NOP_EVT));
- // Running the handler should throw.
- EXPECT_THROW(name_add->addingFwdAddrsHandler(),
+ // Running the handler should throw.
+ EXPECT_THROW(name_add->addingFwdAddrsHandler(),
NameAddTransactionError);
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes only a forward change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
-// A server response is received which indicates successful update
+// A server response is received which indicates successful update
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_fwd_only_add_Ok) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_FwdOnlyAddOK) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT, FORWARD_CHG));
-
- // Should not be an update message yet.
+
+ // Should not be an update message yet.
D2UpdateMessagePtr update_msg = name_add->getDnsUpdateRequest();
- EXPECT_TRUE(!update_msg);
+ ASSERT_FALSE(update_msg);
// At this point completion flags should be false.
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // Run addingFwdAddrsHandler to construct and send the request.
+ // Run addingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Verify that an update message was constructed.
// Verify that we are still in this state and next event is NOP_EVT.
// This indicates we "sent" the message and are waiting for IO completion.
- EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::NOP_EVT,
+ EXPECT_EQ(NameChangeTransaction::NOP_EVT,
name_add->getNextEvent());
// Simulate receiving a succussful update response.
// Since it is a forward only change, we should be done.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
name_add->getNextEvent());
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates successful update.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_fwd_and_rev_add_Ok) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_fwdAndRevAddOK) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT, FWD_AND_REV_CHG));
-
- // Run addingFwdAddrsHandler to construct and send the request.
+
+ // Run addingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Simulate receiving a succussful update response.
EXPECT_TRUE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // Since the request also includes a reverse change we should
+ // Since the request also includes a reverse change we should
// be poised to start it. Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
+ EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
+ EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
name_add->getNextEvent());
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates the FQDN is in use.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_fqdn_in_use) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_FqdnInUse) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT));
-
- // Run addingFwdAddrsHandler to construct and send the request.
+
+ // Run addingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Simulate receiving a FQDN in use response.
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::YXDOMAIN());
- // Run addingFwdAddrsHandler again to process the response.
+ // Run addingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Completion flags should still be false.
// Since the FQDN is in use, per the RFC we must attempt to replace it.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameAddTransaction::FQDN_IN_USE_EVT,
+ EXPECT_EQ(NameAddTransaction::FQDN_IN_USE_EVT,
name_add->getNextEvent());
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates the update was rejected.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_other_rcode) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_OtherRcode) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT));
// Select a server to satisfy log statements.
ASSERT_TRUE(name_add->selectFwdServer());
- // Run addingFwdAddrsHandler to construct and send the request.
+ // Run addingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Simulate receiving server rejection response. Per RFC, anything other
// than no error or FQDN in use is failure. Arbitrarily choosing refused.
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::REFUSED());
- // Run addingFwdAddrsHandler again to process the response.
+ // Run addingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Completion flags should still be false.
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // We should have failed the transaction. Verifiy that we transitioned
+ // We should have failed the transaction. Verifiy that we transitioned
// correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
name_add->getNextEvent());
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request send times out MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_time_out) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_Timeout) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- // The log message issued when this test succeeds, displays the
+ // The log message issued when this test succeeds, displays the
// selected server, so we need to select a server before running this
// test.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
const D2UpdateMessagePtr prev_msg = name_add->getDnsUpdateRequest();
- // Run addingFwdAddrsHandler to send the request.
+ // Run addingFwdAddrsHandler to send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
const D2UpdateMessagePtr curr_msg = name_add->getDnsUpdateRequest();
EXPECT_FALSE(prev_msg);
EXPECT_TRUE(curr_msg);
} else {
- // Subsequent passes should reuse the request.
+ // Subsequent passes should reuse the request. We are only
+ // looking to check that we have not replaced the pointer value
+ // with a new pointer. This tests the on_entry() logic which
+ // clears the request ONLY upon initial entry into the state.
EXPECT_TRUE(prev_msg == curr_msg);
}
- // Simulate a server IO timeout.
+ // Simulate a server IO timeout.
name_add->setDnsUpdateStatus(DNSClient::TIMEOUT);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run addingFwdAddrsHandler again to process the response.
+ // Run addingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent but a corrupt response is received, this occurs
// MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_invalid_response) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_InvalidResponse) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- // The log message issued when this test succeeds, displays the
+ // The log message issued when this test succeeds, displays the
// selected server, so we need to select a server before running this
// test.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::ADDING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
- // Run addingFwdAddrsHandler to construct send the request.
+ // Run addingFwdAddrsHandler to construct send the request.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
- // Simulate a server IO timeout.
+ // Simulate a server IO timeout.
name_add->setDnsUpdateStatus(DNSClient::INVALID_RESPONSE);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run addingFwdAddrsHandler again to process the response.
+ // Run addingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->addingFwdAddrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
// ************************ replacingFwdAddrHandler Tests *****************
// Tests that replacingFwdAddrsHandler rejects invalid events.
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_invalid_event) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_InvalidEvent) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler but with
// an invalid event.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameChangeTransaction::
StateModel::NOP_EVT));
- // Running the handler should throw.
- EXPECT_THROW(name_add->replacingFwdAddrsHandler(),
+ // Running the handler should throw.
+ EXPECT_THROW(name_add->replacingFwdAddrsHandler(),
NameAddTransactionError);
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes only a forward change.
-// Initial posted event is FQDN_IN_USE_EVT.
+// Initial posted event is FQDN_IN_USE_EVT.
// The update request is sent without error.
// A server response is received which indicates successful update.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_fwd_only_add_Ok) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_FwdOnlyAddOK) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FORWARD_CHG));
-
- // Should not be an update message yet.
+
+ // Should not be an update message yet.
D2UpdateMessagePtr update_msg = name_add->getDnsUpdateRequest();
- EXPECT_TRUE(!update_msg);
+ ASSERT_FALSE(update_msg);
// At this point completion flags should be false.
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // Run replacingFwdAddrsHandler to construct and send the request.
+ // Run replacingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Verify that an update message was constructed.
// Verify that we are still in this state and next event is NOP_EVT.
// This indicates we "sent" the message and are waiting for IO completion.
- EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::NOP_EVT,
+ EXPECT_EQ(NameChangeTransaction::NOP_EVT,
name_add->getNextEvent());
// Simulate receiving a succussful update response.
// Since it is a forward only change, we should be done.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
name_add->getNextEvent());
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes only a forward change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates successful update.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_fwd_only_add_Ok_2) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_FwdOnlyAddOK2) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameChangeTransaction::
SERVER_SELECTED_EVT, FORWARD_CHG));
-
- // Run replacingFwdAddrsHandler to construct and send the request.
+
+ // Run replacingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Simulate receiving a succussful update response.
// Since it is a forward only change, we should be done.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
name_add->getNextEvent());
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
// Initial posted event is FQDN_IN_USE_EVT.
// The update request is sent without error.
// A server response is received which indicates successful update.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_fwd_and_rev_add_Ok) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_FwdAndRevAddOK) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FWD_AND_REV_CHG));
-
- // Run replacingFwdAddrsHandler to construct and send the request.
+
+ // Run replacingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Simulate receiving a succussful update response.
EXPECT_TRUE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // Since the request also includes a reverse change we should
+ // Since the request also includes a reverse change we should
// be poised to start it. Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
+ EXPECT_EQ(NameChangeTransaction::SELECTING_REV_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
+ EXPECT_EQ(NameChangeTransaction::SELECT_SERVER_EVT,
name_add->getNextEvent());
}
-// Tests addingFwdAddrsHandler with the following scenario:
+// Tests addingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
// Initial posted event is FQDN_IN_USE_EVT.
// The update request is sent without error.
// A server response is received which indicates the FQDN is NOT in use.
//
-TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_fqdn_not_in_use) {
+TEST_F(NameAddTransactionTest, addingFwdAddrsHandler_FqdnNotInUse) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FWD_AND_REV_CHG));
-
- // Run replacingFwdAddrsHandler to construct and send the request.
+
+ // Run replacingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Simulate receiving a FQDN not in use response.
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::NXDOMAIN());
- // Run replacingFwdAddrsHandler again to process the response.
+ // Run replacingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Completion flags should still be false.
// Since the FQDN is no longer in use, per the RFC, try to add it.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::ADDING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
// The update request is sent without error.
// A server response is received which indicates the update was rejected.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_other_rcode) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_OtherRcode) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FWD_AND_REV_CHG));
// Select a server to satisfy log statements.
ASSERT_TRUE(name_add->selectFwdServer());
- // Run replacingFwdAddrsHandler to construct and send the request.
+ // Run replacingFwdAddrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Simulate receiving server rejection response. Per RFC, anything other
// than no error or FQDN in use is failure. Arbitrarily choosing refused.
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::REFUSED());
- // Run replacingFwdAddrsHandler again to process the response.
+ // Run replacingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Completion flags should still be false.
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // We should have failed the transaction. Verifiy that we transitioned
+ // We should have failed the transaction. Verifiy that we transitioned
// correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
name_add->getNextEvent());
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
// Initial posted event is FQDN_IN_USE_EVT.
// The update request send times out MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_time_out) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_Timeout) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FWD_AND_REV_CHG));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
const D2UpdateMessagePtr prev_msg = name_add->getDnsUpdateRequest();
- // Run replacingFwdAddrsHandler to send the request.
+ // Run replacingFwdAddrsHandler to send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
const D2UpdateMessagePtr curr_msg = name_add->getDnsUpdateRequest();
EXPECT_FALSE(prev_msg);
EXPECT_TRUE(curr_msg);
} else {
- // Subsequent passes should reuse the request.
+ // Subsequent passes should reuse the request. We are only
+ // looking to check that we have not replaced the pointer value
+ // with a new pointer. This tests the on_entry() logic which
+ // clears the request ONLY upon initial entry into the state.
EXPECT_TRUE(prev_msg == curr_msg);
}
- // Simulate a server IO timeout.
+ // Simulate a server IO timeout.
name_add->setDnsUpdateStatus(DNSClient::TIMEOUT);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run replacingFwdAddrsHandler again to process the response.
+ // Run replacingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
}
-// Tests replacingFwdAddrsHandler with the following scenario:
+// Tests replacingFwdAddrsHandler with the following scenario:
//
// The request includes a forward and reverse change.
// Initial posted event is FQDN_IN_USE_EVT.
// The update request is sent but a corrupt response is received, this occurs
// MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_corrupt_response) {
+TEST_F(NameAddTransactionTest, replacingFwdAddrsHandler_CorruptResponse) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
NameAddTransaction::
FQDN_IN_USE_EVT, FWD_AND_REV_CHG));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
const D2UpdateMessagePtr prev_msg = name_add->getDnsUpdateRequest();
- // Run replacingFwdAddrsHandler to send the request.
+ // Run replacingFwdAddrsHandler to send the request.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
const D2UpdateMessagePtr curr_msg = name_add->getDnsUpdateRequest();
EXPECT_FALSE(prev_msg);
EXPECT_TRUE(curr_msg);
} else {
- // Subsequent passes should reuse the request.
+ // Subsequent passes should reuse the request. We are only
+ // looking to check that we have not replaced the pointer value
+ // with a new pointer. This tests the on_entry() logic which
+ // clears the request ONLY upon initial entry into the state.
EXPECT_TRUE(prev_msg == curr_msg);
}
- // Simulate a server corrupt response.
+ // Simulate a server corrupt response.
name_add->setDnsUpdateStatus(DNSClient::INVALID_RESPONSE);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run replacingFwdAddrsHandler again to process the response.
+ // Run replacingFwdAddrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingFwdAddrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_FWD_ADDRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_FWD_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
// Tests the selectingRevServerHandler functionality.
// It verifies behavior for the following scenarios:
//
-// 1. Posted event is SELECT_SERVER_EVT
-// 2. Posted event is SERVER_IO_ERROR_EVT
+// 1. Posted event is SELECT_SERVER_EVT
+// 2. Posted event is SERVER_IO_ERROR_EVT
// 3. Posted event is invalid
//
TEST_F(NameAddTransactionTest, selectingRevServerHandler) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
- SELECTING_REV_SERVER_ST,
+ SELECTING_REV_SERVER_ST,
NameChangeTransaction::SELECT_SERVER_EVT));
-
- // Run selectingRevServerHandler.
- EXPECT_NO_THROW(name_add->selectingRevServerHandler());
- // Verify that a server was selected.
- EXPECT_TRUE(name_add->getCurrentServer());
-
- // Verify that we transitioned correctly.
- EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
- name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
- name_add->getNextEvent());
-
- // Post a server IO error event. This simulates an IO error occuring
- // and a need to select the a new server.
- ASSERT_NO_THROW(name_add->postNextEvent(NameChangeTransaction::
- SERVER_IO_ERROR_EVT));
+ // Call selectingRevServerHandler enough times to select all of the
+ // servers in it's current domain. The first time, it will be with
+ // next event of SELECT_SERVER_EVT. Thereafter it will be with a next
+ // event of SERVER_IO_ERROR_EVT.
+ int num_servers = name_add->getReverseDomain()->getServers()->size();
+ for (int i = 0; i < num_servers; i++) {
+ // Run selectingRevServerHandler.
+ EXPECT_NO_THROW(name_add->selectingRevServerHandler());
+
+ // Verify that a server was selected.
+ EXPECT_TRUE(name_add->getCurrentServer());
+
+ // Verify that we transitioned correctly.
+ EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ name_add->getCurrState());
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ name_add->getNextEvent());
+
+ // Post a server IO error event. This simulates an IO error occuring
+ // and a need to select the new server.
+ ASSERT_NO_THROW(name_add->postNextEvent(NameChangeTransaction::
+ SERVER_IO_ERROR_EVT));
+ }
- // Run selectingRevServerHandler.
+ // We should have exhausted the list of servers. Processing another
+ // SERVER_IO_ERROR_EVT should transition us to failure.
EXPECT_NO_THROW(name_add->selectingRevServerHandler());
-
- // Test domain only has 1 server, so we should have exhausted server
- // list. Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::NO_MORE_SERVERS_EVT,
+ EXPECT_EQ(NameChangeTransaction::NO_MORE_SERVERS_EVT,
name_add->getNextEvent());
// Create and prep transaction, poised to run the handler but with an
// invalid event.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
- SELECTING_REV_SERVER_ST,
+ SELECTING_REV_SERVER_ST,
StateModel::NOP_EVT));
- // Running the handler should throw.
- EXPECT_THROW(name_add->selectingRevServerHandler(),
+ // Running the handler should throw.
+ EXPECT_THROW(name_add->selectingRevServerHandler(),
NameAddTransactionError);
}
//************************** replacingRevPtrsHandler tests *****************
// Tests that replacingRevPtrsHandler rejects invalid events.
-TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_invalid_event) {
+TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_InvalidEvent) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler but with
// an invalid event.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
NameChangeTransaction::
StateModel::NOP_EVT));
- // Running the handler should throw.
- EXPECT_THROW(name_add->replacingRevPtrsHandler(),
+ // Running the handler should throw.
+ EXPECT_THROW(name_add->replacingRevPtrsHandler(),
NameAddTransactionError);
}
-// Tests replacingRevPtrsHandler with the following scenario:
+// Tests replacingRevPtrsHandler with the following scenario:
//
// The request includes only a reverse change.
-// Initial posted event is SERVER_SELECTED_EVT.
+// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates successful update.
//
-TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_fwd_only_add_Ok) {
+TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_FwdOnlyAddOK) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
NameAddTransaction::
SERVER_SELECTED_EVT, REVERSE_CHG));
-
- // Should not be an update message yet.
+
+ // Should not be an update message yet.
D2UpdateMessagePtr update_msg = name_add->getDnsUpdateRequest();
- EXPECT_TRUE(!update_msg);
+ ASSERT_FALSE(update_msg);
// At this point completion flags should be false.
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // Run replacingRevPtrsHandler to construct and send the request.
+ // Run replacingRevPtrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
// Verify that an update message was constructed.
// Verify that we are still in this state and next event is NOP_EVT.
// This indicates we "sent" the message and are waiting for IO completion.
- EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::NOP_EVT,
+ EXPECT_EQ(NameChangeTransaction::NOP_EVT,
name_add->getNextEvent());
// Simulate receiving a succussful update response.
// Since it is a reverse change, we should be done.
// Verify that we transitioned correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_OK_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_OK_EVT,
name_add->getNextEvent());
}
-// Tests replacingRevPtrsHandler with the following scenario:
+// Tests replacingRevPtrsHandler with the following scenario:
//
// The request includes only a reverse change.
// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent without error.
// A server response is received which indicates the update was rejected.
//
-TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_other_rcode) {
+TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_OtherRcode) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
NameAddTransaction::
SERVER_SELECTED_EVT, REVERSE_CHG));
// Select a server to satisfy log statements.
ASSERT_TRUE(name_add->selectRevServer());
- // Run replacingRevPtrsHandler to construct and send the request.
+ // Run replacingRevPtrsHandler to construct and send the request.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
// Simulate receiving server rejection response. Per RFC, anything other
// than no error is failure. Arbitrarily choosing refused.
name_add->fakeResponse(DNSClient::SUCCESS, dns::Rcode::REFUSED());
- // Run replacingRevPtrsHandler again to process the response.
+ // Run replacingRevPtrsHandler again to process the response.
//EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
(name_add->replacingRevPtrsHandler());
EXPECT_FALSE(name_add->getForwardChangeCompleted());
EXPECT_FALSE(name_add->getReverseChangeCompleted());
- // We should have failed the transaction. Verifiy that we transitioned
+ // We should have failed the transaction. Verifiy that we transitioned
// correctly.
- EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ EXPECT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
+ EXPECT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
name_add->getNextEvent());
}
-// Tests replacingRevPtrsHandler with the following scenario:
+// Tests replacingRevPtrsHandler with the following scenario:
//
// The request includes only a reverse change.
// Initial posted event is SERVER_SELECTED_EVT.
// The update request send times out MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_time_out) {
+TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_Timeout) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
NameAddTransaction::
SERVER_SELECTED_EVT, REVERSE_CHG));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
const D2UpdateMessagePtr prev_msg = name_add->getDnsUpdateRequest();
- // Run replacingRevPtrsHandler to send the request.
+ // Run replacingRevPtrsHandler to send the request.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
const D2UpdateMessagePtr curr_msg = name_add->getDnsUpdateRequest();
EXPECT_FALSE(prev_msg);
EXPECT_TRUE(curr_msg);
} else {
- // Subsequent passes should reuse the request.
+ // Subsequent passes should reuse the request. We are only
+ // looking to check that we have not replaced the pointer value
+ // with a new pointer. This tests the on_entry() logic which
+ // clears the request ONLY upon initial entry into the state.
EXPECT_TRUE(prev_msg == curr_msg);
}
- // Simulate a server IO timeout.
+ // Simulate a server IO timeout.
name_add->setDnsUpdateStatus(DNSClient::TIMEOUT);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run replacingRevPtrsHandler again to process the response.
+ // Run replacingRevPtrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_REV_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_REV_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
}
-// Tests replacingRevPtrsHandler with the following scenario:
+// Tests replacingRevPtrsHandler with the following scenario:
//
// The request includes only a reverse change.
// Initial posted event is SERVER_SELECTED_EVT.
// The update request is sent but a corrupt response is received, this occurs
// MAX_UPDATE_TRIES_PER_SERVER times.
//
-TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_corrupt_response) {
+TEST_F(NameAddTransactionTest, replacingRevPtrsHandler_CorruptResponse) {
NameAddStubPtr name_add;
// Create the transaction.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameAddTransaction::REPLACING_REV_PTRS_ST,
NameAddTransaction::
SERVER_SELECTED_EVT, REVERSE_CHG));
// Verify that we can make maximum number of update attempts permitted
// and then transition to selecting a new server.
- int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
+ int max_tries = NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER;
for (int i = 1; i <= max_tries; i++) {
const D2UpdateMessagePtr prev_msg = name_add->getDnsUpdateRequest();
- // Run replacingRevPtrsHandler to send the request.
+ // Run replacingRevPtrsHandler to send the request.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
const D2UpdateMessagePtr curr_msg = name_add->getDnsUpdateRequest();
EXPECT_FALSE(prev_msg);
EXPECT_TRUE(curr_msg);
} else {
- // Subsequent passes should reuse the request.
+ // Subsequent passes should reuse the request. We are only
+ // looking to check that we have not replaced the pointer value
+ // with a new pointer. This tests the on_entry() logic which
+ // clears the request ONLY upon initial entry into the state.
EXPECT_TRUE(prev_msg == curr_msg);
}
- // Simulate a server corrupt response.
+ // Simulate a server corrupt response.
name_add->setDnsUpdateStatus(DNSClient::INVALID_RESPONSE);
name_add->postNextEvent(NameChangeTransaction::IO_COMPLETED_EVT);
- // Run replacingRevPtrsHandler again to process the response.
+ // Run replacingRevPtrsHandler again to process the response.
EXPECT_NO_THROW(name_add->replacingRevPtrsHandler());
// Completion flags should be false.
if (i < max_tries) {
// We should be ready to try again.
- EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
+ EXPECT_EQ(NameAddTransaction::REPLACING_REV_PTRS_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
name_add->getNextEvent());
} else {
// Server retries should be exhausted, time for a new server.
- EXPECT_EQ(NameAddTransaction::SELECTING_REV_SERVER_ST,
+ EXPECT_EQ(NameAddTransaction::SELECTING_REV_SERVER_ST,
name_add->getCurrState());
- EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ EXPECT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
name_add->getNextEvent());
}
}
// Tests the processAddOkHandler functionality.
// It verifies behavior for the following scenarios:
//
-// 1. Posted event is UPDATE_OK_EVT
+// 1. Posted event is UPDATE_OK_EVT
// 2. Posted event is invalid
//
TEST_F(NameAddTransactionTest, processAddOkHandler) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::PROCESS_TRANS_OK_ST,
NameChangeTransaction::UPDATE_OK_EVT));
- // Run processAddOkHandler.
+ // Run processAddOkHandler.
EXPECT_NO_THROW(name_add->processAddOkHandler());
- // Verify that a server was selected.
+ // Verify that a server was selected.
EXPECT_EQ(dhcp_ddns::ST_COMPLETED, name_add->getNcrStatus());
// Verify that the model has ended.
// Create and prep transaction, poised to run the handler but with an
// invalid event.
- ASSERT_NO_THROW(name_add =
- prepHandlerTest(NameChangeTransaction::PROCESS_TRANS_OK_ST,
+ ASSERT_NO_THROW(name_add =
+ prepHandlerTest(NameChangeTransaction::PROCESS_TRANS_OK_ST,
StateModel::NOP_EVT));
- // Running the handler should throw.
+ // Running the handler should throw.
EXPECT_THROW(name_add->processAddOkHandler(), NameAddTransactionError);
}
// Tests the processAddFailedHandler functionality.
// It verifies behavior for the following scenarios:
//
-// 1. Posted event is UPDATE_FAILED_EVT
+// 1. Posted event is UPDATE_FAILED_EVT
// 2. Posted event is invalid
//
TEST_F(NameAddTransactionTest, processAddFailedHandler) {
NameAddStubPtr name_add;
// Create and prep a transaction, poised to run the handler.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
PROCESS_TRANS_FAILED_ST,
NameChangeTransaction::UPDATE_FAILED_EVT));
- // Run processAddFailedHandler.
+ // Run processAddFailedHandler.
EXPECT_NO_THROW(name_add->processAddFailedHandler());
- // Verify that a server was selected.
+ // Verify that a server was selected.
EXPECT_EQ(dhcp_ddns::ST_FAILED, name_add->getNcrStatus());
// Verify that the model has ended. (Remember, the transaction failed NOT
- // the model. The model should have ended normally.)
+ // the model. The model should have ended normally.)
EXPECT_EQ(StateModel::END_ST, name_add->getCurrState());
EXPECT_EQ(StateModel::END_EVT, name_add->getNextEvent());
// Create and prep transaction, poised to run the handler but with an
// invalid event.
- ASSERT_NO_THROW(name_add =
+ ASSERT_NO_THROW(name_add =
prepHandlerTest(NameChangeTransaction::
- PROCESS_TRANS_FAILED_ST,
+ PROCESS_TRANS_FAILED_ST,
StateModel::NOP_EVT));
- // Running the handler should throw.
+ // Running the handler should throw.
EXPECT_THROW(name_add->processAddFailedHandler(), NameAddTransactionError);
}
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <asiolink/interval_timer.h>
#include <d2/nc_trans.h>
+#include <dns/opcode.h>
+#include <dns/messagerenderer.h>
+#include <log/logger_support.h>
+#include <log/macros.h>
+#include <util/buffer.h>
+
+#include <asio/ip/udp.hpp>
+#include <asio/socket_base.hpp>
+#include <asio.hpp>
+#include <asio/error_code.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace {
+const size_t MAX_MSG_SIZE = 1024;
+
/// @brief Test derivation of NameChangeTransaction for exercising state
/// model mechanics.
///
// NameChangeStub events
static const int SEND_UPDATE_EVT = NCT_DERIVED_EVENT_MIN + 2;
+ bool use_stub_callback_;
+
/// @brief Constructor
///
/// Parameters match those needed by NameChangeTransaction.
DdnsDomainPtr forward_domain,
DdnsDomainPtr reverse_domain)
: NameChangeTransaction(io_service, ncr, forward_domain,
- reverse_domain) {
+ reverse_domain),
+ use_stub_callback_(false) {
}
/// @brief Destructor
virtual ~NameChangeStub() {
}
+ /// @brief DNSClient callback
+ /// Overrides the callback in NameChangeTranscation to allow testing
+ /// sendUpdate without incorporating exectution of the state model
+ /// into the test.
+ /// It sets the DNS status update and posts IO_COMPLETED_EVT as does
+ /// the normal callback, but rather than invoking runModel it stops
+ /// the IO service. This allows tests to be constructed that consisted
+ /// of generating a DNS request and invoking sendUpdate to post it and
+ /// wait for response.
+ virtual void operator()(DNSClient::Status status) {
+ if (use_stub_callback_) {
+ setDnsUpdateStatus(status);
+ postNextEvent(IO_COMPLETED_EVT);
+ getIOService()->stop();
+ } else {
+ // For tests which need to use the real callback.
+ NameChangeTransaction::operator()(status);
+ }
+ }
+
+ /// @brief Some tests require a server to be selected. This method
+ /// selects the first server in the forward domain without involving
+ /// state model execution to do so.
+ bool selectFwdServer() {
+ if (getForwardDomain()) {
+ initServerSelection(getForwardDomain());
+ selectNextServer();
+ return (getCurrentServer());
+ }
+
+ return (false);
+ }
+
/// @brief Empty handler used to statisfy map verification.
void dummyHandler() {
isc_throw(NameChangeTransactionError,
// Invoke the base call implementation first.
NameChangeTransaction::verifyStates();
- // Define our states.
+ // Check our states.
getState(DOING_UPDATE_ST);
}
// Expose the protected methods to be tested.
using StateModel::runModel;
+ using StateModel::postNextEvent;
+ using StateModel::setState;
+ using StateModel::initDictionaries;
using NameChangeTransaction::initServerSelection;
using NameChangeTransaction::selectNextServer;
using NameChangeTransaction::getCurrentServer;
using NameChangeTransaction::getReverseChangeCompleted;
using NameChangeTransaction::setForwardChangeCompleted;
using NameChangeTransaction::setReverseChangeCompleted;
+ using NameChangeTransaction::setUpdateAttempts;
+ using NameChangeTransaction::transition;
+ using NameChangeTransaction::retryTransition;
+ using NameChangeTransaction::sendUpdate;
+};
+
+typedef boost::shared_ptr<asio::ip::udp::socket> SocketPtr;
+
+/// @brief This class simulates a DNS server. It is capable of performing
+/// an asynchronous read, governed by an IOService, and responding to received
+/// requests in a given manner.
+class FauxServer {
+public:
+ enum ResponseMode {
+ USE_RCODE, // Generate a response with a given RCODE
+ CORRUPT_RESP // Generate a corrupt response
+ };
+
+ asiolink::IOService& io_service_;
+ asiolink::IOAddress& address_;
+ size_t port_;
+ SocketPtr server_socket_;
+ asio::ip::udp::endpoint remote_;
+ uint8_t receive_buffer_[MAX_MSG_SIZE];
+
+ /// @brief Constructor
+ ///
+ /// @param io_service IOService to be used for socket IO.
+ /// @param address IP address at which the server should listen.
+ /// @param port Port number at which the server should listen.
+ FauxServer(asiolink::IOService& io_service, asiolink::IOAddress& address,
+ size_t port)
+ : io_service_(io_service), address_(address), port_(port),
+ server_socket_() {
+ server_socket_.reset(new asio::ip::udp::
+ socket(io_service_.get_io_service(),
+ asio::ip::udp::v4()));
+ server_socket_->set_option(asio::socket_base::reuse_address(true));
+ server_socket_->bind(asio::ip::udp::
+ endpoint(address_.getAddress(), port_));
+ }
+
+ /// @brief Destructor
+ virtual ~FauxServer() {
+ }
+
+ /// @brief Initiates an asyncrhonrous receive
+ ///
+ /// Starts the server listening for requests. Upon completion of the
+ /// the listen, the callback method, requestHandler, is invoked.
+ ///
+ /// @param response_mode Selects how the server responds to a request
+ /// @param response_rcode The Rcode value set in the response. Not used
+ /// for all modes.
+ void receive (const ResponseMode& response_mode,
+ const dns::Rcode& response_rcode=dns::Rcode::NOERROR()) {
+
+ server_socket_->async_receive_from(asio::buffer(receive_buffer_,
+ sizeof(receive_buffer_)),
+ remote_,
+ boost::bind(&FauxServer::requestHandler,
+ this, _1, _2,
+ response_mode,
+ response_rcode));
+ }
+
+ /// @brief Socket IO Completion callback
+ ///
+ /// This method servers as the Server's UDP socket receive callback handler.
+ /// When the receive completes the handler is invoked with the
+ /// @param error result code of the recieve (determined by asio layer)
+ /// @param bytes_recvd number of bytes received, if any
+ /// @param response_mode type of response the handler should produce
+ /// @param response_rcode value of Rcode in the response constructed by
+ /// handler
+ void requestHandler(const asio::error_code& error,
+ std::size_t bytes_recvd,
+ const ResponseMode& response_mode,
+ const dns::Rcode& response_rcode) {
+
+ // If we encountered an error or received no data then fail.
+ // We expect the client to send good requests.
+ if (error.value() != 0 || bytes_recvd < 1) {
+ ADD_FAILURE() << "FauxServer receive failed" << error.message();
+ return;
+ }
+
+ // We have a successfully received data. We need to turn it into
+ // a request in order to build a proper response.
+ // Note D2UpdateMessage is geared towards making requests and
+ // reading responses. This is the opposite perspective so we have
+ // to a bit of roll-your-own here.
+ dns::Message request(dns::Message::PARSE);
+ util::InputBuffer request_buf(receive_buffer_, bytes_recvd);
+ try {
+ request.fromWire(request_buf);
+ } catch (const std::exception& ex) {
+ // If the request cannot be parsed, then fail the test.
+ // We expect the client to send good requests.
+ ADD_FAILURE() << "FauxServer request is corrupt:" << ex.what();
+ return;
+ }
+
+ // The request parsed ok, so let's build a response.
+ // We must use the QID we received in the response or IOFetch will
+ // toss the response out, resulting in eventual timeout.
+ // We fill in the zone with data we know is from the "server".
+ dns::Message response(dns::Message::RENDER);
+ response.setQid(request.getQid());
+ dns::Question question(dns::Name("response.example.com"),
+ dns::RRClass::ANY(), dns::RRType::SOA());
+ response.addQuestion(question);
+ response.setOpcode(dns::Opcode(dns::Opcode::UPDATE_CODE));
+ response.setHeaderFlag(dns::Message::HEADERFLAG_QR, true);
+
+ // Set the response Rcode to value passed in, default is NOERROR.
+ response.setRcode(response_rcode);
+
+ // Render the response to a buffer.
+ dns::MessageRenderer renderer;
+ util::OutputBuffer response_buf(MAX_MSG_SIZE);
+ renderer.setBuffer(&response_buf);
+ response.toWire(renderer);
+
+ // If mode is to ship garbage, then stomp on part of the rendered
+ // message.
+ if (response_mode == CORRUPT_RESP) {
+ response_buf.writeUint16At(0xFFFF, 2);
+ }
+
+ // Ship the reponse via synchronous send.
+ try {
+ int cnt = server_socket_->send_to(asio::
+ buffer(response_buf.getData(),
+ response_buf.getLength()),
+ remote_);
+ // Make sure we sent what we expect to send.
+ if (cnt != response_buf.getLength()) {
+ ADD_FAILURE() << "FauxServer sent: " << cnt << " expected: "
+ << response_buf.getLength();
+ }
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "FauxServer send failed: " << ex.what();
+ }
+ }
};
/// @brief Defines a pointer to a NameChangeStubPtr instance.
IOServicePtr io_service_;
DdnsDomainPtr forward_domain_;
DdnsDomainPtr reverse_domain_;
-
- NameChangeTransactionTest() : io_service_(new isc::asiolink::IOService()) {
- }
+ asiolink::IntervalTimer timer_;
+ int run_time_;
+
+ NameChangeTransactionTest()
+ : io_service_(new isc::asiolink::IOService()), timer_(*io_service_),
+ run_time_(0) {
+ }
virtual ~NameChangeTransactionTest() {
}
- /// @brief Instantiates a NameChangeStub built around a canned
- /// NameChangeRequest.
+ /// @brief Run the IO service for no more than a given amount of time.
+ ///
+ /// Uses an IntervalTimer to interrupt the invocation of IOService run(),
+ /// after the given number of milliseconds elapse. The timer executes
+ /// the timesUp() method if it expires.
+ ///
+ /// @param run_time amount of time in milliseconds to allow run to execute.
+ void runTimedIO(int run_time) {
+ run_time_ = run_time;
+ timer_.setup(boost::bind(&NameChangeTransactionTest::timesUp, this),
+ run_time_);
+ io_service_->run();
+ }
+
+ /// @brief IO Timer expiration handler
+ ///
+ /// Stops the IOSerivce and FAILs the current test.
+ void timesUp() {
+ io_service_->stop();
+ FAIL() << "Test Time: " << run_time_ << " expired";
+ }
+
+ /// @brief Instantiates a NameChangeStub test transaction
+ /// The transaction is constructed around a predefined (i.e "canned")
+ /// NameChangeRequest. The request has both forward and reverse DNS
+ /// changes requested, and both forward and reverse domains are populated.
NameChangeStubPtr makeCannedTransaction() {
+ // NCR in JSON form.
const char* msg_str =
"{"
" \"change_type\" : 0 , "
" \"lease_length\" : 1300 "
"}";
+ // Create the request from JSON.
dhcp_ddns::NameChangeRequestPtr ncr;
-
DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
DnsServerInfoPtr server;
-
ncr = dhcp_ddns::NameChangeRequest::fromJSON(msg_str);
- // make forward server list
+ // Make forward DdnsDomain with 2 forward servers.
server.reset(new DnsServerInfo("forward.example.com",
- isc::asiolink::IOAddress("1.1.1.1")));
+ isc::asiolink::IOAddress("127.0.0.1"),
+ 5301));
+ servers->push_back(server);
+ server.reset(new DnsServerInfo("forward2.example.com",
+ isc::asiolink::IOAddress("127.0.0.1"),
+ 5302));
+
servers->push_back(server);
- forward_domain_.reset(new DdnsDomain("*", "", servers));
+ forward_domain_.reset(new DdnsDomain("example.com.", "", servers));
- // make reverse server list
- servers->clear();
+ // Make reverse DdnsDomain with one reverse server.
+ servers.reset(new DnsServerInfoStorage());
server.reset(new DnsServerInfo("reverse.example.com",
- isc::asiolink::IOAddress("2.2.2.2")));
+ isc::asiolink::IOAddress("127.0.0.1"),
+ 5301));
servers->push_back(server);
- reverse_domain_.reset(new DdnsDomain("*", "", servers));
+ reverse_domain_.reset(new DdnsDomain("2.168.192.in.addr.arpa.",
+ "", servers));
+
+ // Instantiate the transaction as would be done by update manager.
return (NameChangeStubPtr(new NameChangeStub(io_service_, ncr,
forward_domain_, reverse_domain_)));
-
}
};
EXPECT_TRUE(name_change->getReverseChangeCompleted());
}
+/// @brief Tests DNS update request accessor methods.
TEST_F(NameChangeTransactionTest, dnsUpdateRequestAccessors) {
+ // Create a transction.
NameChangeStubPtr name_change;
ASSERT_NO_THROW(name_change = makeCannedTransaction());
- // Verify that the DNS update request accessors.
- D2UpdateMessagePtr req;
- ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
- // Post construction it is empty.
+ // Post transaction construction, there should not be an update request.
EXPECT_FALSE(name_change->getDnsUpdateRequest());
- /// @param request is the new request packet to assign.
+ // Create a request.
+ D2UpdateMessagePtr req;
+ ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
+
+ // Use the setter and then verify we can fetch the request.
ASSERT_NO_THROW(name_change->setDnsUpdateRequest(req));
// Post set, we should be able to fetch it.
- EXPECT_TRUE(name_change->getDnsUpdateRequest());
+ ASSERT_TRUE(name_change->getDnsUpdateRequest());
// Should be able to clear it.
ASSERT_NO_THROW(name_change->clearDnsUpdateRequest());
EXPECT_FALSE(name_change->getDnsUpdateRequest());
}
+/// @brief Tests DNS update request accessor methods.
TEST_F(NameChangeTransactionTest, dnsUpdateResponseAccessors) {
+ // Create a transction.
NameChangeStubPtr name_change;
ASSERT_NO_THROW(name_change = makeCannedTransaction());
- // Verify that the DNS update response accessors.
+ // Post transaction construction, there should not be an update response.
+ EXPECT_FALSE(name_change->getDnsUpdateResponse());
+
+ // Create a response.
D2UpdateMessagePtr resp;
ASSERT_NO_THROW(resp.reset(new D2UpdateMessage(D2UpdateMessage::INBOUND)));
- // Post construction it is empty.
- EXPECT_FALSE(name_change->getDnsUpdateResponse());
-
- /// @param request is the new request packet to assign.
+ // Use the setter and then verify we can fetch the response.
ASSERT_NO_THROW(name_change->setDnsUpdateResponse(resp));
// Post set, we should be able to fetch it.
}
-
/// @brief Tests event and state dictionary construction and verification.
TEST_F(NameChangeTransactionTest, dictionaryCheck) {
NameChangeStubPtr name_change;
EXPECT_FALSE(name_change->getForwardChangeCompleted());
}
+/// @brief Tests update attempt accessors.
+TEST_F(NameChangeTransactionTest, updateAttempts) {
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+
+ // Post transaction construction, update attempts should be 0.
+ EXPECT_EQ(0, name_change->getUpdateAttempts());
+
+ // Set it to a known value.
+ name_change->setUpdateAttempts(5);
+
+ // Verify that the value is as expected.
+ EXPECT_EQ(5, name_change->getUpdateAttempts());
+}
+
+/// @brief Tests retryTransition method
+///
+/// Verifes that while the maximum number of update attempts has not
+/// been exceeded, the method will leave the state unchanged but post a
+/// SERVER_SELECTED_EVT. Once the maximum is exceeded, the method should
+/// transition to the state given with a next event of SERVER_IO_ERROR_EVT.
+TEST_F(NameChangeTransactionTest, retryTransition) {
+ // Create the transaction.
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+
+ // Define dictionaries.
+ ASSERT_NO_THROW(name_change->initDictionaries());
+
+ // Transition to a known spot.
+ ASSERT_NO_THROW(name_change->transition(
+ NameChangeStub::DOING_UPDATE_ST,
+ NameChangeStub::SEND_UPDATE_EVT));
+
+ // Verify we are at the known spot.
+ ASSERT_EQ(NameChangeStub::DOING_UPDATE_ST,
+ name_change->getCurrState());
+ ASSERT_EQ(NameChangeStub::SEND_UPDATE_EVT,
+ name_change->getNextEvent());
+
+ // Verify that we have not exceeded maximum number of attempts.
+ EXPECT_TRUE(name_change->getUpdateAttempts() <
+ NameChangeTransaction::MAX_UPDATE_TRIES_PER_SERVER);
+
+ // Call retryTransition.
+ ASSERT_NO_THROW(name_change->retryTransition(
+ NameChangeTransaction::PROCESS_TRANS_FAILED_ST));
+
+ // Since the number of udpate attempts is less than the maximum allowed
+ // we should remain in our current state but with next event of
+ // SERVER_SELECTED_EVT posted.
+ ASSERT_EQ(NameChangeStub::DOING_UPDATE_ST,
+ name_change->getCurrState());
+ ASSERT_EQ(NameChangeTransaction::SERVER_SELECTED_EVT,
+ name_change->getNextEvent());
+
+ // Now set the number of attempts to the maximum.
+ name_change->setUpdateAttempts(NameChangeTransaction::
+ MAX_UPDATE_TRIES_PER_SERVER);
+ // Call retryTransition.
+ ASSERT_NO_THROW(name_change->retryTransition(
+ NameChangeTransaction::PROCESS_TRANS_FAILED_ST));
+
+ // Since we have exceeded maximum attempts, we should tranisition to
+ // PROCESS_UPDATE_FAILD_ST with a next event of SERVER_IO_ERROR_EVT.
+ ASSERT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ name_change->getCurrState());
+ ASSERT_EQ(NameChangeTransaction::SERVER_IO_ERROR_EVT,
+ name_change->getNextEvent());
+}
+
+/// @brief Tests sendUpdate method when underlying doUpdate throws.
+///
+/// DNSClient::doUpdate can throw for a variety of reasons. This tests
+/// sendUpdate handling of such a throw by passing doUpdate a request
+/// that will not render.
+TEST_F(NameChangeTransactionTest, sendUpdateDoUpdateFailure) {
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+ ASSERT_NO_THROW(name_change->initDictionaries());
+ ASSERT_TRUE(name_change->selectFwdServer());
+
+ // Set the transaction's request to an empty DNS update.
+ D2UpdateMessagePtr req;
+ ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
+ ASSERT_NO_THROW(name_change->setDnsUpdateRequest(req));
+
+ // Verify that sendUpdate does not throw, but it should fail because
+ // the requset won't render.
+ ASSERT_NO_THROW(name_change->sendUpdate());
+
+ // Verify that we transition to failed state and event.
+ ASSERT_EQ(NameChangeTransaction::PROCESS_TRANS_FAILED_ST,
+ name_change->getCurrState());
+ ASSERT_EQ(NameChangeTransaction::UPDATE_FAILED_EVT,
+ name_change->getNextEvent());
+}
+
+/// @brief Tests sendUpdate method when underlying doUpdate times out.
+TEST_F(NameChangeTransactionTest, sendUpdateTimeout) {
+ log::initLogger();
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+ ASSERT_NO_THROW(name_change->initDictionaries());
+ ASSERT_TRUE(name_change->selectFwdServer());
+
+ // Create a valid request.
+ D2UpdateMessagePtr req;
+ ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
+ ASSERT_NO_THROW(name_change->setDnsUpdateRequest(req));
+ req->setZone(dns::Name("request.example.com"), dns::RRClass::ANY());
+ req->setRcode(dns::Rcode(dns::Rcode::NOERROR_CODE));
+
+ // Set the flag to use the NameChangeStub's DNSClient callback.
+ name_change->use_stub_callback_ = true;
+
+ // Invoke sendUdpate.
+ ASSERT_NO_THROW(name_change->sendUpdate());
+
+ // Update attempt count should be 1, next event should be NOP_EVT.
+ EXPECT_EQ(1, name_change->getUpdateAttempts());
+ ASSERT_EQ(NameChangeTransaction::NOP_EVT,
+ name_change->getNextEvent());
+
+ // Run IO a bit longer than maximum allowed to permit timeout logic to
+ // execute.
+ runTimedIO(NameChangeTransaction::DNS_UPDATE_DEFAULT_TIMEOUT + 100);
+
+ // Verify that next event is IO_COMPLETED_EVT and DNS status is TIMEOUT.
+ ASSERT_EQ(NameChangeTransaction::IO_COMPLETED_EVT,
+ name_change->getNextEvent());
+ ASSERT_EQ(DNSClient::TIMEOUT, name_change->getDnsUpdateStatus());
+}
+
+/// @brief Tests sendUpdate method when it receives a corrupt respons from
+/// the server.
+TEST_F(NameChangeTransactionTest, sendUpdateCorruptResponse) {
+ log::initLogger();
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+ ASSERT_NO_THROW(name_change->initDictionaries());
+ ASSERT_TRUE(name_change->selectFwdServer());
+
+ // Create a server and start it listening.
+ asiolink::IOAddress address("127.0.0.1");
+ FauxServer server(*io_service_, address, 5301);
+ server.receive(FauxServer::CORRUPT_RESP);
+
+ // Create a valid request for the transaction.
+ D2UpdateMessagePtr req;
+ ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
+ ASSERT_NO_THROW(name_change->setDnsUpdateRequest(req));
+ req->setZone(dns::Name("request.example.com"), dns::RRClass::ANY());
+ req->setRcode(dns::Rcode(dns::Rcode::NOERROR_CODE));
+
+ // Set the flag to use the NameChangeStub's DNSClient callback.
+ name_change->use_stub_callback_ = true;
+
+ // Invoke sendUdpate.
+ ASSERT_NO_THROW(name_change->sendUpdate());
+
+ // Update attempt count should be 1, next event should be NOP_EVT.
+ EXPECT_EQ(1, name_change->getUpdateAttempts());
+ ASSERT_EQ(NameChangeTransaction::NOP_EVT,
+ name_change->getNextEvent());
+
+ // Run the IO for 500 ms. This should be more than enough time.
+ runTimedIO(500);
+
+ // Verify that next event is IO_COMPLETED_EVT and DNS status is INVALID.
+ ASSERT_EQ(NameChangeTransaction::IO_COMPLETED_EVT,
+ name_change->getNextEvent());
+ ASSERT_EQ(DNSClient::INVALID_RESPONSE, name_change->getDnsUpdateStatus());
+}
+
+/// @brief Tests sendUpdate method when the exchange succeeds.
+TEST_F(NameChangeTransactionTest, sendUpdate) {
+ log::initLogger();
+ NameChangeStubPtr name_change;
+ ASSERT_NO_THROW(name_change = makeCannedTransaction());
+ ASSERT_NO_THROW(name_change->initDictionaries());
+ ASSERT_TRUE(name_change->selectFwdServer());
+
+ // Create a server and start it listening.
+ asiolink::IOAddress address("127.0.0.1");
+ FauxServer server(*io_service_, address, 5301);
+ server.receive (FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+
+ // Create a valid request for the transaction.
+ D2UpdateMessagePtr req;
+ ASSERT_NO_THROW(req.reset(new D2UpdateMessage(D2UpdateMessage::OUTBOUND)));
+ ASSERT_NO_THROW(name_change->setDnsUpdateRequest(req));
+ req->setZone(dns::Name("request.example.com"), dns::RRClass::ANY());
+ req->setRcode(dns::Rcode(dns::Rcode::NOERROR_CODE));
+
+ // Set the flag to use the NameChangeStub's DNSClient callback.
+ name_change->use_stub_callback_ = true;
+
+ // Invoke sendUdpate.
+ ASSERT_NO_THROW(name_change->sendUpdate());
+
+ // Update attempt count should be 1, next event should be NOP_EVT.
+ EXPECT_EQ(1, name_change->getUpdateAttempts());
+ ASSERT_EQ(NameChangeTransaction::NOP_EVT,
+ name_change->getNextEvent());
+
+ // Run the IO for 500 ms. This should be more than enough time.
+ runTimedIO(500);
+
+ // Verify that next event is IO_COMPLETED_EVT and DNS status is SUCCESS.
+ ASSERT_EQ(NameChangeTransaction::IO_COMPLETED_EVT,
+ name_change->getNextEvent());
+ ASSERT_EQ(DNSClient::SUCCESS, name_change->getDnsUpdateStatus());
+
+ // Verify that we have a response and it's Rcode is NOERROR,
+ // and the zone is as expected.
+ D2UpdateMessagePtr response = name_change->getDnsUpdateResponse();
+ ASSERT_TRUE(response);
+ ASSERT_EQ(dns::Rcode::NOERROR().getCode(), response->getRcode().getCode());
+ D2ZonePtr zone = response->getZone();
+ EXPECT_TRUE(zone);
+ EXPECT_EQ("response.example.com.", zone->getName().toText());
+}
+
}