BIND 10 master, updated. dbe4772246039a1257b6492936fda2a8600cd245 [master] Merge branch 2955 which adds D2Process and DProcessBase to bin/src/D2.
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu May 30 12:35:13 UTC 2013
The branch, master has been updated
via dbe4772246039a1257b6492936fda2a8600cd245 (commit)
via ece829ff0b6b5117ecdfe22439c24b64a8523683 (commit)
via a9b9f641970b7f2db1b1183fab3deaec454b5b75 (commit)
via d7fe718898c7a8d1fbcebd4a4d47548d08ae1d98 (commit)
via b70a49c18a153f40aaf129d6d3f25039e052e887 (commit)
via 419690bf77f83061c4df46291b27a2a5769e1758 (commit)
via cddad16de73088a9e11330746e33a1faed947f64 (commit)
from 72b428b6f9178a08d8e5bf68062b4082bf0b8429 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit dbe4772246039a1257b6492936fda2a8600cd245
Merge: 72b428b ece829f
Author: Thomas Markwalder <tmark at isc.org>
Date: Thu May 30 08:32:59 2013 -0400
[master] Merge branch 2955 which adds D2Process and DProcessBase
to bin/src/D2.
-----------------------------------------------------------------------
Summary of changes:
src/bin/d2/Makefile.am | 5 +
src/bin/d2/d2_messages.mes | 38 +++++--
src/bin/d2/d2_process.cc | 89 ++++++++++++++++
src/bin/d2/d2_process.h | 98 ++++++++++++++++++
src/bin/d2/d_process.h | 151 +++++++++++++++++++++++++++
src/bin/d2/main.cc | 8 +-
src/bin/d2/tests/Makefile.am | 6 ++
src/bin/d2/tests/d2_process_unittests.cc | 166 ++++++++++++++++++++++++++++++
src/bin/d2/tests/d2_test.py | 2 +-
9 files changed, 548 insertions(+), 15 deletions(-)
create mode 100644 src/bin/d2/d2_process.cc
create mode 100644 src/bin/d2/d2_process.h
create mode 100644 src/bin/d2/d_process.h
create mode 100644 src/bin/d2/tests/d2_process_unittests.cc
-----------------------------------------------------------------------
diff --git a/src/bin/d2/Makefile.am b/src/bin/d2/Makefile.am
index 54300c6..8829764 100644
--- a/src/bin/d2/Makefile.am
+++ b/src/bin/d2/Makefile.am
@@ -48,12 +48,17 @@ pkglibexec_PROGRAMS = b10-d2
b10_d2_SOURCES = main.cc
b10_d2_SOURCES += d2_log.cc d2_log.h
+b10_d2_SOURCES += d_process.h
+b10_d2_SOURCES += d2_process.cc d2_process.h
nodist_b10_d2_SOURCES = d2_messages.h d2_messages.cc
EXTRA_DIST += d2_messages.mes
b10_d2_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
b10_d2_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+b10_d2_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+b10_d2_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
+b10_d2_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
b10_d2dir = $(pkgdatadir)
b10_d2_DATA = d2.spec
diff --git a/src/bin/d2/d2_messages.mes b/src/bin/d2/d2_messages.mes
index 08afb9c..804b2cb 100644
--- a/src/bin/d2/d2_messages.mes
+++ b/src/bin/d2/d2_messages.mes
@@ -14,15 +14,35 @@
$NAMESPACE isc::d2
-% D2_STARTING : process starting
-This is a debug message issued during a D2 process startup.
+% D2CTL_STARTING DHCP-DDNS controller starting, pid: %1
+This is an informational message issued when controller for DHCP-DDNS
+service first starts.
-% D2_START_INFO pid: %1, verbose: %2, standalone: %3
-This is a debug message issued during the D2 process startup.
-It lists some information about the parameters with which the
-process is running.
+% D2CTL_STOPPING DHCP-DDNS controller is exiting
+This is an informational message issued when the controller is exiting
+following a shut down (normal or otherwise) of the DDHCP-DDNS process.
-% D2_SHUTDOWN : process is performing a normal shutting down
-This is a debug message issued when a D2 process shuts down
-normally in response to command to stop.
+% D2PRC_SHUTDOWN DHCP-DDNS process is performing a normal shut down
+This is a debug message issued when the service process has been instructed
+to shut down by the controller.
+
+% D2PRC_RUN_ENTER process has entered the event loop
+This is a debug message issued when the D2 process enters it's
+run method.
+
+% D2PRC_RUN_EXIT process is exiting the event loop
+This is a debug message issued when the D2 process exits the
+in event loop.
+
+% D2PRC_FAILED process experienced a fatal error: %1
+This is a debug message issued when the D2 process encounters an
+unrecoverable error from within the event loop.
+
+% D2PRC_CONFIGURE new configuration received: %1
+This is a debug message issued when the D2 process configure method
+has been invoked.
+
+% D2PRC_COMMAND command directive received, command: %1 - args: %2
+This is a debug message issued when the D2 process command method
+has been invoked.
diff --git a/src/bin/d2/d2_process.cc b/src/bin/d2/d2_process.cc
new file mode 100644
index 0000000..4fd420b
--- /dev/null
+++ b/src/bin/d2/d2_process.cc
@@ -0,0 +1,89 @@
+// 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.
+
+#include <config/ccsession.h>
+#include <d2/d2_log.h>
+#include <d2/d2_process.h>
+
+using namespace asio;
+
+namespace isc {
+namespace d2 {
+
+D2Process::D2Process(const char* name, IOServicePtr io_service)
+ : DProcessBase(name, io_service) {
+};
+
+void
+D2Process::init() {
+};
+
+int
+D2Process::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.
+ LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_ENTER);
+ IOServicePtr& io_service = getIoService();
+ while (!shouldShutdown()) {
+ try {
+ io_service->run_one();
+ } catch (const std::exception& ex) {
+ LOG_FATAL(d2_logger, D2PRC_FAILED).arg(ex.what());
+ return (EXIT_FAILURE);
+ }
+ }
+
+ LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_RUN_EXIT);
+ return (EXIT_SUCCESS);
+};
+
+int
+D2Process::shutdown() {
+ LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2PRC_SHUTDOWN);
+ setShutdownFlag(true);
+ return (0);
+}
+
+isc::data::ConstElementPtr
+D2Process::configure(isc::data::ConstElementPtr config_set) {
+ // @TODO This is the initial implementation which simply accepts
+ // any content in config_set as valid. This is sufficient to
+ // allow participation as a BIND10 module, while D2 configuration support
+ // is being developed.
+ LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
+ D2PRC_CONFIGURE).arg(config_set->str());
+
+ return (isc::config::createAnswer(0, "Configuration accepted."));
+}
+
+isc::data::ConstElementPtr
+D2Process::command(const std::string& command, isc::data::ConstElementPtr args){
+ // @TODO This is the initial implementation. If and when D2 is extended
+ // to support its own commands, this implementation must change. Otherwise
+ // it should reject all commands as it does now.
+ LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
+ D2PRC_COMMAND).arg(command).arg(args->str());
+
+ return (isc::config::createAnswer(1, "Unrecognized command:" + command));
+}
+
+D2Process::~D2Process() {
+};
+
+}; // namespace isc::d2
+}; // namespace isc
diff --git a/src/bin/d2/d2_process.h b/src/bin/d2/d2_process.h
new file mode 100644
index 0000000..4d6d36b
--- /dev/null
+++ b/src/bin/d2/d2_process.h
@@ -0,0 +1,98 @@
+// 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.
+
+#ifndef D2_PROCESS_H
+#define D2_PROCESS_H
+
+#include <d2/d_process.h>
+
+namespace isc {
+namespace d2 {
+
+/// @brief @TODO DHCP-DDNS Application Process
+///
+/// D2Process provides the top level application logic for DHCP-driven DDNS
+/// update processing. It provides the asynchronous event processing required
+/// to receive DNS mapping change requests and carry them out.
+/// It implements the DProcessBase interface, which structures it such that it
+/// is a managed "application", controlled by a management layer.
+
+class D2Process : public DProcessBase {
+public:
+ /// @brief Constructor
+ ///
+ /// @param name name is a text label for the process. Generally used
+ /// in log statements, but otherwise arbitrary.
+ /// @param io_service is the io_service used by the caller for
+ /// asynchronous event handling.
+ ///
+ /// @throw DProcessBaseError is io_service is NULL.
+ D2Process(const char* name, IOServicePtr io_service);
+
+ /// @brief Will be used after instantiation to perform initialization
+ /// unique to D2. This will likely include interactions with QueueMgr and
+ /// UpdateMgr, to prepare for request receipt and processing.
+ virtual void init();
+
+ /// @brief Implements the process's event loop.
+ /// The initial implementation is quite basic, surrounding calls to
+ /// io_service->runOne() with a test of the shutdown flag.
+ /// Once invoked, the method will continue until the process itself is
+ /// exiting due to a request to shutdown or some anomaly forces an exit.
+ /// @return returns 0 upon a successful, "normal" termination, non
+ /// zero to indicate an abnormal termination.
+ virtual int run();
+
+ // @TODO need brief
+ virtual int shutdown();
+
+ // @TODO need brief
+ /// @brief Processes the given configuration.
+ ///
+ /// This method may be called multiple times during the process lifetime.
+ /// Certainly once during process startup, and possibly later if the user
+ /// alters configuration. This method must not throw, it should catch any
+ /// processing errors and return a success or failure answer as described
+ /// below.
+ ///
+ /// @param config_set a new configuration (JSON) for the process
+ /// @return an Element that contains the results of configuration composed
+ /// of an integer status value (0 means successful, non-zero means failure),
+ /// and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
+ config_set);
+
+ // @TODO need brief
+ /// @brief Processes the given command.
+ ///
+ /// This method is called to execute any custom commands supported by the
+ /// process. This method must not throw, it should catch any processing
+ /// errors and return a success or failure answer as described below.
+ ///
+ /// @param command is a string label representing the command to execute.
+ /// @param args is a set of arguments (if any) required for the given
+ /// command.
+ /// @return an Element that contains the results of command composed
+ /// of an integer status value (0 means successful, non-zero means failure),
+ /// and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr command(const std::string& command,
+ isc::data::ConstElementPtr args);
+ // @TODO need brief
+ virtual ~D2Process();
+};
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif
diff --git a/src/bin/d2/d_process.h b/src/bin/d2/d_process.h
new file mode 100644
index 0000000..5c8e50e
--- /dev/null
+++ b/src/bin/d2/d_process.h
@@ -0,0 +1,151 @@
+// 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.
+
+#ifndef D_PROCESS_H
+#define D_PROCESS_H
+
+#include <asiolink/asiolink.h>
+#include <cc/data.h>
+#include <boost/shared_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+
+typedef boost::shared_ptr<isc::asiolink::IOService> IOServicePtr;
+
+namespace isc {
+namespace d2 {
+
+/// @brief Exception thrown if the process encountered an operational error.
+class DProcessBaseError : public isc::Exception {
+public:
+ DProcessBaseError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Application Process Interface
+///
+/// DProcessBase is an abstract class represents the primary "application"
+/// level object in a "managed" asynchronous application. It provides a uniform
+/// interface such that a managing layer can construct, intialize, and start
+/// the application's event loop. The event processing is centered around the
+/// use of isc::asiolink::io_service. The io_service is shared between the
+/// the managing layer and the DProcessBase. This allows management layer IO
+/// such as directives to be sensed and handled, as well as processing IO
+/// activity specific to the application. In terms of management layer IO,
+/// there are methods shutdown, configuration updates, and commands unique
+/// to the application.
+class DProcessBase {
+public:
+ /// @brief Constructor
+ ///
+ /// @param name name is a text label for the process. Generally used
+ /// in log statements, but otherwise arbitrary.
+ /// @param io_service is the io_service used by the caller for
+ /// asynchronous event handling.
+ ///
+ /// @throw DProcessBaseError is io_service is NULL.
+ DProcessBase(const char* name, IOServicePtr io_service) : name_(name),
+ io_service_(io_service), shut_down_flag_(false) {
+
+ if (!io_service_) {
+ isc_throw (DProcessBaseError, "IO Service cannot be null");
+ }
+ };
+
+ /// @brief May be used after instantiation to perform initialization unique
+ /// to application. It must be invoked prior to invoking run. This would
+ /// likely include the creation of additional IO sources and their
+ /// integration into the io_service.
+ virtual void init() = 0;
+
+ /// @brief Implements the process's event loop. In its simplest form it
+ /// would an invocation io_service_->run(). This method should not exit
+ /// until the process itself is exiting due to a request to shutdown or
+ /// some anomaly is forcing an exit.
+ /// @return returns EXIT_SUCCESS upon a successful, normal termination,
+ /// and EXIT_FAILURE to indicate an abnormal termination.
+ virtual int run() = 0;
+
+ /// @brief Implements the process's shutdown processing. When invoked, it
+ /// should ensure that the process gracefully exits the run method.
+ virtual int shutdown() = 0;
+
+ /// @brief Processes the given configuration.
+ ///
+ /// This method may be called multiple times during the process lifetime.
+ /// Certainly once during process startup, and possibly later if the user
+ /// alters configuration. This method must not throw, it should catch any
+ /// processing errors and return a success or failure answer as described
+ /// below.
+ ///
+ /// @param config_set a new configuration (JSON) for the process
+ /// @return an Element that contains the results of configuration composed
+ /// of an integer status value (0 means successful, non-zero means failure),
+ /// and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr configure(isc::data::ConstElementPtr
+ config_set) = 0;
+
+ /// @brief Processes the given command.
+ ///
+ /// This method is called to execute any custom commands supported by the
+ /// process. This method must not throw, it should catch any processing
+ /// errors and return a success or failure answer as described below.
+ ///
+ /// @param command is a string label representing the command to execute.
+ /// @param args is a set of arguments (if any) required for the given
+ /// command.
+ /// @return an Element that contains the results of command composed
+ /// of an integer status value (0 means successful, non-zero means failure),
+ /// and a string explanation of the outcome.
+ virtual isc::data::ConstElementPtr command(
+ const std::string& command, isc::data::ConstElementPtr args) = 0;
+
+ /// @brief Destructor
+ virtual ~DProcessBase(){};
+
+ bool shouldShutdown() {
+ return (shut_down_flag_);
+ }
+
+ void setShutdownFlag(bool value) {
+ shut_down_flag_ = value;
+ }
+
+ const std::string& getName() const {
+ return (name_);
+ }
+
+ IOServicePtr& getIoService() {
+ return (io_service_);
+ }
+
+private:
+ /// @brief Text label for the process. Generally used in log statements,
+ /// but otherwise can be arbitrary.
+ std::string name_;
+
+ /// @brief The IOService to be used for asynchronous event handling.
+ IOServicePtr io_service_;
+
+ /// @brief Boolean flag set when shutdown has been requested.
+ bool shut_down_flag_;
+};
+
+/// @brief Defines a shared pointer to DProcessBase.
+typedef boost::shared_ptr<DProcessBase> DProcessBasePtr;
+
+}; // namespace isc::d2
+}; // namespace isc
+
+#endif
diff --git a/src/bin/d2/main.cc b/src/bin/d2/main.cc
index 7ef300b..5658a8a 100644
--- a/src/bin/d2/main.cc
+++ b/src/bin/d2/main.cc
@@ -82,16 +82,14 @@ main(int argc, char* argv[]) {
((verbose_mode && stand_alone)
? isc::log::DEBUG : isc::log::INFO),
isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
- LOG_INFO(d2_logger, D2_STARTING);
- LOG_DEBUG(d2_logger, DBGLVL_START_SHUT, D2_START_INFO)
- .arg(getpid()).arg(verbose_mode ? "yes" : "no")
- .arg(stand_alone ? "yes" : "no" );
+
+ LOG_INFO(d2_logger, D2CTL_STARTING);
// For now we will sleep awhile to simulate doing something.
// Without at least a sleep, the process will start, exit and be
// restarted by Bind10/Init endlessley in a rapid succession.
sleep(1000);
- LOG_INFO(d2_logger, D2_SHUTDOWN);
+ LOG_INFO(d2_logger, D2CTL_STOPPING);
return (EXIT_SUCCESS);
}
diff --git a/src/bin/d2/tests/Makefile.am b/src/bin/d2/tests/Makefile.am
index 72e6254..38701e1 100644
--- a/src/bin/d2/tests/Makefile.am
+++ b/src/bin/d2/tests/Makefile.am
@@ -52,7 +52,10 @@ if HAVE_GTEST
TESTS += d2_unittests
d2_unittests_SOURCES = ../d2_log.h ../d2_log.cc
+d2_unittests_SOURCES += ../d_process.h
+d2_unittests_SOURCES += ../d2_process.cc ../d2_process.h
d2_unittests_SOURCES += d2_unittests.cc
+d2_unittests_SOURCES += d2_process_unittests.cc
nodist_d2_unittests_SOURCES = ../d2_messages.h ../d2_messages.cc
d2_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
@@ -60,6 +63,9 @@ d2_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
d2_unittests_LDADD = $(GTEST_LDADD)
d2_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
d2_unittests_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
+d2_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
+d2_unittests_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
+d2_unittests_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
endif
noinst_PROGRAMS = $(TESTS)
diff --git a/src/bin/d2/tests/d2_process_unittests.cc b/src/bin/d2/tests/d2_process_unittests.cc
new file mode 100644
index 0000000..2dc0d3d
--- /dev/null
+++ b/src/bin/d2/tests/d2_process_unittests.cc
@@ -0,0 +1,166 @@
+// 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.
+
+
+#include <config/ccsession.h>
+#include <d2/d2_process.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <gtest/gtest.h>
+
+#include <config.h>
+#include <sstream>
+
+using namespace std;
+using namespace isc;
+using namespace isc::config;
+using namespace isc::d2;
+using namespace boost::posix_time;
+
+namespace {
+
+/// @brief D2Process test fixture class
+class D2ProcessTest : public ::testing::Test {
+public:
+
+ /// @brief Static instance accessible via test callbacks.
+ static DProcessBasePtr process_;
+
+ /// @brief Constructor
+ D2ProcessTest() {
+ io_service_.reset(new isc::asiolink::IOService());
+ process_.reset(new D2Process("TestProcess", io_service_));
+ }
+
+ /// @brief Destructor
+ ~D2ProcessTest() {
+ io_service_.reset();
+ process_.reset();
+ }
+
+ /// @brief Callback that will invoke shutdown method.
+ static void genShutdownCallback() {
+ process_->shutdown();
+ }
+
+ /// @brief Callback that throws an exception.
+ static void genFatalErrorCallback() {
+ isc_throw (DProcessBaseError, "simulated fatal error");
+ }
+
+ /// @brief IOService for event processing. Fills in for IOservice
+ /// supplied by management layer.
+ IOServicePtr io_service_;
+};
+
+// Define the static process instance
+DProcessBasePtr D2ProcessTest::process_;
+
+
+/// @brief Verifies D2Process constructor behavior.
+/// 1. Verifies that constructor fails with an invalid IOService
+/// 2. Verifies that constructor succeeds with a valid IOService
+TEST(D2Process, construction) {
+ // Verify that the constructor will fail if given an empty
+ // io service.
+ IOServicePtr lcl_io_service;
+ EXPECT_THROW (D2Process("TestProcess", lcl_io_service), DProcessBaseError);
+
+ // Verify that the constructor succeeds with a valid io_service
+ lcl_io_service.reset(new isc::asiolink::IOService());
+ ASSERT_NO_THROW (D2Process("TestProcess", lcl_io_service));
+}
+
+/// @brief Verifies basic configure method behavior.
+// @TODO This test is simplistic and will need to be augmented
+// as configuration ability is implemented.
+TEST_F(D2ProcessTest, configure) {
+ // Verify that given a configuration "set", configure returns
+ // a successful response.
+ int rcode = -1;
+ string config = "{ \"test-value\": 1000 } ";
+ isc::data::ElementPtr json = isc::data::Element::fromJSON(config);
+ isc::data::ConstElementPtr answer = process_->configure(json);
+ isc::config::parseAnswer(rcode, answer);
+ EXPECT_EQ(0, rcode);
+}
+
+/// @brief Verifies basic command method behavior.
+// @TODO IF the D2Process is extended to support extra commands
+// this testing will need to augmented accordingly.
+TEST_F(D2ProcessTest, command) {
+ // Verfiy that the process will process unsupported command and
+ // return a failure response.
+ int rcode = -1;
+ string args = "{ \"arg1\": 77 } ";
+ isc::data::ElementPtr json = isc::data::Element::fromJSON(args);
+ isc::data::ConstElementPtr answer =
+ process_->command("bogus_command", json);
+ parseAnswer(rcode, answer);
+ EXPECT_EQ(1, rcode);
+}
+
+/// @brief Verifies that an "external" call to shutdown causes
+/// the run method to exit gracefully with a return value of EXIT_SUCCESS.
+TEST_F(D2ProcessTest, normalShutdown) {
+ // Use an asiolink IntervalTimer and callback to generate the
+ // shutdown invocation. (Note IntervalTimer setup is in milliseconds).
+ isc::asiolink::IntervalTimer timer(*io_service_);
+ timer.setup(genShutdownCallback, 2 * 1000);
+
+ // Record start time, and invoke run().
+ ptime start = microsec_clock::universal_time();
+ int rcode = process_->run();
+
+ // Record stop time.
+ ptime stop = microsec_clock::universal_time();
+
+ // Verify normal shutdown status.
+ EXPECT_EQ(EXIT_SUCCESS, rcode);
+
+ // Verify that duration of the run invocation is the same as the
+ // timer duration. This demonstrates that the shutdown was driven
+ // by an io_service event and callback.
+ time_duration elapsed = stop - start;
+ EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
+ elapsed.total_milliseconds() <= 2100);
+}
+
+/// @brief Verifies that an "uncaught" exception thrown during event loop
+/// processing is treated as a fatal error.
+TEST_F(D2ProcessTest, fatalErrorShutdown) {
+ // Use an asiolink IntervalTimer and callback to generate the
+ // the exception. (Note IntervalTimer setup is in milliseconds).
+ isc::asiolink::IntervalTimer timer(*io_service_);
+ timer.setup(genFatalErrorCallback, 2 * 1000);
+
+ // Record start time, and invoke run().
+ ptime start = microsec_clock::universal_time();
+ int rcode = process_->run();
+
+ // Record stop time.
+ ptime stop = microsec_clock::universal_time();
+
+ // Verify failure status.
+ EXPECT_EQ(EXIT_FAILURE, rcode);
+
+ // Verify that duration of the run invocation is the same as the
+ // timer duration. This demonstrates that the anomaly occurred
+ // during io callback processing.
+ time_duration elapsed = stop - start;
+ EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
+ elapsed.total_milliseconds() <= 2100);
+}
+
+} // end of anonymous namespace
diff --git a/src/bin/d2/tests/d2_test.py b/src/bin/d2/tests/d2_test.py
index ce7bdc3..032aaa4 100644
--- a/src/bin/d2/tests/d2_test.py
+++ b/src/bin/d2/tests/d2_test.py
@@ -161,7 +161,7 @@ class TestD2Daemon(unittest.TestCase):
# soon enough to catch it.
(returncode, output, error) = self.runCommand(["../b10-d2", "-s"])
output_text = str(output) + str(error)
- self.assertEqual(output_text.count("D2_STARTING"), 1)
+ self.assertEqual(output_text.count("D2CTL_STARTING"), 1)
if __name__ == '__main__':
unittest.main()
More information about the bind10-changes
mailing list