conf: Make event intervals configurable

User can specify the intervals for the first Hello Interest,
AdjLsa building, and routing calculation in the conf file.

refs: #2071

Change-Id: Ic8eb29d433069086955178bc42b5f8fc8f4149d3
diff --git a/nlsr.conf b/nlsr.conf
index f669d7f..52ce870 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -49,6 +49,16 @@
    hello-interval  60                  ; interest sending interval in seconds. Default value 60
                                        ; valid values 30-90
 
+  ; adj-lsa-build-interval is the time to wait in seconds after an Adjacency LSA build is scheduled
+  ; before actually building the Adjacency LSA
+
+  adj-lsa-build-interval 5   ; default value 5. Valid values 0-5. It is recommended that
+                             ; adj-lsa-build-interval have a lower value than routing-calc-interval
+
+  ; first-hello-interval is the time to wait in seconds before sending the first Hello Interest
+
+  first-hello-interval  10   ; Default value 10. Valid values 0-10
+
   ; neighbor command is used to configure router's neighbor. Each neighbor will need
   ; one block of neighbor command
 
@@ -98,6 +108,12 @@
 
   max-faces-per-prefix 3   ; default value 0. Valid value 0-60. By default (value 0) NLSR adds
                            ; all available faces for each reachable name prefixes in NDN FIB
+
+  ; routing-calc-interval is the time to wait in seconds after a routing table calculation is
+  ; scheduled before actually performing the routing table calculation
+
+  routing-calc-interval 15   ; default value 15. Valid values 0-15. It is recommended that
+                             ; routing-calc-interval have a higher value than adj-lsa-build-interval
 }
 
 ; the advertising section contains the configuration settings of the name prefixes
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 45890d1..bf07bee 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -39,6 +39,105 @@
 
 using namespace std;
 
