d_test_stubs.cc 11.4 KB
Newer Older
1
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

15
#include <d2/d2_log.h>
16 17 18 19 20 21 22 23
#include <d2/spec_config.h>
#include <d2/tests/d_test_stubs.h>

using namespace asio;

namespace isc {
namespace d2 {

24
const char* valid_d2_config = "{ "
25 26
                        "\"ip_address\" : \"127.0.0.1\" , "
                        "\"port\" : 5031, "
27 28
                        "\"tsig_keys\": ["
                        "{ \"name\": \"d2_key.tmark.org\" , "
29
                        "   \"algorithm\": \"HMAC-MD5\" ,"
30
                        "   \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\" "
31
                        "} ],"
32 33
                        "\"forward_ddns\" : {"
                        "\"ddns_domains\": [ "
34
                        "{ \"name\": \"tmark.org.\" , "
35 36 37
                        "  \"key_name\": \"d2_key.tmark.org\" , "
                        "  \"dns_servers\" : [ "
                        "  { \"hostname\": \"one.tmark\" } "
38
                        "] } ] }, "
39 40 41 42 43 44 45 46 47
                        "\"reverse_ddns\" : {"
                        "\"ddns_domains\": [ "
                        "{ \"name\": \" 0.168.192.in.addr.arpa.\" , "
                        "  \"key_name\": \"d2_key.tmark.org\" , "
                        "  \"dns_servers\" : [ "
                        "  { \"ip_address\": \"127.0.0.101\" , "
                        "    \"port\": 100 } ] } "
                        "] } }";

48
// Initialize the static failure flag.
49 50
SimFailure::FailureType SimFailure::failure_type_ = SimFailure::ftNoFailure;

51
// Define custom process command supported by DStubProcess.
52
const char*  DStubProcess::stub_proc_command_("cool_proc_cmd");
53

54
DStubProcess::DStubProcess(const char* name, IOServicePtr io_service)
55
    : DProcessBase(name, io_service, DCfgMgrBasePtr(new DStubCfgMgr())) {
56 57
};

58

59 60 61
void
DStubProcess::init() {
    if (SimFailure::shouldFailOn(SimFailure::ftProcessInit)) {
62 63
        // Simulates a failure to instantiate the process.
        isc_throw(DProcessBaseError, "DStubProcess simulated init() failure");
64 65 66
    }
};

67
void
68 69 70 71
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.
72
    // To use run(), the "managing" layer must issue an io_service::stop
73 74 75 76 77 78 79
    // or the call to run will continue to block, and shutdown will not
    // occur.
    IOServicePtr& io_service = getIoService();
    while (!shouldShutdown()) {
        try {
            io_service->run_one();
        } catch (const std::exception& ex) {
80 81
            isc_throw (DProcessBaseError,
                std::string("Process run method failed:") + ex.what());
82 83 84 85
        }
    }
};

86 87
isc::data::ConstElementPtr
DStubProcess::shutdown(isc::data::ConstElementPtr /* args */) {
88 89 90 91
    if (SimFailure::shouldFailOn(SimFailure::ftProcessShutdown)) {
        // Simulates a failure during shutdown process.
        isc_throw(DProcessBaseError, "DStubProcess simulated shutdown failure");
    }
92

93 94 95
    setShutdownFlag(true);
    stopIOService();
    return (isc::config::createAnswer(0, "Shutdown inititiated."));
96
}
97

98
isc::data::ConstElementPtr
99
DStubProcess::configure(isc::data::ConstElementPtr /*config_set*/) {
100
    if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
101
        // Simulates a process configure failure.
102 103 104 105 106 107 108
        return (isc::config::createAnswer(1,
                "Simulated process configuration error."));
    }

    return (isc::config::createAnswer(0, "Configuration accepted."));
}

109 110
isc::data::ConstElementPtr
DStubProcess::command(const std::string& command,
111
                      isc::data::ConstElementPtr /* args */) {
112 113
    isc::data::ConstElementPtr answer;
    if (SimFailure::shouldFailOn(SimFailure::ftProcessCommand)) {
114
        // Simulates a process command execution failure.
115 116
        answer = isc::config::createAnswer(COMMAND_ERROR,
                                          "SimFailure::ftProcessCommand");
117
    } else if (command.compare(stub_proc_command_) == 0) {
118 119 120 121 122 123 124 125 126 127 128 129 130 131
        answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
    } else {
        answer = isc::config::createAnswer(COMMAND_INVALID,
                                           "Unrecognized command:" + command);
    }

    return (answer);
}

DStubProcess::~DStubProcess() {
};

//************************** DStubController *************************

132
// Define custom controller command supported by DStubController.
133
const char* DStubController::stub_ctl_command_("spiffy");
134 135 136

// Define custom command line option command supported by DStubController.
const char* DStubController::stub_option_x_ = "x";
137

138 139 140 141 142 143
/// @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";

144

145 146
DControllerBasePtr&
DStubController::instance() {
147
    // If the singleton hasn't been created, do it now.
148
    if (!getController()) {
149 150
        DControllerBasePtr p(new DStubController());
        setController(p);
151 152 153 154 155 156
    }

    return (getController());
}

DStubController::DStubController()
157
    : DControllerBase(stub_app_name_, stub_bin_name_) {
158 159 160

    if (getenv("B10_FROM_BUILD")) {
        setSpecFileName(std::string(getenv("B10_FROM_BUILD")) +
161
            "/src/bin/d2/dhcp-ddns.spec");
162 163 164 165 166 167 168 169
    } else {
        setSpecFileName(D2_SPECFILE_LOCATION);
    }
}

