d_test_stubs.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. // Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <asiolink/io_service.h>
  8. #include <process/d_log.h>
  9. #include <process/spec_config.h>
  10. #include <process/testutils/d_test_stubs.h>
  11. #include <cc/command_interpreter.h>
  12. using namespace boost::asio;
  13. namespace isc {
  14. namespace process {
  15. // Initialize the static failure flag.
  16. SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure;
  17. DStubProcess::DStubProcess(const char* name, asiolink::IOServicePtr io_service)
  18. : DProcessBase(name, io_service, DCfgMgrBasePtr(new DStubCfgMgr())) {
  19. };
  20. void
  21. DStubProcess::init() {
  22. if (SimFailure::shouldFailOn(SimFailure::ftProcessInit)) {
  23. // Simulates a failure to instantiate the process.
  24. isc_throw(DProcessBaseError, "DStubProcess simulated init() failure");
  25. }
  26. };
  27. void
  28. DStubProcess::run() {
  29. // Until shut down or an fatal error occurs, wait for and
  30. // execute a single callback. This is a preliminary implementation
  31. // that is likely to evolve as development progresses.
  32. // To use run(), the "managing" layer must issue an io_service::stop
  33. // or the call to run will continue to block, and shutdown will not
  34. // occur.
  35. asiolink::IOServicePtr& io_service = getIoService();
  36. while (!shouldShutdown()) {
  37. try {
  38. io_service->run_one();
  39. } catch (const std::exception& ex) {
  40. isc_throw (DProcessBaseError,
  41. std::string("Process run method failed:") + ex.what());
  42. }
  43. }
  44. };
  45. isc::data::ConstElementPtr
  46. DStubProcess::shutdown(isc::data::ConstElementPtr /* args */) {
  47. if (SimFailure::shouldFailOn(SimFailure::ftProcessShutdown)) {
  48. // Simulates a failure during shutdown process.
  49. isc_throw(DProcessBaseError, "DStubProcess simulated shutdown failure");
  50. }
  51. setShutdownFlag(true);
  52. stopIOService();
  53. return (isc::config::createAnswer(0, "Shutdown initiated."));
  54. }
  55. isc::data::ConstElementPtr
  56. DStubProcess::configure(isc::data::ConstElementPtr config_set, bool check_only) {
  57. if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
  58. // Simulates a process configure failure.
  59. return (isc::config::createAnswer(1,
  60. "Simulated process configuration error."));
  61. }
  62. return (getCfgMgr()->parseConfig(config_set, check_only));
  63. }
  64. DStubProcess::~DStubProcess() {
  65. };
  66. //************************** DStubController *************************
  67. // Define custom command line option command supported by DStubController.
  68. const char* DStubController::stub_option_x_ = "x";
  69. /// @brief Defines the app name used to construct the controller
  70. const char* DStubController::stub_app_name_ = "TestService";
  71. /// @brief Defines the bin name used to construct the controller
  72. const char* DStubController::stub_bin_name_ = "TestBin";
  73. DControllerBasePtr&
  74. DStubController::instance() {
  75. // If the singleton hasn't been created, do it now.
  76. if (!getController()) {
  77. DControllerBasePtr p(new DStubController());
  78. setController(p);
  79. }
  80. return (getController());
  81. }
  82. DStubController::DStubController()
  83. : DControllerBase(stub_app_name_, stub_bin_name_),
  84. processed_signals_(), record_signal_only_(false), use_alternate_parser_(false) {
  85. if (getenv("KEA_FROM_BUILD")) {
  86. setSpecFileName(std::string(getenv("KEA_FROM_BUILD")) +
  87. "/src/bin/d2/dhcp-ddns.spec");
  88. } else {
  89. setSpecFileName(D2_SPECFILE_LOCATION);
  90. }
  91. }
  92. bool
  93. DStubController::customOption(int option, char* /* optarg */)
  94. {
  95. // Check for the custom option supported by DStubController.
  96. if (static_cast<char>(option) == *stub_option_x_) {
  97. return (true);
  98. }
  99. return (false);
  100. }
  101. DProcessBase* DStubController::createProcess() {
  102. if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessException)) {
  103. // Simulates a failure to instantiate the process due to exception.
  104. throw std::runtime_error("SimFailure::ftCreateProcess");
  105. }
  106. if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessNull)) {
  107. // Simulates a failure to instantiate the process.
  108. return (NULL);
  109. }
  110. // This should be a successful instantiation.
  111. return (new DStubProcess(getAppName().c_str(), getIOService()));
  112. }
  113. const std::string DStubController::getCustomOpts() const {
  114. // Return the "list" of custom options supported by DStubController.
  115. return (std::string(stub_option_x_));
  116. }
  117. void
  118. DStubController::processSignal(int signum){
  119. processed_signals_.push_back(signum);
  120. if (record_signal_only_) {
  121. return;
  122. }
  123. DControllerBase::processSignal(signum);
  124. }
  125. isc::data::ConstElementPtr
  126. DStubController::parseFile(const std::string& /*file_name*/) {
  127. isc::data::ConstElementPtr elements;
  128. if (use_alternate_parser_) {
  129. std::ostringstream os;
  130. os << "{ \"" << getController()->getAppName()
  131. << "\": " << std::endl;
  132. os << "{ \"string_test\": \"alt value\" } ";
  133. os << " } " << std::endl;
  134. elements = isc::data::Element::fromJSON(os.str());
  135. }
  136. return (elements);
  137. }
  138. DStubController::~DStubController() {
  139. }
  140. //************************** DControllerTest *************************
  141. void
  142. DControllerTest::writeFile(const std::string& content,
  143. const std::string& module_name) {
  144. std::ofstream out(CFG_TEST_FILE, std::ios::trunc);
  145. ASSERT_TRUE(out.is_open());
  146. out << "{ \"" << (!module_name.empty() ? module_name
  147. : getController()->getAppName())
  148. << "\": " << std::endl;
  149. out << content;
  150. out << " } " << std::endl;
  151. out.close();
  152. }
  153. void
  154. DControllerTest::timedWriteCallback() {
  155. writeFile(new_cfg_content_);
  156. }
  157. void
  158. DControllerTest::scheduleTimedWrite(const std::string& config,
  159. int write_time_ms) {
  160. new_cfg_content_ = config;
  161. write_timer_.reset(new asiolink::IntervalTimer(*getIOService()));
  162. write_timer_->setup(boost::bind(&DControllerTest::timedWriteCallback, this),
  163. write_time_ms, asiolink::IntervalTimer::ONE_SHOT);
  164. }
  165. void
  166. DControllerTest::runWithConfig(const std::string& config, int run_time_ms,
  167. time_duration& elapsed_time) {
  168. // Create the config file.
  169. writeFile(config);
  170. // Shutdown (without error) after runtime.
  171. isc::asiolink::IntervalTimer timer(*getIOService());
  172. timer.setup(genShutdownCallback, run_time_ms);
  173. // Record start time, and invoke launch().
  174. // We catch and rethrow to allow testing error scenarios.
  175. ptime start = microsec_clock::universal_time();
  176. try {
  177. // Set up valid command line arguments
  178. char* argv[] = { const_cast<char*>("progName"),
  179. const_cast<char*>("-c"),
  180. const_cast<char*>(DControllerTest::CFG_TEST_FILE),
  181. const_cast<char*>("-d") };
  182. launch(4, argv);
  183. } catch (...) {
  184. // calculate elapsed time, then rethrow it
  185. elapsed_time = microsec_clock::universal_time() - start;
  186. throw;
  187. }
  188. elapsed_time = microsec_clock::universal_time() - start;
  189. }
  190. DProcessBasePtr
  191. DControllerTest:: getProcess() {
  192. DProcessBasePtr p;
  193. if (getController()) {
  194. p = getController()->getProcess();
  195. }
  196. return (p);
  197. }
  198. DCfgMgrBasePtr
  199. DControllerTest::getCfgMgr() {
  200. DCfgMgrBasePtr p;
  201. if (getProcess()) {
  202. p = getProcess()->getCfgMgr();
  203. }
  204. return (p);
  205. }
  206. DCfgContextBasePtr
  207. DControllerTest::getContext() {
  208. DCfgContextBasePtr p;
  209. if (getCfgMgr()) {
  210. p = getCfgMgr()->getContext();
  211. }
  212. return (p);
  213. }
  214. // Initialize controller wrapper's static instance getter member.
  215. DControllerTest::InstanceGetter DControllerTest::instanceGetter_ = NULL;
  216. /// @brief Defines the name of the configuration file to use
  217. const char* DControllerTest::CFG_TEST_FILE = "d2-test-config.json";
  218. //************************** DStubContext *************************
  219. DStubContext::DStubContext(): object_values_(new ObjectStorage()) {
  220. }
  221. DStubContext::~DStubContext() {
  222. }
  223. void
  224. DStubContext::getObjectParam(const std::string& name,
  225. isc::data::ConstElementPtr& value) {
  226. value = object_values_->getParam(name);
  227. }
  228. ObjectStoragePtr&
  229. DStubContext::getObjectStorage() {
  230. return (object_values_);
  231. }
  232. DCfgContextBasePtr
  233. DStubContext::clone() {
  234. return (DCfgContextBasePtr(new DStubContext(*this)));
  235. }
  236. DStubContext::DStubContext(const DStubContext& rhs): DCfgContextBase(rhs),
  237. object_values_(new ObjectStorage(*(rhs.object_values_))) {
  238. }
  239. isc::data::ElementPtr
  240. DStubContext::toElement() const {
  241. return (isc::data::Element::createMap());
  242. }
  243. //************************** DStubCfgMgr *************************
  244. DStubCfgMgr::DStubCfgMgr()
  245. : DCfgMgrBase(DCfgContextBasePtr(new DStubContext())) {
  246. }
  247. DStubCfgMgr::~DStubCfgMgr() {
  248. }
  249. DCfgContextBasePtr
  250. DStubCfgMgr::createNewContext() {
  251. return (DCfgContextBasePtr (new DStubContext()));
  252. }
  253. void
  254. DStubCfgMgr::parseElement(const std::string& element_id,
  255. isc::data::ConstElementPtr element) {
  256. DStubContextPtr context
  257. = boost::dynamic_pointer_cast<DStubContext>(getContext());
  258. if (element_id == "bool_test") {
  259. bool value = element->boolValue();
  260. context->getBooleanStorage()->setParam(element_id, value,
  261. element->getPosition());
  262. } else if (element_id == "uint32_test") {
  263. uint32_t value = element->intValue();
  264. context->getUint32Storage()->setParam(element_id, value,
  265. element->getPosition());
  266. } else if (element_id == "string_test") {
  267. std::string value = element->stringValue();
  268. context->getStringStorage()->setParam(element_id, value,
  269. element->getPosition());
  270. } else {
  271. // Fail only if SimFailure dictates we should. This makes it easier
  272. // to test parse ordering, by permitting a wide range of element ids
  273. // to "succeed" without specifically supporting them.
  274. if (SimFailure::shouldFailOn(SimFailure::ftElementUnknown)) {
  275. isc_throw(DCfgMgrBaseError,
  276. "Configuration parameter not supported: " << element_id
  277. << element->getPosition());
  278. }
  279. // Going to assume anything else is an object element.
  280. context->getObjectStorage()->setParam(element_id, element,
  281. element->getPosition());
  282. }
  283. parsed_order_.push_back(element_id);
  284. }
  285. isc::data::ConstElementPtr
  286. DStubCfgMgr::parse(isc::data::ConstElementPtr /*config*/, bool /*check_only*/) {
  287. return (isc::config::createAnswer(0, "It all went fine. I promise"));
  288. }
  289. }; // namespace isc::process
  290. }; // namespace isc