+template <class T>
+class ConfigurationVariable
+{
+public:
+  typedef ndn::function<void(T)> ConfParameterCallback;
+  typedef boost::property_tree::ptree ConfigSection;
+
+  ConfigurationVariable(const std::string& key, const ConfParameterCallback& setter)
+    : m_key(key)
+    , m_setterCallback(setter)
+    , m_minValue(0)
+    , m_maxValue(0)
+    , m_shouldCheckRange(false)
+    , m_isRequired(true)
+  {
+  }
+
+  bool
+  parseFromConfigSection(const ConfigSection& section)
+  {
+    try {
+      T value = section.get<T>(m_key);
+
+      if (!isValidValue(value)) {
+        return false;
+      }
+
+      m_setterCallback(value);
+      return true;
+    }
+    catch (const std::exception& ex) {
+
+      if (m_isRequired) {
+        std::cerr << ex.what() << std::endl;
+        std::cerr << "Missing required configuration variable" << std::endl;
+        return false;
+      }
+      else {
+        m_setterCallback(m_defaultValue);
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  void
+  setMinAndMaxValue(T min, T max)
+  {
+    m_minValue = min;
+    m_maxValue = max;
+    m_shouldCheckRange = true;
+  }
+
+  void
+  setOptional(T defaultValue)
+  {
+    m_isRequired = false;
+    m_defaultValue = defaultValue;
+  }
+
+private:
+  void
+  printOutOfRangeError(T value)
+  {
+    std::cerr << "Invalid value for " << m_key << ": "
+              << value << ". "
+              << "Valid values: "
+              << m_minValue << " - "
+              << m_maxValue << std::endl;
+  }
+
+  bool
+  isValidValue(T value)
+  {
+    if (!m_shouldCheckRange) {
+      return true;
+    }
+    else if (value < m_minValue || value > m_maxValue)
+    {
+      printOutOfRangeError(value);
+      return false;
+    }
+
+    return true;
+  }
+
+private:
+  const std::string m_key;
+  const ConfParameterCallback m_setterCallback;
+  T m_defaultValue;
+
+  T m_minValue;
+  T m_maxValue;
+
+  bool m_shouldCheckRange;
+  bool m_isRequired;
+};
+
 bool
 ConfFileProcessor::processConfFile()
 {
@@ -325,6 +424,30 @@
   catch (const std::exception& ex) {
     std::cerr << ex.what() << std::endl;
   }
+
+  // Event intervals
+  // adj-lsa-build-interval
+  ConfigurationVariable<uint32_t> adjLsaBuildInterval("adj-lsa-build-interval",
+                                                      bind(&ConfParameter::setAdjLsaBuildInterval,
+                                                      &m_nlsr.getConfParameter(), _1));
+  adjLsaBuildInterval.setMinAndMaxValue(ADJ_LSA_BUILD_INTERVAL_MIN, ADJ_LSA_BUILD_INTERVAL_MAX);
+  adjLsaBuildInterval.setOptional(ADJ_LSA_BUILD_INTERVAL_DEFAULT);
+
+  if (!adjLsaBuildInterval.parseFromConfigSection(section)) {
+    return false;
+  }
+
+  // first-hello-interval
+  ConfigurationVariable<uint32_t> firstHelloInterval("first-hello-interval",
+                                                     bind(&ConfParameter::setFirstHelloInterval,
+                                                     &m_nlsr.getConfParameter(), _1));
+  firstHelloInterval.setMinAndMaxValue(FIRST_HELLO_INTERVAL_MIN, FIRST_HELLO_INTERVAL_MAX);
+  firstHelloInterval.setOptional(FIRST_HELLO_INTERVAL_DEFAULT);
+
+  if (!firstHelloInterval.parseFromConfigSection(section)) {
+    return false;
+  }
+
   for (ConfigSection::const_iterator tn =
            section.begin(); tn != section.end(); ++tn) {
 
@@ -425,6 +548,18 @@
     cerr << ex.what() << endl;
     return false;
   }
+
+  // routing-calc-interval
+  ConfigurationVariable<uint32_t> routingCalcInterval("routing-calc-interval",
+                                                      bind(&ConfParameter::setRoutingCalcInterval,
+                                                      &m_nlsr.getConfParameter(), _1));
+  routingCalcInterval.setMinAndMaxValue(ROUTING_CALC_INTERVAL_MIN, ROUTING_CALC_INTERVAL_MAX);
+  routingCalcInterval.setOptional(ROUTING_CALC_INTERVAL_DEFAULT);
+
+  if (!routingCalcInterval.parseFromConfigSection(section)) {
+    return false;
+  }
+
   return true;
 }
 
diff --git a/src/conf-parameter.cpp b/src/conf-parameter.cpp
index f45fea7..f2b8bd2 100644
--- a/src/conf-parameter.cpp
+++ b/src/conf-parameter.cpp
@@ -34,7 +34,7 @@
   _LOG_DEBUG("Site Name: " << m_siteName);
   _LOG_DEBUG("Network: " << m_network);
   _LOG_DEBUG("Router Prefix: " << m_routerPrefix);
-  _LOG_DEBUG("ChronoSync sync Prifex: " << m_chronosyncPrefix);
+  _LOG_DEBUG("ChronoSync sync Prefix: " << m_chronosyncPrefix);
   _LOG_DEBUG("ChronoSync LSA prefix: " << m_lsaPrefix);
   _LOG_DEBUG("Hello Interest retry number: " << m_interestRetryNumber);
   _LOG_DEBUG("Hello Interest resend second: " << m_interestResendTime);
@@ -42,11 +42,16 @@
   _LOG_DEBUG("LSA refresh time: " << m_lsaRefreshTime);
   _LOG_DEBUG("LSA Interest lifetime: " << getLsaInterestLifetime());
   _LOG_DEBUG("Max Faces Per Prefix: " << m_maxFacesPerPrefix);
-  _LOG_DEBUG("Hyperbolic ROuting: " << m_hyperbolicState);
+  _LOG_DEBUG("Hyperbolic Routing: " << m_hyperbolicState);
   _LOG_DEBUG("Hyp R: " << m_corR);
   _LOG_DEBUG("Hyp theta: " << m_corTheta);
   _LOG_DEBUG("Log Directory: " << m_logDir);
   _LOG_DEBUG("Seq Directory: " << m_seqFileDir);
+
+  // Event Intervals
+  _LOG_DEBUG("Adjacency LSA build interval:  " << m_adjLsaBuildInterval);
+  _LOG_DEBUG("First Hello Interest interval: " << m_firstHelloInterval);
+  _LOG_DEBUG("Routing calculation interval:  " << m_routingCalcInterval);
 }
 
 } // namespace nlsr
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 8f2965b..6f51d70 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -46,6 +46,24 @@
 };
 
 enum {
+  ADJ_LSA_BUILD_INTERVAL_MIN = 0,
+  ADJ_LSA_BUILD_INTERVAL_DEFAULT = 5,
+  ADJ_LSA_BUILD_INTERVAL_MAX = 5
+};
+
+enum {
+  FIRST_HELLO_INTERVAL_MIN = 0,
+  FIRST_HELLO_INTERVAL_DEFAULT = 10,
+  FIRST_HELLO_INTERVAL_MAX = 10
+};
+
+enum {
+  ROUTING_CALC_INTERVAL_MIN = 0,
+  ROUTING_CALC_INTERVAL_DEFAULT = 15,
+  ROUTING_CALC_INTERVAL_MAX = 15
+};
+
+enum {
   HELLO_RETRIES_MIN = 1,
   HELLO_RETRIES_DEFAULT = 3,
   HELLO_RETRIES_MAX = 15
@@ -80,6 +98,9 @@
 public:
   ConfParameter()
     : m_lsaRefreshTime(LSA_REFRESH_TIME_DEFAULT)
+    , m_adjLsaBuildInterval(ADJ_LSA_BUILD_INTERVAL_DEFAULT)
+    , m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
+    , m_routingCalcInterval(ROUTING_CALC_INTERVAL_DEFAULT)
     , m_lsaInterestLifetime(ndn::time::seconds(static_cast<int>(LSA_INTEREST_LIFETIME_DEFAULT)))
     , m_routerDeadInterval(2*LSA_REFRESH_TIME_DEFAULT)
     , m_logLevel("INFO")
@@ -189,6 +210,42 @@
   }
 
   void
