Commit 39238e40 authored by Stephen Morris's avatar Stephen Morris
Browse files

[trac555] Update tests

* Move reset() method to logger_manager (and _impl) and remove from the general
  logger classes.
* Correct problem whereby some messages went to stdout and some to stderr.
* Split the shell file testing into separate files, each testing one aspect of
  the logger.
parent 1a32f61c
......@@ -28,8 +28,7 @@ using namespace std;
namespace isc {
namespace log {
// Initialize Logger implementation. Does not check whether the implementation
// has already been initialized - that was done by the caller (getLoggerPtr()).
// Initialize Logger.
void Logger::initLoggerImpl() {
loggerptr_ = new LoggerImpl(name_);
}
......@@ -173,12 +172,5 @@ Logger::operator==(Logger& other) {
return (*getLoggerPtr() == *other.getLoggerPtr());
}
// Reset (used in testing only). This is a static method.
void
Logger::reset() {
LoggerImpl::reset();
}
} // namespace log
} // namespace isc
......@@ -152,12 +152,6 @@ public:
/// \return true if the logger objects are instances of the same logger.
bool operator==(Logger& other);
protected:
/// \brief Clear logging hierachy
///
/// This is for test use only, hence is protected.
static void reset();
private:
friend class isc::log::Formatter<Logger>;
......
......@@ -12,6 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE
#include <iostream>
#include <iomanip>
#include <algorithm>
......@@ -130,29 +131,5 @@ LoggerImpl::outputRaw(const Severity& severity, const string& message) {
}
}
// Reset. Just reset logger hierarchy to default settings (don't remove the
// loggers - this appears awkward); this is effectively the same as removing
// them.
void
LoggerImpl::reset() {
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
// N.B. The documentation is not clear, but it does not appear that the
// methods used to format the new logging levels are removed from the
// log4cxx LogLevelManager class - indeed, there appears to be no way
// to do this. This would seem to suggest that a re-initialization may
// well add another instance of the toString/fromString to the manager's
// list of methods.
//
// We could get round this by making setting the LogManager a truly
// one-shot process. However, apart from taking up memory there is little
// overhead if multiple instances are added. The manager walks the list and
// uses the first method that processes the argument, so multiple methods
// doing the same think will not affect functionality. Besides, this
// reset() method is only used in testing and not in the distributed
// software.
}
} // namespace log
} // namespace isc
......@@ -184,13 +184,6 @@ public:
return (name_ == other.name_);
}
/// \brief Reset logging
///
/// Resets (clears) the log4cplus logging, requiring that an initialization
/// call be performed again.
static void reset();
private:
std::string name_; ///< Full name of this logger
log4cplus::Logger logger_; ///< Underlying log4cplus logger
......
......@@ -150,5 +150,11 @@ LoggerManager::readLocalMessageFile(const char* file) {
}
}
// Reset logging
void
LoggerManager::reset() {
LoggerManagerImpl::reset();
}
} // namespace log
} // namespace isc
......@@ -82,6 +82,12 @@ public:
isc::log::Severity severity = isc::log::INFO,
int dbglevel = 0);
/// \brief Reset logging
///
/// Resets logging to default (just the root logger output INFO or above
/// messages to the console.
static void reset();
/// \brief Read local message file
///
/// Reads the local message file into the global dictionary, overwriting
......
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <algorithm>
#include <iostream>
#include <log4cplus/logger.h>
#include <log4cplus/configurator.h>
......@@ -160,26 +161,33 @@ LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
// Add the additional debug levels
LoggerLevelImpl::init();
// And initialize the root logger
initRootLogger(severity, dbglevel);
reset();
}
// Reset logging to default configuration. This closes all appenders
// and resets the root logger to output INFO messages to the console.
// It is principally used in testing.
void
LoggerManagerImpl::reset() {
// Initialize the root logger
initRootLogger();
}
// Initialize the root logger
void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
int dbglevel) {
int dbglevel)
{
log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
// Set the severity for the root logger
log4cplus::Logger::getRoot().setLogLevel(
LoggerLevelImpl::convertFromBindLevel(Level(severity, dbglevel)));
// Retrieve the appenders on the root instance and set the layout to
// use the "console" pattern.
log4cplus::SharedAppenderPtrList list =
log4cplus::Logger::getRoot().getAllAppenders();
for (log4cplus::SharedAppenderPtrList::iterator i = list.begin();
i != list.end(); ++i) {
setConsoleAppenderLayout(*i);
}
// Set the root to use a console logger.
OutputOption opt;
log4cplus::Logger root = log4cplus::Logger::getRoot();
createConsoleAppender(root, opt);
}
// Set the the "console" layout for the given appenders. This layout includes
......
......@@ -56,19 +56,19 @@ public:
/// root logger reset to logging informational messages.
///
/// \param root_name BIND 10 name of the root logger
void processInit();
static void processInit();
/// \brief Process Specification
///
/// Processes the specification for a single logger.
///
/// \param spec Logging specification for this logger
void processSpecification(const LoggerSpecification& spec);
static void processSpecification(const LoggerSpecification& spec);
/// \brief End Processing
///
/// Terminates the processing of the logging specifications.
void processEnd();
static void processEnd();
/// \brief Implementation-specific initialization
///
......@@ -81,6 +81,12 @@ public:
static void init(isc::log::Severity severity = isc::log::INFO,
int dbglevel = 0);
/// \brief Reset logging
///
/// Resets to default configuration (root logger logging to the console
/// with INFO severity).
static void reset();
private:
/// \brief Create console appender
///
......@@ -89,8 +95,8 @@ private:
///
/// \param logger Log4cplus logger to which the appender must be attached.
/// \param opt Output options for this appender.
void createConsoleAppender(log4cplus::Logger& logger,
const OutputOption& opt);
static void createConsoleAppender(log4cplus::Logger& logger,
const OutputOption& opt);
/// \brief Create file appender
///
......@@ -100,8 +106,8 @@ private:
///
/// \param logger Log4cplus logger to which the appender must be attached.
/// \param opt Output options for this appender.
void createFileAppender(log4cplus::Logger& logger,
const OutputOption& opt);
static void createFileAppender(log4cplus::Logger& logger,
const OutputOption& opt);
/// \brief Create syslog appender
///
......@@ -110,8 +116,8 @@ private:
///
/// \param logger Log4cplus logger to which the appender must be attached.
/// \param opt Output options for this appender.
void createSyslogAppender(log4cplus::Logger& logger,
const OutputOption& opt) {}
static void createSyslogAppender(log4cplus::Logger& logger,
const OutputOption& opt) {}
/// \brief Set default layout and severity for root logger
///
......
......@@ -54,8 +54,8 @@ struct OutputOption {
/// If console, stream on which messages are output
typedef enum {
STR_STDOUT = 0,
STR_STDERR = 1
STR_STDOUT = 1,
STR_STDERR = 2
} Stream;
/// \brief Constructor
......
......@@ -20,12 +20,12 @@ run_unittests_SOURCES += logger_level_unittest.cc
run_unittests_SOURCES += logger_manager_unittest.cc
run_unittests_SOURCES += logger_unittest.cc
run_unittests_SOURCES += logger_specification_unittest.cc
run_unittests_SOURCES += message_dictionary_unittest.cc
run_unittests_SOURCES += message_initializer_unittest_2.cc
run_unittests_SOURCES += message_initializer_unittest.cc
run_unittests_SOURCES += message_reader_unittest.cc
run_unittests_SOURCES += output_option_unittest.cc
run_unittests_SOURCES += root_logger_name_unittest.cc
# run_unittests_SOURCES += message_dictionary_unittest.cc
# run_unittests_SOURCES += message_initializer_unittest_2.cc
# run_unittests_SOURCES += message_initializer_unittest.cc
# run_unittests_SOURCES += message_reader_unittest.cc
# run_unittests_SOURCES += output_option_unittest.cc
# run_unittests_SOURCES += root_logger_name_unittest.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(LOG4CPLUS_LDFLAGS)
......
......@@ -37,22 +37,22 @@ passfail() {
echo "1. Checking that console output to stdout goes to stdout:"
rm -f $tempfile
./logger_example -s error -c stdout 1> $tempfile
./logger_example -c stdout -s error -c stdout 1> $tempfile
passfail 2
echo "2. Checking that console output to stdout does not go to stderr:"
rm -f $tempfile
./logger_example -s error -c stdout 2> $tempfile
./logger_example -c stdout -s error -c stdout 2> $tempfile
passfail 0
echo "3. Checking that console output to stderr goes to stderr:"
rm -f $tempfile
./logger_example -s error -c stderr 2> $tempfile
./logger_example -c stdout -s error -c stderr 2> $tempfile
passfail 2
echo "4. Checking that console output to stderr does not go to stdout:"
rm -f $tempfile
./logger_example -s error -c stderr 1> $tempfile
./logger_example -c stdout -s error -c stderr 1> $tempfile
passfail 0
rm -f $tempfile
......
#!/bin/sh
# Copyright (C) 2011 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.
# \brief Local message file test
#
# Checks that a local message file can override the definitions in the message
# dictionary.
testname="Local message file test"
echo $testname
failcount=0
localmes=@abs_builddir@/localdef_mes_$$
tempfile=@abs_builddir@/run_time_init_test_tempfile_$$
passfail() {
if [ $1 -eq 0 ]; then
echo " -- pass"
else
echo " ** FAIL"
failcount=`expr $failcount + $1`
fi
}
# Create the local message file for testing
cat > $localmes << .
\$PREFIX MSG_
% NOTHERE this message is not in the global dictionary
% READERR replacement read error, parameters: '%1' and '%2'
% RDLOCMES replacement read local message file, parameter is '%1'
.
echo "1. Local message replacement: "
cat > $tempfile << .
WARN [alpha.log] MSG_IDNOTFND, could not replace message text for 'MSG_NOTHERE': no such message
FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
ERROR [alpha.example] MSG_RDLOCMES, replacement read local message file, parameter is 'dummy/file'
WARN [alpha.dlm] MSG_READERR, replacement read error, parameters: 'a.txt' and 'dummy reason'
.
./logger_example -c stdout -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
passfail $?
rm -f $localmes
rm -f $tempfile
if [ $failcount -eq 0 ]; then
echo "PASS: $testname"
elif [ $failcount -eq 1 ]; then
echo "FAIL: $testname - 1 test failed"
else
echo "FAIL: $testname - $failcount tests failed"
fi
exit $failcount
......@@ -146,24 +146,19 @@ int main(int argc, char** argv) {
}
}
// Set the local file
if (optind < argc) {
LoggerManager::readLocalMessageFile(argv[optind]);
}
// Update the logging parameters
// Set an output option if we have not done so already.
if (! (c_found || f_found || l_found)) {
outopt.destination = OutputOption::DEST_CONSOLE;
outopt.stream = OutputOption::STR_STDOUT;
}
// Update the logging parameters. If no output options
// were set, the defaults will be used.
spec.addOutputOption(outopt);
// Set the logging options for the root logger.
LoggerManager manager;
manager.process(spec);
// Set the local file
if (optind < argc) {
LoggerManager::readLocalMessageFile(argv[optind]);
}
// Log a few messages
isc::log::Logger logger_dlm("dlm");
......
......@@ -19,19 +19,25 @@
#include <log/root_logger_name.h>
#include <log/logger.h>
#include <log/logger_manager.h>
#include <log/messagedef.h>
using namespace isc;
using namespace isc::log;
using namespace std;
namespace {
string ROOT_NAME("logleveltest");
}
class LoggerLevelTest : public ::testing::Test {
protected:
LoggerLevelTest()
{}
~LoggerLevelTest()
{}
LoggerLevelTest() {
LoggerManager::init(ROOT_NAME);
}
~LoggerLevelTest() {
LoggerManager::reset();
}
};
......@@ -56,6 +62,11 @@ TEST_F(LoggerLevelTest, Creation) {
}
TEST(LoggerLevel, getSeverity) {
// Should initialize logger as getSeverity() may output
// a message. This gives a properly-qualified logger
// name.
LoggerManager::init(ROOT_NAME);
EXPECT_EQ(DEBUG, getSeverity("DEBUG"));
EXPECT_EQ(DEBUG, getSeverity("debug"));
EXPECT_EQ(DEBUG, getSeverity("DeBuG"));
......@@ -75,4 +86,6 @@ TEST(LoggerLevel, getSeverity) {
// bad values should default to stdout
EXPECT_EQ(INFO, getSeverity("some bad value"));
EXPECT_EQ(INFO, getSeverity(""));
LoggerManager::reset();
}
......@@ -37,29 +37,19 @@ using namespace isc;
using namespace isc::log;
using namespace std;
/// \brief Derived logger
///
/// Only exists to make the protected static methods in Logger public for
/// test purposes.
class DerivedLogger : public isc::log::Logger {
public:
DerivedLogger(std::string name) : isc::log::Logger(name)
{}
static void reset() {
isc::log::Logger::reset();
}
};
namespace {
string ROOT_NAME("logmgrtest");
}
/// \brief LoggerManager Test
class LoggerManagerTest : public ::testing::Test {
public:
LoggerManagerTest()
{}
~LoggerManagerTest()
{
DerivedLogger::reset();
LoggerManagerTest() {
LoggerManager::init(ROOT_NAME);
}
~LoggerManagerTest() {
LoggerManager::reset();
}
};
......@@ -221,9 +211,11 @@ TEST_F(LoggerManagerTest, FileLogger) {
LOG_FATAL(logger, MSG_DUPLNS).arg("test");
ids.push_back(MSG_DUPLNS);
}
DerivedLogger::reset();
LoggerManager::reset();
// At this point, the output file should contain two lines with messages
// LOGTEST_TEST1 and LOGTEST_TEST2 messages - test this.
checkFileContents(file_spec.getFileName(), ids.begin(), ids.end());
//
}
......@@ -19,29 +19,16 @@
#include <log/root_logger_name.h>
#include <log/logger.h>
#include <log/logger_manager.h>
#include <log/messagedef.h>
using namespace isc;
using namespace isc::log;
using namespace std;
/// \brief Derived logger
///
/// Only exists to make the protected static methods in Logger public for
/// test purposes.
class DerivedLogger : public isc::log::Logger {
public:
DerivedLogger(std::string name) : isc::log::Logger(name)
{}
virtual ~DerivedLogger()
{}
static void reset() {
isc::log::Logger::reset();
}
};
namespace {
string ROOT_NAME = "loggertest";
}
/// \brief Logger Test
///
......@@ -50,11 +37,11 @@ public:
class LoggerTest : public ::testing::Test {
public:
LoggerTest()
{}
~LoggerTest()
{
DerivedLogger::reset();
LoggerTest() {
LoggerManager::init(ROOT_NAME);
}
~LoggerTest() {
LoggerManager::reset();
}
};
......@@ -64,11 +51,10 @@ public:
TEST_F(LoggerTest, Name) {
// Create a logger
setRootLoggerName("test1");
Logger logger("alpha");
// ... and check the name
EXPECT_EQ(string("test1.alpha"), logger.getName());
EXPECT_EQ(ROOT_NAME + string(".alpha"), logger.getName());
}
// This test attempts to get two instances of a logger with the same name
......@@ -76,10 +62,6 @@ TEST_F(LoggerTest, Name) {
TEST_F(LoggerTest, GetLogger) {
// Set the root logger name (not strictly needed, but this will be the
// case in the program(.
setRootLoggerName("test2");
const string name1 = "alpha";
const string name2 = "beta";
......@@ -100,7 +82,6 @@ TEST_F(LoggerTest, GetLogger) {
TEST_F(LoggerTest, Severity) {
// Create a logger
setRootLoggerName("test3");
Logger logger("alpha");
// Now check the levels
......@@ -131,7 +112,6 @@ TEST_F(LoggerTest, Severity) {
TEST_F(LoggerTest, DebugLevels) {
// Create a logger
setRootLoggerName("test4");
Logger logger("alpha");
// Debug level should be 0 if not at debug severity
......@@ -173,11 +153,9 @@ TEST_F(LoggerTest, DebugLevels) {
TEST_F(LoggerTest, SeverityInheritance) {
// Create to loggers. We cheat here as we know that the underlying
// Create two loggers. We cheat here as we know that the underlying
// implementation (in this case log4cxx) will set a parent-child
// relationship if the loggers are named <parent> and <parent>.<child>.
setRootLoggerName("test5");
Logger parent("alpha");
Logger child("alpha.beta");
......@@ -205,11 +183,9 @@ TEST_F(LoggerTest, SeverityInheritance) {
TEST_F(LoggerTest, EffectiveSeverityInheritance) {
// Create to loggers. We cheat here as we know that the underlying
// Create two loggers. We cheat here as we know that the underlying
// implementation (in this case log4cxx) will set a parent-child
// relationship if the loggers are named <parent> and <parent>.<child>.
setRootLoggerName("test6");
Logger parent("test6");
Logger child("test6.beta");
......@@ -244,7 +220,6 @@ TEST_F(LoggerTest, EffectiveSeverityInheritance) {
TEST_F(LoggerTest, IsXxxEnabled) {
setRootLoggerName("test7");
Logger logger("test7");
logger.setSeverity(isc::log::INFO);
......@@ -315,7 +290,6 @@ TEST_F(LoggerTest, IsXxxEnabled) {
TEST_F(LoggerTest, IsDebugEnabledLevel) {
setRootLoggerName("test8");
Logger logger("test8");