d_test_stubs.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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. /// @brief Defines the app name used to construct the controller
  169. static const char* stub_app_name_;
  170. /// @brief Defines the executable name used to construct the controller
  171. static const char* stub_bin_name_;
  172. protected:
  173. /// @brief Handles additional command line options that are supported
  174. /// by DStubController. This implementation supports an option "-x".
  175. ///
  176. /// @param option is the option "character" from the command line, without
  177. /// any prefixing hyphen(s)
  178. /// @optarg optarg is the argument value (if one) associated with the option
  179. ///
  180. /// @return returns true if the option is "x", otherwise ti returns false.
  181. virtual bool customOption(int option, char *optarg);
  182. /// @brief Instantiates an instance of DStubProcess.
  183. ///
  184. /// This implementation will fail if SimFailure is set to
  185. /// ftCreateProcessException OR ftCreateProcessNull.
  186. ///
  187. /// @return returns a pointer to the new process instance (DProcessBase*)
  188. /// or NULL if SimFailure is set to ftCreateProcessNull.
  189. /// @throw throws std::runtime_error if SimFailure is set to
  190. /// ftCreateProcessException.
  191. virtual DProcessBase* createProcess();
  192. /// @brief Executes custom controller commands are supported by
  193. /// DStubController. This implementation supports one custom controller
  194. /// command, stub_ctl_command_. It will fail if SimFailure is set
  195. /// to ftControllerCommand.
  196. ///
  197. /// @param command is a string label representing the command to execute.
  198. /// @param args is a set of arguments (if any) required for the given
  199. /// command.
  200. /// @return an Element that contains the results of command composed
  201. /// of an integer status value and a string explanation of the outcome.
  202. /// The status value is:
  203. /// COMMAND_SUCCESS if the command is recognized and executes successfully.
  204. /// COMMAND_ERROR if the command is recognized but fails to execute.
  205. /// COMMAND_INVALID if the command is not recognized.
  206. virtual isc::data::ConstElementPtr customControllerCommand(
  207. const std::string& command, isc::data::ConstElementPtr args);
  208. /// @brief Provides a string of the additional command line options
  209. /// supported by DStubController. DStubController supports one
  210. /// addition option, stub_option_x_.
  211. ///
  212. /// @return returns a string containing the option letters.
  213. virtual const std::string getCustomOpts() const;
  214. private:
  215. /// @brief Constructor is private to protect singleton integrity.
  216. DStubController();
  217. public:
  218. virtual ~DStubController();
  219. };
  220. /// @brief Abstract Test fixture class that wraps a DControllerBase. This class
  221. /// is a friend class of DControllerBase which allows it access to class
  222. /// content to facilitate testing. It provides numerous wrapper methods for
  223. /// the protected and private methods and member of the base class.
  224. class DControllerTest : public ::testing::Test {
  225. public:
  226. /// @brief Defines a function pointer for controller singleton fetchers.
  227. typedef DControllerBasePtr& (*InstanceGetter)();
  228. /// @brief Static storage of the controller class's singleton fetcher.
  229. /// We need this this statically available for callbacks.
  230. static InstanceGetter instanceGetter_;
  231. /// @brief Constructor
  232. ///
  233. /// @param instance_getter is a function pointer to the static instance
  234. /// method of the DControllerBase derivation under test.
  235. DControllerTest(InstanceGetter instance_getter) {
  236. // Set the static fetcher member, then invoke it via getController.
  237. // This ensures the singleton is instantiated.
  238. instanceGetter_ = instance_getter;
  239. getController();
  240. }
  241. /// @brief Destructor
  242. /// Note the controller singleton is destroyed. This is essential to ensure
  243. /// a clean start between tests.
  244. virtual ~DControllerTest() {
  245. getController().reset();
  246. }
  247. /// @brief Convenience method that destructs and then recreates the
  248. /// controller singleton under test. This is handy for tests within
  249. /// tests.
  250. void resetController() {
  251. getController().reset();
  252. getController();
  253. }
  254. /// @brief Static method which returns the instance of the controller
  255. /// under test.
  256. /// @return returns a reference to the controller instance.
  257. static DControllerBasePtr& getController() {
  258. return ((*instanceGetter_)());
  259. }
  260. /// @brief Returns true if the Controller's app name matches the
  261. /// given value.
  262. ///
  263. /// @param should_be is the value to compare against.
  264. ///
  265. /// @return returns true if the values are equal.
  266. bool checkAppName(const std::string& should_be) {
  267. return (getController()->getAppName().compare(should_be) == 0);
  268. }
  269. /// @brief Returns true if the Controller's service name matches the
  270. /// given value.
  271. ///
  272. /// @param should_be is the value to compare against.
  273. ///
  274. /// @return returns true if the values are equal.
  275. bool checkBinName(const std::string& should_be) {
  276. return (getController()->getBinName().compare(should_be) == 0);
  277. }
  278. /// @brief Returns true if the Controller's spec file name matches the
  279. /// given value.
  280. ///
  281. /// @param should_be is the value to compare against.
  282. ///
  283. /// @return returns true if the values are equal.
  284. bool checkSpecFileName(const std::string& should_be) {
  285. return (getController()->getSpecFileName().compare(should_be) == 0);
  286. }
  287. /// @brief Tests the existence of the Controller's application process.
  288. ///
  289. /// @return returns true if the process instance exists.
  290. bool checkProcess() {
  291. return (getController()->process_);
  292. }
  293. /// @brief Tests the existence of the Controller's IOService.
  294. ///
  295. /// @return returns true if the IOService exists.
  296. bool checkIOService() {
  297. return (getController()->io_service_);
  298. }
  299. /// @brief Gets the Controller's IOService.
  300. ///
  301. /// @return returns a reference to the IOService
  302. IOServicePtr& getIOService() {
  303. return (getController()->io_service_);
  304. }
  305. /// @brief Compares stand alone flag with the given value.
  306. ///
  307. /// @param value
  308. ///
  309. /// @return returns true if the stand alone flag is equal to the given
  310. /// value.
  311. bool checkStandAlone(bool value) {
  312. return (getController()->isStandAlone() == value);
  313. }
  314. /// @brief Sets the controller's stand alone flag to the given value.
  315. ///
  316. /// @param value is the new value to assign.
  317. ///
  318. void setStandAlone(bool value) {
  319. getController()->setStandAlone(value);
  320. }
  321. /// @brief Compares verbose flag with the given value.
  322. ///
  323. /// @param value
  324. ///
  325. /// @return returns true if the verbose flag is equal to the given value.
  326. bool checkVerbose(bool value) {
  327. return (getController()->isVerbose() == value);
  328. }
  329. /// @Wrapper to invoke the Controller's parseArgs method. Please refer to
  330. /// DControllerBase::parseArgs for details.
  331. void parseArgs(int argc, char* argv[]) {
  332. getController()->parseArgs(argc, argv);
  333. }
  334. /// @Wrapper to invoke the Controller's init method. Please refer to
  335. /// DControllerBase::init for details.
  336. void initProcess() {
  337. getController()->initProcess();
  338. }
  339. /// @Wrapper to invoke the Controller's establishSession method. Please
  340. /// refer to DControllerBase::establishSession for details.
  341. void establishSession() {
  342. getController()->establishSession();
  343. }
  344. /// @Wrapper to invoke the Controller's launch method. Please refer to
  345. /// DControllerBase::launch for details.
  346. void launch(int argc, char* argv[]) {
  347. optind = 1;
  348. getController()->launch(argc, argv);
  349. }
  350. /// @Wrapper to invoke the Controller's disconnectSession method. Please
  351. /// refer to DControllerBase::disconnectSession for details.
  352. void disconnectSession() {
  353. getController()->disconnectSession();
  354. }
  355. /// @Wrapper to invoke the Controller's updateConfig method. Please
  356. /// refer to DControllerBase::updateConfig for details.
  357. isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
  358. new_config) {
  359. return (getController()->updateConfig(new_config));
  360. }
  361. /// @Wrapper to invoke the Controller's executeCommand method. Please
  362. /// refer to DControllerBase::executeCommand for details.
  363. isc::data::ConstElementPtr executeCommand(const std::string& command,
  364. isc::data::ConstElementPtr args){
  365. return (getController()->executeCommand(command, args));
  366. }
  367. /// @brief Callback that will generate shutdown command via the
  368. /// command callback function.
  369. static void genShutdownCallback() {
  370. isc::data::ElementPtr arg_set;
  371. DControllerBase::commandHandler(SHUT_DOWN_COMMAND, arg_set);
  372. }
  373. /// @brief Callback that throws an exception.
  374. static void genFatalErrorCallback() {
  375. isc_throw (DProcessBaseError, "simulated fatal error");
  376. }
  377. };
  378. }; // namespace isc::d2
  379. }; // namespace isc
  380. #endif