+  setAdjLsaBuildInterval(uint32_t interval)
+  {
+    m_adjLsaBuildInterval = interval;
+  }
+
+  uint32_t
+  getAdjLsaBuildInterval() const
+  {
+    return m_adjLsaBuildInterval;
+  }
+
+  void
+  setFirstHelloInterval(uint32_t interval)
+  {
+    m_firstHelloInterval = interval;
+  }
+
+  uint32_t
+  getFirstHelloInterval() const
+  {
+    return m_firstHelloInterval;
+  }
+
+  void
+  setRoutingCalcInterval(uint32_t interval)
+  {
+    m_routingCalcInterval = interval;
+  }
+
+  uint32_t
+  getRoutingCalcInterval() const
+  {
+    return m_routingCalcInterval;
+  }
+
+  void
   setRouterDeadInterval(int64_t rdt)
   {
     m_routerDeadInterval = rdt;
@@ -339,6 +396,11 @@
   ndn::Name m_lsaPrefix;
 
   int32_t  m_lsaRefreshTime;
+
+  uint32_t m_adjLsaBuildInterval;
+  uint32_t m_firstHelloInterval;
+  uint32_t m_routingCalcInterval;
+
   ndn::time::seconds m_lsaInterestLifetime;
   int64_t  m_routerDeadInterval;
   std::string m_logLevel;
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index cefaa29..1af254e 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -155,7 +155,7 @@
       _LOG_DEBUG("Scheduling scheduledAdjLsaBuild");
       m_nlsr.setIsBuildAdjLsaSheduled(true);
       // event here
-      m_scheduler.scheduleEvent(ndn::time::seconds(5),
+      m_scheduler.scheduleEvent(m_adjLsaBuildInterval,
                                 ndn::bind(&Lsdb::scheduledAdjLsaBuild, &m_nlsr.getLsdb()));
     }
   }
@@ -200,7 +200,7 @@
         _LOG_DEBUG("Scheduling scheduledAdjLsaBuild");
         m_nlsr.setIsBuildAdjLsaSheduled(true);
         // event here
-        m_scheduler.scheduleEvent(ndn::time::seconds(5),
+        m_scheduler.scheduleEvent(m_adjLsaBuildInterval,
                                   ndn::bind(&Lsdb::scheduledAdjLsaBuild, &m_nlsr.getLsdb()));
       }
     }
