d_test_stubs.cc 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
//
// 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
};

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

66
void
67 68 69 70
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.
71
    // To use run(), the "managing" layer must issue an io_service::stop
72 73 74 75 76 77 78
    // 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) {
79 80
            isc_throw (DProcessBaseError,
                std::string("Process run method failed:") + ex.what());
81 82 83 84
        }
    }
};

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

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

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

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

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

    return (answer);
}

DStubProcess::~DStubProcess() {
};

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

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

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

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

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

    return (getController());
}

DStubController::DStubController()
155
    : DControllerBase(stub_app_name_, stub_bin_name_) {
156 157 158

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

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

173 174 175 176 177
    return (false);
}

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

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

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

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

    return (answer);
}

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

DStubController::~DStubController() {
}

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

220
//************************** ObjectParser *************************
221

222 223 224
ObjectParser::ObjectParser(const std::string& param_name,
                       ObjectStoragePtr& object_values)
    : param_name_(param_name), object_values_(object_values) {
225 226
}

227
ObjectParser::~ObjectParser(){
228 229 230
}

void
231
ObjectParser::build(isc::data::ConstElementPtr new_config) {
232 233 234 235 236 237 238 239 240
    if (SimFailure::shouldFailOn(SimFailure::ftElementBuild)) {
        // Simulates an error during element data parsing.
        isc_throw (DCfgMgrBaseError, "Simulated build exception");
    }

    value_ = new_config;
}

void
241
ObjectParser::commit() {
242 243 244 245
    if (SimFailure::shouldFailOn(SimFailure::ftElementCommit)) {
        // Simulates an error while committing the parsed element data.
        throw std::runtime_error("Simulated commit exception");
    }
246 247 248

    object_values_->setParam(param_name_, value_,
                             isc::data::Element::Position());
249 250 251 252
}

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

253
DStubContext::DStubContext(): object_values_(new ObjectStorage()) {
254 255 256 257 258 259
}

DStubContext::~DStubContext() {
}

void
260 261 262
DStubContext::getObjectParam(const std::string& name,
                             isc::data::ConstElementPtr& value) {
    value = object_values_->getParam(name);
263 264
}

265 266 267
ObjectStoragePtr&
DStubContext::getObjectStorage() {
    return (object_values_);
268 269
}

270
DCfgContextBasePtr
271
DStubContext::clone() {
272
    return (DCfgContextBasePtr(new DStubContext(*this)));
273 274 275
}

DStubContext::DStubContext(const DStubContext& rhs): DCfgContextBase(rhs),
276
    object_values_(new ObjectStorage(*(rhs.object_values_))) {
277 278 279 280 281 282 283 284 285 286 287
}

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

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

DStubCfgMgr::~DStubCfgMgr() {
}

288 289 290 291 292
DCfgContextBasePtr 
DStubCfgMgr::createNewContext() {
    return (DCfgContextBasePtr (new DStubContext()));
}

293 294
isc::dhcp::ParserPtr
DStubCfgMgr::createConfigParser(const std::string& element_id) {
295 296 297
    isc::dhcp::ParserPtr parser;
    DStubContextPtr context
        = boost::dynamic_pointer_cast<DStubContext>(getContext());
298 299

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

318 319
        // Going to assume anything else is an object element.
        parser.reset(new ObjectParser(element_id, context->getObjectStorage()));
320 321
    }

322 323
    parsed_order_.push_back(element_id);
    return (parser);
324 325
}

326
}; // namespace isc::d2
327
}; // namespace isc