123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- // Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this
- // file, You can obtain one at http://mozilla.org/MPL/2.0/.
- #include <config.h>
- #include <asiolink/io_service.h>
- #include <process/d_log.h>
- #include <process/spec_config.h>
- #include <process/testutils/d_test_stubs.h>
- using namespace boost::asio;
- namespace isc {
- namespace process {
- // Initialize the static failure flag.
- SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure;
- // Define custom process command supported by DStubProcess.
- const char* DStubProcess::stub_proc_command_("cool_proc_cmd");
- DStubProcess::DStubProcess(const char* name, asiolink::IOServicePtr io_service)
- : DProcessBase(name, io_service, DCfgMgrBasePtr(new DStubCfgMgr())) {
- };
- void
- DStubProcess::init() {
- if (SimFailure::shouldFailOn(SimFailure::ftProcessInit)) {
- // Simulates a failure to instantiate the process.
- isc_throw(DProcessBaseError, "DStubProcess simulated init() failure");
- }
- };
- void
- DStubProcess::run() {
- // Until shut down or an fatal error occurs, wait for and
- // execute a single callback. This is a preliminary implementation
- // that is likely to evolve as development progresses.
- // To use run(), the "managing" layer must issue an io_service::stop
- // or the call to run will continue to block, and shutdown will not
- // occur.
- asiolink::IOServicePtr& io_service = getIoService();
- while (!shouldShutdown()) {
- try {
- io_service->run_one();
- } catch (const std::exception& ex) {
- isc_throw (DProcessBaseError,
- std::string("Process run method failed:") + ex.what());
- }
- }
- };
- isc::data::ConstElementPtr
- DStubProcess::shutdown(isc::data::ConstElementPtr /* args */) {
- if (SimFailure::shouldFailOn(SimFailure::ftProcessShutdown)) {
- // Simulates a failure during shutdown process.
- isc_throw(DProcessBaseError, "DStubProcess simulated shutdown failure");
- }
- setShutdownFlag(true);
- stopIOService();
- return (isc::config::createAnswer(0, "Shutdown inititiated."));
- }
- isc::data::ConstElementPtr
- DStubProcess::configure(isc::data::ConstElementPtr config_set) {
- if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
- // Simulates a process configure failure.
- return (isc::config::createAnswer(1,
- "Simulated process configuration error."));
- }
- return (getCfgMgr()->parseConfig(config_set));
- }
- isc::data::ConstElementPtr
- DStubProcess::command(const std::string& command,
- isc::data::ConstElementPtr /* args */) {
- isc::data::ConstElementPtr answer;
- if (SimFailure::shouldFailOn(SimFailure::ftProcessCommand)) {
- // Simulates a process command execution failure.
- answer = isc::config::createAnswer(COMMAND_ERROR,
- "SimFailure::ftProcessCommand");
- } else if (command.compare(stub_proc_command_) == 0) {
- answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
- } else {
- answer = isc::config::createAnswer(COMMAND_INVALID,
- "Unrecognized command:" + command);
- }
- return (answer);
- }
- DStubProcess::~DStubProcess() {
- };
- //************************** DStubController *************************
- // Define custom controller command supported by DStubController.
- const char* DStubController::stub_ctl_command_("spiffy");
- // Define custom command line option command supported by DStubController.
- const char* DStubController::stub_option_x_ = "x";
- /// @brief Defines the app name used to construct the controller
- const char* DStubController::stub_app_name_ = "TestService";
- /// @brief Defines the bin name used to construct the controller
- const char* DStubController::stub_bin_name_ = "TestBin";
- DControllerBasePtr&
- DStubController::instance() {
- // If the singleton hasn't been created, do it now.
- if (!getController()) {
- DControllerBasePtr p(new DStubController());
- setController(p);
- }
- return (getController());
- }
- DStubController::DStubController()
- : DControllerBase(stub_app_name_, stub_bin_name_),
- processed_signals_(), record_signal_only_(false), use_alternate_parser_(false) {
- if (getenv("KEA_FROM_BUILD")) {
- setSpecFileName(std::string(getenv("KEA_FROM_BUILD")) +
- "/src/bin/d2/dhcp-ddns.spec");
- } else {
- setSpecFileName(D2_SPECFILE_LOCATION);
- }
- }
- bool
- DStubController::customOption(int option, char* /* optarg */)
- {
- // Check for the custom option supported by DStubController.
- if (static_cast<char>(option) == *stub_option_x_) {
- return (true);
- }
- return (false);
- }
- DProcessBase* DStubController::createProcess() {
- if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessException)) {
- // Simulates a failure to instantiate the process due to exception.
- throw std::runtime_error("SimFailure::ftCreateProcess");
- }
- if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessNull)) {
- // Simulates a failure to instantiate the process.
- return (NULL);
- }
- // This should be a successful instantiation.
- return (new DStubProcess(getAppName().c_str(), getIOService()));
- }
- isc::data::ConstElementPtr
- DStubController::customControllerCommand(const std::string& command,
- isc::data::ConstElementPtr /* args */) {
- isc::data::ConstElementPtr answer;
- if (SimFailure::shouldFailOn(SimFailure::ftControllerCommand)) {
- // Simulates command failing to execute.
- answer = isc::config::createAnswer(COMMAND_ERROR,
- "SimFailure::ftControllerCommand");
- } else if (command.compare(stub_ctl_command_) == 0) {
- answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
- } else {
- answer = isc::config::createAnswer(COMMAND_INVALID,
- "Unrecognized command:" + command);
- }
- return (answer);
- }
- const std::string DStubController::getCustomOpts() const {
- // Return the "list" of custom options supported by DStubController.
- return (std::string(stub_option_x_));
- }
- void
- DStubController::processSignal(int signum){
- processed_signals_.push_back(signum);
- if (record_signal_only_) {
- return;
- }
- DControllerBase::processSignal(signum);
- }
- isc::data::ConstElementPtr
- DStubController::parseFile(const std::string& /*file_name*/) {
- isc::data::ConstElementPtr elements;
- if (use_alternate_parser_) {
- std::ostringstream os;
- os << "{ \"" << getController()->getAppName()
- << "\": " << std::endl;
- os << "{ \"string_test\": \"alt value\" } ";
- os << " } " << std::endl;
- elements = isc::data::Element::fromJSON(os.str());
- }
- return (elements);
- }
- DStubController::~DStubController() {
- }
- //************************** DControllerTest *************************
- void
- DControllerTest::writeFile(const std::string& content,
- const std::string& module_name) {
- std::ofstream out(CFG_TEST_FILE, std::ios::trunc);
- ASSERT_TRUE(out.is_open());
- out << "{ \"" << (!module_name.empty() ? module_name
- : getController()->getAppName())
- << "\": " << std::endl;
- out << content;
- out << " } " << std::endl;
- out.close();
- }
- void
- DControllerTest::timedWriteCallback() {
- writeFile(new_cfg_content_);
- }
- void
- DControllerTest::scheduleTimedWrite(const std::string& config,
- int write_time_ms) {
- new_cfg_content_ = config;
- write_timer_.reset(new asiolink::IntervalTimer(*getIOService()));
- write_timer_->setup(boost::bind(&DControllerTest::timedWriteCallback, this),
- write_time_ms, asiolink::IntervalTimer::ONE_SHOT);
- }
- void
- DControllerTest::runWithConfig(const std::string& config, int run_time_ms,
- time_duration& elapsed_time) {
- // Create the config file.
- writeFile(config);
- // Shutdown (without error) after runtime.
- isc::asiolink::IntervalTimer timer(*getIOService());
- timer.setup(genShutdownCallback, run_time_ms);
- // Record start time, and invoke launch().
- // We catch and rethrow to allow testing error scenarios.
- ptime start = microsec_clock::universal_time();
- try {
- // Set up valid command line arguments
- char* argv[] = { const_cast<char*>("progName"),
- const_cast<char*>("-c"),
- const_cast<char*>(DControllerTest::CFG_TEST_FILE),
- const_cast<char*>("-d") };
- launch(4, argv);
- } catch (...) {
- // calculate elasped time, then rethrow it
- elapsed_time = microsec_clock::universal_time() - start;
- throw;
- }
- elapsed_time = microsec_clock::universal_time() - start;
- }
- DProcessBasePtr
- DControllerTest:: getProcess() {
- DProcessBasePtr p;
- if (getController()) {
- p = getController()->getProcess();
- }
- return (p);
- }
- DCfgMgrBasePtr
- DControllerTest::getCfgMgr() {
- DCfgMgrBasePtr p;
- if (getProcess()) {
- p = getProcess()->getCfgMgr();
- }
- return (p);
- }
- DCfgContextBasePtr
- DControllerTest::getContext() {
- DCfgContextBasePtr p;
- if (getCfgMgr()) {
- p = getCfgMgr()->getContext();
- }
- return (p);
- }
- // Initialize controller wrapper's static instance getter member.
- DControllerTest::InstanceGetter DControllerTest::instanceGetter_ = NULL;
- /// @brief Defines the name of the configuration file to use
- const char* DControllerTest::CFG_TEST_FILE = "d2-test-config.json";
- //************************** DStubContext *************************
- DStubContext::DStubContext(): object_values_(new ObjectStorage()) {
- }
- DStubContext::~DStubContext() {
- }
- void
- DStubContext::getObjectParam(const std::string& name,
- isc::data::ConstElementPtr& value) {
- value = object_values_->getParam(name);
- }
- ObjectStoragePtr&
- DStubContext::getObjectStorage() {
- return (object_values_);
- }
- DCfgContextBasePtr
- DStubContext::clone() {
- return (DCfgContextBasePtr(new DStubContext(*this)));
- }
- DStubContext::DStubContext(const DStubContext& rhs): DCfgContextBase(rhs),
- object_values_(new ObjectStorage(*(rhs.object_values_))) {
- }
- //************************** DStubCfgMgr *************************
- DStubCfgMgr::DStubCfgMgr()
- : DCfgMgrBase(DCfgContextBasePtr(new DStubContext())) {
- }
- DStubCfgMgr::~DStubCfgMgr() {
- }
- DCfgContextBasePtr
- DStubCfgMgr::createNewContext() {
- return (DCfgContextBasePtr (new DStubContext()));
- }
- void
- DStubCfgMgr::parseElement(const std::string& element_id,
- isc::data::ConstElementPtr element) {
- DStubContextPtr context
- = boost::dynamic_pointer_cast<DStubContext>(getContext());
- if (element_id == "bool_test") {
- bool value = element->boolValue();
- context->getBooleanStorage()->setParam(element_id, value,
- element->getPosition());
- } else if (element_id == "uint32_test") {
- uint32_t value = element->intValue();
- context->getUint32Storage()->setParam(element_id, value,
- element->getPosition());
- } else if (element_id == "string_test") {
- std::string value = element->stringValue();
- context->getStringStorage()->setParam(element_id, value,
- element->getPosition());
- } else {
- // Fail only if SimFailure dictates we should. This makes it easier
- // to test parse ordering, by permitting a wide range of element ids
- // to "succeed" without specifically supporting them.
- if (SimFailure::shouldFailOn(SimFailure::ftElementUnknown)) {
- isc_throw(DCfgMgrBaseError,
- "Configuration parameter not supported: " << element_id
- << element->getPosition());
- }
- // Going to assume anything else is an object element.
- context->getObjectStorage()->setParam(element_id, element,
- element->getPosition());
- }
- parsed_order_.push_back(element_id);
- }
- }; // namespace isc::process
- }; // namespace isc
|