core: change logging from environment variable to configuration file-based
GlobalConfigurationFixture uses unit-tests.conf to determine default
and module specific logging levels. Logging will gracefully default to
INFO if unit-tests.conf is not found. See unit-tests.conf.sample for a
sample configuration file.
refs: #1375, #1267
Change-Id: Ib0c4eb4149748e6658f94ef1afa23ddd3072c0fa
diff --git a/daemon/common.hpp b/daemon/common.hpp
index 32ad4a4..76a553d 100644
--- a/daemon/common.hpp
+++ b/daemon/common.hpp
@@ -33,6 +33,8 @@
#include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/functional/hash.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
#include <vector>
#include <list>
@@ -44,8 +46,6 @@
#include <algorithm>
#include <numeric>
-#include "core/logger.hpp"
-
namespace nfd {
using boost::noncopyable;
diff --git a/daemon/core/logger-factory.cpp b/daemon/core/logger-factory.cpp
new file mode 100644
index 0000000..4a353f1
--- /dev/null
+++ b/daemon/core/logger-factory.cpp
@@ -0,0 +1,178 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "logger-factory.hpp"
+
+namespace nfd {
+
+LoggerFactory&
+LoggerFactory::getInstance()
+{
+ static LoggerFactory globalLoggerFactory;
+
+ return globalLoggerFactory;
+}
+
+LoggerFactory::LoggerFactory()
+ : m_defaultLevel(LOG_INFO)
+{
+ m_levelNames["NONE"] = LOG_NONE;
+ m_levelNames["ERROR"] = LOG_ERROR;
+ m_levelNames["WARN"] = LOG_WARN;
+ m_levelNames["INFO"] = LOG_INFO;
+ m_levelNames["DEBUG"] = LOG_DEBUG;
+ m_levelNames["TRACE"] = LOG_TRACE;
+ m_levelNames["ALL"] = LOG_ALL;
+}
+
+void
+LoggerFactory::setConfigFile(ConfigFile& config)
+{
+ config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
+}
+
+LogLevel
+LoggerFactory::parseLevel(const std::string& level)
+{
+ std::string upperLevel = level;
+ boost::to_upper(upperLevel);
+
+ // std::cerr << "parsing level: " << upperLevel << std::endl;;
+ // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
+ // std::cerr << m_levelNames.begin()->first << std::endl;
+
+ LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
+ if (levelIt != m_levelNames.end())
+ {
+ return levelIt->second;
+ }
+ try
+ {
+ uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
+
+ if ((LOG_NONE <= levelNo && levelNo <= LOG_TRACE) ||
+ levelNo == LOG_ALL)
+ {
+ return static_cast<LogLevel>(levelNo);
+ }
+ }
+ catch (const boost::bad_lexical_cast& error)
+ {
+ }
+ throw LoggerFactory::Error("Unsupported logging level \"" +
+ level + "\"");
+}
+
+
+void
+LoggerFactory::onConfig(const ConfigSection& section,
+ bool isDryRun,
+ const std::string& filename)
+{
+// log
+// {
+// ; default_level specifies the logging level for modules
+// ; that are not explicitly named. All debugging levels
+// ; listed above the selected value are enabled.
+//
+// default_level INFO
+//
+// ; You may also override the default for specific modules:
+//
+// FibManager DEBUG
+// Forwarder WARN
+// }
+
+ // std::cerr << "loading logging configuration" << std::endl;
+ for (ConfigSection::const_iterator item = section.begin();
+ item != section.end();
+ ++item)
+ {
+ std::string levelString;
+ try
+ {
+ levelString = item->second.get_value<std::string>();
+ }
+ catch (const boost::property_tree::ptree_error& error)
+ {
+ }
+
+ if (levelString.empty())
+ {
+ throw LoggerFactory::Error("No logging level found for option \"" + item->first + "\"");
+ }
+
+ LogLevel level = parseLevel(levelString);
+
+ if (item->first == "default_level")
+ {
+ if (!isDryRun)
+ {
+ setDefaultLevel(level);
+ }
+ }
+ else
+ {
+ LoggerMap::iterator loggerIt = m_loggers.find(item->first);
+ if (loggerIt == m_loggers.end())
+ {
+ throw LoggerFactory::Error("Invalid module name \"" +
+ item->first + "\" in configuration file");
+ }
+
+ if (!isDryRun)
+ {
+ // std::cerr << "changing level for module " << item->first << " to " << level << std::endl;
+ loggerIt->second.setLogLevel(level);
+ }
+ }
+ }
+}
+
+void
+LoggerFactory::setDefaultLevel(LogLevel level)
+{
+ // std::cerr << "changing to default_level " << level << std::endl;
+
+ m_defaultLevel = level;
+ for (LoggerMap::iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
+ {
+ // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
+ i->second.setLogLevel(m_defaultLevel);
+ }
+}
+
+Logger&
+LoggerFactory::create(const std::string& moduleName)
+{
+ return LoggerFactory::getInstance().createLogger(moduleName);
+}
+
+Logger&
+LoggerFactory::createLogger(const std::string& moduleName)
+{
+ // std::cerr << "creating logger for " << moduleName
+ // << " with level " << m_defaultLevel << std::endl;
+
+ std::pair<LoggerMap::iterator, bool> loggerIt =
+ m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
+
+ return loggerIt.first->second;
+}
+
+std::list<std::string>
+LoggerFactory::getModules() const
+{
+ std::list<std::string> modules;
+ for (LoggerMap::const_iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
+ {
+ modules.push_back(i->first);
+ }
+
+ return modules;
+}
+
+} // namespace nfd
diff --git a/daemon/core/logger-factory.hpp b/daemon/core/logger-factory.hpp
new file mode 100644
index 0000000..52a05f4
--- /dev/null
+++ b/daemon/core/logger-factory.hpp
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_CORE_LOGGER_FACTORY_HPP
+#define NFD_CORE_LOGGER_FACTORY_HPP
+
+#include "common.hpp"
+#include "mgmt/config-file.hpp"
+#include "logger.hpp"
+
+namespace nfd {
+
+class LoggerFactory : noncopyable
+{
+public:
+
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& error)
+ : std::runtime_error(error)
+ {
+ }
+ };
+
+ static LoggerFactory&
+ getInstance();
+
+ void
+ setConfigFile(ConfigFile& config);
+
+ void
+ onConfig(const ConfigSection& section, bool isDryRun, const std::string& filename);
+
+ std::list<std::string>
+ getModules() const;
+
+ static Logger&
+ create(const std::string& moduleName);
+
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+
+ // these methods are used during unit-testing
+
+ LogLevel
+ getDefaultLevel() const;
+
+ void
+ setDefaultLevel(LogLevel level);
+
+private:
+
+ LoggerFactory();
+
+ Logger&
+ createLogger(const std::string& moduleName);
+
+ LogLevel
+ parseLevel(const std::string& level);
+
+private:
+
+ typedef std::map<std::string, LogLevel> LevelMap;
+ typedef std::pair<std::string, LogLevel> NameAndLevel;
+
+ LevelMap m_levelNames;
+
+ typedef std::map<std::string, Logger> LoggerMap;
+ typedef std::pair<std::string, Logger> NameAndLogger;
+
+ LoggerMap m_loggers;
+
+ LogLevel m_defaultLevel;
+};
+
+inline LogLevel
+LoggerFactory::getDefaultLevel() const
+{
+ return m_defaultLevel;
+}
+
+} // namespace nfd
+
+#endif // NFD_CORE_LOGGER_FACTORY_HPP
diff --git a/daemon/core/logger.cpp b/daemon/core/logger.cpp
deleted file mode 100644
index 928b112..0000000
--- a/daemon/core/logger.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- *
- * Author: Ilya Moiseenko <iliamo@ucla.edu>
- */
-
-#include "logger.hpp"
-#include <boost/algorithm/string.hpp>
-
-namespace nfd {
-
-inline static bool
-isNumber(const std::string& s)
-{
- if (s.empty())
- return false;
-
- for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
- {
- if (!std::isdigit(*i))
- return false;
- }
-
- return true;
-}
-
-Logger::Logger(const std::string& name)
- : m_moduleName(name)
-{
- char* nfdLog = getenv("NFD_LOG");
- if (nfdLog)
- {
- std::string level = nfdLog;
- if (isNumber(nfdLog))
- {
- setLogLevel(boost::lexical_cast<uint32_t>(nfdLog));
- }
- else if (boost::iequals(level, "none"))
- {
- m_enabledLogLevel = LOG_NONE;
- }
- else if (boost::iequals(level, "error"))
- {
- m_enabledLogLevel = LOG_ERROR;
- }
- else if (boost::iequals(level, "warn"))
- {
- m_enabledLogLevel = LOG_WARN;
- }
- else if (boost::iequals(level, "info"))
- {
- m_enabledLogLevel = LOG_INFO;
- }
- else if (boost::iequals(level, "debug"))
- {
- m_enabledLogLevel = LOG_DEBUG;
- }
- else if (boost::iequals(level, "trace"))
- {
- m_enabledLogLevel = LOG_TRACE;
- }
- else
- {
- m_enabledLogLevel = LOG_ALL;
- }
- }
- else
- {
- m_enabledLogLevel = LOG_WARN;
- }
-}
-
-std::ostream&
-operator<<(std::ostream& output, const Logger& obj)
-{
- output << obj.getName();
- return output;
-}
-
-} // namespace nfd
diff --git a/daemon/core/logger.hpp b/daemon/core/logger.hpp
index aad2394..604c304 100644
--- a/daemon/core/logger.hpp
+++ b/daemon/core/logger.hpp
@@ -10,7 +10,6 @@
#define NFD_CORE_LOGGER_HPP
#include "common.hpp"
-#include <iostream>
namespace nfd {
@@ -28,81 +27,103 @@
class Logger
{
public:
- explicit
- Logger(const std::string& name);
-
- bool
- isEnabled(LogLevel level)
+
+ Logger(const std::string& name, LogLevel level)
+ : m_moduleName(name)
+ , m_enabledLogLevel(level)
{
+ }
+
+ bool
+ isEnabled(LogLevel level) const
+ {
+ // std::cerr << m_moduleName <<
+ // " enabled = " << m_enabledLogLevel
+ // << " level = " << level << std::endl;
return (m_enabledLogLevel >= level);
}
void
- setLogLevel(uint32_t level)
+ setLogLevel(LogLevel level)
{
- m_enabledLogLevel = static_cast<LogLevel>(level);
+ m_enabledLogLevel = level;
}
-
+
const std::string&
getName() const
{
return m_moduleName;
}
-
+
+ void
+ setName(const std::string& name)
+ {
+ m_moduleName = name;
+ }
+
private:
std::string m_moduleName;
- uint32_t m_enabledLogLevel;
+ LogLevel m_enabledLogLevel;
};
-std::ostream&
-operator<<(std::ostream& output, const Logger& obj);
+inline std::ostream&
+operator<<(std::ostream& output, const Logger& obj)
+{
+ output << obj.getName();
+ return output;
+}
+
+} // namespace nfd
+
+#include "core/logger-factory.hpp"
+
+namespace nfd {
#define NFD_LOG_INIT(name) \
- static nfd::Logger \
- g_logger = nfd::Logger(name);
+static nfd::Logger& g_logger = nfd::LoggerFactory::create(name);
#define NFD_LOG_INCLASS_DECLARE() \
- static nfd::Logger g_logger;
+static nfd::Logger& g_logger;
#define NFD_LOG_INCLASS_DEFINE(cls, name) \
- nfd::Logger cls::g_logger = nfd::Logger(name);
+nfd::Logger& cls::g_logger = nfd::LoggerFactory::create(name);
#define NFD_LOG_INCLASS_TEMPLATE_DEFINE(cls, name) \
- template<class T> \
- nfd::Logger cls<T>::g_logger = nfd::Logger(name);
+template<class T> \
+nfd::Logger& cls<T>::g_logger = nfd::LoggerFactory::create(name);
-#define NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(cls, specialization, name) \
- template<> \
- nfd::Logger cls<specialization>::g_logger = nfd::Logger(name);
+#define NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(cls, specialization, name) \
+template<> \
+nfd::Logger& cls<specialization>::g_logger = nfd::LoggerFactory::create(name);
#define NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(cls, s1, s2, name) \
- template<> \
- nfd::Logger cls<s1, s2>::g_logger = nfd::Logger(name);
+template<> \
+nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name);
+
#define NFD_LOG_TRACE(expression) \
- if(g_logger.isEnabled(nfd::LOG_TRACE)) \
- std::cerr<<"TRACE: "<<"["<<g_logger<<"] " << expression << "\n"
+if (g_logger.isEnabled(nfd::LOG_TRACE)) \
+ std::cerr<<"TRACE: "<<"["<<g_logger<<"] " << expression << "\n"
#define NFD_LOG_DEBUG(expression)\
- if(g_logger.isEnabled(nfd::LOG_DEBUG)) \
- std::cerr<<"DEBUG: "<<"["<<g_logger<<"] " << expression <<"\n"
+if (g_logger.isEnabled(nfd::LOG_DEBUG)) \
+ std::cerr<<"DEBUG: "<<"["<<g_logger<<"] " << expression <<"\n"
-#define NFD_LOG_WARN(expression) \
- if(g_logger.isEnabled(nfd::LOG_WARN)) \
- std::cerr<<"WARNING: "<<"["<<g_logger<<"] " << expression <<"\n"
+#define NFD_LOG_WARN(expression) \
+if (g_logger.isEnabled(nfd::LOG_WARN)) \
+ std::cerr<<"WARNING: "<<"["<<g_logger<<"] " << expression <<"\n"
#define NFD_LOG_INFO(expression)\
- if(g_logger.isEnabled(nfd::LOG_INFO)) \
- std::cerr<<"INFO: "<<"["<<g_logger<<"] " << expression <<"\n"
-
-#define NFD_LOG_ERROR(expression)\
- if(g_logger.isEnabled(nfd::LOG_ERROR)) \
- std::cerr<<"ERROR: "<<"["<<g_logger<<"] " << expression <<"\n"
-
-#define NFD_LOG_FATAL(expression)\
- std::cerr<<"FATAL: "<<"["<<g_logger<<"] " << expression <<"\n"
-
-} //namespace nfd
+if (g_logger.isEnabled(nfd::LOG_INFO)) \
+ std::cerr<<"INFO: "<<"["<<g_logger<<"] " << expression <<"\n"
+#define NFD_LOG_ERROR(expression) \
+if (g_logger.isEnabled(nfd::LOG_ERROR)) \
+ std::cerr<<"ERROR: "<<"["<<g_logger<<"] " << expression <<"\n"
+
+#define NFD_LOG_FATAL(expression)\
+std::cerr<<"FATAL: "<<"["<<g_logger<<"] " << expression <<"\n"
+
+} //namespace nfd
#endif
diff --git a/daemon/core/network-interface.cpp b/daemon/core/network-interface.cpp
index 65a690c..7319e97 100644
--- a/daemon/core/network-interface.cpp
+++ b/daemon/core/network-interface.cpp
@@ -5,6 +5,7 @@
*/
#include "network-interface.hpp"
+#include "core/logger.hpp"
#include <boost/foreach.hpp>
diff --git a/daemon/face/datagram-face.hpp b/daemon/face/datagram-face.hpp
index cbda459..f59374f 100644
--- a/daemon/face/datagram-face.hpp
+++ b/daemon/face/datagram-face.hpp
@@ -8,6 +8,7 @@
#define NFD_FACE_DATAGRAM_FACE_HPP
#include "face.hpp"
+#include "core/logger.hpp"
namespace nfd {
@@ -30,14 +31,14 @@
virtual
~DatagramFace();
-
+
// from Face
virtual void
sendInterest(const Interest& interest);
-
+
virtual void
sendData(const Data& data);
-
+
virtual void
close();
@@ -54,13 +55,13 @@
*/
void
resetRecentUsage();
-
+
bool
hasBeenUsedRecently() const;
void
setOnDemand(bool isOnDemand);
-
+
protected:
void
receiveDatagram(const uint8_t* buffer,
@@ -69,10 +70,10 @@
void
keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face);
-
+
void
closeSocket();
-
+
protected:
shared_ptr<typename protocol::socket> m_socket;
uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
@@ -101,7 +102,7 @@
DatagramFace<T>::~DatagramFace()
{
}
-
+
template <class T>
inline void
DatagramFace<T>::sendInterest(const Interest& interest)
@@ -110,10 +111,10 @@
m_socket->async_send(boost::asio::buffer(interest.wireEncode().wire(),
interest.wireEncode().size()),
bind(&DatagramFace<T>::handleSend, this, _1, interest.wireEncode()));
-
+
// anything else should be done here?
}
-
+
template <class T>
inline void
DatagramFace<T>::sendData(const Data& data)
@@ -122,7 +123,7 @@
m_socket->async_send(boost::asio::buffer(data.wireEncode().wire(),
data.wireEncode().size()),
bind(&DatagramFace<T>::handleSend, this, _1, data.wireEncode()));
-
+
// anything else should be done here?
}
@@ -134,20 +135,20 @@
if (error != 0) {
if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
return;
-
+
if (!m_socket->is_open())
{
onFail("Tunnel closed");
return;
}
-
+
NFD_LOG_WARN("[id:" << this->getId()
<< ",endpoint:" << m_socket->local_endpoint()
<< "] Send operation failed, closing socket: "
<< error.category().message(error.value()));
-
+
closeSocket();
-
+
if (error == boost::asio::error::eof)
{
onFail("Tunnel closed");
@@ -159,24 +160,24 @@
}
return;
}
-
+
NFD_LOG_TRACE("[id:" << this->getId()
<< ",endpoint:" << m_socket->local_endpoint()
<< "] Successfully sent: " << wire.size() << " bytes");
// do nothing (needed to retain validity of wire memory block
}
-
+
template <class T>
inline void
DatagramFace<T>::close()
{
if (!m_socket->is_open())
return;
-
+
NFD_LOG_INFO("[id:" << this->getId()
<< ",endpoint:" << m_socket->local_endpoint()
<< "] Close tunnel");
-
+
closeSocket();
onFail("Close tunnel");
}
@@ -273,20 +274,20 @@
DatagramFace<T>::keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face)
{
}
-
+
template <class T>
inline void
DatagramFace<T>::closeSocket()
{
NFD_LOG_DEBUG("closeSocket " << m_socket->local_endpoint());
boost::asio::io_service& io = m_socket->get_io_service();
-
+
// use the non-throwing variants and ignore errors, if any
boost::system::error_code error;
m_socket->shutdown(protocol::socket::shutdown_both, error);
m_socket->close(error);
// after this, handlers will be called with an error code
-
+
// ensure that the Face object is alive at least until all pending
// handlers are dispatched
io.post(bind(&DatagramFace<T>::keepFaceAliveUntilAllHandlersExecuted,
diff --git a/daemon/face/ethernet-face.cpp b/daemon/face/ethernet-face.cpp
index e619724..66dcf08 100644
--- a/daemon/face/ethernet-face.cpp
+++ b/daemon/face/ethernet-face.cpp
@@ -5,6 +5,7 @@
*/
#include "ethernet-face.hpp"
+#include "core/logger.hpp"
#include "core/network-interface.hpp"
#include <pcap/pcap.h>
diff --git a/daemon/face/ethernet-factory.cpp b/daemon/face/ethernet-factory.cpp
index 2801c4f..4b1d8c1 100644
--- a/daemon/face/ethernet-factory.cpp
+++ b/daemon/face/ethernet-factory.cpp
@@ -5,6 +5,7 @@
*/
#include "ethernet-factory.hpp"
+#include "core/logger.hpp"
#include "core/global-io.hpp"
#include "core/network-interface.hpp"
diff --git a/daemon/face/multicast-udp-face.cpp b/daemon/face/multicast-udp-face.cpp
index b5632e2..34d40f0 100644
--- a/daemon/face/multicast-udp-face.cpp
+++ b/daemon/face/multicast-udp-face.cpp
@@ -33,7 +33,7 @@
interest.wireEncode().size()),
m_multicastGroup,
bind(&DatagramFace<protocol>::handleSend, this, _1, interest.wireEncode()));
-
+
// anything else should be done here?
}
diff --git a/daemon/face/stream-face.hpp b/daemon/face/stream-face.hpp
index a1aa7c1..1b5b124 100644
--- a/daemon/face/stream-face.hpp
+++ b/daemon/face/stream-face.hpp
@@ -9,6 +9,7 @@
#include "face.hpp"
#include "local-face.hpp"
+#include "core/logger.hpp"
namespace nfd {
diff --git a/daemon/fw/client-control-strategy.cpp b/daemon/fw/client-control-strategy.cpp
index 5028879..14b138d 100644
--- a/daemon/fw/client-control-strategy.cpp
+++ b/daemon/fw/client-control-strategy.cpp
@@ -5,6 +5,7 @@
*/
#include "client-control-strategy.hpp"
+#include "core/logger.hpp"
namespace nfd {
namespace fw {
diff --git a/daemon/fw/face-table.cpp b/daemon/fw/face-table.cpp
index ca7b56f..8601598 100644
--- a/daemon/fw/face-table.cpp
+++ b/daemon/fw/face-table.cpp
@@ -6,6 +6,7 @@
#include "face-table.hpp"
#include "forwarder.hpp"
+#include "core/logger.hpp"
namespace nfd {
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index 58ce5a3..8ffda2f 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -6,6 +6,7 @@
#include "forwarder.hpp"
#include "available-strategies.hpp"
+#include "core/logger.hpp"
namespace nfd {
@@ -26,6 +27,11 @@
fw::installStrategies(*this);
}
+Forwarder::~Forwarder()
+{
+
+}
+
void
Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
{
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index c3898c6..51a75dc 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -32,6 +32,9 @@
public:
Forwarder();
+ VIRTUAL_WITH_TESTS
+ ~Forwarder();
+
const ForwarderCounters&
getCounters() const;
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index d41786d..8ce46c1 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -6,6 +6,7 @@
#include "strategy.hpp"
#include "forwarder.hpp"
+#include "core/logger.hpp"
namespace nfd {
namespace fw {
diff --git a/daemon/main.cpp b/daemon/main.cpp
index dff26cd..542d2a0 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -24,39 +24,81 @@
struct ProgramOptions
{
bool showUsage;
+ bool showModules;
std::string config;
};
class Nfd : noncopyable
{
public:
- explicit
- Nfd(const std::string& configFile)
- : m_internalFace(new InternalFace())
- , m_fibManager(m_forwarder.getFib(),
- bind(&Forwarder::getFace, &m_forwarder, _1),
- m_internalFace)
- , m_faceManager(m_forwarder.getFaceTable(), m_internalFace)
- , m_strategyChoiceManager(m_forwarder.getStrategyChoice(), m_internalFace)
- , m_statusServer(m_internalFace, m_forwarder)
+
+ void
+ initialize(const std::string& configFile)
{
+ initializeLogging(configFile);
+
+ m_forwarder = make_shared<Forwarder>();
+
+ initializeManagement(configFile);
+ }
+
+
+ void
+ initializeLogging(const std::string& configFile)
+ {
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
+ {
+ if (SUPPORTED_CONFIG_SECTIONS[i] != "log")
+ {
+ config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
+ bind(std::plus<int>(), 0, 0)); // no-op.
+ }
+ }
+
+ config.parse(configFile, true);
+ config.parse(configFile, false);
+ }
+
+ void
+ initializeManagement(const std::string& configFile)
+ {
+ m_internalFace = make_shared<InternalFace>();
+
+ m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
+ bind(&Forwarder::getFace, m_forwarder.get(), _1),
+ m_internalFace);
+
+ m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
+ m_internalFace);
+
+ m_strategyChoiceManager =
+ make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
+ m_internalFace);
+
+ m_statusServer = make_shared<StatusServer>(m_internalFace,
+ boost::ref(*m_forwarder));
+
ConfigFile config;
m_internalFace->getValidator().setConfigFile(config);
- m_forwarder.addFace(m_internalFace);
+ m_forwarder->addFace(m_internalFace);
- m_faceManager.setConfigFile(config);
+ m_faceManager->setConfigFile(config);
+
+ config.addSectionHandler("log", bind(std::plus<int>(), 0, 0)); // no-op
// parse config file
config.parse(configFile, true);
config.parse(configFile, false);
// add FIB entry for NFD Management Protocol
- shared_ptr<fib::Entry> entry = m_forwarder.getFib().insert("/localhost/nfd").first;
+ shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
entry->addNextHop(m_internalFace, 0);
}
-
static void
printUsage(std::ostream& os, const std::string& programName)
{
@@ -67,21 +109,38 @@
<< "\n"
<< "Options:\n"
<< " [--help] - print this help message\n"
+ << " [--modules] - list available logging modules\n"
<< " [--config /path/to/nfd.conf] - path to configuration file "
<< "(default: " << DEFAULT_CONFIG_FILE << ")\n"
;
}
+ static void
+ printModules(std::ostream& os)
+ {
+ using namespace std;
+
+ os << "Available logging modules: \n";
+
+ list<string> modules(LoggerFactory::getInstance().getModules());
+ for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
+ {
+ os << *i << "\n";
+ }
+ }
+
static bool
parseCommandLine(int argc, char** argv, ProgramOptions& options)
{
options.showUsage = false;
+ options.showModules = false;
options.config = DEFAULT_CONFIG_FILE;
while (true) {
int optionIndex = 0;
static ::option longOptions[] = {
{ "help" , no_argument , 0, 0 },
+ { "modules", no_argument , 0, 0 },
{ "config" , required_argument, 0, 0 },
{ 0 , 0 , 0, 0 }
};
@@ -90,21 +149,23 @@
break;
switch (c) {
- case 0:
- switch (optionIndex) {
- case 0: // help
- options.showUsage = true;
+ case 0:
+ switch (optionIndex) {
+ case 0: // help
+ options.showUsage = true;
+ break;
+ case 1: // modules
+ options.showModules = true;
+ break;
+ case 2: // config
+ options.config = ::optarg;
+ break;
+ default:
+ return false;
+ }
break;
- case 1: // config
- options.config = ::optarg;
- break;
- default:
- return false;
- }
- break;
}
}
-
return true;
}
@@ -131,15 +192,28 @@
}
private:
- Forwarder m_forwarder;
- shared_ptr<InternalFace> m_internalFace;
+ shared_ptr<Forwarder> m_forwarder;
- FibManager m_fibManager;
- FaceManager m_faceManager;
- StrategyChoiceManager m_strategyChoiceManager;
- StatusServer m_statusServer;
+ shared_ptr<InternalFace> m_internalFace;
+ shared_ptr<FibManager> m_fibManager;
+ shared_ptr<FaceManager> m_faceManager;
+ shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
+ shared_ptr<StatusServer> m_statusServer;
+
+ static const std::string SUPPORTED_CONFIG_SECTIONS[];
+ static const size_t N_SUPPORTED_CONFIG_SECTIONS;
};
+const std::string Nfd::SUPPORTED_CONFIG_SECTIONS[] =
+ {
+ "log",
+ "face_system",
+ "authorizations",
+ };
+
+const size_t Nfd::N_SUPPORTED_CONFIG_SECTIONS =
+ sizeof(SUPPORTED_CONFIG_SECTIONS) / sizeof(std::string);
+
} // namespace nfd
int
@@ -158,33 +232,46 @@
return 0;
}
+ if (options.showModules) {
+ Nfd::printModules(std::cout);
+ return 0;
+ }
+
+ Nfd nfdInstance;
+
try {
- Nfd nfdInstance(options.config);
-
- boost::asio::signal_set signalSet(getGlobalIoService());
- signalSet.add(SIGINT);
- signalSet.add(SIGTERM);
- signalSet.add(SIGHUP);
- signalSet.add(SIGUSR1);
- signalSet.add(SIGUSR2);
- signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
- boost::ref(signalSet)));
-
- getGlobalIoService().run();
+ nfdInstance.initialize(options.config);
}
catch (boost::filesystem::filesystem_error& e) {
if (e.code() == boost::system::errc::permission_denied) {
- NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". "
- << argv[0] << " should be run as superuser");
+ NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
+ argv[0] << " should be run as superuser");
}
else {
NFD_LOG_FATAL(e.what());
}
+ return 1;
+ }
+ catch (const std::exception& e) {
+ NFD_LOG_FATAL(e.what());
return 2;
}
+
+ boost::asio::signal_set signalSet(getGlobalIoService());
+ signalSet.add(SIGINT);
+ signalSet.add(SIGTERM);
+ signalSet.add(SIGHUP);
+ signalSet.add(SIGUSR1);
+ signalSet.add(SIGUSR2);
+ signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
+ boost::ref(signalSet)));
+
+ try {
+ getGlobalIoService().run();
+ }
catch (std::exception& e) {
NFD_LOG_FATAL(e.what());
- return 1;
+ return 3;
}
return 0;
diff --git a/daemon/mgmt/command-validator.cpp b/daemon/mgmt/command-validator.cpp
index fd8a124..eb76572 100644
--- a/daemon/mgmt/command-validator.cpp
+++ b/daemon/mgmt/command-validator.cpp
@@ -5,6 +5,8 @@
*/
#include "command-validator.hpp"
+#include "core/logger.hpp"
+
#include <ndn-cpp-dev/util/io.hpp>
#include <ndn-cpp-dev/security/identity-certificate.hpp>
@@ -178,4 +180,3 @@
}
} // namespace nfd
-
diff --git a/daemon/mgmt/command-validator.hpp b/daemon/mgmt/command-validator.hpp
index 290cabd..0162796 100644
--- a/daemon/mgmt/command-validator.hpp
+++ b/daemon/mgmt/command-validator.hpp
@@ -7,6 +7,7 @@
#ifndef NFD_MGMT_COMMAND_VALIDATOR_HPP
#define NFD_MGMT_COMMAND_VALIDATOR_HPP
+#include "common.hpp"
#include "config-file.hpp"
#include <ndn-cpp-dev/util/command-interest-validator.hpp>
@@ -19,6 +20,7 @@
class Error : public std::runtime_error
{
public:
+ explicit
Error(const std::string& what)
: std::runtime_error(what)
{
diff --git a/daemon/mgmt/config-file.cpp b/daemon/mgmt/config-file.cpp
index d0eddd5..bc1a495 100644
--- a/daemon/mgmt/config-file.cpp
+++ b/daemon/mgmt/config-file.cpp
@@ -4,8 +4,8 @@
* See COPYING for copyright and distribution information.
*/
-
#include "config-file.hpp"
+#include "core/logger.hpp"
#include <boost/property_tree/info_parser.hpp>
@@ -105,4 +105,3 @@
}
}
-
diff --git a/daemon/mgmt/config-file.hpp b/daemon/mgmt/config-file.hpp
index 15eca05..dd5a43c 100644
--- a/daemon/mgmt/config-file.hpp
+++ b/daemon/mgmt/config-file.hpp
@@ -25,6 +25,7 @@
class Error : public std::runtime_error
{
public:
+ explicit
Error(const std::string& what)
: std::runtime_error(what)
{
@@ -86,4 +87,3 @@
#endif // NFD_MGMT_CONFIG_FILE_HPP
-
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 518021a..55f4d9c 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -6,6 +6,7 @@
#include "face-manager.hpp"
+#include "core/logger.hpp"
#include "core/face-uri.hpp"
#include "core/network-interface.hpp"
#include "fw/face-table.hpp"
diff --git a/daemon/mgmt/face-status-publisher.cpp b/daemon/mgmt/face-status-publisher.cpp
index 89c731e..3589d7b 100644
--- a/daemon/mgmt/face-status-publisher.cpp
+++ b/daemon/mgmt/face-status-publisher.cpp
@@ -3,7 +3,9 @@
* Copyright (C) 2014 Named Data Networking Project
* See COPYING for copyright and distribution information.
*/
+
#include "face-status-publisher.hpp"
+#include "core/logger.hpp"
namespace nfd {
diff --git a/daemon/mgmt/fib-enumeration-publisher.cpp b/daemon/mgmt/fib-enumeration-publisher.cpp
index 79532ba..b672e7e 100644
--- a/daemon/mgmt/fib-enumeration-publisher.cpp
+++ b/daemon/mgmt/fib-enumeration-publisher.cpp
@@ -6,7 +6,7 @@
#include "fib-enumeration-publisher.hpp"
-#include "common.hpp"
+#include "core/logger.hpp"
#include <ndn-cpp-dev/management/nfd-fib-entry.hpp>
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 0bf4f34..34554e6 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -6,6 +6,7 @@
#include "fib-manager.hpp"
+#include "core/logger.hpp"
#include "table/fib.hpp"
#include "fw/forwarder.hpp"
#include "mgmt/internal-face.hpp"
diff --git a/daemon/mgmt/internal-face.cpp b/daemon/mgmt/internal-face.cpp
index 81bd2de..a5bcf5a 100644
--- a/daemon/mgmt/internal-face.cpp
+++ b/daemon/mgmt/internal-face.cpp
@@ -5,6 +5,7 @@
*/
#include "internal-face.hpp"
+#include "core/logger.hpp"
#include "core/global-io.hpp"
namespace nfd {
diff --git a/daemon/mgmt/manager-base.cpp b/daemon/mgmt/manager-base.cpp
index 08d845c..e608ffc 100644
--- a/daemon/mgmt/manager-base.cpp
+++ b/daemon/mgmt/manager-base.cpp
@@ -5,6 +5,7 @@
*/
#include "manager-base.hpp"
+#include "core/logger.hpp"
namespace nfd {
diff --git a/daemon/mgmt/segment-publisher.cpp b/daemon/mgmt/segment-publisher.cpp
index 82ae31e..993330f 100644
--- a/daemon/mgmt/segment-publisher.cpp
+++ b/daemon/mgmt/segment-publisher.cpp
@@ -6,7 +6,7 @@
#include "segment-publisher.hpp"
-#include "common.hpp"
+#include "core/logger.hpp"
#include "face/face.hpp"
#include <ndn-cpp-dev/util/time.hpp>
diff --git a/daemon/mgmt/strategy-choice-manager.cpp b/daemon/mgmt/strategy-choice-manager.cpp
index a4c4e38..43824f2 100644
--- a/daemon/mgmt/strategy-choice-manager.cpp
+++ b/daemon/mgmt/strategy-choice-manager.cpp
@@ -6,6 +6,7 @@
#include "strategy-choice-manager.hpp"
#include "table/strategy-choice.hpp"
+#include "core/logger.hpp"
#include "mgmt/app-face.hpp"
namespace nfd {
@@ -166,5 +167,3 @@
} // namespace nfd
-
-
diff --git a/daemon/table/cs-entry.cpp b/daemon/table/cs-entry.cpp
index 9e99886..c98a66c 100644
--- a/daemon/table/cs-entry.cpp
+++ b/daemon/table/cs-entry.cpp
@@ -7,6 +7,7 @@
*/
#include "cs-entry.hpp"
+#include "core/logger.hpp"
namespace nfd {
namespace cs {
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index bad684e..a4c0525 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -7,6 +7,8 @@
*/
#include "cs.hpp"
+#include "core/logger.hpp"
+
#include <ndn-cpp-dev/util/crypto.hpp>
#define SKIPLIST_MAX_LAYERS 32
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index db4d498..ee63d04 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -5,6 +5,7 @@
*/
#include "strategy-choice.hpp"
+#include "core/logger.hpp"
#include "fw/strategy.hpp"
#include "pit-entry.hpp"
#include "measurements-entry.hpp"
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 3cbfc0f..b825cca 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -3,6 +3,38 @@
; {
; }
+log
+{
+ ; default_level specifies the logging level for modules
+ ; that are not explicitly named. All debugging levels
+ ; listed above the selected value are enabled.
+ ;
+ ; Valid values:
+ ;
+ ; NONE ; no messages
+ ; ERROR ; error messages
+ ; WARN ; warning messages
+ ; INFO ; informational messages (default)
+ ; DEBUG ; debugging messages
+ ; TRACE ; trace messages (most verbose)
+ ; ALL ; all messages
+
+ ; default_level INFO
+
+ ; You may override default_level by assigning a logging level
+ ; to the desired module name. Module names can be found in two ways:
+ ;
+ ; Run:
+ ; nfd --modules
+ ;
+ ; Or look for NFD_LOG_INIT(<module name>) statements in .cpp files
+ ;
+ ; Example module-level settings:
+ ;
+ ; FibManager DEBUG
+ ; Forwarder INFO
+}
+
; The face_system section defines what faces and channels are created.
face_system
{
diff --git a/tests/core/global-configuration.cpp b/tests/core/global-configuration.cpp
new file mode 100644
index 0000000..a288147
--- /dev/null
+++ b/tests/core/global-configuration.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "../test-common.hpp"
+#include "core/logger.hpp"
+#include "mgmt/config-file.hpp"
+
+#include <boost/filesystem.hpp>
+
+namespace nfd {
+namespace tests {
+
+class GlobalConfigurationFixture
+{
+public:
+ GlobalConfigurationFixture()
+ {
+ const std::string filename = "unit-tests.conf";
+ if (boost::filesystem::exists(filename))
+ {
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ config.parse(filename, false);
+ }
+ }
+};
+
+BOOST_GLOBAL_FIXTURE(GlobalConfigurationFixture)
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/core/limited-io.cpp b/tests/core/limited-io.cpp
index a7b1115..784bddf 100644
--- a/tests/core/limited-io.cpp
+++ b/tests/core/limited-io.cpp
@@ -5,6 +5,7 @@
*/
#include "limited-io.hpp"
+#include "core/logger.hpp"
namespace nfd {
namespace tests {
diff --git a/tests/core/logger.cpp b/tests/core/logger.cpp
index 0530dcc..0aa2e47 100644
--- a/tests/core/logger.cpp
+++ b/tests/core/logger.cpp
@@ -7,7 +7,9 @@
*/
#include "core/logger.hpp"
+
#include <boost/test/unit_test.hpp>
+
#include <iostream>
#include "tests/test-common.hpp"
@@ -17,10 +19,12 @@
BOOST_FIXTURE_TEST_SUITE(CoreLogger, BaseFixture)
-struct LoggerFixture : protected BaseFixture
+class LoggerFixture : protected BaseFixture
{
+public:
LoggerFixture()
: m_savedBuf(std::cerr.rdbuf())
+ , m_savedLevel(LoggerFactory::getInstance().getDefaultLevel())
{
std::cerr.rdbuf(m_buffer.rdbuf());
}
@@ -28,10 +32,12 @@
~LoggerFixture()
{
std::cerr.rdbuf(m_savedBuf);
+ LoggerFactory::getInstance().setDefaultLevel(m_savedLevel);
}
std::stringstream m_buffer;
std::streambuf* m_savedBuf;
+ LogLevel m_savedLevel;
};
BOOST_FIXTURE_TEST_CASE(Basic, LoggerFixture)
@@ -56,9 +62,172 @@
);
}
+BOOST_FIXTURE_TEST_CASE(ConfigureFactory, LoggerFixture)
+{
+ NFD_LOG_INIT("ConfigureFactoryTests");
+
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " default_level INFO\n"
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ config.parse(LOG_CONFIG, false, "LOG_CONFIG");
+
+ NFD_LOG_TRACE("trace message JHGFDSR^1");
+ NFD_LOG_DEBUG("debug message IGg2474fdksd fo " << 15 << 16 << 17);
+ NFD_LOG_WARN("warning message XXXhdhd11" << 1 << "x");
+ NFD_LOG_INFO("info message Jjxjshj13");
+ NFD_LOG_ERROR("error message !#$&^%$#@");
+ NFD_LOG_FATAL("fatal message JJSjaamcng");
+
+ BOOST_CHECK_EQUAL(m_buffer.str(),
+ "WARNING: [ConfigureFactoryTests] warning message XXXhdhd111x\n"
+ "INFO: [ConfigureFactoryTests] info message Jjxjshj13\n"
+ "ERROR: [ConfigureFactoryTests] error message !#$&^%$#@\n"
+ "FATAL: [ConfigureFactoryTests] fatal message JJSjaamcng\n"
+ );
+}
+
+BOOST_FIXTURE_TEST_CASE(TestNumberLevel, LoggerFixture)
+{
+ NFD_LOG_INIT("TestNumberLevel");
+
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " default_level 2\n" // equivalent of WARN
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ config.parse(LOG_CONFIG, false, "LOG_CONFIG");
+
+ NFD_LOG_TRACE("trace message JHGFDSR^1");
+ NFD_LOG_DEBUG("debug message IGg2474fdksd fo " << 15 << 16 << 17);
+ NFD_LOG_WARN("warning message XXXhdhd11" << 1 << "x");
+ NFD_LOG_INFO("info message Jjxjshj13");
+ NFD_LOG_ERROR("error message !#$&^%$#@");
+ NFD_LOG_FATAL("fatal message JJSjaamcng");
+
+ BOOST_CHECK_EQUAL(m_buffer.str(),
+ "WARNING: [TestNumberLevel] warning message XXXhdhd111x\n"
+ "ERROR: [TestNumberLevel] error message !#$&^%$#@\n"
+ "FATAL: [TestNumberLevel] fatal message JJSjaamcng\n"
+ );
+}
+
+static void
+testModuleBPrint()
+{
+ NFD_LOG_INIT("TestModuleB");
+ NFD_LOG_DEBUG("debug message IGg2474fdksd fo " << 15 << 16 << 17);
+}
+
+BOOST_FIXTURE_TEST_CASE(LimitModules, LoggerFixture)
+{
+ NFD_LOG_INIT("TestModuleA");
+
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " default_level WARN\n"
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ config.parse(LOG_CONFIG, false, "LOG_CONFIG");
+
+ // this should print
+ NFD_LOG_WARN("warning message XXXhdhd11" << 1 << "x");
+
+ // this should not because it's level is < WARN
+ testModuleBPrint();
+
+ BOOST_CHECK_EQUAL(m_buffer.str(),
+ "WARNING: [TestModuleA] warning message XXXhdhd111x\n"
+ );
+}
+
+BOOST_FIXTURE_TEST_CASE(ExplicitlySetModule, LoggerFixture)
+{
+ NFD_LOG_INIT("TestModuleA");
+
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " default_level WARN\n"
+ " TestModuleB DEBUG\n"
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ config.parse(LOG_CONFIG, false, "LOG_CONFIG");
+
+ // this should print
+ NFD_LOG_WARN("warning message XXXhdhd11" << 1 << "x");
+
+ // this too because its level is explicitly set to DEBUG
+ testModuleBPrint();
+
+ BOOST_CHECK_EQUAL(m_buffer.str(),
+ "WARNING: [TestModuleA] warning message XXXhdhd111x\n"
+ "DEBUG: [TestModuleB] debug message IGg2474fdksd fo 151617\n"
+ );
+}
+
+static bool
+checkError(const LoggerFactory::Error& error, const std::string& expected)
+{
+ return error.what() == expected;
+}
+
+BOOST_FIXTURE_TEST_CASE(UnknownLevelString, LoggerFixture)
+{
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " default_level TestMadeUpLevel\n"
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ BOOST_REQUIRE_EXCEPTION(config.parse(LOG_CONFIG, false, "LOG_CONFIG"),
+ LoggerFactory::Error,
+ bind(&checkError,
+ _1,
+ "Unsupported logging level \"TestMadeUpLevel\""));
+}
+
+BOOST_FIXTURE_TEST_CASE(UnknownOption, LoggerFixture)
+{
+ const std::string LOG_CONFIG =
+ "log\n"
+ "{\n"
+ " TestMadeUpOption\n"
+ "}\n";
+
+ ConfigFile config;
+ LoggerFactory::getInstance().setConfigFile(config);
+
+ BOOST_REQUIRE_EXCEPTION(config.parse(LOG_CONFIG, false, "LOG_CONFIG"),
+ LoggerFactory::Error,
+ bind(&checkError,
+ _1,
+ "No logging level found for option \"TestMadeUpOption\""));
+}
+
class InClassLogger : public LoggerFixture
{
public:
+
InClassLogger()
{
g_logger.setLogLevel(LOG_ALL);
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index 8095431..c65d1c2 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -9,6 +9,7 @@
#include <boost/test/unit_test.hpp>
#include "core/global-io.hpp"
+#include "core/logger.hpp"
#include <ndn-cpp-dev/security/key-chain.hpp>
namespace nfd {
diff --git a/unit-tests.conf.sample b/unit-tests.conf.sample
new file mode 100644
index 0000000..d75c19c
--- /dev/null
+++ b/unit-tests.conf.sample
@@ -0,0 +1,31 @@
+log
+{
+ ; default_level specifies the logging level for modules
+ ; that are not explicitly named. All debugging levels
+ ; listed above the selected value are enabled.
+ ;
+ ; Valid values:
+ ;
+ ; NONE ; no messages
+ ; ERROR ; error messages
+ ; WARN ; warning messages
+ ; INFO ; informational messages (default)
+ ; DEBUG ; debugging messages
+ ; TRACE ; trace messages (most verbose)
+ ; ALL ; all messages
+
+ ; default_level INFO
+
+ ; You may override default_level by assigning a logging level
+ ; to the desired module name. Module names can be found in two ways:
+ ;
+ ; Run:
+ ; nfd --modules
+ ;
+ ; Or look for NFD_LOG_INIT(<module name>) statements in .cpp files
+ ;
+ ; Example module-level settings:
+ ;
+ ; FibManager DEBUG
+ ; Forwarder INFO
+}
\ No newline at end of file