@@ -285,7 +285,7 @@
         _LOG_DEBUG("Scheduling scheduledAdjLsaBuild");
         m_nlsr.setIsBuildAdjLsaSheduled(true);
         // event here
-        m_scheduler.scheduleEvent(ndn::time::seconds(5),
+        m_scheduler.scheduleEvent(m_adjLsaBuildInterval,
                                   ndn::bind(&Lsdb::scheduledAdjLsaBuild, &m_nlsr.getLsdb()));
       }
     }
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index 30385d9..25868bd 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -33,15 +33,14 @@
 
 class HelloProtocol
 {
-
 public:
   HelloProtocol(Nlsr& nlsr, ndn::Scheduler& scheduler)
     : m_nlsr(nlsr)
     , m_scheduler(scheduler)
+    , m_adjLsaBuildInterval(static_cast<uint32_t>(ADJ_LSA_BUILD_INTERVAL_DEFAULT))
   {
   }
 
-public:
   void
   scheduleInterest(uint32_t seconds);
 
@@ -54,6 +53,18 @@
   void
   processInterest(const ndn::Name& name, const ndn::Interest& interest);
 
+  void
+  setAdjLsaBuildInterval(uint32_t interval)
+  {
+    m_adjLsaBuildInterval = ndn::time::seconds(interval);
+  }
+
+  const ndn::time::seconds&
+  getAdjLsaBuildInterval() const
+  {
+    return m_adjLsaBuildInterval;
+  }
+
 private:
   void
   processInterestTimedOut(const ndn::Interest& interest);
@@ -85,6 +96,8 @@
 
   static const std::string INFO_COMPONENT;
   static const std::string NLSR_COMPONENT;
+
+  ndn::time::seconds m_adjLsaBuildInterval;
 };
 
 } //namespace nlsr
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 930dc33..a66e6aa 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -142,7 +142,13 @@
   m_nlsrLsdb.buildAndInstallOwnCoordinateLsa();
 
   registerKeyPrefix();
-  m_helloProtocol.scheduleInterest(10);
+
+  // Set event intervals
+  setFirstHelloInterval(m_confParam.getFirstHelloInterval());
+  m_helloProtocol.setAdjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval());
+  m_routingTable.setRoutingCalcInterval(m_confParam.getRoutingCalcInterval());
+
+  m_helloProtocol.scheduleInterest(m_firstHelloInterval);
 
   // Need to set direct neighbors' costs to 0 for hyperbolic routing
   if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 00b7877..866ad7c 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -43,6 +43,7 @@
 #include "route/fib.hpp"
 #include "communication/sync-logic-handler.hpp"
 #include "hello-protocol.hpp"
+#include "test-access-control.hpp"
 
 #include "validator.hpp"
 
@@ -86,6 +87,7 @@
     , m_certificateCache(new ndn::CertificateCacheTtl(ioService))
     , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
     , m_faceMonitor(m_nlsrFace)
+    , m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
   {
     m_faceMonitor.onNotification += ndn::bind(&Nlsr::onFaceEventNotification, this, _1);
     m_faceMonitor.start();
@@ -313,6 +315,12 @@
   void
   daemonize();
 
+  uint32_t
+  getFirstHelloInterval() const
+  {
+    return m_firstHelloInterval;
+  }
+
 private:
   void
   registerKeyPrefix();
@@ -332,6 +340,12 @@
   void
   onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification);
 
+  void
+  setFirstHelloInterval(uint32_t interval)
+  {
+    m_firstHelloInterval = interval;
+  }
+
 private:
   typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > CertMap;
 
@@ -352,8 +366,11 @@
   Fib m_fib;
   NamePrefixTable m_namePrefixTable;
   SyncLogicHandler m_syncLogicHandler;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   HelloProtocol m_helloProtocol;
 
+private:
   ndn::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
   CertMap m_certToPublish;
   Validator m_validator;
@@ -362,6 +379,8 @@
   ndn::Name m_defaultCertName;
 
   ndn::nfd::FaceMonitor m_faceMonitor;
+
+  uint32_t m_firstHelloInterval;
 };
 
 } //namespace nlsr
