nc_trans_unittests.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <d2/nc_trans.h>
  15. #include <boost/function.hpp>
  16. #include <boost/bind.hpp>
  17. #include <gtest/gtest.h>
  18. using namespace std;
  19. using namespace isc;
  20. using namespace isc::d2;
  21. namespace {
  22. /// @brief Test derivation of NameChangeTransaction for exercising state
  23. /// model mechanics.
  24. ///
  25. /// This class facilitates testing by making non-public methods accessible so
  26. /// they can be invoked directly in test routines. It implements a very
  27. /// rudimentary state model, sufficient to test the state model mechanics
  28. /// supplied by the base class.
  29. class NameChangeStub : public NameChangeTransaction {
  30. public:
  31. // NameChangeStub states
  32. static const int DOING_UPDATE_ST = NCT_STATE_MAX + 1;
  33. // NameChangeStub events
  34. static const int SEND_UPDATE_EVT = NCT_EVENT_MAX + 2;
  35. /// @brief Constructor
  36. ///
  37. /// Parameters match those needed by NameChangeTransaction.
  38. NameChangeStub(isc::asiolink::IOService& io_service,
  39. dhcp_ddns::NameChangeRequestPtr& ncr,
  40. DdnsDomainPtr forward_domain,
  41. DdnsDomainPtr reverse_domain)
  42. : NameChangeTransaction(io_service, ncr, forward_domain,
  43. reverse_domain) {
  44. }
  45. /// @brief Destructor
  46. virtual ~NameChangeStub() {
  47. }
  48. /// @brief Empty handler used to statisfy map verification.
  49. void dummyHandler() {
  50. isc_throw(NameChangeTransactionError,
  51. "dummyHandler - invalid event: " << getContextStr());
  52. }
  53. /// @brief State handler for the READY_ST.
  54. ///
  55. /// Serves as the starting state handler, it consumes the
  56. /// START_EVT "transitioning" to the state, DOING_UPDATE_ST and
  57. /// sets the next event to SEND_UPDATE_EVT.
  58. void readyHandler() {
  59. switch(getNextEvent()) {
  60. case START_EVT:
  61. transition(DOING_UPDATE_ST, SEND_UPDATE_EVT);
  62. break;
  63. default:
  64. // its bogus
  65. isc_throw(NameChangeTransactionError,
  66. "readyHandler - invalid event: " << getContextStr());
  67. }
  68. }
  69. /// @brief State handler for the DOING_UPDATE_ST.
  70. ///
  71. /// Simulates a state that starts some form of asynchronous work.
  72. /// When next event is SEND_UPDATE_EVT it sets the status to pending
  73. /// and signals the state model must "wait" for an event by setting
  74. /// next event to NOP_EVT.
  75. ///
  76. /// When next event is IO_COMPLETED_EVT, it transitions to the state,
  77. /// PROCESS_TRANS_OK_ST, and sets the next event to UPDATE_OK_EVT.
  78. void doingUpdateHandler() {
  79. switch(getNextEvent()) {
  80. case SEND_UPDATE_EVT:
  81. setNcrStatus(dhcp_ddns::ST_PENDING);
  82. postNextEvent(NOP_EVT);
  83. break;
  84. case IO_COMPLETED_EVT:
  85. if (getDnsUpdateStatus() == DNSClient::SUCCESS) {
  86. setForwardChangeCompleted(true);
  87. transition(PROCESS_TRANS_OK_ST, UPDATE_OK_EVT);
  88. } else {
  89. transition(PROCESS_TRANS_FAILED_ST, UPDATE_FAILED_EVT);
  90. }
  91. break;
  92. default:
  93. // its bogus
  94. isc_throw(NameChangeTransactionError,
  95. "doingUpdateHandler - invalid event: "
  96. << getContextStr());
  97. }
  98. }
  99. /// @brief State handler for the PROCESS_TRANS_OK_ST.
  100. ///
  101. /// This is the last state in the model. Note that it sets the
  102. /// status to completed and next event to NOP_EVT.
  103. void processTransDoneHandler() {
  104. switch(getNextEvent()) {
  105. case UPDATE_OK_EVT:
  106. setNcrStatus(dhcp_ddns::ST_COMPLETED);
  107. endModel();
  108. break;
  109. case UPDATE_FAILED_EVT:
  110. setNcrStatus(dhcp_ddns::ST_FAILED);
  111. endModel();
  112. break;
  113. default:
  114. // its bogus
  115. isc_throw(NameChangeTransactionError,
  116. "processTransDoneHandler - invalid event: "
  117. << getContextStr());
  118. }
  119. }
  120. /// @brief Construct the event dictionary.
  121. virtual void defineEvents() {
  122. // Invoke the base call implementation first.
  123. NameChangeTransaction::defineEvents();
  124. // Define our events.
  125. defineEvent(SEND_UPDATE_EVT, "SEND_UPDATE_EVT");
  126. }
  127. /// @brief Verify the event dictionary.
  128. virtual void verifyEvents() {
  129. // Invoke the base call implementation first.
  130. NameChangeTransaction::verifyEvents();
  131. // Define our events.
  132. getEvent(SEND_UPDATE_EVT);
  133. }
  134. /// @brief Construct the state dictionary.
  135. virtual void defineStates() {
  136. // Invoke the base call implementation first.
  137. NameChangeTransaction::defineStates();
  138. // Define our states.
  139. defineState(READY_ST, "READY_ST",
  140. boost::bind(&NameChangeStub::readyHandler, this));
  141. defineState(SELECTING_FWD_SERVER_ST, "SELECTING_FWD_SERVER_ST",
  142. boost::bind(&NameChangeStub::dummyHandler, this));
  143. defineState(SELECTING_REV_SERVER_ST, "SELECTING_REV_SERVER_ST",
  144. boost::bind(&NameChangeStub::dummyHandler, this));
  145. defineState(DOING_UPDATE_ST, "DOING_UPDATE_ST",
  146. boost::bind(&NameChangeStub::doingUpdateHandler,
  147. this));
  148. defineState(PROCESS_TRANS_OK_ST, "PROCESS_TRANS_OK_ST",
  149. boost::bind(&NameChangeStub::
  150. processTransDoneHandler, this));
  151. defineState(PROCESS_TRANS_FAILED_ST, "PROCESS_TRANS_FAILED_ST",
  152. boost::bind(&NameChangeStub::
  153. processTransDoneHandler, this));
  154. }
  155. /// @brief Verify the event dictionary.
  156. virtual void verifyStates() {
  157. // Invoke the base call implementation first.
  158. NameChangeTransaction::verifyStates();
  159. // Define our states.
  160. getState(DOING_UPDATE_ST);
  161. }
  162. // Expose the protected methods to be tested.
  163. using StateModel::runModel;
  164. using NameChangeTransaction::initServerSelection;
  165. using NameChangeTransaction::selectNextServer;
  166. using NameChangeTransaction::getCurrentServer;
  167. using NameChangeTransaction::getDNSClient;
  168. using NameChangeTransaction::setNcrStatus;
  169. using NameChangeTransaction::setDnsUpdateStatus;
  170. using NameChangeTransaction::getDnsUpdateResponse;
  171. using NameChangeTransaction::getForwardChangeCompleted;
  172. using NameChangeTransaction::getReverseChangeCompleted;
  173. using NameChangeTransaction::setForwardChangeCompleted;
  174. using NameChangeTransaction::setReverseChangeCompleted;
  175. };
  176. /// @brief Defines a pointer to a NameChangeStubPtr instance.
  177. typedef boost::shared_ptr<NameChangeStub> NameChangeStubPtr;
  178. /// @brief Test fixture for testing NameChangeTransaction
  179. ///
  180. /// Note this class uses NameChangeStub class to exercise non-public
  181. /// aspects of NameChangeTransaction.
  182. class NameChangeTransactionTest : public ::testing::Test {
  183. public:
  184. isc::asiolink::IOService io_service_;
  185. DdnsDomainPtr forward_domain_;
  186. DdnsDomainPtr reverse_domain_;
  187. virtual ~NameChangeTransactionTest() {
  188. }
  189. /// @brief Instantiates a NameChangeStub built around a canned
  190. /// NameChangeRequest.
  191. NameChangeStubPtr makeCannedTransaction() {
  192. const char* msg_str =
  193. "{"
  194. " \"change_type\" : 0 , "
  195. " \"forward_change\" : true , "
  196. " \"reverse_change\" : true , "
  197. " \"fqdn\" : \"example.com.\" , "
  198. " \"ip_address\" : \"192.168.2.1\" , "
  199. " \"dhcid\" : \"0102030405060708\" , "
  200. " \"lease_expires_on\" : \"20130121132405\" , "
  201. " \"lease_length\" : 1300 "
  202. "}";
  203. dhcp_ddns::NameChangeRequestPtr ncr;
  204. DnsServerInfoStoragePtr servers(new DnsServerInfoStorage());
  205. DnsServerInfoPtr server;
  206. ncr = dhcp_ddns::NameChangeRequest::fromJSON(msg_str);
  207. // make forward server list
  208. server.reset(new DnsServerInfo("forward.example.com",
  209. isc::asiolink::IOAddress("1.1.1.1")));
  210. servers->push_back(server);
  211. forward_domain_.reset(new DdnsDomain("*", "", servers));
  212. // make reverse server list
  213. servers->clear();
  214. server.reset(new DnsServerInfo("reverse.example.com",
  215. isc::asiolink::IOAddress("2.2.2.2")));
  216. servers->push_back(server);
  217. reverse_domain_.reset(new DdnsDomain("*", "", servers));
  218. return (NameChangeStubPtr(new NameChangeStub(io_service_, ncr,
  219. forward_domain_, reverse_domain_)));
  220. }
  221. };
  222. /// @brief Tests NameChangeTransaction construction.
  223. /// This test verifies that:
  224. /// 1. Construction with null NameChangeRequest
  225. /// 2. Construction with null forward domain is not allowed when the request
  226. /// requires forward change.
  227. /// 3. Construction with null reverse domain is not allowed when the request
  228. /// requires reverse change.
  229. /// 4. Valid construction functions properly
  230. TEST(NameChangeTransaction, construction) {
  231. isc::asiolink::IOService io_service;
  232. const char* msg_str =
  233. "{"
  234. " \"change_type\" : 0 , "
  235. " \"forward_change\" : true , "
  236. " \"reverse_change\" : true , "
  237. " \"fqdn\" : \"example.com.\" , "
  238. " \"ip_address\" : \"192.168.2.1\" , "
  239. " \"dhcid\" : \"0102030405060708\" , "
  240. " \"lease_expires_on\" : \"20130121132405\" , "
  241. " \"lease_length\" : 1300 "
  242. "}";
  243. dhcp_ddns::NameChangeRequestPtr ncr;
  244. dhcp_ddns::NameChangeRequestPtr empty_ncr;
  245. DnsServerInfoStoragePtr servers;
  246. DdnsDomainPtr forward_domain;
  247. DdnsDomainPtr reverse_domain;
  248. DdnsDomainPtr empty_domain;
  249. ASSERT_NO_THROW(ncr = dhcp_ddns::NameChangeRequest::fromJSON(msg_str));
  250. ASSERT_NO_THROW(forward_domain.reset(new DdnsDomain("*", "", servers)));
  251. ASSERT_NO_THROW(reverse_domain.reset(new DdnsDomain("*", "", servers)));
  252. // Verify that construction with an empty NameChangeRequest throws.
  253. EXPECT_THROW(NameChangeTransaction(io_service, empty_ncr,
  254. forward_domain, reverse_domain),
  255. NameChangeTransactionError);
  256. // Verify that construction with an empty forward domain when the
  257. // NameChangeRequest calls for a forward change throws.
  258. EXPECT_THROW(NameChangeTransaction(io_service, ncr,
  259. empty_domain, reverse_domain),
  260. NameChangeTransactionError);
  261. // Verify that construction with an empty reverse domain when the
  262. // NameChangeRequest calls for a reverse change throws.
  263. EXPECT_THROW(NameChangeTransaction(io_service, ncr,
  264. forward_domain, empty_domain),
  265. NameChangeTransactionError);
  266. // Verify that a valid construction attempt works.
  267. EXPECT_NO_THROW(NameChangeTransaction(io_service, ncr,
  268. forward_domain, reverse_domain));
  269. // Verify that an empty forward domain is allowed when the requests does
  270. // not include a forward change.
  271. ncr->setForwardChange(false);
  272. ncr->setReverseChange(true);
  273. EXPECT_NO_THROW(NameChangeTransaction(io_service, ncr,
  274. empty_domain, reverse_domain));
  275. // Verify that an empty reverse domain is allowed when the requests does
  276. // not include a reverse change.
  277. ncr->setForwardChange(true);
  278. ncr->setReverseChange(false);
  279. EXPECT_NO_THROW(NameChangeTransaction(io_service, ncr,
  280. forward_domain, empty_domain));
  281. }
  282. /// @brief General testing of member accessors.
  283. /// Most if not all of these are also tested as a byproduct off larger tests.
  284. TEST_F(NameChangeTransactionTest, accessors) {
  285. NameChangeStubPtr name_change;
  286. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  287. // Verify that fetching the NameChangeRequest works.
  288. dhcp_ddns::NameChangeRequestPtr ncr = name_change->getNcr();
  289. ASSERT_TRUE(ncr);
  290. // Verify that getTransactionKey works.
  291. EXPECT_EQ(ncr->getDhcid(), name_change->getTransactionKey());
  292. // Verify that NcrStatus can be set and retrieved.
  293. EXPECT_NO_THROW(name_change->setNcrStatus(dhcp_ddns::ST_FAILED));
  294. EXPECT_EQ(dhcp_ddns::ST_FAILED, ncr->getStatus());
  295. // Verify that the forward domain can be retrieved.
  296. ASSERT_TRUE(name_change->getForwardDomain());
  297. EXPECT_EQ(forward_domain_, name_change->getForwardDomain());
  298. // Verify that the reverse domain can be retrieved.
  299. ASSERT_TRUE(name_change->getReverseDomain());
  300. EXPECT_EQ(reverse_domain_, name_change->getReverseDomain());
  301. // Neither of these have direct setters, but are tested under server
  302. // selection.
  303. EXPECT_FALSE(name_change->getDNSClient());
  304. EXPECT_FALSE(name_change->getCurrentServer());
  305. // Verify that DNS update status can be set and retrieved.
  306. EXPECT_NO_THROW(name_change->setDnsUpdateStatus(DNSClient::TIMEOUT));
  307. EXPECT_EQ(DNSClient::TIMEOUT, name_change->getDnsUpdateStatus());
  308. // Verify that the DNS update response can be retrieved.
  309. EXPECT_FALSE(name_change->getDnsUpdateResponse());
  310. // Verify that the forward change complete flag can be set and fetched.
  311. EXPECT_NO_THROW(name_change->setForwardChangeCompleted(true));
  312. EXPECT_TRUE(name_change->getForwardChangeCompleted());
  313. // Verify that the reverse change complete flag can be set and fetched.
  314. EXPECT_NO_THROW(name_change->setReverseChangeCompleted(true));
  315. EXPECT_TRUE(name_change->getReverseChangeCompleted());
  316. }
  317. /// @brief Tests event and state dictionary construction and verification.
  318. TEST_F(NameChangeTransactionTest, dictionaryCheck) {
  319. NameChangeStubPtr name_change;
  320. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  321. // Verify that the event and state dictionary validation fails prior
  322. // dictionary construction.
  323. ASSERT_THROW(name_change->verifyEvents(), StateModelError);
  324. ASSERT_THROW(name_change->verifyStates(), StateModelError);
  325. // Construct both dictionaries.
  326. ASSERT_NO_THROW(name_change->defineEvents());
  327. ASSERT_NO_THROW(name_change->defineStates());
  328. // Verify both event and state dictionaries now pass validation.
  329. ASSERT_NO_THROW(name_change->verifyEvents());
  330. ASSERT_NO_THROW(name_change->verifyStates());
  331. }
  332. /// @brief Tests server selection methods.
  333. /// Each transaction has a list of one or more servers for each DNS direction
  334. /// it is required to update. The transaction must be able to start at the
  335. /// beginning of a server list and cycle through them one at time, as needed,
  336. /// when a DNS exchange fails due to an IO error. This test verifies the
  337. /// ability to iteratively select a server from the list as the current server.
  338. TEST_F(NameChangeTransactionTest, serverSelectionTest) {
  339. NameChangeStubPtr name_change;
  340. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  341. // Verify that the forward domain and its list of servers can be retrieved.
  342. DdnsDomainPtr& domain = name_change->getForwardDomain();
  343. ASSERT_TRUE(domain);
  344. DnsServerInfoStoragePtr servers = domain->getServers();
  345. ASSERT_TRUE(servers);
  346. // Get the number of entries in the server list.
  347. int num_servers = servers->size();
  348. ASSERT_TRUE(num_servers > 0);
  349. // Verify that we can initialize server selection. This "resets" the
  350. // selection process to start over using the list of servers in the
  351. // given domain.
  352. ASSERT_NO_THROW(name_change->initServerSelection(domain));
  353. // The server selection process determines the current server,
  354. // instantiates a new DNSClient, and a DNS response message buffer.
  355. // We need to save the values before each selection, so we can verify
  356. // they are correct after each selection.
  357. DnsServerInfoPtr prev_server = name_change->getCurrentServer();
  358. DNSClientPtr prev_client = name_change->getDNSClient();
  359. D2UpdateMessagePtr prev_response = name_change->getDnsUpdateResponse();
  360. // Iteratively select through the list of servers.
  361. int passes = 0;
  362. while (name_change->selectNextServer()) {
  363. // Get the new values after the selection has been made.
  364. DnsServerInfoPtr server = name_change->getCurrentServer();
  365. DNSClientPtr client = name_change->getDNSClient();
  366. D2UpdateMessagePtr response = name_change->getDnsUpdateResponse();
  367. // Verify that the new values are not empty.
  368. EXPECT_TRUE(server);
  369. EXPECT_TRUE(client);
  370. EXPECT_TRUE(response);
  371. // Verify that the new values are indeed new.
  372. EXPECT_NE(server, prev_server);
  373. EXPECT_NE(client, prev_client);
  374. EXPECT_NE(response, prev_response);
  375. // Remember the selected values for the next pass.
  376. prev_server = server;
  377. prev_client = client;
  378. prev_response = response;
  379. ++passes;
  380. }
  381. // Verify that the number of passes made equal the number of servers.
  382. EXPECT_EQ (passes, num_servers);
  383. // Repeat the same test using the reverse domain.
  384. // Verify that the reverse domain and its list of servers can be retrieved.
  385. domain = name_change->getReverseDomain();
  386. ASSERT_TRUE(domain);
  387. servers = domain->getServers();
  388. ASSERT_TRUE(servers);
  389. // Get the number of entries in the server list.
  390. num_servers = servers->size();
  391. ASSERT_TRUE(num_servers > 0);
  392. // Verify that we can initialize server selection. This "resets" the
  393. // selection process to start over using the list of servers in the
  394. // given domain.
  395. ASSERT_NO_THROW(name_change->initServerSelection(domain));
  396. // The server selection process determines the current server,
  397. // instantiates a new DNSClient, and a DNS response message buffer.
  398. // We need to save the values before each selection, so we can verify
  399. // they are correct after each selection.
  400. prev_server = name_change->getCurrentServer();
  401. prev_client = name_change->getDNSClient();
  402. prev_response = name_change->getDnsUpdateResponse();
  403. // Iteratively select through the list of servers.
  404. passes = 0;
  405. while (name_change->selectNextServer()) {
  406. // Get the new values after the selection has been made.
  407. DnsServerInfoPtr server = name_change->getCurrentServer();
  408. DNSClientPtr client = name_change->getDNSClient();
  409. D2UpdateMessagePtr response = name_change->getDnsUpdateResponse();
  410. // Verify that the new values are not empty.
  411. EXPECT_TRUE(server);
  412. EXPECT_TRUE(client);
  413. EXPECT_TRUE(response);
  414. // Verify that the new values are indeed new.
  415. EXPECT_NE(server, prev_server);
  416. EXPECT_NE(client, prev_client);
  417. EXPECT_NE(response, prev_response);
  418. // Remember the selected values for the next pass.
  419. prev_server = server;
  420. prev_client = client;
  421. prev_response = response;
  422. ++passes;
  423. }
  424. // Verify that the number of passes made equal the number of servers.
  425. EXPECT_EQ (passes, num_servers);
  426. }
  427. /// @brief Tests that the transaction will be "failed" upon model errors.
  428. TEST_F(NameChangeTransactionTest, modelFailure) {
  429. NameChangeStubPtr name_change;
  430. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  431. // Now call runModel() with an undefined event which should not throw,
  432. // but should result in a failed model and failed transaction.
  433. EXPECT_NO_THROW(name_change->runModel(9999));
  434. // Verify that the model reports are done but failed.
  435. EXPECT_TRUE(name_change->isModelDone());
  436. EXPECT_TRUE(name_change->didModelFail());
  437. // Verify that the transaction has failed.
  438. EXPECT_EQ(dhcp_ddns::ST_FAILED, name_change->getNcrStatus());
  439. }
  440. /// @brief Tests the ability to use startTransaction to initate the state
  441. /// model execution, and DNSClient callback, operator(), to resume the
  442. /// the model with a update successful outcome.
  443. TEST_F(NameChangeTransactionTest, successfulUpdateTest) {
  444. NameChangeStubPtr name_change;
  445. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  446. EXPECT_TRUE(name_change->isModelNew());
  447. EXPECT_FALSE(name_change->getForwardChangeCompleted());
  448. // Launch the transaction by calling startTransaction. The state model
  449. // should run up until the "IO" operation is initiated in DOING_UPDATE_ST.
  450. ASSERT_NO_THROW(name_change->startTransaction());
  451. // Verify that the model is running but waiting, and that forward change
  452. // completion is still false.
  453. EXPECT_TRUE(name_change->isModelRunning());
  454. EXPECT_TRUE(name_change->isModelWaiting());
  455. EXPECT_FALSE(name_change->getForwardChangeCompleted());
  456. // Simulate completion of DNSClient exchange by invoking the callback, as
  457. // DNSClient would. This should cause the state model to progress through
  458. // completion.
  459. EXPECT_NO_THROW((*name_change)(DNSClient::SUCCESS));
  460. // The model should have worked through to completion.
  461. // Verify that the model is done and not failed.
  462. EXPECT_TRUE(name_change->isModelDone());
  463. EXPECT_FALSE(name_change->didModelFail());
  464. // Verify that NCR status is completed, and that the forward change
  465. // was completed.
  466. EXPECT_EQ(dhcp_ddns::ST_COMPLETED, name_change->getNcrStatus());
  467. EXPECT_TRUE(name_change->getForwardChangeCompleted());
  468. }
  469. /// @brief Tests the ability to use startTransaction to initate the state
  470. /// model execution, and DNSClient callback, operator(), to resume the
  471. /// the model with a update failure outcome.
  472. TEST_F(NameChangeTransactionTest, failedUpdateTest) {
  473. NameChangeStubPtr name_change;
  474. ASSERT_NO_THROW(name_change = makeCannedTransaction());
  475. // Launch the transaction by calling startTransaction. The state model
  476. // should run up until the "IO" operation is initiated in DOING_UPDATE_ST.
  477. ASSERT_NO_THROW(name_change->startTransaction());
  478. // Vefity that the model is running but waiting, and that the forward
  479. // change has not been completed.
  480. EXPECT_TRUE(name_change->isModelRunning());
  481. EXPECT_TRUE(name_change->isModelWaiting());
  482. EXPECT_FALSE(name_change->getForwardChangeCompleted());
  483. // Simulate completion of DNSClient exchange by invoking the callback, as
  484. // DNSClient would. This should cause the state model to progress through
  485. // to completion.
  486. EXPECT_NO_THROW((*name_change)(DNSClient::TIMEOUT));
  487. // The model should have worked through to completion.
  488. // Verify that the model is done and not failed.
  489. EXPECT_TRUE(name_change->isModelDone());
  490. EXPECT_FALSE(name_change->didModelFail());
  491. // Verify that the NCR status is failed and that the forward change
  492. // was not completed.
  493. EXPECT_EQ(dhcp_ddns::ST_FAILED, name_change->getNcrStatus());
  494. EXPECT_FALSE(name_change->getForwardChangeCompleted());
  495. }
  496. }