From 4c99c52099502e14977d9f070b49d39c27ce3c42 Mon Sep 17 00:00:00 2001 From: Tomek Mrugalski Date: Wed, 16 Jul 2014 15:30:03 +0200 Subject: [PATCH] [3427] Configuration unit-tests written. --- src/lib/dhcpsrv/configuration.h | 2 + src/lib/dhcpsrv/logging.h | 2 +- src/lib/dhcpsrv/tests/Makefile.am | 2 + src/lib/dhcpsrv/tests/cfgmgr_unittest.cc | 10 ++ .../dhcpsrv/tests/configuration_unittest.cc | 63 +++++++++ src/lib/dhcpsrv/tests/daemon_unittest.cc | 43 ++++++ src/lib/dhcpsrv/tests/logging_unittest.cc | 126 ++++++++++++++++++ 7 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 src/lib/dhcpsrv/tests/configuration_unittest.cc create mode 100644 src/lib/dhcpsrv/tests/logging_unittest.cc diff --git a/src/lib/dhcpsrv/configuration.h b/src/lib/dhcpsrv/configuration.h index 348e4f6866..b350dfb14e 100644 --- a/src/lib/dhcpsrv/configuration.h +++ b/src/lib/dhcpsrv/configuration.h @@ -17,6 +17,8 @@ #include #include +#include +#include namespace isc { namespace dhcp { diff --git a/src/lib/dhcpsrv/logging.h b/src/lib/dhcpsrv/logging.h index 37fd70001e..cc2f625ff3 100644 --- a/src/lib/dhcpsrv/logging.h +++ b/src/lib/dhcpsrv/logging.h @@ -43,7 +43,7 @@ public: /// Walks over specified logging configuration JSON structures and store /// parsed information in config_->logging_info_. /// - /// @param log_config JSON structures to be parsed + /// @param log_config JSON structures to be parsed (loggers list) void parseConfiguration(isc::data::ConstElementPtr log_config); /// @brief Applies stored configuration diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index 0df7d579ef..f15a750929 100644 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/src/lib/dhcpsrv/tests/Makefile.am @@ -55,6 +55,7 @@ libdhcpsrv_unittests_SOURCES = run_unittests.cc libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc libdhcpsrv_unittests_SOURCES += alloc_engine_unittest.cc libdhcpsrv_unittests_SOURCES += callout_handle_store_unittest.cc +libdhcpsrv_unittests_SOURCES += configuration_unittest.cc libdhcpsrv_unittests_SOURCES += cfgmgr_unittest.cc libdhcpsrv_unittests_SOURCES += csv_lease_file4_unittest.cc libdhcpsrv_unittests_SOURCES += csv_lease_file6_unittest.cc @@ -66,6 +67,7 @@ libdhcpsrv_unittests_SOURCES += lease_file_io.cc lease_file_io.h libdhcpsrv_unittests_SOURCES += lease_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc +libdhcpsrv_unittests_SOURCES += logging_unittest.cc libdhcpsrv_unittests_SOURCES += generic_lease_mgr_unittest.cc generic_lease_mgr_unittest.h libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc diff --git a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc index 37f8e8f263..94d1510029 100644 --- a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc @@ -289,6 +289,16 @@ public: isc::dhcp::ClientClasses classify_; }; +// Checks that there is a configuration structure available and that +// it is empty by default. +TEST_F(CfgMgrTest, configuration) { + + ConfigurationPtr configuration = CfgMgr::instance().getConfiguration(); + ASSERT_TRUE(configuration); + + EXPECT_TRUE(configuration->logging_info_.empty()); +} + // This test verifies that multiple option definitions can be added // under different option spaces. TEST_F(CfgMgrTest, getOptionDefs) { diff --git a/src/lib/dhcpsrv/tests/configuration_unittest.cc b/src/lib/dhcpsrv/tests/configuration_unittest.cc new file mode 100644 index 0000000000..4873719ed7 --- /dev/null +++ b/src/lib/dhcpsrv/tests/configuration_unittest.cc @@ -0,0 +1,63 @@ +// Copyright (C) 2012-2014 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 + +#include +#include + +using namespace isc::dhcp; + +// Those are the tests for Configuration storage. Right now they are minimal, +// but the number is expected to grow significantly once we migrate more +// parameters from CfgMgr storage to Configuration storage. + +namespace { + +// Check that by default there are no logging entries +TEST(ConfigurationTest, basic) { + Configuration x; + + EXPECT_TRUE(x.logging_info_.empty()); +} + +// Check that Configuration can store logging information. +TEST(ConfigurationTest, loggingInfo) { + + Configuration x; + + LoggingInfo log1; + log1.name_ = "foo"; + log1.severity_ = isc::log::WARN; + log1.debuglevel_ = 77; + + LoggingDestination dest; + dest.output_ = "some-logfile.txt"; + dest.maxver_ = 5; + dest.maxsize_ = 2097152; + + log1.destinations_.push_back(dest); + + x.logging_info_.push_back(log1); + + EXPECT_EQ("foo", x.logging_info_[0].name_); + EXPECT_EQ(isc::log::WARN, x.logging_info_[0].severity_); + EXPECT_EQ(77, x.logging_info_[0].debuglevel_); + + EXPECT_EQ("some-logfile.txt", x.logging_info_[0].destinations_[0].output_); + EXPECT_EQ(5, x.logging_info_[0].destinations_[0].maxver_); + EXPECT_EQ(2097152, x.logging_info_[0].destinations_[0].maxsize_); +} + +} // end of anonymous namespace diff --git a/src/lib/dhcpsrv/tests/daemon_unittest.cc b/src/lib/dhcpsrv/tests/daemon_unittest.cc index 315148b5d4..075aff3bd2 100644 --- a/src/lib/dhcpsrv/tests/daemon_unittest.cc +++ b/src/lib/dhcpsrv/tests/daemon_unittest.cc @@ -15,10 +15,13 @@ #include #include #include +#include +#include #include using namespace isc; using namespace isc::dhcp; +using namespace isc::data; namespace { @@ -27,6 +30,46 @@ TEST(DaemonTest, noop) { EXPECT_NO_THROW(Daemon x); } +// Checks that configureLogger method is behaving properly. +// More dedicated tests are availablef for LogConfigParser class. +// See logger_unittest.cc +TEST(DaemonTest, parsingConsoleOutput) { + + // Storage - parsed configuration will be stored here + ConfigurationPtr storage(new Configuration()); + + const char* config_txt = + "{ \"loggers\": [" + " {" + " \"name\": \"kea\"," + " \"output_options\": [" + " {" + " \"output\": \"stdout\"" + " }" + " ]," + " \"debuglevel\": 99," + " \"severity\": \"DEBUG\"" + " }" + "]}"; + ConstElementPtr config = Element::fromJSON(config_txt); + + // Spawn a daemon and tell it to configure logger + Daemon x; + EXPECT_NO_THROW(x.configureLogger(config, storage)); + + // The parsed configuration should be processed by the daemon and + // stored in configuration storage. + ASSERT_EQ(1, storage->logging_info_.size()); + + EXPECT_EQ("kea", storage->logging_info_[0].name_); + EXPECT_EQ(99, storage->logging_info_[0].debuglevel_); + EXPECT_EQ(isc::log::DEBUG, storage->logging_info_[0].severity_); + + ASSERT_EQ(1, storage->logging_info_[0].destinations_.size()); + EXPECT_EQ("stdout" , storage->logging_info_[0].destinations_[0].output_); +} + + // More tests will appear here as we develop Daemon class. }; diff --git a/src/lib/dhcpsrv/tests/logging_unittest.cc b/src/lib/dhcpsrv/tests/logging_unittest.cc new file mode 100644 index 0000000000..b5804b25eb --- /dev/null +++ b/src/lib/dhcpsrv/tests/logging_unittest.cc @@ -0,0 +1,126 @@ +// Copyright (C) 2014 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 +#include +#include +#include +#include + +using namespace isc; +using namespace isc::dhcp; +using namespace isc::data; + +namespace { + +// Checks that contructor is able to process specified storage properly +TEST(LoggingTest, constructor) { + + ConfigurationPtr nullPtr; + EXPECT_THROW(LogConfigParser parser(nullPtr), InvalidOperation); + + ConfigurationPtr nonnull(new Configuration()); + + EXPECT_NO_THROW(LogConfigParser parser(nonnull)); +} + +// Checks if the LogConfigParser class is able to transform JSON structures +// into Configuration usable by log4cplus. This test checks for output +// configured to stdout on debug level. +TEST(LoggingTest, parsingConsoleOutput) { + + const char* config_txt = + "{ \"loggers\": [" + " {" + " \"name\": \"kea\"," + " \"output_options\": [" + " {" + " \"output\": \"stdout\"" + " }" + " ]," + " \"debuglevel\": 99," + " \"severity\": \"DEBUG\"" + " }" + "]}"; + + ConfigurationPtr storage(new Configuration()); + + LogConfigParser parser(storage); + + // We need to parse properly formed JSON and then extract + // "loggers" element from it. For some reason fromJSON is + // throwing at opening square bracket + ConstElementPtr config = Element::fromJSON(config_txt); + config = config->get("loggers"); + + EXPECT_NO_THROW(parser.parseConfiguration(config)); + + ASSERT_EQ(1, storage->logging_info_.size()); + + EXPECT_EQ("kea", storage->logging_info_[0].name_); + EXPECT_EQ(99, storage->logging_info_[0].debuglevel_); + EXPECT_EQ(isc::log::DEBUG, storage->logging_info_[0].severity_); + + ASSERT_EQ(1, storage->logging_info_[0].destinations_.size()); + EXPECT_EQ("stdout" , storage->logging_info_[0].destinations_[0].output_); +} + +// Checks if the LogConfigParser class is able to transform JSON structures +// into Configuration usable by log4cplus. This test checks for output +// configured to a file on INFO level. +TEST(LoggingTest, parsingFile) { + + const char* config_txt = + "{ \"loggers\": [" + " {" + " \"name\": \"kea\"," + " \"output_options\": [" + " {" + " \"output\": \"logfile.txt\"" + " }" + " ]," + " \"severity\": \"INFO\"" + " }" + "]}"; + + ConfigurationPtr storage(new Configuration()); + + LogConfigParser parser(storage); + + // We need to parse properly formed JSON and then extract + // "loggers" element from it. For some reason fromJSON is + // throwing at opening square bracket + ConstElementPtr config = Element::fromJSON(config_txt); + config = config->get("loggers"); + + EXPECT_NO_THROW(parser.parseConfiguration(config)); + + ASSERT_EQ(1, storage->logging_info_.size()); + + EXPECT_EQ("kea", storage->logging_info_[0].name_); + EXPECT_EQ(0, storage->logging_info_[0].debuglevel_); + EXPECT_EQ(isc::log::INFO, storage->logging_info_[0].severity_); + + ASSERT_EQ(1, storage->logging_info_[0].destinations_.size()); + EXPECT_EQ("logfile.txt" , storage->logging_info_[0].destinations_[0].output_); +} + +// There is no easy way to test applyConfiguration() and defaultLogging(). +// To test them, it would require instrumenting log4cplus to actually fake +// the logging set up. Alternatively, we could develop set of test suites +// that check each logging destination spearately (e.g. configure log file, then +// check if the file is indeed created or configure stdout destination, then +// swap console file descriptors and check that messages are really logged. + +};