diff --git a/src/route/routing-table.cpp b/src/route/routing-table.cpp
index 09b9430..371d977 100644
--- a/src/route/routing-table.cpp
+++ b/src/route/routing-table.cpp
@@ -156,7 +156,7 @@
 RoutingTable::scheduleRoutingTableCalculation(Nlsr& pnlsr)
 {
   if (pnlsr.getIsRouteCalculationScheduled() != true) {
-    m_scheduler.scheduleEvent(ndn::time::seconds(15),
+    m_scheduler.scheduleEvent(m_routingCalcInterval,
                               ndn::bind(&RoutingTable::calculate, this, ndn::ref(pnlsr)));
 
     pnlsr.setIsRouteCalculationScheduled(true);
diff --git a/src/route/routing-table.hpp b/src/route/routing-table.hpp
index 6dd3ef2..c85efe9 100644
--- a/src/route/routing-table.hpp
+++ b/src/route/routing-table.hpp
@@ -29,6 +29,7 @@
 #include <boost/cstdint.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
 
+#include "conf-parameter.hpp"
 #include "routing-table-entry.hpp"
 
 namespace nlsr {
@@ -42,8 +43,10 @@
   RoutingTable(ndn::Scheduler& scheduler)
     : m_scheduler(scheduler)
     , m_NO_NEXT_HOP(-12345)
+    , m_routingCalcInterval(static_cast<uint32_t>(ROUTING_CALC_INTERVAL_DEFAULT))
   {
   }
+
   void
   calculate(Nlsr& pnlsr);
 
@@ -65,6 +68,18 @@
     return m_NO_NEXT_HOP;
   }
 
+  void
+  setRoutingCalcInterval(uint32_t interval)
+  {
+    m_routingCalcInterval = ndn::time::seconds(interval);
+  }
+
+  const ndn::time::seconds&
+  getRoutingCalcInterval() const
+  {
+    return m_routingCalcInterval;
+  }
+
 private:
   void
   calculateLsRoutingTable(Nlsr& pnlsr);
@@ -91,6 +106,8 @@
 
   std::list<RoutingTableEntry> m_rTable;
   std::list<RoutingTableEntry> m_dryTable;
+
+  ndn::time::seconds m_routingCalcInterval;
 };
 
 }//namespace nlsr
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index d05e39c..fc0d663 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -35,85 +35,220 @@
 using ndn::DummyFace;
 using ndn::shared_ptr;
 
-BOOST_FIXTURE_TEST_SUITE(TestConfFileProcessor, BaseFixture)
+const std::string SECTION_GENERAL =
+  "general\n"
+  "{\n"
+  "  network /ndn/\n"
+  "  site /memphis.edu/\n"
+  "  router /cs/pollux/\n"
+  "  lsa-refresh-time 1800\n"
+  "  lsa-interest-lifetime 3\n"
+  "  log-level  INFO\n"
+  "  log-dir /tmp\n"
+  "  seq-dir /tmp\n"
+  "}\n\n";
 
-BOOST_AUTO_TEST_CASE(ConfFileProcessorSample)
+const std::string SECTION_NEIGHBORS =
+  "neighbors\n"
+  "{\n"
+  "  hello-retries 3\n"
+  "  hello-timeout 1\n"
+  "  hello-interval  60\n\n"
+  "  adj-lsa-build-interval 3\n"
+  "  first-hello-interval  6\n"
+  "  neighbor\n"
+  "  {\n"
+  "    name /ndn/memphis.edu/cs/castor\n"
+  "    face-uri  udp4://localhost\n"
+  "    link-cost 20\n"
+  "  }\n\n"
+  "  neighbor\n"
+  "  {\n"
+  "    name /ndn/memphis.edu/cs/mira\n"
+  "    face-uri  udp4://localhost\n"
+  "    link-cost 30\n"
+  "  }\n"
+  "}\n\n";
+
+const std::string SECTION_HYPERBOLIC_ON =
+  "hyperbolic\n"
+  "{\n"
+  "  state on\n"
+  "  radius   123.456\n"
+  "  angle    1.45\n"
+  "}\n\n";
+
+const std::string SECTION_HYPERBOLIC_OFF =
+  "hyperbolic\n"
+  "{\n"
+  "  state off\n"
+  "  radius   123.456\n"
+  "  angle    1.45\n"
+  "}\n\n";
+
+const std::string SECTION_FIB =
+  "fib\n"
+  "{\n"
+  "   max-faces-per-prefix 3\n"
+  "   routing-calc-interval 9\n"
+  "}\n\n";
+
+const std::string SECTION_ADVERTISING =
+  "advertising\n"
+  "{\n"
+  "  prefix /ndn/edu/memphis/cs/netlab\n"
+  "  prefix /ndn/edu/memphis/sports/basketball\n"
+  "}\n";
+
+const std::string CONFIG_LINK_STATE = SECTION_GENERAL + SECTION_NEIGHBORS +
+                                      SECTION_HYPERBOLIC_OFF + SECTION_FIB + SECTION_ADVERTISING;
+
+const std::string CONFIG_HYPERBOLIC = SECTION_GENERAL + SECTION_NEIGHBORS +
+                                      SECTION_HYPERBOLIC_ON + SECTION_FIB + SECTION_ADVERTISING;
+
+class ConfFileProcessorFixture : public BaseFixture
 {
-  shared_ptr<DummyFace> face = ndn::makeDummyFace();
+public:
+  ConfFileProcessorFixture()
+    : face(ndn::makeDummyFace())
+    , nlsr(g_ioService, g_scheduler, ndn::ref(*face))
+    , CONFIG_FILE("unit-test-nlsr.conf")
+  {
+  }
 
-  Nlsr nlsr1(g_ioService, g_scheduler, ndn::ref(*face));
+  ~ConfFileProcessorFixture()
+  {
+    remove("unit-test-nlsr.conf");
+  }
 
-  const std::string CONFIG =
-     "general\n"
-    "{\n"
-    "  network /ndn/\n"
-    "  site /memphis.edu/\n"
-    "  router /cs/pollux/\n"
-    "  lsa-refresh-time 1800\n"
-    "  lsa-interest-lifetime 3\n"
-    "  log-level  INFO\n"
-    "  log-dir /tmp\n"
-    "  seq-dir /tmp\n"
-    "}\n\n"
-    "neighbors\n"
-    "{\n"
-    "  hello-retries 3\n"
-    "  hello-timeout 1\n"
-    "  hello-interval  60\n\n"
-    "  neighbor\n"
-    "  {\n"
-    "    name /ndn/memphis.edu/cs/castor\n"
-    "    face-uri  udp4://localhost\n"
-    "    link-cost 20\n"
-    "  }\n\n"
-    "  neighbor\n"
-    "  {\n"
-    "    name /ndn/memphis.edu/cs/mira\n"
-    "    face-uri  udp4://localhost\n"
-    "    link-cost 30\n"
-    "  }\n"
-    "}\n\n"
-    "hyperbolic\n"
-    "{\n"
-    "state off\n"
-    "radius   123.456\n"
-    "angle    1.45\n"
-    "}\n\n"
-    "fib\n"
-    "{\n"
-    "   max-faces-per-prefix 3\n"
-    "}\n\n"
-    "advertising\n"
-    "{\n"
-    "prefix /ndn/edu/memphis/cs/netlab\n"
-    "prefix /ndn/edu/memphis/sports/basketball\n"
-    "}\n";
+  bool processConfigurationString(std::string confString)
+  {
+    std::ofstream config;
+    config.open("unit-test-nlsr.conf");
+    config << confString;
+    config.close();
 
-  std::ofstream config;
-  config.open("unit-test-nlsr.conf");
-  config << CONFIG;
-  config.close();
+    ConfFileProcessor processor(nlsr, CONFIG_FILE);
+    return processor.processConfFile();
+  }
 
-  const std::string CONFIG_FILE = "unit-test-nlsr.conf";
+public:
+  shared_ptr<ndn::DummyFace> face;
+  Nlsr nlsr;
 
-  ConfFileProcessor cfp1(nlsr1, CONFIG_FILE);
+private:
+  const std::string CONFIG_FILE;
+};
 
-  cfp1.processConfFile();
+BOOST_FIXTURE_TEST_SUITE(TestConfFileProcessor, ConfFileProcessorFixture)
 
-  BOOST_CHECK(nlsr1.getAdjacencyList().isNeighbor("/ndn/memphis.edu/cs/mira"));
-  BOOST_CHECK_EQUAL(
-    nlsr1.getAdjacencyList().getAdjacent("/ndn/memphis.edu/cs/mira").getName(),
-    "/ndn/memphis.edu/cs/mira");
-  BOOST_CHECK_EQUAL(
-    nlsr1.getAdjacencyList().getAdjacent("/ndn/memphis.edu/cs/mira").getLinkCost(),
-    30);
+BOOST_AUTO_TEST_CASE(LinkState)
+{
+  processConfigurationString(CONFIG_LINK_STATE);
 
-  BOOST_CHECK_EQUAL(nlsr1.getNamePrefixList().getSize(), 2);
+  ConfParameter& conf = nlsr.getConfParameter();
+  conf.buildRouterPrefix();
 
-  BOOST_CHECK_EQUAL(nlsr1.getConfParameter().getLsaInterestLifetime(),
-                    ndn::time::seconds(3));
+  // General
+  BOOST_CHECK_EQUAL(conf.getNetwork(), "/ndn/");
+  BOOST_CHECK_EQUAL(conf.getSiteName(), "/memphis.edu/");
+  BOOST_CHECK_EQUAL(conf.getRouterName(), "/cs/pollux/");
+  BOOST_CHECK_EQUAL(conf.getRouterPrefix(), "/ndn/memphis.edu/cs/pollux/");
+  BOOST_CHECK_EQUAL(conf.getChronosyncPrefix(), "/ndn/NLSR/sync");
+  BOOST_CHECK_EQUAL(conf.getLsaPrefix(), "/ndn/NLSR/LSA");
+  BOOST_CHECK_EQUAL(conf.getLsaRefreshTime(), 1800);
+  BOOST_CHECK_EQUAL(conf.getLsaInterestLifetime(), ndn::time::seconds(3));
+  BOOST_CHECK_EQUAL(conf.getRouterDeadInterval(), 3600);
+  BOOST_CHECK_EQUAL(conf.getLogLevel(), "INFO");
+  BOOST_CHECK_EQUAL(conf.getLogDir(), "/tmp");
+  BOOST_CHECK_EQUAL(conf.getSeqFileDir(), "/tmp");
 
-  remove("unit-test-nlsr.conf");
+  // Neighbors
+  BOOST_CHECK_EQUAL(conf.getInterestRetryNumber(), 3);
+  BOOST_CHECK_EQUAL(conf.getInterestResendTime(), 1);
+  BOOST_CHECK_EQUAL(conf.getInfoInterestInterval(), 60);
+
+  BOOST_CHECK_EQUAL(conf.getAdjLsaBuildInterval(), 3);
+  BOOST_CHECK_EQUAL(conf.getFirstHelloInterval(), 6);
+
+  BOOST_CHECK(nlsr.getAdjacencyList().isNeighbor("/ndn/memphis.edu/cs/mira"));
+  BOOST_CHECK(nlsr.getAdjacencyList().isNeighbor("/ndn/memphis.edu/cs/castor"));
+  BOOST_CHECK(!nlsr.getAdjacencyList().isNeighbor("/ndn/memphis.edu/cs/fail"));
+
+  Adjacent mira = nlsr.getAdjacencyList().getAdjacent("/ndn/memphis.edu/cs/mira");
+  BOOST_CHECK_EQUAL(mira.getName(), "/ndn/memphis.edu/cs/mira");
+  BOOST_CHECK_EQUAL(mira.getLinkCost(), 30);
+
+  Adjacent castor = nlsr.getAdjacencyList().getAdjacent("/ndn/memphis.edu/cs/castor");
+  BOOST_CHECK_EQUAL(castor.getName(), "/ndn/memphis.edu/cs/castor");
+  BOOST_CHECK_EQUAL(castor.getLinkCost(), 20);
+
+  // Hyperbolic
+  BOOST_CHECK_EQUAL(conf.getHyperbolicState(), 0);
+
+  // FIB
+  BOOST_CHECK_EQUAL(conf.getMaxFacesPerPrefix(), 3);
+  BOOST_CHECK_EQUAL(conf.getRoutingCalcInterval(), 9);
+
+  // Advertising
+  BOOST_CHECK_EQUAL(nlsr.getNamePrefixList().getSize(), 2);
+}
+
+BOOST_AUTO_TEST_CASE(Hyperbolic)
+{
+  processConfigurationString(CONFIG_HYPERBOLIC);
+
+  ConfParameter& conf = nlsr.getConfParameter();
+  BOOST_CHECK_EQUAL(conf.getHyperbolicState(), 1);
+  BOOST_CHECK_EQUAL(conf.getCorR(), 123.456);
+  BOOST_CHECK_EQUAL(conf.getCorTheta(), 1.45);
+}
+
+BOOST_AUTO_TEST_CASE(DefaultValues)
+{
+  // Missing adj-lsa-build-interval
+  const std::string SECTION_NEIGHBORS_DEFAULT_VALUES =
+  "neighbors\n"
+  "{\n"
+  "  hello-retries 3\n"
+  "  hello-timeout 1\n"
+  "  hello-interval  60\n\n"
+  "  first-hello-interval  6\n"
+  "  neighbor\n"
+  "  {\n"
+  "    name /ndn/memphis.edu/cs/castor\n"
+  "    face-uri  udp4://localhost\n"
+  "    link-cost 20\n"
+  "  }\n\n"
+  "  neighbor\n"
+  "  {\n"
+  "    name /ndn/memphis.edu/cs/mira\n"
+  "    face-uri  udp4://localhost\n"
+  "    link-cost 30\n"
+  "  }\n"
+  "}\n\n";
+
+  processConfigurationString(SECTION_NEIGHBORS_DEFAULT_VALUES);
+
+  ConfParameter& conf = nlsr.getConfParameter();
+
+  BOOST_CHECK_EQUAL(conf.getAdjLsaBuildInterval(),
+                    static_cast<uint32_t>(ADJ_LSA_BUILD_INTERVAL_DEFAULT));
+
+  BOOST_CHECK_EQUAL(conf.getFirstHelloInterval(), 6);
+}
+
+BOOST_AUTO_TEST_CASE(OutOfRangeValue)
+{
+  const std::string SECTION_FIB_OUT_OF_RANGE =
+  "fib\n"
+  "{\n"
+  "   max-faces-per-prefix 3\n"
+  "   routing-calc-interval 999\n" // Larger than max value
+  "}\n\n";
+
+  // Processing should fail due to out of range value
+  BOOST_CHECK_EQUAL(processConfigurationString(SECTION_FIB_OUT_OF_RANGE), false);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index e76508c..01480d9 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -85,6 +85,27 @@
   }
 }
 
