2017-04-04 22:12:21 +02:00
|
|
|
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
|
2014-07-16 15:30:03 +02:00
|
|
|
//
|
2015-12-15 21:37:34 +01:00
|
|
|
// 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/.
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <exceptions/exceptions.h>
|
|
|
|
#include <cc/data.h>
|
2015-07-03 18:40:08 +02:00
|
|
|
#include <config/module_spec.h>
|
2014-07-16 15:30:03 +02:00
|
|
|
#include <dhcpsrv/logging.h>
|
|
|
|
#include <gtest/gtest.h>
|
2014-09-05 17:10:03 +01:00
|
|
|
#include <log/logger_support.h>
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
using namespace isc;
|
|
|
|
using namespace isc::dhcp;
|
|
|
|
using namespace isc::data;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-09-05 17:10:03 +01:00
|
|
|
/// @brief Logging Test Fixture Class
|
|
|
|
///
|
|
|
|
/// Trivial class that ensures that the logging is reset to its defaults after
|
|
|
|
/// each test. Strictly speaking this only resets the testing root logger (which
|
|
|
|
/// has the name "kea") but as the only other logger mentioned here ("wombat")
|
|
|
|
/// is not used elsewhere, that is sufficient.
|
|
|
|
|
|
|
|
class LoggingTest : public ::testing::Test {
|
|
|
|
public:
|
|
|
|
/// @brief Constructor
|
|
|
|
LoggingTest() {}
|
|
|
|
|
|
|
|
/// @brief Destructor
|
|
|
|
///
|
|
|
|
/// Reset root logger back to defaults.
|
|
|
|
~LoggingTest() {
|
2014-09-25 12:42:17 +02:00
|
|
|
isc::log::setDefaultLoggingOutput();
|
2014-09-05 17:10:03 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-07-03 18:40:08 +02:00
|
|
|
// Tests that the spec file is valid.
|
|
|
|
TEST_F(LoggingTest, basicSpec) {
|
2015-09-02 12:54:32 +02:00
|
|
|
std::string specfile = std::string(LOGGING_SPEC_FILE);
|
2015-07-08 22:25:24 +02:00
|
|
|
ASSERT_NO_THROW(isc::config::moduleSpecFromFile(specfile));
|
2015-07-03 18:40:08 +02:00
|
|
|
}
|
2014-09-05 17:10:03 +01:00
|
|
|
|
2016-12-14 16:57:44 +02:00
|
|
|
// Checks that the constructor is able to process specified storage properly.
|
2014-09-05 17:10:03 +01:00
|
|
|
TEST_F(LoggingTest, constructor) {
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr null_ptr;
|
2014-07-18 21:11:42 +02:00
|
|
|
EXPECT_THROW(LogConfigParser parser(null_ptr), BadValue);
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr nonnull(new SrvConfig());
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
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.
|
2014-09-05 17:10:03 +01:00
|
|
|
TEST_F(LoggingTest, parsingConsoleOutput) {
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-07-18 21:11:42 +02:00
|
|
|
const char* config_txt =
|
2014-07-16 15:30:03 +02:00
|
|
|
"{ \"loggers\": ["
|
|
|
|
" {"
|
|
|
|
" \"name\": \"kea\","
|
|
|
|
" \"output_options\": ["
|
|
|
|
" {"
|
2015-07-08 23:07:44 +02:00
|
|
|
" \"output\": \"stdout\","
|
|
|
|
" \"flush\": true"
|
2014-07-16 15:30:03 +02:00
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"debuglevel\": 99,"
|
|
|
|
" \"severity\": \"DEBUG\""
|
|
|
|
" }"
|
|
|
|
"]}";
|
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr storage(new SrvConfig());
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
LogConfigParser parser(storage);
|
|
|
|
|
|
|
|
// We need to parse properly formed JSON and then extract
|
|
|
|
// "loggers" element from it. For some reason fromJSON is
|
2014-07-18 21:11:42 +02:00
|
|
|
// throwing at opening square bracket
|
2014-07-16 15:30:03 +02:00
|
|
|
ConstElementPtr config = Element::fromJSON(config_txt);
|
|
|
|
config = config->get("loggers");
|
|
|
|
|
|
|
|
EXPECT_NO_THROW(parser.parseConfiguration(config));
|
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo().size());
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
|
|
|
|
EXPECT_EQ(99, storage->getLoggingInfo()[0].debuglevel_);
|
|
|
|
EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[0].severity_);
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
|
|
|
|
EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[0].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
|
2014-07-16 15:30:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2014-09-05 17:10:03 +01:00
|
|
|
TEST_F(LoggingTest, parsingFile) {
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-07-18 21:11:42 +02:00
|
|
|
const char* config_txt =
|
2014-07-16 15:30:03 +02:00
|
|
|
"{ \"loggers\": ["
|
|
|
|
" {"
|
|
|
|
" \"name\": \"kea\","
|
|
|
|
" \"output_options\": ["
|
|
|
|
" {"
|
|
|
|
" \"output\": \"logfile.txt\""
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"severity\": \"INFO\""
|
|
|
|
" }"
|
|
|
|
"]}";
|
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr storage(new SrvConfig());
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
LogConfigParser parser(storage);
|
|
|
|
|
|
|
|
// We need to parse properly formed JSON and then extract
|
|
|
|
// "loggers" element from it. For some reason fromJSON is
|
2014-07-18 21:11:42 +02:00
|
|
|
// throwing at opening square bracket
|
2014-07-16 15:30:03 +02:00
|
|
|
ConstElementPtr config = Element::fromJSON(config_txt);
|
|
|
|
config = config->get("loggers");
|
|
|
|
|
|
|
|
EXPECT_NO_THROW(parser.parseConfiguration(config));
|
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo().size());
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
|
|
|
|
EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
|
|
|
|
EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
|
2014-07-16 15:30:03 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
|
|
|
|
EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
// Default for immediate flush is true
|
|
|
|
EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
|
2014-07-16 15:30:03 +02:00
|
|
|
}
|
|
|
|
|
2014-07-18 21:11:42 +02:00
|
|
|
// Checks if the LogConfigParser class is able to transform data structures
|
|
|
|
// into Configuration usable by log4cplus. This test checks that more than
|
|
|
|
// one logger can be configured.
|
2014-09-05 17:10:03 +01:00
|
|
|
TEST_F(LoggingTest, multipleLoggers) {
|
2014-07-18 21:11:42 +02:00
|
|
|
|
|
|
|
const char* config_txt =
|
|
|
|
"{ \"loggers\": ["
|
|
|
|
" {"
|
|
|
|
" \"name\": \"kea\","
|
|
|
|
" \"output_options\": ["
|
|
|
|
" {"
|
2015-07-08 23:07:44 +02:00
|
|
|
" \"output\": \"logfile.txt\","
|
|
|
|
" \"flush\": true"
|
2014-07-18 21:11:42 +02:00
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"severity\": \"INFO\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"name\": \"wombat\","
|
|
|
|
" \"output_options\": ["
|
|
|
|
" {"
|
2015-07-08 23:07:44 +02:00
|
|
|
" \"output\": \"logfile2.txt\","
|
|
|
|
" \"flush\": false"
|
2014-07-18 21:11:42 +02:00
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"severity\": \"DEBUG\","
|
|
|
|
" \"debuglevel\": 99"
|
|
|
|
" }"
|
|
|
|
"]}";
|
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr storage(new SrvConfig());
|
2014-07-18 21:11:42 +02:00
|
|
|
|
|
|
|
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));
|
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(2, storage->getLoggingInfo().size());
|
2014-07-18 21:11:42 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
|
|
|
|
EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
|
|
|
|
EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
|
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo()[0].destinations_.size());
|
|
|
|
EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
|
2014-07-18 21:11:42 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("wombat", storage->getLoggingInfo()[1].name_);
|
|
|
|
EXPECT_EQ(99, storage->getLoggingInfo()[1].debuglevel_);
|
|
|
|
EXPECT_EQ(isc::log::DEBUG, storage->getLoggingInfo()[1].severity_);
|
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo()[1].destinations_.size());
|
|
|
|
EXPECT_EQ("logfile2.txt" , storage->getLoggingInfo()[1].destinations_[0].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
EXPECT_FALSE(storage->getLoggingInfo()[1].destinations_[0].flush_);
|
2014-07-18 21:11:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Checks if the LogConfigParser class is able to transform data structures
|
|
|
|
// into Configuration usable by log4cplus. This test checks that more than
|
|
|
|
// one logging destination can be configured.
|
2014-09-05 17:10:03 +01:00
|
|
|
TEST_F(LoggingTest, multipleLoggingDestinations) {
|
2014-07-18 21:11:42 +02:00
|
|
|
|
|
|
|
const char* config_txt =
|
|
|
|
"{ \"loggers\": ["
|
|
|
|
" {"
|
|
|
|
" \"name\": \"kea\","
|
|
|
|
" \"output_options\": ["
|
|
|
|
" {"
|
|
|
|
" \"output\": \"logfile.txt\""
|
|
|
|
" },"
|
|
|
|
" {"
|
|
|
|
" \"output\": \"stdout\""
|
|
|
|
" }"
|
|
|
|
" ],"
|
|
|
|
" \"severity\": \"INFO\""
|
|
|
|
" }"
|
|
|
|
"]}";
|
|
|
|
|
2014-09-15 19:27:53 +02:00
|
|
|
SrvConfigPtr storage(new SrvConfig());
|
2014-07-18 21:11:42 +02:00
|
|
|
|
|
|
|
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));
|
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
ASSERT_EQ(1, storage->getLoggingInfo().size());
|
2014-07-18 21:11:42 +02:00
|
|
|
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("kea", storage->getLoggingInfo()[0].name_);
|
|
|
|
EXPECT_EQ(0, storage->getLoggingInfo()[0].debuglevel_);
|
|
|
|
EXPECT_EQ(isc::log::INFO, storage->getLoggingInfo()[0].severity_);
|
|
|
|
ASSERT_EQ(2, storage->getLoggingInfo()[0].destinations_.size());
|
|
|
|
EXPECT_EQ("logfile.txt" , storage->getLoggingInfo()[0].destinations_[0].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[0].flush_);
|
2014-08-29 09:54:47 +02:00
|
|
|
EXPECT_EQ("stdout" , storage->getLoggingInfo()[0].destinations_[1].output_);
|
2015-07-08 23:07:44 +02:00
|
|
|
EXPECT_TRUE(storage->getLoggingInfo()[0].destinations_[1].flush_);
|
2014-07-18 21:11:42 +02:00
|
|
|
}
|
|
|
|
|
2015-07-08 23:11:00 +02:00
|
|
|
/// @todo Add tests for malformed logging configuration
|
|
|
|
|
2014-07-18 21:11:42 +02:00
|
|
|
/// @todo 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
|
2016-12-14 16:57:44 +02:00
|
|
|
/// that check each logging destination separately (e.g. configure log file, then
|
2014-07-18 21:11:42 +02:00
|
|
|
/// check if the file is indeed created or configure stdout destination, then
|
|
|
|
/// swap console file descriptors and check that messages are really logged.
|
2014-07-16 15:30:03 +02:00
|
|
|
|
|
|
|
};
|