d2_controller_unittests.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 <config/ccsession.h>
  15. #include <d_test_stubs.h>
  16. #include <d2/d2_controller.h>
  17. #include <d2/spec_config.h>
  18. #include <boost/pointer_cast.hpp>
  19. #include <boost/date_time/posix_time/posix_time.hpp>
  20. #include <gtest/gtest.h>
  21. #include <config.h>
  22. #include <sstream>
  23. using namespace boost::posix_time;
  24. namespace isc {
  25. namespace d2 {
  26. /// @brief Test fixture class for testing D2Controller class. This class
  27. /// derives from DControllerTest and wraps a D2Controller. Much of the
  28. /// underlying functionality is in the DControllerBase class which has an
  29. /// extensive set of unit tests that are independent of DHCP-DDNS.
  30. /// @TODO Currently These tests are relatively light and duplicate some of
  31. /// the testing done on the base class. These tests are sufficient to ensure
  32. /// that D2Controller properly derives from its base class and to test the
  33. /// logic that is unique to D2Controller. These tests will be augmented and
  34. /// or new tests added as additional functionality evolves.
  35. /// Unlike the stub testing, there is no use of SimFailure to induce error
  36. /// conditions as this is production code.
  37. class D2ControllerTest : public DControllerTest {
  38. public:
  39. /// @brief Constructor
  40. /// Note the constructor passes in the static D2Controller instance
  41. /// method.
  42. D2ControllerTest() : DControllerTest(D2Controller::instance) {
  43. }
  44. /// @brief Destructor
  45. ~D2ControllerTest() {
  46. }
  47. };
  48. /// @brief Basic Controller instantiation testing.
  49. /// Verfies that the controller singleton gets created and that the
  50. /// basic derivation from the base class is intact.
  51. TEST_F(D2ControllerTest, basicInstanceTesting) {
  52. // Verify the we can the singleton instance can be fetched and that
  53. // it is the correct type.
  54. DControllerBasePtr& controller = DControllerTest::getController();
  55. ASSERT_TRUE(controller);
  56. ASSERT_NO_THROW(boost::dynamic_pointer_cast<D2Controller>(controller));
  57. // Verify that controller's app name is correct.
  58. EXPECT_TRUE(checkAppName(D2Controller::d2_app_name_));
  59. // Verify that controller's bin name is correct.
  60. EXPECT_TRUE(checkBinName(D2Controller::d2_bin_name_));
  61. // Verify that controller's spec file name is correct.
  62. EXPECT_TRUE(checkSpecFileName(D2_SPECFILE_LOCATION));
  63. // Verify that controller's IOService exists.
  64. EXPECT_TRUE(checkIOService());
  65. // Verify that the Process does NOT exist.
  66. EXPECT_FALSE(checkProcess());
  67. }
  68. /// @brief Tests basic command line processing.
  69. /// Verfies that:
  70. /// 1. Standard command line options are supported.
  71. /// 2. Invalid options are detected.
  72. TEST_F(D2ControllerTest, commandLineArgs) {
  73. char* argv[] = { const_cast<char*>("progName"),
  74. const_cast<char*>("-s"),
  75. const_cast<char*>("-v") };
  76. int argc = 3;
  77. // Verify that both flags are false initially.
  78. EXPECT_TRUE(checkStandAlone(false));
  79. EXPECT_TRUE(checkVerbose(false));
  80. // Verify that standard options can be parsed without error.
  81. EXPECT_NO_THROW(parseArgs(argc, argv));
  82. // Verify that flags are now true.
  83. EXPECT_TRUE(checkStandAlone(true));
  84. EXPECT_TRUE(checkVerbose(true));
  85. // Verify that an unknown option is detected.
  86. char* argv2[] = { const_cast<char*>("progName"),
  87. const_cast<char*>("-x") };
  88. argc = 2;
  89. EXPECT_THROW(parseArgs(argc, argv2), InvalidUsage);
  90. }
  91. /// @brief Tests application process creation and initialization.
  92. /// Verifies that the process can be successfully created and initialized.
  93. TEST_F(D2ControllerTest, initProcessTesting) {
  94. ASSERT_NO_THROW(initProcess());
  95. EXPECT_TRUE(checkProcess());
  96. }
  97. /// @brief Tests launch and normal shutdown (stand alone mode).
  98. /// This creates an interval timer to generate a normal shutdown and then
  99. /// launches with a valid, stand-alone command line and no simulated errors.
  100. TEST_F(D2ControllerTest, launchNormalShutdown) {
  101. // command line to run standalone
  102. char* argv[] = { const_cast<char*>("progName"),
  103. const_cast<char*>("-s"),
  104. const_cast<char*>("-v") };
  105. int argc = 3;
  106. // Use an asiolink IntervalTimer and callback to generate the
  107. // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
  108. isc::asiolink::IntervalTimer timer(*getIOService());
  109. timer.setup(genShutdownCallback, 2 * 1000);
  110. // Record start time, and invoke launch().
  111. ptime start = microsec_clock::universal_time();
  112. EXPECT_NO_THROW(launch(argc, argv));
  113. // Record stop time.
  114. ptime stop = microsec_clock::universal_time();
  115. // Verify that duration of the run invocation is the same as the
  116. // timer duration. This demonstrates that the shutdown was driven
  117. // by an io_service event and callback.
  118. time_duration elapsed = stop - start;
  119. EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
  120. elapsed.total_milliseconds() <= 2100);
  121. }
  122. /// @brief Configuration update event testing.
  123. /// This really tests just the ability of the handlers to invoke the necessary
  124. /// chain of methods and handle error conditions. Configuration parsing and
  125. /// retrieval should be tested as part of the d2 configuration management
  126. /// implementation. Note that this testing calls the configuration update event
  127. /// callback, configHandler, directly.
  128. /// This test verifies that:
  129. /// 1. Configuration will be rejected in integrated mode when there is no
  130. /// session established. (This is a very contrived situation).
  131. /// 2. In stand-alone mode a configuration update results in successful
  132. /// status return.
  133. /// 3. That an application process error in configuration updating is handled
  134. /// properly.
  135. TEST_F(D2ControllerTest, configUpdateTests) {
  136. int rcode = -1;
  137. isc::data::ConstElementPtr answer;
  138. // Initialize the application process.
  139. ASSERT_NO_THROW(initProcess());
  140. EXPECT_TRUE(checkProcess());
  141. // Create a configuration set. Content is arbitrary, just needs to be
  142. // valid JSON.
  143. std::string config = "{ \"test-value\": 1000 } ";
  144. isc::data::ElementPtr config_set = isc::data::Element::fromJSON(config);
  145. // We are not stand-alone, so configuration should be rejected as there is
  146. // no session. This is a pretty contrived situation that shouldn't be
  147. // possible other than the handler being called directly (like this does).
  148. answer = DControllerBase::configHandler(config_set);
  149. isc::config::parseAnswer(rcode, answer);
  150. EXPECT_EQ(1, rcode);
  151. // Verify that in stand alone we get a successful update result.
  152. setStandAlone(true);
  153. answer = DControllerBase::configHandler(config_set);
  154. isc::config::parseAnswer(rcode, answer);
  155. EXPECT_EQ(0, rcode);
  156. }
  157. /// @brief Command execution tests.
  158. /// This really tests just the ability of the handler to invoke the necessary
  159. /// chain of methods and to handle error conditions. Note that this testing
  160. /// calls the command callback, commandHandler, directly.
  161. /// This test verifies that:
  162. /// 1. That an unrecognized command is detected and returns a status of
  163. /// d2::COMMAND_INVALID.
  164. /// 2. Shutdown command is recognized and returns a d2::COMMAND_SUCCESS status.
  165. TEST_F(D2ControllerTest, executeCommandTests) {
  166. int rcode = -1;
  167. isc::data::ConstElementPtr answer;
  168. isc::data::ElementPtr arg_set;
  169. // Initialize the application process.
  170. ASSERT_NO_THROW(initProcess());
  171. EXPECT_TRUE(checkProcess());
  172. // Verify that an unknown command returns an COMMAND_INVALID response.
  173. std::string bogus_command("bogus");
  174. answer = DControllerBase::commandHandler(bogus_command, arg_set);
  175. isc::config::parseAnswer(rcode, answer);
  176. EXPECT_EQ(COMMAND_INVALID, rcode);
  177. // Verify that shutdown command returns COMMAND_SUCCESS response.
  178. //answer = executeCommand(SHUT_DOWN_COMMAND, isc::data::ElementPtr());
  179. answer = DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
  180. isc::config::parseAnswer(rcode, answer);
  181. EXPECT_EQ(COMMAND_SUCCESS, rcode);
  182. }
  183. }; // end of isc::d2 namespace
  184. }; // end of isc namespace