+BOOST_AUTO_TEST_CASE(SetEventIntervals)
+{
+  shared_ptr<DummyFace> face = ndn::makeDummyFace();
+  Nlsr nlsr(g_ioService, g_scheduler, ndn::ref(*face));
+
+  // Simulate loading configuration file
+  ConfParameter& conf = nlsr.getConfParameter();
+  conf.setAdjLsaBuildInterval(3);
+  conf.setFirstHelloInterval(6);
+  conf.setRoutingCalcInterval(9);
+
+  nlsr.initialize();
+
+  const HelloProtocol& hello = nlsr.m_helloProtocol;
+  const RoutingTable& rt = nlsr.getRoutingTable();
+
+  BOOST_CHECK_EQUAL(hello.getAdjLsaBuildInterval(), ndn::time::seconds(3));
+  BOOST_CHECK_EQUAL(nlsr.getFirstHelloInterval(), 6);
+  BOOST_CHECK_EQUAL(rt.getRoutingCalcInterval(), ndn::time::seconds(9));
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } //namespace test
diff --git a/tests/wscript b/tests/wscript
index 63bcafa..e7ce752 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -47,7 +47,7 @@
             target='../unit-tests-nlsr',
             features='cxx cxxprogram',
             source=bld.path.ant_glob(['nlsr/**/*.cpp']),
-            use='nslr-objects unit-tests-main',
+            use='nlsr-objects unit-tests-main',
             includes='.',
             install_prefix=None,
           )