bool
DStubController::customOption(int option, char* /* optarg */)
{
170
    // Check for the custom option supported by DStubController.
171
    if (static_cast<char>(option) == *stub_option_x_) {
172
        return (true);
173
    }
174

175 176 177 178 179
    return (false);
}

DProcessBase* DStubController::createProcess() {
    if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessException)) {
180
        // Simulates a failure to instantiate the process due to exception.
181 182 183 184
        throw std::runtime_error("SimFailure::ftCreateProcess");
    }

    if (SimFailure::shouldFailOn(SimFailure::ftCreateProcessNull)) {
185
        // Simulates a failure to instantiate the process.
186 187 188 189
        return (NULL);
    }

    // This should be a successful instantiation.
190
    return (new DStubProcess(getAppName().c_str(), getIOService()));
191 192 193 194 195 196 197
}

isc::data::ConstElementPtr
DStubController::customControllerCommand(const std::string& command,
                                     isc::data::ConstElementPtr /* args */) {
    isc::data::ConstElementPtr answer;
    if (SimFailure::shouldFailOn(SimFailure::ftControllerCommand)) {
198
        // Simulates command failing to execute.
199 200
        answer = isc::config::createAnswer(COMMAND_ERROR,
                                          "SimFailure::ftControllerCommand");
201
    } else if (command.compare(stub_ctl_command_) == 0) {
202 203 204 205 206 207 208 209 210
        answer = isc::config::createAnswer(COMMAND_SUCCESS, "Command accepted");
    } else {
        answer = isc::config::createAnswer(COMMAND_INVALID,
                                           "Unrecognized command:" + command);
    }

    return (answer);
}

211
const std::string DStubController::getCustomOpts() const {
212 213
    // Return the "list" of custom options supported by DStubController.
    return (std::string(stub_option_x_));
214 215 216 217 218
}

DStubController::~DStubController() {
}

219
// Initialize controller wrapper's static instance getter member.
220 221
DControllerTest::InstanceGetter DControllerTest::instanceGetter_ = NULL;

222 223 224
/// @brief Defines the name of the configuration file to use
const char* DControllerTest::CFG_TEST_FILE = "d2-test-config.json";

225
//************************** ObjectParser *************************
226

227 228 229
ObjectParser::ObjectParser(const std::string& param_name,
                       ObjectStoragePtr& object_values)
    : param_name_(param_name), object_values_(object_values) {
230 231
}

232
ObjectParser::~ObjectParser(){
233 234 235
}

void
236
ObjectParser::build(isc::data::ConstElementPtr new_config) {
237 238 239 240 241 242 243 244 245
    if (SimFailure::shouldFailOn(SimFailure::ftElementBuild)) {
        // Simulates an error during element data parsing.
        isc_throw (DCfgMgrBaseError, "Simulated build exception");
    }

    value_ = new_config;
}

void
246
ObjectParser::commit() {
247 248 249 250
    if (SimFailure::shouldFailOn(SimFailure::ftElementCommit)) {
        // Simulates an error while committing the parsed element data.
        throw std::runtime_error("Simulated commit exception");
    }
251 252 253

    object_values_->setParam(param_name_, value_,
                             isc::data::Element::Position());
254 255 256 257
}

//************************** DStubContext *************************

258
DStubContext::DStubContext(): object_values_(new ObjectStorage()) {
259 260 261 262 263 264
}

DStubContext::~DStubContext() {
}

void
265 266 267
DStubContext::getObjectParam(const std::string& name,
                             isc::data::ConstElementPtr& value) {
    value = object_values_->getParam(name);
268 269
}

270 271 272
ObjectStoragePtr&
DStubContext::getObjectStorage() {
    return (object_values_);
273 274
}

275
DCfgContextBasePtr
276
DStubContext::clone() {
277
    return (DCfgContextBasePtr(new DStubContext(*this)));
278 279 280
}

DStubContext::DStubContext(const DStubContext& rhs): DCfgContextBase(rhs),
281
    object_values_(new ObjectStorage(*(rhs.object_values_))) {
282 283 284 285 286 287 288 289 290 291 292
}

//************************** DStubCfgMgr *************************

DStubCfgMgr::DStubCfgMgr()
    : DCfgMgrBase(DCfgContextBasePtr(new DStubContext())) {
}

DStubCfgMgr::~DStubCfgMgr() {
}

293 294 295 296 297
DCfgContextBasePtr 
DStubCfgMgr::createNewContext() {
    return (DCfgContextBasePtr (new DStubContext()));
}

298 299
isc::dhcp::ParserPtr
DStubCfgMgr::createConfigParser(const std::string& element_id) {
300 301 302
    isc::dhcp::ParserPtr parser;
    DStubContextPtr context
        = boost::dynamic_pointer_cast<DStubContext>(getContext());
303 304

    if (element_id == "bool_test") {
305 306 307
        parser.reset(new isc::dhcp::
                         BooleanParser(element_id,
                                       context->getBooleanStorage()));
308
    } else if (element_id == "uint32_test") {
309 310
        parser.reset(new isc::dhcp::Uint32Parser(element_id,
                                                 context->getUint32Storage()));
311
    } else if (element_id == "string_test") {
312 313
        parser.reset(new isc::dhcp::StringParser(element_id,
                                                 context->getStringStorage()));
314 315 316 317 318
    } 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)) {
319 320
            isc_throw(DCfgMgrBaseError,
                      "Configuration parameter not supported: " << element_id);
321 322
        }

323 324
        // Going to assume anything else is an object element.
        parser.reset(new ObjectParser(element_id, context->getObjectStorage()));
325 326
    }

327 328
    parsed_order_.push_back(element_id);
    return (parser);
329 330
}

331
}; // namespace isc::d2
332
}; // namespace isc