d_test_stubs.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. #ifndef D_TEST_STUBS_H
  15. #define D_TEST_STUBS_H
  16. #include <asiolink/asiolink.h>
  17. #include <cc/data.h>
  18. #include <cc/session.h>
  19. #include <config/ccsession.h>
  20. #include <d2/d_controller.h>
  21. #include <gtest/gtest.h>
  22. namespace isc {
  23. namespace d2 {
  24. /// @brief Class is used to set a globally accessible value that indicates
  25. /// a specific type of failure to simulate. Test derivations of base classes
  26. /// can exercise error handling code paths by testing for specific SimFailure
  27. /// values at the appropriate places and then causing the error to "occur".
  28. /// The class consists of an enumerated set of failures, and static methods
  29. /// for getting, setting, and testing the current value.
  30. class SimFailure {
  31. public:
  32. enum FailureType {
  33. ftUnknown = -1,
  34. ftNoFailure = 0,
  35. ftCreateProcessException,
  36. ftCreateProcessNull,
  37. ftProcessInit,
  38. ftProcessConfigure,
  39. ftControllerCommand,
  40. ftProcessCommand,
  41. ftProcessShutdown
  42. };
  43. /// @brief Sets the SimFailure value to the given value.
  44. ///
  45. /// @param value is the new value to assign to the global value.
  46. static void set(enum FailureType value) {
  47. failure_type_ = value;
  48. }
  49. /// @brief Gets the current global SimFailure value
  50. ///
  51. /// @return returns the current SimFailure value
  52. static enum FailureType get() {
  53. return (failure_type_);
  54. }
  55. /// @brief One-shot test of the SimFailure value. If the global
  56. /// SimFailure value is equal to the given value, clear the global
  57. /// value and return true. This makes it convenient for code to
  58. /// test and react without having to explicitly clear the global
  59. /// value.
  60. ///
  61. /// @param value is the value against which the global value is
  62. /// to be compared.
  63. ///
  64. /// @return returns true if current SimFailure value matches the
  65. /// given value.
  66. static bool shouldFailOn(enum FailureType value) {
  67. if (failure_type_ == value) {
  68. clear();
  69. return (true);
  70. }
  71. return (false);
  72. }
  73. static void clear() {
  74. failure_type_ = ftNoFailure;
  75. }
  76. static enum FailureType failure_type_;
  77. };
  78. /// @brief Test Derivation of the DProcessBase class.
  79. ///
  80. /// This class is used primarily to server as a test process class for testing
  81. /// DControllerBase. It provides minimal, but sufficient implementation to
  82. /// test the majority of DControllerBase functionality.
  83. class DStubProcess : public DProcessBase {
  84. public:
  85. /// @brief Static constant that defines a custom process command string.
  86. static const char* stub_proc_command_;
  87. /// @brief Constructor
  88. ///
  89. /// @param name name is a text label for the process. Generally used
  90. /// in log statements, but otherwise arbitrary.
  91. /// @param io_service is the io_service used by the caller for
  92. /// asynchronous event handling.
  93. ///
  94. /// @throw DProcessBaseError is io_service is NULL.
  95. DStubProcess(const char* name, IOServicePtr io_service);
  96. /// @brief Invoked after process instantiation to perform initialization.
  97. /// This implementation supports simulating an error initializing the
  98. /// process by throwing a DProcessBaseError if SimFailure is set to
  99. /// ftProcessInit.
  100. virtual void init();
  101. /// @brief Implements the process's event loop.
  102. /// This implementation is quite basic, surrounding calls to
  103. /// io_service->runOne() with a test of the shutdown flag. Once invoked,
  104. /// the method will continue until the process itself is exiting due to a
  105. /// request to shutdown or some anomaly forces an exit.
  106. /// @return returns 0 upon a successful, "normal" termination, non-zero to
  107. /// indicate an abnormal termination.
  108. virtual void run();
  109. /// @brief Implements the process shutdown procedure. Currently this is
  110. /// limited to setting the instance shutdown flag, which is monitored in
  111. /// run().
  112. virtual void shutdown();
  113. /// @brief Processes the given configuration.
  114. ///
  115. /// This implementation fails if SimFailure is set to ftProcessConfigure.
  116. /// Otherwise it will complete successfully. It does not check the content
  117. /// of the inbound configuration.
  118. ///
  119. /// @param config_set a new configuration (JSON) for the process
  120. /// @return an Element that contains the results of configuration composed
  121. /// of an integer status value (0 means successful, non-zero means failure),
  122. /// and a string explanation of the outcome.
  123. virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
  124. config_set);
  125. /// @brief Executes the given command.
  126. ///
  127. /// This implementation will recognizes one "custom" process command,
  128. /// stub_proc_command_. It will fail if SimFailure is set to
  129. /// ftProcessCommand.
  130. ///
  131. /// @param command is a string label representing the command to execute.
  132. /// @param args is a set of arguments (if any) required for the given
  133. /// command.
  134. /// @return an Element that contains the results of command composed
  135. /// of an integer status value and a string explanation of the outcome.
  136. /// The status value is:
  137. /// COMMAND_SUCCESS if the command is recognized and executes successfully.
  138. /// COMMAND_ERROR if the command is recognized but fails to execute.
  139. /// COMMAND_INVALID if the command is not recognized.
  140. virtual isc::data::ConstElementPtr command(const std::string& command,
  141. isc::data::ConstElementPtr args);
  142. // @brief Destructor
  143. virtual ~DStubProcess();
  144. };
  145. /// @brief Test Derivation of the DControllerBase class.
  146. ///
  147. /// DControllerBase is an abstract class and therefore requires a derivation
  148. /// for testing. It allows testing the majority of the base class code
  149. /// without polluting production derivations (e.g. D2Process). It uses
  150. /// DStubProcess as its application process class. It is a full enough
  151. /// implementation to support running both stand alone and integrated.
  152. /// Obviously BIND10 connectivity is not available under unit tests, so
  153. /// testing here is limited to "failures" to communicate with BIND10.
  154. class DStubController : public DControllerBase {
  155. public:
  156. /// @brief Static singleton instance method. This method returns the
  157. /// base class singleton instance member. It instantiates the singleton
  158. /// and sets the base class instance member upon first invocation.
  159. ///
  160. /// @return returns a pointer reference to the singleton instance.
  161. static DControllerBasePtr& instance();
  162. /// @brief Defines a custom controller command string. This is a
  163. /// custom command supported by DStubController.
  164. static const char* stub_ctl_command_;
  165. /// @brief Defines a custom command line option supported by
  166. /// DStubController.
  167. static const char* stub_option_x_;
  168. protected:
  169. /// @brief Handles additional command line options that are supported
  170. /// by DStubController. This implementation supports an option "-x".
  171. ///
  172. /// @param option is the option "character" from the command line, without
  173. /// any prefixing hyphen(s)
  174. /// @optarg optarg is the argument value (if one) associated with the option
  175. ///
  176. /// @return returns true if the option is "x", otherwise ti returns false.
  177. virtual bool customOption(int option, char *optarg);
  178. /// @brief Instantiates an instance of DStubProcess.
  179. ///
  180. /// This implementation will fail if SimFailure is set to
  181. /// ftCreateProcessException OR ftCreateProcessNull.
  182. ///
  183. /// @return returns a pointer to the new process instance (DProcessBase*)
  184. /// or NULL if SimFailure is set to ftCreateProcessNull.
  185. /// @throw throws std::runtime_error if SimFailure is set to
  186. /// ftCreateProcessException.
  187. virtual DProcessBase* createProcess();
  188. /// @brief Executes custom controller commands are supported by
  189. /// DStubController. This implementation supports one custom controller
  190. /// command, stub_ctl_command_. It will fail if SimFailure is set
  191. /// to ftControllerCommand.
  192. ///
  193. /// @param command is a string label representing the command to execute.
  194. /// @param args is a set of arguments (if any) required for the given
  195. /// command.
  196. /// @return an Element that contains the results of command composed
  197. /// of an integer status value and a string explanation of the outcome.
  198. /// The status value is:
  199. /// COMMAND_SUCCESS if the command is recognized and executes successfully.
  200. /// COMMAND_ERROR if the command is recognized but fails to execute.
  201. /// COMMAND_INVALID if the command is not recognized.
  202. virtual isc::data::ConstElementPtr customControllerCommand(
  203. const std::string& command, isc::data::ConstElementPtr args);
  204. /// @brief Provides a string of the additional command line options
  205. /// supported by DStubController. DStubController supports one
  206. /// addition option, stub_option_x_.
  207. ///
  208. /// @return returns a string containing the option letters.
  209. virtual const std::string getCustomOpts() const;
  210. private:
  211. /// @brief Constructor is private to protect singleton integrity.
  212. DStubController();
  213. public:
  214. virtual ~DStubController();
  215. };
  216. /// @brief Abstract Test fixture class that wraps a DControllerBase. This class
  217. /// is a friend class of DControllerBase which allows it access to class
  218. /// content to facilitate testing. It provides numerous wrapper methods for
  219. /// the protected and private methods and member of the base class.
  220. class DControllerTest : public ::testing::Test {
  221. public:
  222. /// @brief Defines a function pointer for controller singleton fetchers.
  223. typedef DControllerBasePtr& (*InstanceGetter)();
  224. /// @brief Static storage of the controller class's singleton fetcher.
  225. /// We need this this statically available for callbacks.
  226. static InstanceGetter instanceGetter_;
  227. /// @brief Constructor
  228. ///
  229. /// @param instance_getter is a function pointer to the static instance
  230. /// method of the DControllerBase derivation under test.
  231. DControllerTest(InstanceGetter instance_getter) {
  232. // Set the static fetcher member, then invoke it via getController.
  233. // This ensures the singleton is instantiated.
  234. instanceGetter_ = instance_getter;
  235. getController();
  236. }
  237. /// @brief Destructor
  238. /// Note the controller singleton is destroyed. This is essential to ensure
  239. /// a clean start between tests.
  240. virtual ~DControllerTest() {
  241. getController().reset();
  242. }
  243. /// @brief Convenience method that destructs and then recreates the
  244. /// controller singleton under test. This is handy for tests within
  245. /// tests.
  246. void resetController() {
  247. getController().reset();
  248. getController();
  249. }
  250. /// @brief Static method which returns the instance of the controller
  251. /// under test.
  252. /// @return returns a reference to the controller instance.
  253. static DControllerBasePtr& getController() {
  254. return ((*instanceGetter_)());
  255. }
  256. /// @brief Returns true if the Controller's name matches the given value.
  257. ///
  258. /// @param should_be is the value to compare against.
  259. ///
  260. /// @return returns true if the values are equal.
  261. bool checkName(const std::string& should_be) {
  262. return (getController()->getName().compare(should_be) == 0);
  263. }
  264. /// @brief Returns true if the Controller's spec file name matches the
  265. /// given value.
  266. ///
  267. /// @param should_be is the value to compare against.
  268. ///
  269. /// @return returns true if the values are equal.
  270. bool checkSpecFileName(const std::string& should_be) {
  271. return (getController()->getSpecFileName().compare(should_be) == 0);
  272. }
  273. /// @brief Tests the existence of the Controller's application process.
  274. ///
  275. /// @return returns true if the process instance exists.
  276. bool checkProcess() {
  277. return (getController()->process_);
  278. }
  279. /// @brief Tests the existence of the Controller's IOService.
  280. ///
  281. /// @return returns true if the IOService exists.
  282. bool checkIOService() {
  283. return (getController()->io_service_);
  284. }
  285. /// @brief Gets the Controller's IOService.
  286. ///
  287. /// @return returns a reference to the IOService
  288. IOServicePtr& getIOService() {
  289. return (getController()->io_service_);
  290. }
  291. /// @brief Compares stand alone flag with the given value.
  292. ///
  293. /// @param value
  294. ///
  295. /// @return returns true if the stand alone flag is equal to the given
  296. /// value.
  297. bool checkStandAlone(bool value) {
  298. return (getController()->isStandAlone() == value);
  299. }
  300. /// @brief Sets the controller's stand alone flag to the given value.
  301. ///
  302. /// @param value is the new value to assign.
  303. ///
  304. void setStandAlone(bool value) {
  305. getController()->setStandAlone(value);
  306. }
  307. /// @brief Compares verbose flag with the given value.
  308. ///
  309. /// @param value
  310. ///
  311. /// @return returns true if the verbose flag is equal to the given value.
  312. bool checkVerbose(bool value) {
  313. return (getController()->isVerbose() == value);
  314. }
  315. /// @Wrapper to invoke the Controller's parseArgs method. Please refer to
  316. /// DControllerBase::parseArgs for details.
  317. void parseArgs(int argc, char* argv[]) {
  318. getController()->parseArgs(argc, argv);
  319. }
  320. /// @Wrapper to invoke the Controller's init method. Please refer to
  321. /// DControllerBase::init for details.
  322. void initProcess() {
  323. getController()->initProcess();
  324. }
  325. /// @Wrapper to invoke the Controller's establishSession method. Please
  326. /// refer to DControllerBase::establishSession for details.
  327. void establishSession() {
  328. getController()->establishSession();
  329. }
  330. /// @Wrapper to invoke the Controller's launch method. Please refer to
  331. /// DControllerBase::launch for details.
  332. void launch(int argc, char* argv[]) {
  333. optind = 1;
  334. getController()->launch(argc, argv);
  335. }
  336. /// @Wrapper to invoke the Controller's disconnectSession method. Please
  337. /// refer to DControllerBase::disconnectSession for details.
  338. void disconnectSession() {
  339. getController()->disconnectSession();
  340. }
  341. /// @Wrapper to invoke the Controller's updateConfig method. Please
  342. /// refer to DControllerBase::updateConfig for details.
  343. isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
  344. new_config) {
  345. return (getController()->updateConfig(new_config));
  346. }
  347. /// @Wrapper to invoke the Controller's executeCommand method. Please
  348. /// refer to DControllerBase::executeCommand for details.
  349. isc::data::ConstElementPtr executeCommand(const std::string& command,
  350. isc::data::ConstElementPtr args){
  351. return (getController()->executeCommand(command, args));
  352. }
  353. /// @brief Callback that will generate shutdown command via the
  354. /// command callback function.
  355. static void genShutdownCallback() {
  356. isc::data::ElementPtr arg_set;
  357. DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
  358. }
  359. /// @brief Callback that throws an exception.
  360. static void genFatalErrorCallback() {
  361. isc_throw (DProcessBaseError, "simulated fatal error");
  362. }
  363. };
  364. }; // namespace isc::d2
  365. }; // namespace isc
  366. #endif